不同大小的相同枚举类型

时间:2017-08-23 11:50:39

标签: c enums embedded

以下代码中枚举类型的大小不同,为什么?枚举类型的声明是否会导致gcc将其视为signed int?此功能会导致我的项目出现问题,例如,一个枚举类型的大小在" file_1.c"中为1,但在" file_2.c&#34中它的大小为4 ;。

我的测试代码:

enum foo foo_test(void);

enum foo {
    FOO_0
};

enum bar {
    BAR_0
};

int main(int argc, char **argv)
{
    printf("sizeof(enum foo) %d, sizeof(enum bar) %d\n", sizeof(enum foo), sizeof(enum bar));
    return 0;
}
  • 当我在嵌入式项目中使用arm-none-eabi-gcc v4.9.3编译它时

    • 输出为sizeof(enum foo) 4, sizeof(enum bar) 1
  • 当我在Windows中用gcc v4.8.3编译它时

    • 使用gcc -Wall -o sizeofTest.exe sizeofTest.c进行编译
      • 输出为sizeof(enum foo) 4, sizeof(enum bar) 4
    • 使用gcc -Wall -fshort-enums -o sizeofTest.exe sizeofTest.c进行编译
      • 输出为sizeof(enum foo) 4, sizeof(enum bar) 1

4 个答案:

答案 0 :(得分:6)

正如在中询问特殊结果的问题一样常见,这里的原因是未定义的行为。 C11标准草案n1570 6.7.2.3p3

  
      
  1. 表单的类型说明符

    enum identifier
    
         

    没有枚举器列表 仅在指定的类型完成后才会显示。

  2.   

C11 6.7.2.2p4中的完整性:

  
      
  1. [...]枚举类型直到完成枚举器声明列表的}之后才完成,之后完成。
  2.   

由于违反约束部分中的 ,符合标准的编译器必须输出诊断消息 - 但默认情况下GCC不是符合要求的实现,除非您提出要求是-pedantic

ISO C forbids forward references to ‘enum’ types [-Werror=pedantic]
 enum foo foo_test(void);
      ^

现在,似乎那里的编译器使用任何类型的最短可能的枚举。由于您在之前使用了enum foo ,实际上已经定义了其中的内容,因此编译器必须求助于int类型,否则使用char。它可以用-fshort-enums复制。您的程序会打印4 1,而此程序会在我的gcc上打印1 1 -fshort-enums

#include <stdio.h>

enum foo {
    FOO_0
};

enum foo foo_test(void);    

enum bar {
    BAR_0
};

int main(int argc, char **argv)
{
    printf("sizeof(enum foo) %zu, sizeof(enum bar) %zu\n", 
            sizeof(enum foo), sizeof(enum bar));
    return 0;
}

答案 1 :(得分:4)

首先,修复代码中的未定义行为sizeof表达式类型的正确格式说明符为%zu

C中的枚举器的支持类型可以是charintunsigned。只要能够存储所有枚举值,编译器就可以选择其中任何一个。

因此值为1是可行的(因为sizeof(char)总是1),并且您已经要求某些编译器挤压enum支持类型。

对于int的支持类型似乎选择了foo这一事实,我认为,在您定义它之前引用enum foo,以及您的友好C编译器正在使用某种隐式int。这种隐式声明不再是标准C,而且您的代码不是严格可移植的。

参考:http://en.cppreference.com/w/c/language/enum

答案 2 :(得分:2)

这是未定义的行为。

您必须使用%zuprintf()格式化为size_t类型的值。

如果值的大小与int的大小不同,printf()中的代码将误读varargs-argument并错误地了解其值(va_arg(args, int);而不是va_arg(args, size_t); TextView tv = view.findViewbyId(R.id.textView);

答案 3 :(得分:-1)

答案其实很简单。

由于函数原型返回枚举类型,编译器将其假定为int并且其大小与硬件相关(在您的情况下为4个字节)它是为了优化目的而完成的。对于另一个,存储在尽可能小的数据类型中。 (可能使用-Os optimization和/或-shshort-enums)

对于具有真实编程经验的编码人员来说,这种行为是众所周知的,如果你想让它们保持简短,这就是没有将函数声明为返回枚举的原因。

对于C标准狂热分子uint8_t foo();return FOO_0;可能是不可接受的,但编程是一门真实的,现实的和实用的科学。