学习笔记
- 移位操作符。右移位操作有两种选择方案:一种是逻辑移位,左边移入的位用0填充;另一种是算数移位,左边移入的位由原先该值的符号位决定,符号位为1则移入的位均为1,符号位为0则移入的位均为0,这样能够保持原数的正负形式不变。算数左移和逻辑左移是相同的,右边空出来的位用0补齐
- 标准说明无符号值执行的所有移位操作都是逻辑移位,但对于有符号值,到底是采用逻辑移位还是算术移位取决于编译器。有符号值的右移位操作是不可移植的
- 编译器只要不违背优先级和结合性规则,它可以自由决定复杂表达式的求值顺序。表达式的结果如果依赖于求值的顺序,那么它在本质上就是不可移植的,应该避免使用
static
修饰函数中的局部变量,初始化只在第一次调用函数时进行初始化。后续调用时,该变量使用前一次函数调用完成之后保存的值
书后练习
问题2
下面这个程序的结果是什么
int
func( void )
{
static int counter = 1;
return ++counter;
}
int
main()
{
int answer;
answer = func() - func() * func();
printf( "%d\n", answer );
}
根据上述学习到的知识点:编译器只要不违背优先级和结合性规则,它可以自由决定复杂表达式的求值顺序
所以该程序可能有三种结果,在gcc编译器上结果为-10
2 - 3 * 4 = -10
3 - 2 * 4 = -5
4 - 2 * 3 = -2
问题4
条件操作符在运行时较之if语句是更快还是更慢?试比较下面两个代码段
if( a > 3 )
i = b + 1;
else
i = c * 5;
i = a > 3 ? b + 1 : c * 5;
一样快,都需要先判断a与3的值,然后再对i进行赋值
问题6
哪些操作符具有副作用?它们具体有什么副作用
操作符 | 副作用 |
---|---|
++,– | 不论是前缀还是后缀形式,这些操作符都会修改它们的操作数 |
= | 包括所有其他的复合赋值符,它们都修改作为左值的左操作数 |
编程练习1
编写一个程序,从标准输入读取字符,并把它们写道标准输出中。除了大写字母字符要转换为小写字母之外,所有字符的输出形式应该和它的输入形式完全相同。
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ){
#if 1
/* 从标准输入读取字符并写到标准输出中 */
char ch;
while( 1 ) {
scanf( "%c", &ch );
/* 如果是大写字母,则转换为小写字母 */
if( ch >= 'A' && ch <= 'Z' ) {
ch += 32;
}
printf( "%c", ch );
}
#endif
#if 0
char x = 'a', y = 'A';
printf( "%d\n", x - y );
#endif
return EXIT_SUCCESS;
}
标准答案
#include <stdio.h>
#include <ctype.h>
int main( void ) {
int ch;
/* 提倡使用的转换字母大小写的方法是使用tolower库函数 */
while( (ch = getchar()) != EOF )
putchar( tolower( ch ) );
}
编程练习3
请编写函数
unsigned int reverse_bits( unsigned int value );
这个函数的返回值是把value的二进制位模式从左到右变换一下后的值。例如,在32位机器上,25这个值包含下列各个位
0000 0000 0000 0000 0000 0000 0001 1001
函数的返回值应该是2550136832,它的二进制位模式是
1001 1000 0000 0000 0000 0000 0000 0000
编写函数时要注意不要让它依赖于你的机器上整型值的长度
#include <stdio.h>
#include <stdlib.h>
/* 把value的二进制位模式从左到右变换一下后的值 */
unsigned int reverse_bits( unsigned int value ) {
unsigned int res = 0;
/* 计算存储value使用的字节数,并转换为相应的位数 */
int len = sizeof(value) * 8;
/* 把value的二进制位模式翻转 */
for( int i = 0; i < len; i++ ) {
/* 得到value值最低位的数值 */
unsigned int num = value & 1;
/* 将value逻辑右移 */
value >>= 1;
/* 将res结果值逻辑左移 */
res <<= 1;
/* 将value值最低位的数值保存到res中 */
res |= num;
}
return res;
}
int main( int argc, char *argv[] ) {
unsigned int res = reverse_bits(25);
printf( "%u\n", res );
return EXIT_SUCCESS;
}
标准答案
unsigned int i;
/* 只要i不是0就可以继续进行,使得循环与机器字长无关,从而避免了可移植性的问题 */
for( i = 1; i != 0; i <<= 1 ) {
...
}