3

I'm learning function pointers in C. I learned that a function pointer stores the address of the starting point of a function. Consider the following program:

#include <stdio.h>
void display(); 

int main()
{
 void (*ptr)(); 
 ptr = &display;
 (*ptr)(); 
 return 0;
}

void display() 
{
 printf("hello"); 
}

If the address of void display() gets stored in ptr, then what will be the address of #include <stdio.h> and so on?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
anna poorani
  • 690
  • 1
  • 8
  • 17
  • 1
    Though the dupe is marked as C++, it's applicable for C also, in general. Please let me know if anybody disagrees. – Sourav Ghosh Oct 04 '16 at 17:57
  • 1
    Compilation isn't that linear a transformation. Source code can be mapped to object code only very roughly. The beginning of a function is bound to exist and will have an address. However, the compilation will mangle the function body pretty much beyond recognition, which is basically why we don't have decompilers. – Petr Skocik Oct 04 '16 at 18:01
  • A C function doesn't have a "starting point" to which the pointer refers; such a thing appears in implementations. (E.g. a function image is a sequence of machine instructions, and the pointer might point to the first one at the lowest address.) No such thing is required in the ISO C standard, AFAIR. – Kaz Oct 04 '16 at 18:08
  • 2
    I cannot make sense of "what will be the size of address for #include ". – Kaz Oct 04 '16 at 18:10
  • You can label and arbitrary point in the function body with a goto-abel label (an identifier followed by a colon), and a fairly common C extension (present in clang, gcc, and tcc) allows you to get an address of that label. The address-of-a-label functionality isn't standard C, but I think it's about as closest to what you seem to be asking as you can get. – Petr Skocik Oct 04 '16 at 18:10
  • 1
    @SouravGhosh It's clearly not a dupe of that. – Petr Skocik Oct 04 '16 at 18:18
  • Apparently the dup hammer comes with an undup hammer as well. (It occurs to me that that sentence makes no sense at all without context.) – Keith Thompson Oct 04 '16 at 18:32
  • 1
    @KeithThompson: That'd be a pry bar, wouldn't it? – Kerrek SB Oct 04 '16 at 19:02

1 Answers1

3

A function pointer is typically implemented as the address of the code for the function's entry point, but as far as the language is concerned it's just an opaque value that can be used to call the function (and compared for [in]equality to other function pointers of the same type). It could be an index into a program-wide or system-wide table, and/or it could contain extra information.

The language does not provide a way to query the address of a statement; as far as the C standard is concerned, that concept doesn't even exist.

If you want to look at the generated machine code, you could reasonably talk about the address of the code generated for a given statement. For example, your statement

ptr = &display;

might correspond to a MOV instruction, and that instruction probably has a (machine-level) address, though the standard language gives you no way to use that information. A goto statement jumps to a specified statement, and it's probably implemented with an instruction that refers to the machine address of the first instruction for that statement, but the standard's description of goto doesn't talk about it at that level of detail; it only describes the semantics.

Some compilers, including gcc, have an extension (documented here) that lets you take the address of a label. But that applies only to labelled statements.

In particular, the directive

#include <stdio.h>

is processed by an early phase of the compiler, often implemented as a separate preprocessor. It introduces a number of declarations that can be referred to by the following code. There is typically no generated code that corresponds to the #include directive, so it's meaningless to talk about its "address".

And as PSkocik points out in a comment, code generation is not necessarily linear; there might not be any code associated with a given statement if the compiler is able to reorder it for better speed. (If you use the gcc extension to take the address of a label, then the compiler might inhibit optimization if necessary to ensure that that address is meaningful.)

As far as standard C is concerned, even if you could take the address of a given statement, the language doesn't have any constructs that would let you do anything with it; the standard goto statement, for example, only takes a literal label name.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Maybe some link to how a C/C++ program would be useful to know the difference between compilation and preprocessing, where includes are processed: http://users.cs.cf.ac.uk/Dave.Marshall/C/node3.html – Jorge Bellon Oct 04 '16 at 18:32
  • 1
    @JorgeBellón: As far as the standard is concerned, preprocessing is just the early phases of compilation. But I've added a reference to the preprocessor. – Keith Thompson Oct 04 '16 at 18:32