7073|17

253

帖子

1

TA的资源

一粒金砂(高级)

楼主
 

编译器认为十六进制值是无符号? [复制链接]

编译器认为十六进制值是无符号?如果不是,那么为什么库里面都是写成 (u32int_t)0x0001234?
此帖出自ARM技术论坛

最新回复

单纯的一个16进制的数据,很多时候会依赖编译器,还有你应用这个16进制数的环境。所以一般的16进制的数据,都需要进行强制类型转换。  详情 回复 发表于 2015-9-16 10:35
点赞 关注
 

回复
举报

118

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
(u32int_t)0x0001234?  强制转换为  无符号int型
此帖出自ARM技术论坛

点评

我的意思是,0x00001234是有符号还是无符号?或者换一个数 0xffffffff  详情 回复 发表于 2015-6-21 21:13
 
 
 

回复

253

帖子

1

TA的资源

一粒金砂(高级)

板凳
 
本帖最后由 白手梦想家 于 2015-6-21 21:14 编辑
靠谱的小小帆 发表于 2015-6-21 21:11
(u32int_t)0x0001234?  强制转换为  无符号int型

我的意思是,0x00001234是有符号还是无符号?或者换一个数 0xffffffff,它是大于0,还是小于0?虽然我已经测试过了,但是还是想和大家讨论下要不要加(uint32_t)
此帖出自ARM技术论坛

点评

0x1234这种属于整数常数integer constant,在8进制和16进制且没有u,l,ll等后缀修饰的情况下首先匹配有符号整形,如果不能放下再匹配无符号整形,如果还是放不下,则继续匹配有符号long 整形和无符号long 整形,再  详情 回复 发表于 2015-6-21 23:04
 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

4
 
白手梦想家 发表于 2015-6-21 21:13
我的意思是,0x00001234是有符号还是无符号?或者换一个数 0xffffffff,它是大于0,还是小于0?虽然我已 ...

0x1234这种属于整数常数integer constant,在8进制和16进制且没有u,l,ll等后缀修饰的情况下首先匹配有符号整形,如果不能放下再匹配无符号整形,如果还是放不下,则继续匹配有符号long 整形和无符号long 整形,再继续是有符号long long整形和无符号long long整形。
(uint32_t) 的意义是统一编译器行为,使这个东西对所有编译器都成为确定性行为而不是依赖每一种编译器的默认实现。
学嵌入式,千万不要只盯着keil,iar,gcc等具体编译器来讨论问题,因为跨平台这个需求,嵌入式环境比PC环境常见的多。
此帖出自ARM技术论坛

点评

不是只有以十进制表示才有范围问题吗?十六进制我已经指明了它的存储形式,所以问题就只剩当最高位为1时,是看成正数还是负数?  详情 回复 发表于 2015-6-22 07:56
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

253

帖子

1

TA的资源

一粒金砂(高级)

5
 
freebsder 发表于 2015-6-21 23:04
0x1234这种属于整数常数integer constant,在8进制和16进制且没有u,l,ll等后缀修饰的情况下首先匹配有 ...


此帖出自ARM技术论坛
 
 
 

回复

253

帖子

1

TA的资源

一粒金砂(高级)

6
 
freebsder 发表于 2015-6-21 23:04
0x1234这种属于整数常数integer constant,在8进制和16进制且没有u,l,ll等后缀修饰的情况下首先匹配有 ...

不是只有以十进制表示才有范围问题吗?十六进制我已经指明了它的存储形式,所以问题就只剩当最高位为1时,是看成正数还是负数?
此帖出自ARM技术论坛

点评

问的好,这个问题的答案有一个背景在里面。 十进制和十六进制等东西实质上是一个东西两种说法,他们之间,以及他们之间的补码表示是一一对应的关系,是同构的。所以10进制有的限制,操作,运算等,16进制也会有。正  详情 回复 发表于 2015-6-22 15:44
 
 
 

回复

1万

帖子

25

TA的资源

裸片初长成(高级)

7
 

具体的数据,与它在编译里的存储类型是两个概念。正象 “ 一米等于几斤 ” 的问题一样。

但是,具体的数据在处理时,都要和存储类型联系,只有和存储类型联系时,楼主的问题才有意义。
此帖出自ARM技术论坛
 
 
 

回复

253

帖子

1

TA的资源

一粒金砂(高级)

8
 
dontium 发表于 2015-6-22 10:31
具体的数据,与它在编译里的存储类型是两个概念。正象 “ 一米等于几斤 ” 的问题一样。

但是,具体的 ...

此帖出自ARM技术论坛
 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

9
 


