Expert C Programming阅读笔记

类型的自动转

Operands with different types get converted when you do arithmetic. Everything is converted to the
type of the floatiest, longest operand, signed if possible without losing bits.

The value preserving approach (ANSI C) says that when you mix integral operand types like this, the
result type is signed or unsigned depending on the relative sizes of the operand types.

The defined variable TOTAL_ELEMENTS has type unsigned int (because the return type
of sizeof is "unsigned"). The test is comparing a signed int with an unsigned int quantity. So
d is promoted to unsigned int. Interpreting -1 as an unsigned int yields a big positive
number, making the clause false. This bug occurs under ANSI C, and under K&R C if
sizeof() had an unsigned return type in a given implementation.

Avoid unnecessary complexity by minimizing your use of unsigned types. Specifically,
don't use an unsigned type to represent a quantity just because it will never be negative
e.g., "age" or "national_debt").
Use a signed type like int and you won't have to worry about boundary cases in the
detailed rules for promoting mixed types.
Only use unsigned types for bitfields or binary masks. Use casts in expressions, to make all
he operands signed or unsigned, so the compiler does not have to choose the result type.

Chapter 2 

Why Language Features Matter

The one "l" NUL ends an ASCII string,
The two "l" NULL points to no thing.

Switches Let You Down with Fall Through

Switch has several problems, one of which is that it is too relaxed about what it accepts in the cases.
For example, you can declare some local storage by following the switch's opening curly brace with a
declaration.

It is always the case in C that where you have some statements opening a block 
 
 {
    statements
you can always add some declarations in between, like this: 
 
 {
    declarations 
    statements
You might use this if allocating memory was expensive, and hence avoided if possible. A
compiler is free to ignore it, though, and allocate the space for all local blocks on calling a
function. Another use is to declare some variables whose use is really localized to this
block. 

Another problem is that any statements inside a switch can be labelled and jumped to, allowing
control to be passed around arbitrarily:
 
switch (i) {
  case 5+3: do_again: 
  case 2: printf("I loop unremittingly /n"); goto do_again; 
  default : i++; 
  case 3: ; 
}

Perhaps the biggest defect in the switch statement is that cases don't break automatically after the
actions for a case label. Once a case statement is executed, the flow of control continues down,
executing all the following cases until a break statement is reached

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值