为什么标准禁止sizeof应用于函数

时间:2014-03-05 07:36:39

标签: c sizeof

标准C(ISO / IEC 9899:1999)第6.5.3.4节说

  

sizeof运算符不应用于具有的表达式   功能类型或不完整类型

但为什么呢? 使用readelf检查可执行文件可以发现在编译期间完全知道函数大小。

Symbol table '.symtab' contains 67 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
.......
    37: 0000000000400541    16 FUNC    LOCAL  DEFAULT   13 clean
.......
    46: 00000000004005f0     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
......
    49: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@@GLIBC_2.2.5
    52: 00000000004005f4     0 FUNC    GLOBAL DEFAULT   14 _fini
    53: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_
ed
    58: 0000000000400560   137 FUNC    GLOBAL DEFAULT   13 __libc_csu_init

    62: 000000000040052c    21 FUNC    GLOBAL DEFAULT   13 main

此处,大小0属于共享库中的函数,例如puts@@GLIBC_2.2.5函数。所以我查看了libc信息,这里有一段与readelf -a /lib/x86_64-linux-gnu/libc.so.6相关的puts@@GLIBC_2.2.5输出

                          Size  Type 
  ...........   
  399: 0000000000070ec0   392 FUNC    WEAK   DEFAULT   12 puts@@GLIBC_2.2.5

它只是不必要的功能,还是它打破了C哲学,还是有一些我看不到的技术问题?

3 个答案:

答案 0 :(得分:4)

我认为这是因为sizeof仅对于具有unsigned char [sizeof(type)]表示的对象有意义。现在在C中,函数没有表示(没有从函数指针类型到数据指针类型的转换),所以你可以说没有有意义的sizeof用法。

答案 1 :(得分:2)

  

使用readelf检查可执行文件显示在编译期间完全知道函数大小。

但是如果在同一系统上使用不同的编译器编译代码,或者甚至使用具有不同优化选项的相同编译器编译代码,则此大小通常会更改。例如,如果您使用gcc,请尝试使用gcc -O0gcc -O2,然后比较函数的代码大小。

但编译器所做的优化并不是要改变他们试图优化的代码行为。让表达式在不同的优化级别下具有不同的价值正在改变代码的行为。

汇编程序和/或链接程序也可以对编译器生成的汇编代码进行一些优化或修改,因此会更改某些函数的代码大小。

另外,C不是函数式编程语言,函数不是第一类对象,这意味着你不能将它存储到变量中,将它作为参数传递给另一个函数,依此类推,似乎没有意义。得到一个函数的大小。

答案 2 :(得分:1)

C的要点是它对指令进行了抽象,因此您不必处理程序的二进制表示。与汇编程序相比,这提供了许多优点 - 主要是提高生产率,便携性。

sizeof功能并不是全部有用,因为你无论如何都无法访问数据,或者复制它等等。系统可以将可执行内存标记为仅执行,因此需要你的C标准能够做到这些事情无法在这样的系统上实现。

编译会更难。在完成所有操作之后,它基本上需要单独传递,以回过头来填写函数的大小。

话虽如此,这将是一个非常可怕的功能,你可以检查是否(sizeof(* function)== 0)看看它是否内联,等等。但是,考虑到c99并没有真正实现然而,我会说,即使在最好的情况下,它也不会比2050年更容易获得。