问的好,这个问题的答案有一个背景在里面。
十进制和十六进制等东西实质上是一个东西两种说法,他们之间,以及他们之间的补码表示是一一对应的关系,是同构的。所以10进制有的限制,操作,运算等,16进制也会有。正常来说10进制和16进制除了0x这个前缀之外,不应该有其他区别。
而工程上(这里工程特指C标准,环境,运行等),有一个背景叫最小惊讶,意思是说,你弄的东西出来,除了正确之外,要最大程度符合大众的习惯,意识,舆论,历史等等。我们一般认为123456这样的10进制表示是实数,当然了从小学学过负数开始,我们潜意识里这种表示就是有正有负的,没有任何人怀疑,所以这样设计对绝大部分人来说最熟悉也就是惊讶最小。因此工程上的设计为什么10进制字面量的表示缺省情况下只匹配int,long,而8,16进制int匹配不下来还能匹配unsigned  int。
10进制的字面量缺省表示的符号性是正确的,可在工程场合是不全面的,毕竟不要负数这种情况字面量缺省情况不满足,这可以通过其他手段弥补。
另一个可以对比的现象出现在对错误,偏差,趣味等工程设计的延续上,比如一个最著名的就是creat函数名,这本是一个失误,如果后面的设计改成正确的create反而是不良设计,因为creat已经被大众熟知接受。
此帖出自ARM技术论坛
 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

10
 
本帖最后由 freebsder 于 2015-6-22 15:52 编辑

至于数字字面量默认是什么符号的,标准里有规定: 10进制是依次放int,long,longlong,哪个放得下,就是那种类型,注意没有出现unsigned,说明,都是有符号的。而8,16进制依次匹配int,unsigned int,long,unsigned long,说明符号和你的数的大小相关,所以上面回复帖子里说了为什么要用(uint32_t)来强制成与数的大小无关。
此帖出自ARM技术论坛

点评

首先感谢大神的回答,回答很专业,膜拜~ 但是我还是有疑问,具体如下: [attachimg]203018[/attachimg] 0xf0000000 无符号数值为:4026531840 有符号数值为:-268435455 为何在keil和VC6里面测试  详情 回复 发表于 2015-6-22 16:34
 
 
 

回复

253

帖子

1

TA的资源

一粒金砂(高级)

11
 
freebsder 发表于 2015-6-22 15:49
至于数字字面量默认是什么符号的,标准里有规定: 10进制是依次放int,long,longlong,哪个放得下,就是那 ...


首先感谢大神的回答,回答很专业,膜拜~

但是我还是有疑问,具体如下:


0xf0000000

无符号数值为:4026531840

有符号数值为:-268435455

为何在keil和VC6里面测试都是判断出是正的?VC汇编代码直接将 0xf0000000>0视为1,keil只有个nop。而如果强制类型转换成有符号型:


此帖出自ARM技术论坛

点评

没错啊,上面你可能没注意,我一直说的是数字字面量,字面量,不是变量,也不是经过类型推倒之后的某某。 字面量上说,0xf0000000 用int放不下,因为int的2^31 = 2147483648 表示不了 0xf0000000 = 4026531840,那  详情 回复 发表于 2015-6-22 23:24
 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

12
 
本帖最后由 freebsder 于 2015-6-23 00:00 编辑
白手梦想家 发表于 2015-6-22 16:34
首先感谢大神的回答,回答很专业,膜拜~

但是我还是有疑问,具体如下:


0xf0000000

无符号 ...

没错啊,上面你可能没注意,我一直说的是数字字面量,字面量,不是变量,也不是经过类型推倒之后的某某。
字面量上说,0xf0000000 用int放不下,因为int的2^31 = 2147483648 表示不了 0xf0000000 = 4026531840,那就用unsigned int放啊。

  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.         if ((signed)0xf0000000 > 0)
  5.         {
  6.                 printf("true %d\n", 0xf0000000);
  7.         }
复制代码


每次都吃帖子,算了,懒得编辑了。
此帖出自ARM技术论坛

点评

我大概得出以下结论,请指正 1、意思也就是编译器始终将十六进制看成是正数喽(signed int上限不够,但是可以将0xf0000000看成负数,下限够,却没有这样做)。 2、虽然printf输出的是负值,但是那是库函数中的标准  详情 回复 发表于 2015-6-24 08:28
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

253

帖子

1

TA的资源

一粒金砂(高级)

13
 
freebsder 发表于 2015-6-22 23:24
没错啊,上面你可能没注意,我一直说的是数字字面量,字面量,不是变量,也不是经过类型推倒之后的某某。 ...

我大概得出以下结论,请指正
1、意思也就是编译器始终将十六进制看成是正数喽(signed int上限不够,但是可以将0xf0000000看成负数,下限够,却没有这样做)。
2、虽然printf输出的是负值,但是那是库函数中的标准,默认是有符号的。
3、指定了十六进制的值,就是指定了存储形式,而不用关心它是有符号和无符号。对于单片机来说,我就是想明确地通过十六进制数来操作寄存器,那么十六进制数就可以不用(unsigned int)转换了吧。
此帖出自ARM技术论坛

点评

>>>意思也就是编译器始终将十六进制看成是正数喽(signed int上限不够,但是可以将0xf0000000看成负数,下限够,却没有这样做)。 可以认为是正数>0。符号却和数字字面量有关。举例说,0x80000000是unsigned int,0  详情 回复 发表于 2015-6-24 17:54
 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

