微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如果“long”和“int”的大小在一个平台上相同——“long”和“int”有什么不同吗?

如何解决如果“long”和“int”的大小在一个平台上相同——“long”和“int”有什么不同吗?

如果 long intint 在平台上的表示相同,它们是否严格相同?根据 C 标准,这些类型在平台上的行为是否有任何不同?

例如。这是否总是有效:

int int_var;
long long_var;

void long_bar(long *l);
void int_bar(int *i);

void foo() 
{
    long_bar(&int_var); /* Always OK? */
    int_bar(&long_var);
}

我想同样的问题也适用于 short 和 int,如果它们碰巧是相同的表示。

在讨论如何为没有 stdint.h 的嵌入式 C89 编译器(即 int32_tint)定义类似 long 的 typedef 以及这是否重要时出现了问题。

解决方法

它们是不兼容的类型,您可以通过一个简单的示例看到:

int* iptr;
long* lptr = iptr; // compiler error here

因此在处理指向这些类型的指针时最重要。同样,有“严格别名规则”使此代码行为未定义:

int i;
long* lptr = (long*)&i;
*lptr = ...;  // undefined behavior

另一个微妙的问题是隐式提升。如果您有 some_int + some_long,则该表达式的结果类型为 long。或者,如果任一参数未签名,则为 unsigned long。这是因为通过通常的算术转换进行整数提升,请参阅Implicit type promotion rules。 大多数情况下应该无关紧要,但这样的代码会失败:_Generic(some_int + some_long,int: stuff() ) 因为表达式中没有 long 子句。

一般来说,在类型之间赋值时,应该不会有任何问题。在 uint32_t 的情况下,它对应于哪种类型并不重要,因为无论如何您都应该将 uint32_t 视为单独的类型。我选择 long 是为了与小型微控制器兼容,typedef unsigned int uint32_t; 会损坏。 (显然,typedef signed long int32_t; 表示已签名的等价物。)

,

类型 longint 具有不同的等级。 long 类型的等级高于 int 类型的等级。因此,在使用 long 类型的对象和 int 类型的对象的二进制表达式中,最后一个始终转换为 long 类型。

比较以下代码片段。

int x = 0;
unsigned int y = 0;

表达式 x + y 的类型是 unsigned int

long x = 0;
unsigned int y = 0;

表达式 x + y 的类型是 unsigned long(由于通常的算术转换),前提是 sizeof( int ) 等于 sizeof( long)

这在 C++ 中比在允许函数重载的 C 中更重要。

在 C 中,您必须考虑到这一点,例如,当您使用 i/o 函数时,例如 printf 来指定正确的转换说明符。

,

即使在 longint 具有相同表示的平台上,该标准也允许编译器故意忽视将值存储到 long* 的行为可能影响 int* 的值,反之亦然。鉴于以下内容:

#include <stdint.h>

void store_to_int32(void *p,int index)
{
    ((int32_t*)p)[index] = 2;
}
int array1[10];
int test1(int index)
{
    array1[0] = 1;
    store_to_int32(array1,index);
    return array1[0];
}
long array2[10];
long test2(int index)
{
    array2[0] = 1;
    store_to_int32(array2,index);
    return array2[0];
}

gcc 的 32 位 ARM 版本会将 int32_t 视为 long 的同义词,并忽略将 array1 的地址传递给 store_to_int32 可能导致要写入该数组的第一个元素,并且 32 位版本的 clang 会将 int32_t 视为 int 的同义词,并忽略将 array2 的地址传递给 {{1 }} 可能会导致该数组的第一个元素被写入。

可以肯定的是,标准中的任何内容都不会禁止编译器以这种方式行事,但我认为标准未能禁止这种盲目性源于“越愚蠢的东西,就越不需要禁止它”。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。