【发布时间】:2026-01-04 07:15:02
【问题描述】:
当我们使用sizeof() 检查函数的大小时,我们总是得到1 个字节。
这 1 个字节代表什么?
【问题讨论】:
当我们使用sizeof() 检查函数的大小时,我们总是得到1 个字节。
这 1 个字节代表什么?
【问题讨论】:
这是违反约束的,您的编译器应该诊断它。如果它编译它尽管如此,你的程序有未定义的行为[感谢@Steve Jessop 对故障模式的澄清,请参阅@Michael Burr's answer 了解为什么一些编译器允许这样做]:来自 C11,6.5.3.4./1 :
sizeof运算符不得应用于具有函数类型的表达式
【讨论】:
-pedantic),你有一个不符合标准的编译器并且每个程序都有未定义的行为。
-std=c11 也是如此,不是 gnu11。这是一个非常奇怪的编译器扩展。
sizeof(void) 在 GNU C 中为 1 一样。
-std=c11:有人应该将-std=c* 选项参考广告标准。它们不启用一致性模式,它们只是禁用会阻止格式正确的程序编译的扩展(例如 typeof 是关键字,因为格式正确的 C 程序可以将其用作变量名,但 @987654330 @ 默认情况下会拒绝)。要另外禁用允许格式错误的程序通过未诊断的扩展,您需要-pedantic 或-pedantic-errors。
这不是未定义的行为 - C 语言标准需要在将 sizeof 运算符与函数指示符(函数名称)一起使用时进行诊断,因为它违反了 sizeof 运算符的约束。
但是,作为 C 语言的扩展,GCC 允许对 void 指针和函数指针进行算术运算,这是通过将 void 或函数的大小视为 1 来完成的。因此,sizeof 运算符将评估为 1 用于 void 或带有 GCC 的函数。见http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-Arith
通过使用 GCC 的 -pedantic 或 -Wpointer-arith 选项,您可以让 GCC 在将 sizeof 与这些操作数一起使用时发出警告。或者使用-Werror=pointer-arith 使其成为错误。
【讨论】:
sizeof 一个函数不是 UB(我之所以提到这一点只是因为其他答案说它是 UB)之外,我真的没有说明任何关于 UB 的任何内容。但也许我混淆了这一点,因为我构建句子的方式。要更清楚。 sizeof 一个函数不是 UB(正如几个答案所声称的)。这是违反约束的。因此,它需要诊断。 GCC 允许它作为扩展。
这表示编译器编写者决定使用 1 的值,而不是让恶魔从你的鼻子上飞走(事实上,这是 sizeof 的另一个未定义用法,它给了我们这样的表达:“C 编译器本身必须发出诊断如果这是您的程序产生的第一个必需的诊断,那么它本身可能会导致恶魔从您的鼻子飞出(顺便说一句,这很可能是记录在案的诊断消息),就像它可能会发出进一步的诊断以进一步违反语法规则或约束(或者,就此而言,出于它选择的任何原因)。”https://groups.google.com/forum/?fromgroups=#!msg/comp.std.c/ycpVKxTZkgw/S2hHdTbv4d8J
由此而来的俚语术语“鼻恶魔”表示编译器为响应未定义的构造而决定执行的任何操作。 1 是本例编译器的鼻恶魔。
【讨论】:
正如其他人指出的那样, sizeof() 可以采用任何有效的标识符,但它不会为函数名称返回有效的(真实有效的)结果。此外,它肯定可能会或可能不会导致“鬼出鼻”综合症。
如果您想分析您的程序函数大小,请检查链接器映射,它可以在中间结果目录中找到(东西被编译成 .obj/.o 或生成的图像/可执行文件所在的位置)。有时可以选择是否生成此映射文件...它取决于编译器/链接器。
如果您想要指向函数的指针的大小,它们的大小都是相同的,即 CPU 上寻址字的大小。
【讨论】:
int x = 1;,但对于符合标准的编译器,只允许其中一个。将sizeof() 应用于函数时,它可能会或可能不会返回设定值,或拒绝编译,或根据当时特定寄存器中的任何内容返回随机值。字面鼻恶魔不太可能,但在标准的字母范围内。
sizeof 应用于指向函数的指针。