一个经常被忽略的c语言问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个经常被忽略的c语言问题相关的知识,希望对你有一定的参考价值。

c语言无符号数和有符号数运算得到什么样的结果
int main()

int a=6;

unsigned int b=-20;

(a+b>6)?puts(">6"):puts("<=6");

return 0;


该函数返回〉6为什么呀??
如果把unsigned a=6;int b=12
结果为什么 还是错误的

编译器是不会加65536的,其实内存存储的都是一样的,
-20就是FFEC,也就是1111 1111 1110 1100,这样有符号就是-20,无符号就是65516。
编译器会尽可能用一个合适的类型去存放a+b,
所以你没有把a+b的值赋值给一个特定类型的变量时,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
它的结果就是无符号的,所以会大于6,如果你写成
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int temp = a+b;
(temp>6)?puts(">6"):puts("<=6");
则应该会输出<=6

所以你改成unsigned a = 6; int b = -12;也没用
参考技术A 变量b本来是unsigned型变量,它是个非负数,你偏偏把-20赋给了它,当然会出错。
把负数赋给一个unsigned型变量将会发生溢出。
unsigned型变量的取值范围为0~65536,如果赋给它的值不在这个范围内,则会把这个值加上或减去N个65536,使得这个值还是在0~65536的范围内,这就是溢出!
你把-20赋给unsigned型变量b,它会加上65536把这个数调整到0~65536的范围内,所以b的值是-20 + 65536 = 65516

因此,a + b 当然大于 6 了!!
参考技术B 4: int a=6;
00401028 mov dword ptr [ebp-4],6
5:
6: unsigned int b=-20;
0040102F mov dword ptr [ebp-8],0FFFFFFECh
7:
8: (a+b>6)?puts(">6"):puts("<=6");
00401036 mov eax,dword ptr [ebp-4]
00401039 add eax,dword ptr [ebp-8]
0040103C cmp eax,6

这是程序在vc下反汇编的片段,c语言混合运算遵循自动类型转换由低数据类型向高数据类型转换,即char,short->int->unsigned->long->double<-float
-20=0FFFFFFECh在无符号变量范围内,所以b接收-20时-20自动转换成无符号数值即0FFFFFFECh
a+b=0FFFFFFECh+6=0fffffff2h>6,期间运算无溢出
参考技术C 可能是结果因为是负值,而加了一个65535,所以得不到接过了吧 参考技术D 同意DannyPotter。

解决protobuf忽略空返回值的问题

参考技术A 最近在用Kratos开发项目的时候遇到了问题,repeated类型的字段在值为空的情况下,字段被直接忽略掉了。

我希望的是即使为空的情况下也能返回一个空数组,而不是直接把整个字段忽略掉,就像下面这样:

经过多方排查之后找到了问题所在,google会在生成pb.go文件时在json标签里插入 omitempty 属性,而json库在转换json时一旦遇到这个标签就会忽略掉空字段,这不符合我的需求,所以把这个字段去掉就好了。

先写一个shell脚本来递归遍历api目录下的pb.go文件:

接着修改Makefile文件:

在api的最下面添加替换脚本,流程就是遍历scandir脚本查出来的pb.go文件,替换掉文件里所有的omitempty,然后将文件暂存为.tmp,最后再覆盖原文件。

今后每次执行make api时就会连带自动替换掉所有生成文件中的omitempty,免得每次手动替换麻烦又容易出错。

参考: https://ld246.com/article/1591110788411

以上是关于一个经常被忽略的c语言问题的主要内容,如果未能解决你的问题,请参考以下文章

C语言重点难点精讲关键字精讲

书来了 | 经常被忽略的Go语言,全球需求量最大!

17个不能犯的C语言常见错误!

C语言中返回值问题

解决protobuf忽略空返回值的问题

C 语言 进阶