C-《C和指针》第五章读书笔记

最近组织了网上的朋友们一起在读《C和指针》这本书。如果想要加入的可以加入我们:213867076,群里主要是玩STM32单片机和嵌入式方面的,进群验证就写C和指针把。


第五章有好多的干货,把一些我之前不太熟悉或者我觉的有必要记住的记录下来。

1、数据截短。在第70页中讲到由于数据类型的不同,会导致数据截短。下面是例子:

char x;

int a ;

int y = 1000;

x = a = y + 3;


可以看到,由于 x 是char类型,所以将EAX的值传给CL时(给 x 赋值时我这编译器用的CX寄存器),

自动将0x03eb截成了0xeb。所以运行后,a= 1003 而x=235(0xeb)。

2、还是数据截短。书上的例子

char ch;

while((ch = getch() ) != EOF

{

//执行相应任务

}

这里面有一个问题,getchar()函数返回值是int类型,返回的是用户输入字符对应的ASCⅡ码值。

getchar()的返回值存储于ch中将导致它被截短。然后这个被截短的值被提升为整型并与EOF比较。


标准ASCⅡ码只到127。值128255对应的ASCⅡ码在它的扩展表中。好像我们普通的计算机敲不出这样的字符来。

所以虽然char在这里算是有符号字符集,但是还是会永不停止的循环,除非我按ctrl+z


3、if语句的条件语句。程序中经常遇到这样的代码

x = get_some_value();

if(x = 1)

{

//执行相应任务

}

x从函数获得一个值,但接下来把1赋值给x,而不是把x与字面值1比较,从而丢失了从函数获得的那个值。

这个意图显然不是程序员的意图所在。另外一个问题是x获得了新值,所以if语句一直为真。

有一种更好的方式,让编译器来帮助我们检查这一疏忽。写成如下方式

x = get_some_value();

if(1 == x)

{

//执行相应任务

}

这样,如果写成if(1 = x)的话,编译器就会告诉你这里少写了个等号。


4、隐式类型转换。这个小的知识点是以前不知道的

下面这段话是从书上抄下来的,在书的P80页:

C的整形运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,

表达式中的字符型和短整型操作数在使用之前会被转换成普通整型,这种转换称为整型提升。

例如下面的表达式:

char a,b,c

a = b + c;

b和c的值被提升为普通整型,然后再执行加法运算。加法运算的结果会被截短,然后再存储于a中。让我们测试一下:



观察反汇编代码,可以看到在做加法的时候,用的是32位寄存器:EAX = EAX + ECX

做完加法赋值的时候,按照char类型的长度8位,只将 EAX 寄存器的 AL 部分赋值给了a


5、类似于a+b+c这样的语句,编译器自由决定以任何顺序对表达式求值。(这部分是书上的,在P84页)

之所以允许先计算b+c是因为这个值可能可以从前面的一些表达式中获得,所以直接复用这个值比重新求值效率更高。

下面的表达式说明了一个相关的问题:

f() + g() + h()

尽管左边那个加法运算必须在右边那个加法运算之前执行,但对于各个函数的调用顺序,并没有规则加以限制。

如果他们的执行具有副作用,比如执行一些I/O任务或修改全局变量,那么函数调用顺序的不同可能会产生不同的效果。

因此,如果顺序会导致结果产生区别,最好使用临时变量,让每个函数调用都在单独的语句中执行。

temp = f();

temp += g();

temp += h();


6、还有一个可以当成公式记住的。这个在单片机里面经常会遇到。

对指定的位 置1                  value =value | 1<< n

对指定的位 置0                   value = value & ~(1<< n)

对指定位测试,若是1,则表达式结果非0      value & 1 << n    。 注意 这里的n是从0开始算的。0就是不移位。1往左移1位




















猜你喜欢

转载自blog.csdn.net/fxltsbl007/article/details/59618083