C语言中函数名的含义是什么?定义函数时编译器做了什么?函数名是指针吗?
C语言中函数名的本质与编译行为
一、函数名代表什么?
函数名是函数代码在内存中起始地址的标识符,它直接关联着函数体的执行入口。在多数代码上下文里,函数名会被隐式转换为指向该函数的指针,但它本身和函数指针并非完全等同。
举个简单例子:
void print_msg() { printf("hello"); }
这里的print_msg就代表这个打印函数的入口地址,当你调用print_msg()时,程序就是通过这个地址找到对应的函数代码并执行。
二、定义函数时编译器的操作
当你写出一个函数定义,编译器会依次完成以下核心操作:
- 语法与语义校验:检查函数的返回值类型、参数列表、函数体语法是否符合C标准,比如参数类型是否匹配、局部变量是否未定义等。
- 生成可执行代码:把函数体的C代码翻译成对应平台的汇编指令,再进一步转换为机器码,这些代码会被归类到可执行段(比如Linux系统下的
.text段)。 - 符号表登记:将函数名作为一个符号,关联到它在可执行文件中的入口地址,这个符号表会被后续的链接器用来处理跨文件的函数调用地址解析。
- 栈帧布局规划:根据函数的参数数量、局部变量大小,规划栈帧的结构,包括参数的栈存储位置、局部变量的分配空间,以及返回地址的保存逻辑。
三、函数名是指针吗?
不是。函数名和函数指针是相关但完全不同的概念:
- 函数名属于函数类型的标识符,比如上面的
print_msg属于void(void)类型。 - 当你在表达式中使用函数名(除了
sizeof、&运算符的场景),它会被自动转换为指向该函数的指针(对应类型为void(*)(void))。
看这段代码就能明白区别:
void print_msg() {} void (*func_ptr)() = print_msg; // 函数名自动转为函数指针,完成赋值 void (*func_ptr2)() = &print_msg; // 直接取函数地址,和上面效果一致
但你不能对函数名执行指针的操作,比如print_msg++是非法的——因为函数名不是可修改的左值,而函数指针变量则可以进行这类合理操作。另外,sizeof(print_msg)不合法,但sizeof(func_ptr)是合法的,因为指针有明确的内存大小。
内容的提问来源于stack exchange,提问作者yuangsc
相关产品推荐
相关产品推荐

