As noted in other answers, there are distinct answers to your question depending on whether you are talking about calling the function "externally" or calling it "internally."
Within the same contract, recent Solidity versions include language features to pass around a "function pointer" (it's not really a pointer per-se but it behaves like one). In other words, there exist variables of type "function." This is what I mean by "internally" passing around a function and calling it.
For "external" calls, i.e., function calls to an on-chain address, you would use Solidity address type member "call()" and/or Yul (assembly) etc to emulate a contract call as Solidity would compile such a function call when expressed as "someAddr.someFunction()" ... and this amounts to encoding the function signature as a selector (selectors are the first 4 bytes of the hash of the function signature) plus the arguments you want to pass, and executing the necessary EVM bytecodes (assembly) using those data.
In other words, for "external" functions, the "function pointer" is the tuple (address,selector).