Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当C(或C+;+;)中的“unsigned long”和“unsigned int”都是32位宽时,是否存在可观察到的差异?_C++_C_Implicit Conversion_Language Lawyer - Fatal编程技术网

C++ 当C(或C+;+;)中的“unsigned long”和“unsigned int”都是32位宽时,是否存在可观察到的差异?

C++ 当C(或C+;+;)中的“unsigned long”和“unsigned int”都是32位宽时,是否存在可观察到的差异?,c++,c,implicit-conversion,language-lawyer,C++,C,Implicit Conversion,Language Lawyer,我使用的是带有编译器的MPC56XX(嵌入式系统),其中int和long都是32位宽 在所需的软件包中,我们对32位宽类型有以下定义: typedef signed int sint32; typedef unsigned int uint32; 在一个新版本中,在没有太多文档的情况下将其更改为: typedef signed long sint32; typedef unsigned long uint32; 我可以理解为什么这是一件好事:整数的转换等级介于short和long之间

我使用的是带有编译器的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/C94C,但我对C和C++问题都感兴趣。 编辑:我知道将

int
sint32
混合使用可能会在重新定义时产生不同的结果。但是我们不允许直接使用原始的C类型,只允许使用类型定义的类型。

我在使用常量、一元/二进制运算符、转换等来查找一个示例(表达式或代码段),基于不同的类型定义,不同的编译结果是正确的。C++中的

< P>可能会遇到函数重载的问题。假设您有以下情况:

signed int func(signed int x) {
    return x + 1;
}

signed long func(signed long x) {
    return x - 1;
}

int main(void) {
    sint32 x = 5;
    std::cout << func(x) << std::endl;
}
并使用以下命令调用函数:

sint32 x;
func(x);

在更改之前,函数调用是明确的,
func(int)
将是完全匹配的。typedef更改后,不再存在精确匹配(两个函数都不需要长时间),编译器将失败,因为它将无法确定要调用的重载。

如果在需要指向int/long的指针的地方使用指向sint32/uint32的指针(反之亦然),并且它们不匹配int与int或long与long,您可能会在编译时收到警告或错误(可能是C语言,保证是C++)

#包括
#如果UINT_MAX!=乌龙乔马克斯酒店
#错误这是针对sizeof(int)=sizeof(long)系统的测试
#恩迪夫
typedef无符号uint32i;
typedef无符号长uint32l;
uint32i-i1;
uint32l-l1;
无符号*p1i=&i1;
无符号长*p1l=&l1;
无符号*p2il=&l1;//此处编译时出现警告或错误
无符号长*p2li=&i1;//此处编译时出现警告或错误
内部主(空)
{
返回0;
}

这可能会导致一些微妙的问题,因为默认情况下,文字数字是
int

考虑一下:

然而它以前工作得很好


所以在使用文本的地方可能会有一些意外的重载。如果您总是使用命名(并因此键入)常量,那就没问题了。

标准中没有任何内容允许代码安全地将32位
int
视为可互换的。鉴于代码:

#include <stdio.h>

typedef int i32;
typedef long si32;

int main(void)
{
  void *m = calloc(4,4); // Four 32-bit integers
  char ch = getchar();
  int i1 = ch & 3;
  int i2 = (ch >> 2) & 3;
  si32 *p1=(si32*)m + i1;
  i32 *p2=(i32*)m + i2;

  *p1 = 1234;
  *p2 = 5678;
  printf("%d", *p1);
  return 0;
}
#包括
typedef int i32;
typedef长si32;
内部主(空)
{
void*m=calloc(4,4);//四个32位整数
char ch=getchar();
int i1=ch&3;
inti2=(ch>>2)和3;
si32*p1=(si32*)m+i1;
i32*p2=(i32*)m+i2;
*p1=1234;
*p2=5678;
printf(“%d”,*p1);
返回0;
}
编译器有权假设,由于
p1
p2
被声明为不同的类型(一个是
int
,另一个是
long
),它们不可能指向同一个对象(不调用未定义的行为)。对于任何输入字符,上述程序都需要执行任何操作(即通过导致
i1
i2
不相等来避免未定义行为的操作),程序需要输出1234。由于严格的别名规则,编译器有权对“P”、“E”、“J”或“O”等字符执行任何它喜欢的操作,这将导致
i
J
接收匹配值;因此,它也可以输出1234个


尽管出于严格的别名规则的目的,许多
int
long
都是32位的编译器可能(事实上很可能)实际上会将它们视为等效类型,但标准中并没有规定此类行为。

它们仍然是不同的类型·@johanneschaub litb在其评论中指出,它们是不同的类型。这意味着您可以从重载解析中获得不同的结果,您可以得到不同的
typeid
结果,等等。然而,关于算术运算,它是相同的,除非您有真正反常的内部编译器。干杯,@AlfP.Steinbach是的,这是我最初的想法。但我有一种感觉,类似的情况可能存在。我现在想不出有比我更聪明的人了,但我倒想问问。什么时候使用
int
?什么时候使用的是
sint32
?键入的内容完全相同,但速度更快;)此外,模板也存在同样的“问题”——例如,想想
boost::is_same
会导致错误+1好的结果。但是(参见我的编辑)我们只允许使用typedef'ed类型,而不允许使用原生C类型,并且至少不鼓励混合使用不同的类型。但是,根据定义,常量具有本机类型。不同类型的混合是不可避免的…几乎所有我在嵌入式系统中遇到的可移植性问题,我们都有相同的规则(没有原始INT)来自数字文字被视为不同大小的文件platforms@AShelly:一个特别令人发指的问题可能是十六进制文字太大,无法放入
int
,但会放入
无符号int
。考虑<代码> LoVaR和= ~0x000 000 000 800万的影响;<代码>。它将失败(INT_MAX+1)
#include <limits.h>

#if UINT_MAX != ULONG_MAX
#error this is a test for systems with sizeof(int)=sizeof(long)
#endif

typedef unsigned uint32i;
typedef unsigned long uint32l;

uint32i i1;
uint32l l1;

unsigned* p1i = &i1;
unsigned long* p1l = &l1;

unsigned* p2il = &l1; // warning or error at compile time here
unsigned long* p2li = &i1; // warning or error at compile time here

int main(void)
{
  return 0;
}
#include <iostream>

typedef signed short old16;
typedef signed int old32;

void old(old16) { std::cout << "16\n"; }
void old(old32) { std::cout << "32\n"; }

typedef signed short new16;
typedef signed long new32;

void newp(new16) { std::cout << "16\n"; }
void newp(new32) { std::cout << "32\n"; }

int main() {
  old(3);
  newp(3); // expected-error{{call of overload ‘newp(int)’ is ambiguous}}
}
prog.cpp: In function ‘int main()’:
prog.cpp:17: error: call of overloaded ‘newp(int)’ is ambiguous
prog.cpp:12: note: candidates are: void newp(new16)
prog.cpp:13: note:                 void newp(new32)
#include <stdio.h>

typedef int i32;
typedef long si32;

int main(void)
{
  void *m = calloc(4,4); // Four 32-bit integers
  char ch = getchar();
  int i1 = ch & 3;
  int i2 = (ch >> 2) & 3;
  si32 *p1=(si32*)m + i1;
  i32 *p2=(i32*)m + i2;

  *p1 = 1234;
  *p2 = 5678;
  printf("%d", *p1);
  return 0;
}