APP下载
报价宝  ›  科技  › 

C语言是极其重视基本功的程式语言 不然很简单的问题也可能弄错

报价宝 来源:baojiabao.com 发布时间:2019-07-01 20:02:00 09月11日更新
报价宝综合消息C语言是极其重视基本功的程式语言 不然很简单的问题也可能弄错

前两天,我在我的圈子里发了一个小问题,相关的C语言程式码如下,这段程式会输出什么呢?

#include

int main()

{

signed char a = (unsigned char)-1;

unsigned char b = a;

int c = a;

int d = b;

printf("%d %d %d %d ", a, b, c, d);

return 0;

}

这段C语言程式会输出什么呢?

题外话

在分析这个问题之前,先说些题外话。有程序员认为研究这样的程式码没有意义,无异于孔乙己的“茴”字有几种写法。

这个问题其实并不是我空想出来的。

这个问题其实并不是我空想出来的。

最近,我的一个同事被他的C语言程式 bug 困扰了好几天,始终无法找到问题究竟出在哪里,于是找我,我看到他的C语言程式码混用了无符号变数和有符号变数,于是就提醒他注意这个方面,后来发现果然是这个原因。

他的问题涉及到比较复杂的专案,完整的复述一遍不太现实,于是我把他的问题精简一下,就构成了上述C语言程式码段。

事实上,很多公司招聘时,都有一些面试题或者笔试题看起来很怪异,很不符合标准的开发规范,于是有些程序员就认为做这样的面试题是完全没有意义的,甚至觉得做这些题目是一种侮辱。

C语言是一门极其重视基本功的程式语言

其实换个角度想想,这些题目很能考察一个人的基本功,它们很可能来自公司内部的某个专案的某次重大 bug。C语言是一门极其重视基本功的程式语言,这些题目很能查漏补缺。

分析

现在来考虑上面这段C语言程式码,我们编译并执行它,得到了下面的输出:

# gcc t.c

# ./a.out

-1 255 -1 255

C语言程式的输出出乎了一些朋友的预料,-1 容易理解,255 是怎么回事呢?

首先要明白的是,在计算机中,整数通常采取补码的形式储存。负数的补码等于其反码+1,负数的反码符号位不变,数值为按位取反。对于 signed char 型变数,大部分C语言编译器都是由 8 个 bit 组成的,最高一个 bit 通常表示符号位。

负数的补码等于其反码+1

所以对于 -1,其原码原本是 0b10000001,但是计算机内部储存该数值时,是以补码形式储存的。-1 的补码等于反码+1,也即 0b11111110 +1 = 0b11111111 = 0xff。

到这里就清楚了,变数 b 在内存里的 8 个 bit 都是 1,它是一个 unsigned char 型的变数,最高 bit 也表示数值,也即 b 等于 255。

现在再来分析变数 c 和变数 d 的值,它俩都是有符号型的 int 型。按理说,a 和 b 在内存中的布局是一样的,都是 8 个 bit 的 1,为什么传递给 c 和 d 就不一样了呢?

整形提升

其实C语言在处理 c = a; 和 d = b; 这两句赋值语句时,有一个过程没有显式的表现出来,即“整形提升”。以 c=a; 为例,因为 c 和 a 的资料型别不同,所以C语言在处理赋值时,为了不丢失精度,会将 a 中的数值也强制转换为 int 型。

a 中的数值是 -1,提升为 int 型后依然是 -1,而不是 0x000000ff(255,这里假设 int 型别占用 4 字节内存空间)。至于变数 d 的值,就更简单了,就是简单的赋值而已。

小结

本节讨论的问题虽然很简单,但是仍然有很多人做错,这其中也包含我工作多年的同事。C语言是一门极其重视基本功的程式语言,事实上,本节涉及的知识点非常基础,无非就是原码补码,以及整型提升的相关知识。

点个赞再走吧

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言、linux等嵌入式开发,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。

文章标签: 报价宝 降噪耳机价格 耳机价格 红米手机价格 华为手机价格 小米手机价格 电视机价格 笔记本电脑价格 笔记本价格 汽车价格 数码相机价格 手机价格 汽车价格 笔记本电脑价格 降噪耳机价格