首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >gcc隐性类型化的意外结果

问gcc隐性类型化的意外结果
EN

Stack Overflow用户
提问于 2018-01-30 13:49:57
回答 1查看 94关注 0票数 4

正如标题中所述,我遇到了一件非常奇怪的事情,就是在Linux上对GCC进行显式和隐式的类型转换。

我有以下简单的代码来演示这个问题:

代码语言:javascript
复制
#include <stdio.h>
#include <stdint.h>

int main(void)
{
   int i;
   uint32_t e1 = 0;
   uint32_t e2 = 0;
   const float p = 27.7777;

   printf("#   e1 (unsigned)   e1 (signed)       e2 (unsigned)   e2 (signed)\n");
   for (i = 0; i < 10; i++) {
      printf("%d   %13u   %11d       %13u   %11d\n", i, e1, e1, e2, e2);
      e1 -= (int)p;
      e2 -= p;
   }
   return 0;
}

如您所见,e1由p显式类型减少到int,而e2由p隐式类型减少。

我希望e1和e2包含相同的值,但它们不.事实上,结果似乎与系统有关。

为了测试代码,我有两个虚拟机(VirtualBox是从Vagrant开始的)。这是第一台机器:

代码语言:javascript
复制
vagrant@vagrant:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.3 LTS
Release:        16.04
Codename:       xenial
vagrant@vagrant:~$ uname -a
Linux vagrant 4.4.0-92-generic #115-Ubuntu SMP Thu Aug 10 16:02:55 UTC 2017 i686 i686 i686 GNU/Linux
vagrant@vagrant:~$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

要构建和执行,我使用以下

代码语言:javascript
复制
vagrant@vagrant:~$ gcc -Wall /vagrant/test.c
vagrant@vagrant:~$ ./a.out
#   e1 (unsigned)   e1 (signed)       e2 (unsigned)   e2 (signed)
0               0             0                   0             0
1      4294967269           -27          4294967269           -27
2      4294967242           -54          4294967268           -28
3      4294967215           -81          4294967268           -28
4      4294967188          -108          4294967268           -28
5      4294967161          -135          4294967268           -28
6      4294967134          -162          4294967268           -28
7      4294967107          -189          4294967268           -28
8      4294967080          -216          4294967268           -28
9      4294967053          -243          4294967268           -28
vagrant@vagrant:~$

如您所见,对于使用显式类型转换的e1来说,一切看起来都很好,但是对于e2来说,结果非常奇怪.

然后,我在另一个虚拟机上尝试了同样的方法,这是Ubuntu的64位版本:

代码语言:javascript
复制
vagrant@ubuntu-xenial:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.3 LTS
Release:        16.04
Codename:       xenial
vagrant@ubuntu-xenial:~$ uname -a
Linux ubuntu-xenial 4.4.0-112-generic #135-Ubuntu SMP Fri Jan 19 11:48:36 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
vagrant@ubuntu-xenial:~$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.5) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

下面是应用程序的输出:

代码语言:javascript
复制
vagrant@ubuntu-xenial:~$ gcc -Wall /vagrant/test.c
vagrant@ubuntu-xenial:~$ ./a.out
#   e1 (unsigned)   e1 (signed)       e2 (unsigned)   e2 (signed)
0               0             0                   0             0
1      4294967269           -27          4294967269           -27
2      4294967242           -54                   0             0
3      4294967215           -81          4294967269           -27
4      4294967188          -108                   0             0
5      4294967161          -135          4294967269           -27
6      4294967134          -162                   0             0
7      4294967107          -189          4294967269           -27
8      4294967080          -216                   0             0
9      4294967053          -243          4294967269           -27

e2的值仍然与我所期望的不一样,但现在与我在32位系统上的值不同了。

我不知道这种差异是由32位对64位造成的,还是与其他相关的。

然而,我想了解为什么在e1和e2上存在差异,以及在发生这种情况时是否有可能至少得到GCC的警告。

谢谢:-)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-30 14:13:22

语句e2 -= p等效于e2 = e2 - p。因为e2 - p是一个包含float (e2 = unsigned_val - float_val)的减法,所以这个表达式的计算结果是float,这意味着您实际上要将float值赋值给一个无符号整数变量。

另一个语句e1 -= (int) p不是等价的,因为这里发生的是e1 = unsigned_val - int_val,所以分配给e1的值是一个整数,而不是浮点。

由于将浮点值分配到整数的值超出整数类型范围的整数是未定义的行为(请参见C标准的6.3.1.4实浮点数和整数),因此您在分配给e2时,在不同的平台上都会遇到不同的行为。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48523073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档