【问题标题】:What does 'sizeof (function name)' return?'sizeof(函数名)'返回什么?
【发布时间】:2011-02-09 14:50:07
【问题描述】:

示例代码:

int main(void)
{
    printf ("size = %d\n", sizeof(main));
}

sizeof 应用于函数名的返回值是什么,例如main

【问题讨论】:

  • 我的猜测是 -1 是因为 TIAS(“试试看”)。
  • TIAS 的问题在于它通常不起作用,因为您所看到的只是 您当前的编译器与您当前的选项 实际执行的操作,这可能与编译器应该做什么。通过下面的讨论再次证明了这一点。 (实际上,您必须在 GCC 的命令行中添加一个 -pedantic 选项来观察“官方”行为。这只是一个编译器)所以这是我的 +1,只是为了对抗愚蠢的 TIAS 否决票。

标签: c function sizeof


【解决方案1】:

C 标准禁止它 - 当使用 gcc -pedantic 编译时,它会产生 invalid application of ‘sizeof’ to a function type 警告。

但是gcc 编译它并为sizeof(main) 返回1,它不是函数指针的大小。

它似乎依赖于编译器。

【讨论】:

  • 虽然gcc 可以编译它,但不清楚它是否正在执行从main&main 的翻译。例如,使用 gcc 4.1.2 的 codepad 为 sizeof(main) 返回大小为 1,但为 sizeof(&main) 返回大小为 4。
  • @Aeth 你是完全正确的,我用最新最好的 GCC 4.5 得到了同样的结果。帖子已编辑。
【解决方案2】:

The sizeof Operator

 sizeof unary-expression
 sizeof ( type-name )

操作数可以是作为一元表达式的标识符,也可以是类型转换表达式(即括在括号中的类型说明符)。 一元表达式不能表示位域对象、不完整类型或function designator。结果是一个无符号整数常数。标准头文件 STDDEF.H 将此类型定义为size_t

使用编译标志-Wall -pedanticsizeof 发出有关不正确操作数的警告(记住sizeof 是编译时运算符),代码:

$ cat sizeof.c 
#include<stdio.h> 
int main(){
    printf("%zu %p\n", sizeof(main), (void*)main);
    return 0;
} 

使用 GCC 版本 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) 的编译消息:

$ gcc -Wall -pedantic sizeof.c -std=c99
sizeof.c: In function ‘main’:
sizeof.c:3:30: warning: invalid application of ‘sizeof’ to a function type 
              [-pedantic]
sizeof.c:3:38: warning: ISO C forbids conversion of function pointer to 
              object pointer type [-pedantic]

另请阅读:

6.5.3.4 The sizeof operator

1118 — sizeof 运算符不应应用于具有函数类型或不完整类型的表达式、此类类型的括号名称或指定位的表达式-字段成员
1127 — 结果的值是实现定义的,它的类型(无符号整数类型)是size_t,在&lt;stddef.h&gt;(和其他头文件)中定义

另外,size_t 的正确格式字符串是 %zu,如果它不存在,例如 Microsoft 的编译器,那么您可以使用 %lu 并将返回值转换为 unsigned long

【讨论】:

    【解决方案3】:

    ISO C++ 禁止将sizeof 应用于函数类型的表达式。

    C++ 上的 ISO/IEC 14882 说(第 5.3.3 节):

    "大小运算符不能应用于具有函数或不完整类型的表达式,..."

    标准 C (ISO/IEC 9899:1999) 第 6.5.3.4 节同样适用:

    "sizeof 运算符不得应用于具有函数类型或不完整类型的表达式、此类类型的括号名称或指定位域成员的表达式。" em>

    【讨论】:

    • 这背后的道理是什么?
    • 这个问题被标记为C,所以C++标准没有意义。
    • @Aeth C++ 标准的许多部分都是从 C 中采用的。请参阅更新后的答案并添加参考。
    • @yassin:sizeof 可能只对具有unsigned char [sizeof(type)] 表示形式的对象有意义。在 C 中,函数没有表示形式(没有从函数指针类型到数据指针类型的转换),因此sizeof 没有任何意义。
    【解决方案4】:

    根据 ISO C11 部分 6.5.3.4 The sizeof and _Alignof operators,第 1 小节(约束):

    sizeof 运算符不应应用于具有函数类型或不完整类型的表达式、此类类型的括号名称或指定位域成员的表达式。

    6.3.2.1 Lvalues, arrays, and function designators 部分中还有一个小节 4,其中指出:

    函数指示符是具有函数类型的表达式。除非它是 sizeof 运算符、_Alignof 运算符(65) 或一元 &amp; 运算符的操作数,否则为“函数返回”类型的函数指示符 type”被转换为具有“指向函数返回的指针”类型的表达式 输入“”。

    从那里引用的脚注 65 阐明了这一点:

    由于没有发生这种转换,sizeof_Alignof 运算符的操作数仍然是函数指示符,并且违反了 6.5.3.4 中的约束。

    根据4 Conformance部分:

    在本国际标准中,“应”被解释为对实现或程序的要求;相反,“不应”被解释为禁令。

    因此,严格遵守的程序永远不应该占用函数的大小。但是,话又说回来,它可能也应该使用正确的main() 形式:-)

    然而,这里有一个漏洞。允许一致的实现提供扩展“只要它们不改变任何严格的行为 符合程序”(4 Conformance 小节,6 小节)。

    您可能会争辩说这 一种行为改变(允许 sizeof(function) 而不是不允许它)但是,由于最初的程序不会严格遵守,所以小节确实不禁止。

    【讨论】:

    • 符合标准的实现可以提供扩展,只要它们在需要时报告诊断,并且扩展不会改变任何符合标准的程序的行为
    • 如果我没记错的话,gcc 被定义为返回1。如果我的大脑又卡住了,请纠正我。
    • @Matt,好点,我最初认为这是一种行为改变,因此被禁止。但是,由于对严格符合的程序进行了更改,因此无关紧要。更新了调整的答案。
    猜你喜欢
    • 2013-02-17
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2013-11-21
    • 1970-01-01
    相关资源
    最近更新 更多