C语言之遇见整形提升

在写一个串口程序时,因为收发数据很简单,只有一个字节,所以就加了一个取反字节作为和校验,在收到数据时用以下代码校验数据有有效性:

    uint8_t rxBuffer[2];
    bool rxMsgValid = false;
    ...
    if (rxBuffer[0] == ~rxBuffer[1]) {
      rxMsgValid = true;
    }
    ...

但是运行程序的时候发现,设备永远都收不到有效数据,查了半天链路也没问题,最后调试才发现,这一段代码直接被优化掉了…百思不得姐啊!!!!

后来去同事群里问了一下,然后有个韩国小哥提点了一下,想起来写个测试程序验证一下:


#include "stdint.h"
#include "stdbool.h"
#include "stdio.h"


int	main(int argc, char **argv)
{
	
	uint8_t a[] = {0x01, 0xFE};
	uint8_t b;

	printf("a[0] = 0x%02x, a[1] = 0x%02x, ~a[1] = 0x%02x\n", a[0], a[1], ~a[1]);

	b = a[1] + 0xFF;
	printf("b = a[1] + 0xFF = 0x%02x\n", b);

	if (a[0] == ~a[1]) {
		printf("a[0] == ~a[1]\n");
	} else {
		printf("a[0] != ~a[1]\n");
	}

	system("pause");
	return 0;
}

没想到这段代码的输出是这样的…

a[0] = 0x01, a[1] = 0xfe, ~a[1] = 0xffffff01
b = a[1] + 0xFF = 0xfd
a[0] != ~a[1]
Press any key to continue . . .

为什么本来8位的数据一取反就自动扩展成32位了???这个有点不太科学吧。。。。。。

仔细想来这也就是个王八屁股–规定,但本着刨根问底的科学态度,让我们来找找编译器文档里是怎么说的:

The result of the ~ operator is the bitwise complement of its (promoted) operand (that is, each bit in the result is set if and only if the corresponding bit in the converted operand is not set). The integer promotions are performed on the operand, and the result has the promoted type. If the promoted type is an unsigned type, the expression ~E is equivalent to the maximum value representable in that type minus E.

~ 运算符的结果是其(提升的)操作数的按位取反(即,当且仅当被转换的操作数中的相应位未置位时,将结果中的相应位置位。 译者注:说得太严谨了,用我大中文来说就四个字:按位取反)。 整型提升在操作数上执行,结果具有提升后的类型. 如果提升后的类型是无符号类型,则表达式 ~E 等效于该类型中可表示的最大值减去 E。

找这个文档也是百转千回,某SDN上还有很多人收费。。。基于本人强烈的开源精神这里Share给大家! FOR FREE:

ISO/IEC 9899:TC3, C Standard

在查找这个文档的过程中,看到很多人写的例程都会用字节甚至是随便用几位来演示按位取反的操作结果,这对学C语言的人来说是非常不严谨以及有强烈的误导性的。

通过多方查找资料后才明白,这种情形叫***整形提升***,是C语言中非常重要的概念。干了十多年程序员了还不知道这个概念,真是有点。。。

这篇文章算是讲得比较好的,供大家参考:

C语言 — 整形提升

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值