打印

遇到的一个神奇的C编程问题

[复制链接]
2943|39
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
问题不好表述,看个例子应该会好理解些:typedef unsigned int u16;
typedef unsigned char u8;


void Test1(void)
{
    u16 temp_u16;

    u8 temp1_u8,temp2_u8;

    temp1_u8 = 2;
    temp2_u8 = 2;

    temp_u16 = temp1_u8<<8 + temp2_u8;
}

void Test2(void)
{
    u16 temp_u16;

    u8 temp1_u8,temp2_u8;

    temp1_u8 = 2;
    temp2_u8 = 2;

    temp_u16 = temp1_u8;
    temp_u16 <<=8;
    temp_u16 +=temp2_u8;
}


这两个函数最后计算出的temp_u16数值是不一样的,Test1函数中的temp_u16为何和预期的不一样?
按说temp_u16是u16变量,在运算前,temp1_u8和temp2_u8应该会被隐式转换成u16再进行计算。
我想可能是隐式转换的规则没弄清,有哪位比较清楚该问题的麻烦给点意见呗。

相关帖子

沙发
along1980| | 2016-5-11 18:24 | 只看该作者
那本书上说的,,这样的隐式转换
http://blog.csdn.net/miaouu/article/details/5213042

使用特权

评论回复
板凳
zyj9490| | 2016-5-11 18:36 | 只看该作者
第一个,TEMP_U16 2,第二个,2*256+2

使用特权

评论回复
地板
zyj9490| | 2016-5-11 18:41 | 只看该作者
左边跟右边没有关糸,TEMP1_U8 <<8,equal:  u8 temp;
temp=temp1;
temp<<=8;//overflow,temp=0

使用特权

评论回复
5
zyj9490| | 2016-5-11 18:52 | 只看该作者
是你自已没有理解好那段话。

使用特权

评论回复
6
zyj9490| | 2016-5-11 18:55 | 只看该作者
最后赋值时,右边转换成左边的类型,而没有说中间计算过程。

使用特权

评论回复
7
nethopper| | 2016-5-11 19:28 | 只看该作者
第一答案应该是0x800,  第二答案应该是0x202。运算符号的优先顺序是“+”先,“<<”后。
“temp_u16 = temp1_u8<<8 + temp2_u8;”改为“temp_u16 = (temp1_u8<<8) + temp2_u8;”应该就对了。

使用特权

评论回复
评论
datouyuan 2016-5-11 20:09 回复TA
赞一个.我是搞怕了,只要看到这类表达式都会下意识增加括号,而懒得去查那个优先. 
8
江枫渔火| | 2016-5-11 20:11 | 只看该作者
nethopper 发表于 2016-5-11 19:28
第一答案应该是0x800,  第二答案应该是0x202。运算符号的优先顺序是“+”先,“ ...

验证过吗?我怎么觉得不加括号时,移位运算符优先级本来就比算术运算符高呢?
我怎么觉得你说的这个结果依然是错的呢~

使用特权

评论回复
9
datouyuan| | 2016-5-11 20:15 | 只看该作者
nethopper 发表于 2016-5-11 19:28
第一答案应该是0x800,  第二答案应该是0x202。运算符号的优先顺序是“+”先,“ ...

应该是7楼说得对.
我也碰到几次类似的疑难杂症,我是搞怕了.
以后只要看到这类表达式都会下意识增加括号,而懒得去查那个优先.

使用特权

评论回复
10
nethopper| | 2016-5-11 20:25 | 只看该作者
江枫渔火 发表于 2016-5-11 20:11
验证过吗?我怎么觉得不加括号时,移位运算符优先级本来就比算术运算符高呢?
我怎么觉得你说的这个结果 ...

你不信可以验证一下看,我刚在网上找了两个不同的网站验证查询运算符号的顺序问题,供参考,两个表格基本上是一致的。一般编程的时候,有时候也记不太清楚,加括号比较保险。

使用特权

评论回复
11
ticomi| | 2016-5-12 07:58 | 只看该作者
很基础的问题,非常不建议将这样的语句写成一句,分开写,即明白清晰,也不用死记优先级等。为何喜欢这样写呢?

效率是一样的

使用特权

评论回复
12
robter| | 2016-5-12 07:59 | 只看该作者
这个要好好看看

使用特权

评论回复
13
hgjinwei| | 2016-5-12 08:10 | 只看该作者
第一,temp_u16 = temp1_u8<<8 + temp2_u8; 运算优先级上有问题,“+”会先运算,然后“<<”,最后“=”
第二,即使是"temp_u16 = (temp1_u8<<8) + temp2_u8; ",存在类型隐式转换问题,也不一定对,至少不一定在所有编译环境都对;

最好写成:temp_u16 = ((u16)temp1_u8<<8) + temp2_u8;
或者干脆采用第二种写法;
这两种写法,对编译器而言,除了Keil的0级优化不好说,一般会编译成一样的汇编代码的。

使用特权

评论回复
14
mini1986| | 2016-5-12 08:32 | 只看该作者
不懂优先级,就使劲加括号就行了......

使用特权

评论回复
15
shauew| | 2016-5-12 08:35 | 只看该作者
u8    temp1_u8  <<8位 和
u16  temp_u16  <<8位 是不一样的

使用特权

评论回复
16
wsnsyy| | 2016-5-12 08:40 | 只看该作者
能写的通俗易懂吗,这样写为哪般

使用特权

评论回复
17
yangwenguan| | 2016-5-12 09:55 | 只看该作者
用强制转换, 无问题
temp_u16 = (u16 *)(temp1_u8<<8 + temp2_u8);

使用特权

评论回复
18
anvy178| | 2016-5-12 14:14 | 只看该作者
不要想当然得那么美   编译器优化级别不一样都有可能不一样的结果 你还是老老实实的先保证中间不溢出的好

使用特权

评论回复
19
幸福至上|  楼主 | 2016-5-12 14:33 | 只看该作者
zxqchongchi 发表于 2016-5-12 11:19
对于移位操作符 >,这是双目操作符,有两个操作数。在C标准中规定,移位时被移位数(左操作数)有个类型转 ...

你好。我看了下你的链接所贴出的笔记,大致理解是:移位操作前,会转换成范围大一些的有符号数进行运算,所以如果移位操作前,数据的最高位为1,如0xF0,移位操作后编程有符号数:0xF000,反而成负数了。但这样来看:02<<8+02的数据还是应该为:0x0202,但实际并非如此。是哪儿有问题吗?另这个移位符运算的类型转换资料有更具体的吗?

使用特权

评论回复
20
幸福至上|  楼主 | 2016-5-12 14:36 | 只看该作者
yangwenguan 发表于 2016-5-12 09:55
用强制转换, 无问题
temp_u16 = (u16 *)(temp1_u8

即便是强制转换,也不用加指针符号吧

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:重庆电子交流圈:521107487,欢迎各位工程师朋友们加入,一起交流讨论,互动分享,共同进步。

38

主题

854

帖子

10

粉丝