【问题标题】:using sizeof () to find function type length in ANSI C [duplicate]使用 sizeof () 在 ANSI C 中查找函数类型长度 [重复]
【发布时间】:2013-09-24 18:09:52
【问题描述】:

当我需要查找函数类型长度时,我用sizeof()来做。

预期的结果是 4 字节和 8 字节,但现在通过 GCC 得到的结果是 1 字节。

为什么输出是 1 字节,而不是 4 字节和 8 字节?

#include <stdio.h>

int foo (); 
double bar (); 

int 
main (void)
{
    printf ("int foo () %lu\n", sizeof (foo));  
    printf ("double bar () %lu\n", sizeof (bar));
}

double 
bar (void)
{
    return 1.1;
}

int
foo (void)
{
    return 0;
}               

【问题讨论】:

  • sizeof 仅在对象类型上明确定义。
  • 使用-Wpointer-arith编译看看
  • 养成使用-pedantic-errors命令行选项运行GCC的习惯。总是。省略-pedantic-errors,只有你们有非常非常好的理由这样做。
  • @P0W,这是一个很棒的链接——其中一个答案甚至有一个合理的理由说明它为什么会这样工作。

标签: c sizeof


【解决方案1】:

sizeof 运算符不得用于函数类型,这是 ISO/IEC C 标准明确禁止的。所以返回值没有意义。

参考ISO/IEC 9899:201x §6.5.3.4

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

我猜启用-pedantic 标志应该会引发警告。

【讨论】:

    【解决方案2】:

    您正在尝试查找函数本身的大小而不是其返回值。为了找到返回值的类型,你需要添加一对括号,告诉编译器你需要函数调用表达式的类型,像这样:

    printf ("int foo () %lu\n", sizeof (foo()));  
    printf ("double bar () %lu\n", sizeof (bar()));
    

    请注意,这些函数不会被调用:它们的返回类型的 sizeof 将在编译时计算出来。

    Demo on ideone.

    【讨论】:

      【解决方案3】:

      虽然标准规定 sizeof 运算符不得应用于具有函数类型的表达式”(第 6.5.3.4/1 节),但在 GNU C 中,这样做的结果定义明确:

      sizeof 也可以用于 void 和函数类型,并返回 1”
      ~GCC, 6.23 Arithmetic on void- and Function-Pointers

      也可以看看:Why is the size of a function in C always 1 byte?

      【讨论】:

        【解决方案4】:

        不应将 sizeof 应用于具有函数类型的变量。因此,您所看到的基本上是未定义的行为。理想情况下,编译器应该抱怨它..

        【讨论】:

          【解决方案5】:

          sizeof 应用于函数名是违反约束,需要任何符合标准的编译器进行诊断。 gcc 默认情况下不符合要求,但可以(几乎)使用正确的命令行选项进行设置,例如:

          gcc -std=c99 -pedantic
          

          (如果您愿意,请将c99 替换为c90c11)。

          gcc 有一个扩展,允许在void* 和函数指针上进行指针运算。 (这种扩展是 ISO 标准允许的,但符合标准的编译器仍必须诊断出任何违反约束的情况。)例如,将 1 加到函数指针上,将其前移 1 个字节。

          不幸的是,恕我直言,gcc 开发人员选择通过为函数和 void 类型指定大小为 1 来做到这一点。指针算术的行为由此而来,但它有一个缺点,即试图计算函数或 void 表达式不会被拒绝。

          标准 C 没有提供确定函数大小的方法;它甚至没有讨论这样的概念。据我所知,gcc 没有提供这样做的扩展; sizeof func 产生一个虚构的值 1,与函数的代码大小无关。

          您始终可以确定函数指针的大小,通常为 4 或 8 个字节,但当然这不是函数本身的大小。你不能通过将sizeof 应用于函数名称来做到这一点。

          如果 C 程序可以获得函数的大小(大概是实现它的代码的大小),那么除了显示它之外,我想不出它可以对这些信息做什么有用的事情。如果这是您要查找的信息,您可能会检查程序集列表或目标文件。例如,在类 Unix 系统上,nm foo.o 的输出显示了每个函数的地址;这通常可以告诉您每个函数的代码大小(可能最后一个函数除外)。这都是非常特定于系统的。

          【讨论】:

            猜你喜欢
            • 2019-09-21
            • 1970-01-01
            • 2015-11-22
            • 2018-04-23
            • 2013-07-09
            • 2014-07-22
            • 2013-07-16
            • 2015-02-22
            • 1970-01-01
            相关资源
            最近更新 更多