错误使用 ARM C 编译器选项 "Enum container always int" 的示例是什么?
What's an example of incorrect use of the ARM C Compiler Option "Enum container always int"?
在http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0065d/Cihejcda.html中有一个选项和一个注释:
Enum container always int
Select this option to force all enumerations to be stored in integers. By default, the compiler uses the smallest data type that can hold all values in an enum.
Note
This option is not recommended for general use and is not required for ANSI-compatible source. If used incorrectly, this option can cause errors in the resulting image.
C 语言中这种错误用法的例子是什么?
背景:
我正在用 C 开发嵌入式应用程序,删除此编译器标志修复了一个错误(或仅修复了另一个错误的症状)。错误是
sprintf(big_enought_char_array, "%4.1f", float_var)
函数调用未正确格式化浮点数。
这几乎通过对用作堆栈的内存使用右对齐来解决。 “几乎”修复了,因为数组的内容没问题,但小数点有错误的字符。删除上面提到的编译器选项解决了这个问题。所以问题是这个编译器选项 究竟在做什么 什么是不正确的使用?
what is this compiler option doing exactly
嗯,通常你的平均值 enum
没有,例如2³² 个条目——在大多数情况下,它甚至没有 256 个。在这种情况下,C 编译器通常可以自由使用更短的值表示形式,例如一个字节。
使用该标志将使所有 enum
占用相同的 int
大小(读取:字长)内存。这只是在一些非常特殊的情况下,显然,它打破了 sprintf
;我认为这不是经常发生的事情,所以:您使用的是什么 libc
实现?确保它没有明确禁止使用该标志,并在必要时提交错误报告。做一个最小的测试用例来演示这个问题。
我假设你指的是这个选项:
Enum container always int
Select this option to force all enumerations to be stored in integers. By default, the compiler uses the smallest data type that can hold all values in an enum.
在 C 中,用于枚举类型的类型是实现定义的(但 enum
常量始终是 int
):它是一个整数类型,可以表示所有 enum
常数。
如果将枚举类型的类型设置为int
,我可以想到两个问题:
1) 如果你的程序依赖于 enum
是 int
这一事实(例如假设 sizeof
与 sizeof (int)
相同),它是在其他系统上不可移植
2) 如果你定义一个值大于 INT_MAX
的常量(或者 int
不能表示),比如 UINT_MAX
,你的类型将无法在保证 C enum
代表它的地方代表它。
关于 sprintf
调用的具体问题,似乎与此选项完全无关。您可能在调用之前调用了一些未定义的行为。
这是我对 sprintf()
的猜测:
你的堆栈实际上被声明为一个 char[]
数组,它是一些 enum
变量或者在一个 __packed
结构中。将 enum
从 char
更改为 int
(或相反)更改了堆栈变量的对齐方式,使浮点数对齐。 (sprintf()
的第三个变量是 float
几乎肯定会在堆栈上传递)
ARM 要求堆栈为 8 字节对齐。最好将其声明为 uint64_t
(并且绝对不是在 __packed
结构中),因此它的对齐总是正确的。
在http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0065d/Cihejcda.html中有一个选项和一个注释:
Enum container always int
Select this option to force all enumerations to be stored in integers. By default, the compiler uses the smallest data type that can hold all values in an enum.
Note
This option is not recommended for general use and is not required for ANSI-compatible source. If used incorrectly, this option can cause errors in the resulting image.
C 语言中这种错误用法的例子是什么?
背景:
我正在用 C 开发嵌入式应用程序,删除此编译器标志修复了一个错误(或仅修复了另一个错误的症状)。错误是
sprintf(big_enought_char_array, "%4.1f", float_var)
函数调用未正确格式化浮点数。
这几乎通过对用作堆栈的内存使用右对齐来解决。 “几乎”修复了,因为数组的内容没问题,但小数点有错误的字符。删除上面提到的编译器选项解决了这个问题。所以问题是这个编译器选项 究竟在做什么 什么是不正确的使用?
what is this compiler option doing exactly
嗯,通常你的平均值 enum
没有,例如2³² 个条目——在大多数情况下,它甚至没有 256 个。在这种情况下,C 编译器通常可以自由使用更短的值表示形式,例如一个字节。
使用该标志将使所有 enum
占用相同的 int
大小(读取:字长)内存。这只是在一些非常特殊的情况下,显然,它打破了 sprintf
;我认为这不是经常发生的事情,所以:您使用的是什么 libc
实现?确保它没有明确禁止使用该标志,并在必要时提交错误报告。做一个最小的测试用例来演示这个问题。
我假设你指的是这个选项:
Enum container always int
Select this option to force all enumerations to be stored in integers. By default, the compiler uses the smallest data type that can hold all values in an enum.
在 C 中,用于枚举类型的类型是实现定义的(但 enum
常量始终是 int
):它是一个整数类型,可以表示所有 enum
常数。
如果将枚举类型的类型设置为int
,我可以想到两个问题:
1) 如果你的程序依赖于 enum
是 int
这一事实(例如假设 sizeof
与 sizeof (int)
相同),它是在其他系统上不可移植
2) 如果你定义一个值大于 INT_MAX
的常量(或者 int
不能表示),比如 UINT_MAX
,你的类型将无法在保证 C enum
代表它的地方代表它。
关于 sprintf
调用的具体问题,似乎与此选项完全无关。您可能在调用之前调用了一些未定义的行为。
这是我对 sprintf()
的猜测:
你的堆栈实际上被声明为一个 char[]
数组,它是一些 enum
变量或者在一个 __packed
结构中。将 enum
从 char
更改为 int
(或相反)更改了堆栈变量的对齐方式,使浮点数对齐。 (sprintf()
的第三个变量是 float
几乎肯定会在堆栈上传递)
ARM 要求堆栈为 8 字节对齐。最好将其声明为 uint64_t
(并且绝对不是在 __packed
结构中),因此它的对齐总是正确的。