简体   繁体   English

x64 和 arm64 之间的隐式类型转换和不同行为

[英]Implicit type conversion and different behavior between x64 and arm64

I'm facing a weird issue when testing my software on arm64.在 arm64 上测试我的软件时,我遇到了一个奇怪的问题。

I've written a bit of code to reproduce the issue :我写了一些代码来重现这个问题:

char c;
int sum = 0;
for (int i = 0; i <= 255; i++)
{
   c = i;
   int a = c * 10;
   sum += a;
   std::cout << a << std::endl;
}

When I run it on Windows (built with Visual Studio 2017) or Ubuntu x64 (gcc 9.3.0-17) I have the following results :当我在 Windows(使用 Visual Studio 2017 构建)或 Ubuntu x64(gcc 9.3.0-17)上运行它时,我得到以下结果:

0
10
...
1260
1270
-1280
-1270
-20
-10
sum=-1280

if I run the same code on Ubuntu arm64 (gcc 9.3.0-17), I have different results :如果我在 Ubuntu arm64 (gcc 9.3.0-17) 上运行相同的代码,我会得到不同的结果:

0
10
...
1260
1270
1280
1290
...
2540
2550
sum=326400

I don't know if there is some extra optimization in gcc on arm64 (using -O3) or if there is some issue I don't see ?我不知道 arm64 上的 gcc 是否有一些额外的优化(使用 -O3),或者是否有一些我看不到的问题? Any idea on how I can solve this issue?关于如何解决这个问题的任何想法?

The char data type can be either signed or unsigned . char数据类型可以是signedunsigned In the case of the former (as seems to be the case when targeting x64), the c = i statement will cause overflow on the 129 th iteration of the for loop (the maximum value for a signed char is 127) and the value it is being assigned has 'wrapped round' to a negative value.在前者的情况下(似乎是针对 x64 的情况), c = i语句将导致for循环的129迭代(有signed char的最大值为 127)和它的值溢出正在分配的“环绕”为负值。

However, when targeting arm64, your compiler appears to use an unsigned char type (with a range of 0 thru 255 ), so there is no overflow in that statement and the arithmetic proceeds 'as expected'.但是,当以 arm64 为目标时,您的编译器似乎使用unsigned char类型(范围为0255 ),因此该语句中没有溢出,并且算术“按预期”进行。


To confirm (or otherwise) the above diagnosis, just check the value of the CHAR_MAX constant (defined in the <climits> header file) in your different build environments.要确认(或以其他方式)上述诊断,只需检查不同构建环境中的CHAR_MAX常量(在<climits>头文件中定义)的值。

char is signed by standard . char由标准签名。
However, ARM decided to make it unsigned by default decades ago.然而,ARM 几十年前决定默认不签名。

It's that simple.就这么简单。

char is represented by 8 bit and it is signed. char用 8 位表示,并有符号。 You can store 0-127, after that first bit is interpreted as a negative number.在第一位被解释为负数之后,您可以存储 0-127。 Maybe it is better to use uint8_t or similar instead of char .也许最好使用uint8_t或类似的代替char

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM