《C和指针》—第四章:语句、操作符和表达式

语句

空语句

C最简单的语句就是空语句,它本身只包含一个分号。并不执行任何任务。

代码块

就是位于一对花括号之内的可选的声明和语句列表。

if语句

C并不具备布尔值类型,而是用整型来代替。这样零值表示假,非零值表示真。

另外。else子句从属于最靠近他的不完整的if语句。所以,请注意语法要求,及时用花括号将语句分开。

while语句

在while循环中,可以使用break语句,用于永久结束循环。在执行完break语句之后,执行流下一条执行的语句就是循环正常结束后应该执行的那条语句。

在while中,也可以使用continue语句,用于永久结束当前的那次循环。在执行完continue之后,执行流接下来就是从新测试表达式的值,决定是否继续执行循环。

这两个语句只对最内层的循环起作用,不影响外部的循环。

switch语句

每一个case标签必须具有一个唯一的值。常量表达式是指编译期间进行求值的表达式,他不能是任何变量。这里不同寻常之处是case文件标签并不能把语句列表划分为几个部分,他们只是确定语句列表的进入点。

 

 

操作符

算术操作符

+ - * / %

除了%操作符,其余几个既适用于浮点类型又适用于整数类型。

移位操作符

移位操作只是简单地把一个值的位向左或者向右移动。在左移位中,值最左边的几位被丢弃,右边多出来的几个空位由0补齐。

右移位操作存在一个左移位操作不曾存在的问题:从左边移入新位时,可以选择两种方案。一种是逻辑移位,左边移入的位用0填充;另一种是算术移位,左边移入的位由原先该值的符号位决定,符号位为1则移入的位均为1,符号位为0则移入的均为0;这样能保持原数的正负形式不变。

左移位操作符为<<,右移位操作符为>>。左操作数的值将移动由右操作符指定的位数。两个操作数都必须是整型类型。

注:对于有符号值,到底是采用逻辑移位还是算术移位取决于编译器。

位操作符

位操作符有 & |  ^,分别执行,与,或,异或。

他们要求操作符为整数类型,他们对操作数对应的位进行指定的操作,每次对左右操作数的各一位进行操作。

举例说明:假定变量a的二进制为00101110,变量b的二进制值为01011011,a&b的结果为00001010,a | b的结果为01111111,a^b结果为011110101。

位的操纵

下面的表达式显示了你可以怎样使用移位操作符位操作符来操纵一个整型值中的单个位。表达式假定bit_number为一个整型值,它的范围是从0至整型值的位数减1,并且整型值的位从右向左计数。第一个例子把指定的位设置成1.

value = value | 1<< bit_number;

下一个例子把指定的位清0。

value = value & ~( 1 << bit_number);

这些表达式常常写成|=和&=操作符的形式。

最后,下面这个表达式对指定的位进行测试,如果该位已被设置为1,则表达式的结果为非零值。

value & 1 << bit_number;

赋值

在下面的语句中,认为x和a被赋予相同的值的说法是不正确的,

a = x = y + 3;

如果x是一个字符型变量,那么y + 3的值就会被截去一段,以便于容纳字符类型的变量中。那么a所赋的值就是这个被截断后的值,在下面这个常见的错误中,这种截短正是问题的根据所在:

char ch;
....
while ( (ch = getchar() ) != EOF )...

EOF需要的位数比字符型值所能提供的位数要多,这也是getchar()返回一个整型值而不是字符值的原因。然而把getchar的返回值首先存储于ch中将导致它被截短。

表达式求值

表达式求值顺序一部分是由它所包含的操作符的优先级和结合性决定。同样,有些表达式的操作数在求值过程中可能需要转换为其他类型。

1.隐式类型转换

C的整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符型和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。

例如,在下面的表达式的求值中,

char a, b, c ;

a = b + c;

b和c的值被提升为普通整型,然后在执行加法运算。加法运算的结果将被截短,然后在存储于字符a中。这个例子的结果和使用8位算术的结果是一样的。但是在下面这个例子中,他的结果就不再相同。这个例子用于计算一系列字符的简单检验和。

a = ( ~a ^ b << 1 ) >> 1;

由于存在求补和左移操作,所以8位的精度是不够的。标准要求进行完整的整型求值,所以对于这类表达式的结果,不会存在歧义性。

2.算术转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换

long double
double
float
unsigned long int
long int
unsigned int 
int

如果某个操作数的类型在上面这个表中排名较低,那么他首先将转换为另一个操作数的类型然后进行操作。

例子:

int a =5000;
int b = 25;
long c = a * b;

例子的问题在于ab是以整型进行计算,在32位的机器上,这段代码运行起来没有问题,但是在16位整数的机器上,这个乘法运算会产生溢出,这样c就会被初始化为错误的值。

解决方案是在执行乘法之前,将其中一个操作数转换为长整型。

long c = (long)a * b;

当整型值转换为float型值时,也有可能损失精度。float型值仅要求6位数字的精度。如果将一个超过6位数字的整型值赋值给一个float型变量时,其结果可能只是该整形值的近似值。

当float型值转换为整型值时,小数部分被舍弃,如果浮点数的值过于庞大,无法容纳于整型值中,那么其结果将是未定义的。

你可能感兴趣的:(C,指针)