14
 
白手梦想家 发表于 2015-6-24 08:28
我大概得出以下结论,请指正
1、意思也就是编译器始终将十六进制看成是正数喽(signed int上限不够,但 ...

>>>意思也就是编译器始终将十六进制看成是正数喽(signed int上限不够,但是可以将0xf0000000看成负数,下限够,却没有这样做)。
可以认为是正数>0。符号却和数字字面量有关。举例说,0x80000000是unsigned int,0x40000000是signed int 这是默认行为,很操蛋。


>>>虽然printf输出的是负值,但是那是库函数中的标准,默认是有符号的。

printf决定正负的是控制字符,%d是十进制decimal,记得前面说的工程背景,十进制是signed的吗?%u是无符号的。


>>>指定了十六进制的值,就是指定了存储形式,而不用关心它是有符号和无符号。对于单片机来说,我就是想明确地通过十六进制数来操作寄存器,那么十六进制数就可以不用(unsigned int)转换了吧。


存储形式是一定的,不随进制而变化:计算机里的数字是补码。xx进制,是给编译器识别的,实质都是那个数,只是表示法不一样,就像f(x),中间的x你换成y这个表示,不影响f这个函数的实质。

强制类型转化的明显化,是告诉编译器,告诉人,一个确定的类型。如上面说的,0x80000000是unsigned int,0x40000000是signed int,如此撕逼的行为你还希望你自己写程序的时候每一个都去核实吗?当做程序的时候,考虑程序的健壮和稳定,我们更期望类型的相容和匹配,一个不匹配的类型,往往很大程度上意味着一个潜在的错误。比如,int x = 0x80000000, if (x > 0)就是不成立的,而你不能要求大家伙在使用左边的声明时还要去看一下右边的数字具体量是有符号还是无符号。如果你的代码里统一成int x = (unsigned int)0x80000000,那么编译器就知道你的实际意图,它至少会给你一个警告提醒。

代码里做显示转化,是给自己一个摆脱编译器模糊的傻逼行为的机会。
此帖出自ARM技术论坛

点评

版主先森说的很有道理,但是啊,我为什么提这个问题呢?是因为另外一个问题,#if不能识别(处理)(unsigned int)或者其他强制类型转换,比如头文件定义了一个宏 #define CRL ((unsigned int)0x00000001 然后我判断  详情 回复 发表于 2015-6-24 19:38

赞赏

1

查看全部赞赏

 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

253

帖子

1

TA的资源

一粒金砂(高级)

15
 
freebsder 发表于 2015-6-24 17:54
>>>意思也就是编译器始终将十六进制看成是正数喽(signed int上限不够,但是可以将0xf0000000看成负数, ...

版主先森说的很有道理,但是啊,我为什么提这个问题呢?是因为另外一个问题,#if不能识别(处理)(unsigned int)或者其他强制类型转换,比如头文件定义了一个宏
#define CRL ((unsigned int)0x00000001
然后我判断
#if (CRL==0x00000001)
就会出现说(unsigned int)不是一个可用的preprocessor运算符啊,那我就只能把它去掉或者后面加个u了。所以我就有了对十六进制数加不加unsigned int是否有区别的问题,于是就测试,于是就有了这个帖子。但是#if这个问题还是没有很好的解决(在不删除unsigned int的情况下)。
此帖出自ARM技术论坛

点评

加u是可以的,和加f识别成浮点是一个道理,预处理识别不了c语意,但是他们的数字系统是一样的,预处理也要做词法分析嘛。 另一个帖子说了,关公战秦琼,如果一个手法从根上就是不可行的,那就不要多纠结了,重点在  详情 回复 发表于 2015-6-24 20:10
 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

16
 


加u是可以的,和加f识别成浮点是一个道理,预处理识别不了c语意,但是他们的数字系统是一样的,预处理也要做词法分析嘛。
另一个帖子说了,关公战秦琼,如果一个手法从根上就是不可行的,那就不要多纠结了,重点在知道为什么不可行,而不是把不可行变成可行。是吧。
此帖出自ARM技术论坛

点评

恩,感谢版主啊,的确是一流水平  详情 回复 发表于 2015-6-24 21:13
 
 
 

回复

253

帖子

1

TA的资源

一粒金砂(高级)

17
 
freebsder 发表于 2015-6-24 20:10
加u是可以的,和加f识别成浮点是一个道理,预处理识别不了c语意,但是他们的数字系统是一样的,预处理也 ...

恩,感谢版主啊,的确是一流水平
此帖出自ARM技术论坛
 
 
 

回复

19

帖子

4

TA的资源

一粒金砂(中级)

18
 
单纯的一个16进制的数据,很多时候会依赖编译器,还有你应用这个16进制数的环境。所以一般的16进制的数据,都需要进行强制类型转换。
此帖出自ARM技术论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表