第七章
-
有符号整数溢出,程序行为是未定义的
-
无符号整数运算过程中发生溢出,结果是有定义的:对2^n取模,n适用于存储结果的位数
-
C标准未说明
char类型是有符号还是无符号型 -
「惯用法」
while(getchar()!='\n');//skip rest of linewhile((c=getchar())==' ');//skip blanks
-
C89算术类型
- 整值类型
- 字符类型
char - 有符号整型
signed char、short int、int、long int - 无符号整型
unsigned char、unsigned short、unsigned int、unsigned long - 枚举类型
- 字符类型
- 浮点类型
float、double、long double
- 整值类型
-
C99算术类型
- 整数类型
- 字符类型
char - 有符号整型 包括标准的(
signed char、short int、int、long int、long long int)和扩展的 - 无符号整型 包括标准的(
unsigned char、unsigned short int、unsigned int、unsigned long int、unsigned long long int、_Bool)和扩展的 - 枚举类型
- 字符类型
- 浮点类型
- 实数浮点类型
float、double、long double - 复数类型
float_Complex、double _Complex、long double _Complex
- 实数浮点类型
- 整数类型
-
以下情况进行隐式转换
- 当算术表达式或逻辑表达式中操作数的类型不相同时(C语言执行所谓的常用算术转换)
- 当赋值运算符的右侧表达式类型与左侧变量的类型不匹配时
- 当函数调用的实参类型与形参类型不匹配时
- 当return语句中表达式的类型与函数返回值的类型不匹配时
-
常用算术转换
-
整值提升(integral promotion)把字符或短整型转换成int类型(如果
int类型整数没有大到足以包含所有可能的原始类型值,那么是unsigned int) -
任一操作数是浮点类型的情况。
float->double->long double -
两个操作数均不是浮点类型。首先进行整值提升(保证没有一个操作数是字符类型或者短整型),然后
int->unsigned int->long int->unsigned long int。有一种特殊情况,在unsigned int和long int相同时,如果一个操作数是unsigned int,另一个是long int,那么都被转换为unsigned long int -
当把有符号操作数和无符号操作数组合时,把有符号操作数“转换”成无符号的值。转换过程中需要加上或者减去
n+1的倍数,n是无符号类型能表示的最大值。这条规则会导致一些隐蔽的编程错误。例:#include <stdio.h> int main(int argc, char **argv){ unsigned int a=10; int b = -10; printf("yes, i am %d\n", b < a); printf("yes, i am %d\n", -10 < 10); return 0; }运行结果是:
yes, i am 0 yes, i am 1结论就是:尽量避免使用无符号整数!
-
-
赋值过程中的转换
- 常用算术转换不适用于赋值运算。C语言遵循另一条简单的转换规则,那就是把赋值运算符右侧的表达式转换为左侧变量的类型
- 如果变量类型至少和表达式类型一样宽,那么转换没有任何障碍
- 其他情况是有问题的。把浮点数赋值给整型丢掉小数部分。把某种类型的值赋给类型更狭小的变量时,如果该值在变量类型范围之外,那么会得到无意义的结果(甚至更糟)
-
C99中的隐式转换
- 为了定义转换规则,C99允许每个整数类型具有“整数转换等级”。下面是从最高到最低的排序(这里忽略了扩展的整数类型和枚举类型)
-
long long int、unsigned long long int -
long int、unsigned long int -
int、unsigned int -
short int、unsigned short int -
char、signed char、unsigned char _Bool
-
- C99用整数提升(integer promotion)取代了C89中的整值提升(integral promotion),可以将任何等级低于
int和unsigned int的类型转换为int或unsigned int - 任一操作数是浮点类型的情况。只要两个操作数都不是复数类型,
float->double->long double - 两个操作数均不是浮点类型。首先进行整数提升,如果两个操作数类型相同,过程结束。否则一次尝试以下规则,一旦遇到可应用的规则,就不再考虑其他的规则:
- 如果两个操作数均为有符号型或无符号型,将整数转换等级低的转换如为等级高的操作数类型
- 如果无符号操作数的等级高于或等于有符号操作数的等级,将有符号操作数转换为无符号操作数的类型
- 如果有符号操作数的类型可以表示无符号操作数类型的所有制,将无符号操作数转换为有符号操作数的类型
- 否则,将两个操作数都转换为与有符号操作数的类型相对应的无符号类型
- 为了定义转换规则,C99允许每个整数类型具有“整数转换等级”。下面是从最高到最低的排序(这里忽略了扩展的整数类型和枚举类型)
-
强制类型转换
- 有时需要使用强制类型转换来避免溢出,例:
long i; int j = 1000; i = j * j;//overflow may occur在有些机器上
j*j的值过大,无法表示为int型,导致溢出。
可以改为i = (long)j * j; -
sizeof运算符- 编译器通常就能确定
sizeof表达式的值,C99值变长数组不可以。
- 编译器通常就能确定










网友评论