当 C(或 C++)中的“unsigned long”和“unsigned int”都是 32 位宽时,使用它们是否存在可观察到的差异?
我使用的是带有编译器的 MPC56XX(嵌入式系统),其 int
和 long
均为 32 位宽。
在所需的软件包中,我们对 32 位宽类型进行了以下定义:
typedef signed int sint32;
typedef unsigned int uint32;
在新版本中,在没有太多文档的情况下将其更改为:
typedef signed long sint32;
typedef unsigned long uint32;
我可以明白为什么这将是一件好事:整数在 short 之间有一个转换等级
和 long
,因此理论上在使用第一组定义时可以应用额外的转换。
我的问题:考虑到包作者强加给我们的上述更改,是否存在可以想象的情况,这样的更改会更改编译的代码,从而正确地导致不同的结果?
我熟悉“通常的一元转换”和“通常的二进制转换”,但我很难想出一个具体的情况,这可能会真正破坏我现有的代码。但这真的无关紧要吗?
我目前在纯 C 环境中工作,使用 C89/C94,但我对 C 和 C++ 问题都感兴趣。
编辑:我知道重新定义时将 int
与 sint32
混合可能会产生不同的结果。但我们不允许直接使用原始的 C 类型,只能使用 typedef 的类型。
我正在寻找使用常量、一元/二元运算符、强制转换等的示例(表达式或片段),并根据更改的类型定义具有不同但正确的编译结果。
I'm using an MPC56XX (embedded systems) with a compiler for which an int
and a long
are both 32 bits wide.
In a required software package we had the following definitions for 32-bit wide types:
typedef signed int sint32;
typedef unsigned int uint32;
In a new release this was changed without much documentation to:
typedef signed long sint32;
typedef unsigned long uint32;
I can see why this would be a good thing: Integers have a conversion rank between short
and long
, so theoretically extra conversions can apply when using the first set of definitions.
My question: Given the above change forced upon us by the package authors, is there a situation imaginable where such a change would change the compiled code, correctly leading to a different result?
I'm familiar with the "usual unary conversions" and the "usual binary conversions", but I have a hard time coming up with a concrete situation where this could really ruin my existing code. But is it really irrelevant?
I'm currently working in a pure C environment, using C89/C94, but I'd be interested in both C and C++ issues.
EDIT: I know that mixing int
with sint32
may produce different results when it's redefined. But we're not allowed to use the original C types directly, only the typedef'ed ones.
I'm looking for a sample (expression or snippet) using constants, unary/binary operators, casts, etc. with a different but correct compilation result based on the changed type definition.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在 C++ 中,您可能会遇到函数重载的问题。假设您有以下内容:
在 typedef 定义更改之前,将打印值
6
。更改后,将打印值4
。虽然重载不太可能产生如此不同的行为,但这是有可能的。您还可能会遇到重载解析问题。假设您有两个具有以下定义的函数:
并使用以下方式调用函数:
在更改之前,函数调用是明确的,
func(int)
将是完全匹配的。 typedef 更改后,不再存在精确匹配(两个函数都不需要很长时间),并且编译器会失败,因为它将无法确定要调用哪个重载。In C++ you may run into issues with function overloading. Say you had the following:
Prior to the typedef definition change, the value
6
would be printed. After the change the value4
would be printed. While it's unlikely that an overload would have behavior that's this different, it is a possibility.You could also run into issues with overload resolution. Assume you had two functions with the following definitions:
and were calling the functions with:
Prior to the change, the function call was unambiguous,
func(int)
would be an exact match. After the typedef change, there is no longer an exact match (neither function takes a long), and the compiler fails since it will not be able to determine which overload to invoke.这可能会导致一些微妙的问题,因为默认情况下文字数字是
int
。考虑以下程序:
这会导致错误,因为对
newp
的调用现在不明确:而它工作得很好前。
因此,在使用文字的地方可能会出现一些意外的重载。如果您总是使用命名(因此类型化)常量,那么应该没问题。
It might lead to subtle issues because literal numbers are
int
by default.Consider the following program:
This leads to an error because the call to
newp
is now ambiguous:whereas it worked fine before.
So there might be some overloads surprises where literals were used. If you always use named (and thus typed) constants, you should be fine.
如果在需要指向 int/long 的指针的地方使用了指向 sint32/uint32 的指针(反之亦然),并且它们不匹配 int 与 int 或 long 与 long,则可能会在编译时收到警告或错误(可能在C,在 C++ 中保证)。
If a pointer to sint32/uint32 is used where a pointer to int/long is expected (or vice versa) and they don't match int with int or long with long, you may get a warning or error at compile time (may in C, guaranteed in C++).
标准中没有任何内容允许代码安全地将 32 位
int
和long
视为可互换的。给定代码:编译器有权假设,因为
p1
和p2
被声明为不同的类型(一个为int
,另一个为 < code>long),它们不可能指向同一个对象(不调用未定义行为)。对于任何输入字符,如果上述程序需要执行任何操作(即通过导致i1
和i2
不相等来避免未定义行为的操作),则该程序将是需要输出 1234。由于严格别名规则,编译器有权对“P”、“E”、“J”或“O”等字符执行任何操作,这会导致i和
j
接收匹配值;因此它也可以输出 1234。虽然许多
int
和long
均为 32 位的编译器有可能(事实上很可能)实际上将它们视为严格别名规则的等效类型,标准中没有任何内容强制要求此类行为。Nothing in the Standard would allow code to safely regard a 32-bit
int
andlong
as interchangeable. Given the code:A compiler would be entitled to assume that because
p1
andp2
are declared as different types (one asint
and the otherlong
), they cannot possibly point to the same object (without invoking Undefined Behavior). For any input character were the above program would be required to do anything (i.e. those which would avoid Undefined Behavior by causingi1
andi2
to be unequal), the program would be required to output 1234. Because of the Strict Aliasing Rule, a compiler would be entitled to do anything it likes for characters like 'P', 'E', 'J', or 'O' which would causei
andj
to receive matching values; it could thus output 1234 for those as well.While it's possible (and in fact likely) that many compilers where both
int
andlong
are 32 bits will in fact regard them as equivalent types for purposes of the Strict Aliasing Rule, nothing in the Standard mandates such behavior.