1.如果一个值的类型无法简单地通过观察它的位模式来判断,那么机器是如何知道应该怎样对这个值进行操纵的?
解析:
机器无法做出判断。编译器根据值的声明类型创建适当的指令,机器只是盲目地执行这些指令而已。
2.C为什么没有一种方法来声明字面值指针常量呢?
解析:
因为通常无法预测编译器会把某个特定的变量放在内存中的什么位置,所以无法预先知道它的地址。用&操作符得到变量的地址是很容易的,但表达式在程序执行时才会进行求值,此时已经来不及把它的结果作为字面值复制到源代码中。
3.假定一个整数的值是244,为什么机器不会把这个值解释为一个内存地址呢?
解析:
因为通常无法预测编译器会把某个特定的变量放在内存中的什么位置,所以无法预先知道它的地址。把244这个值解释为内存地址是编译器的工作。
4.在有些机器上,编译器在内存位置零存储0这个值,对NULL指针进行解引用操作时将访问这个位置。这种方法会产生什么后果呢?
解析:
这是很危险的。首先,解引用一个NULL指针的结果因编译器而异,所以程序不应该这样做。允许程序员在这样的访问之后还能继续运行是很不幸的,因为这时程序很可能没有正确运行。
#include
#include
int main( void ){
int *pi = 0;
printf( "%dn", *pi );
return EXIT_SUCCESS;
}
5.表达式(a)和(b)的求值过程有没有区别?如果有的话,区别在哪里?假定变量offset的值为3。
int i[10];
int *p = &i[0];
int offset = 3;
p += offset; (a)
p += 3; (b)
#include
#include
int main( void ){
int i[10];
int *p = &i[0];
int offset = 3;
p += offset;
p += 3;
return EXIT_SUCCESS;
}
6.下面的代码段有没有问题?如果有的话,问题在哪里?
int array[ARRAY_SIZE];
int *pi;
for( pi = &array[0]; pi < &array[ARRAY_SIZE]; ){
*++pi = 0;
}
解析:
有两个错误。对增值后的指针进行解引用时,数组的第一个数组并没有被清零。另外,若指针在越过数组的右边界以后仍然进行解引用,它将把其他某个内存地址的内容清零。 注意,pi在数组之后 立即声明。如果编译器恰好把它放在紧跟数组后面的内存位置,结果将是灾难性的。当指针移到数组后面的那个内存位置时,那个最后被清零的内存位置就是保存指针的位置。这个指针(现在变成了零)因为仍然小于&array[ARRAY_SIZE],所以循环将继续执行。指针在它被解引用之前增值,所以下一个被破坏的值就是存储于内存位置4的变量(假定整数的长度为4字节)。如果硬件并没有捕捉到这个错误并终止程序,这个循环将一直继续下去,指针在内存中继续前行,破坏它遇见的所有值。当再一次到达这个数组的位置时,它就会重复上面这个过程,从而导致一个微妙的无限循环。
*/
#include
#include
#define ARRAY_SIZE 5
int main( void ){
int array[ARRAY_SIZE];
int *pi;
printf( "pi = %p, &array[0] = %p, &array[%d] = %p.n", pi, &array[0], ARRAY_SIZE, &array[ARRAY_SIZE] );
for( pi = &array[0]; pi < &array[ARRAY_SIZE]; ){
*++pi = 0;
}
printf( "print the elements in array by using pointer points to the array:n" );
for( pi = &array[0]; pi < &array[ARRAY_SIZE]; ){
printf( "%d ", *pi++ );
}
printf( "n" );
printf( "pi = %pn", pi );
return EXIT_SUCCESS;
}
7.下面显示了几个内存位置的内容。每个位置由它的地址和存储于该位置的变量名标识。所有数字以十进制形式表示。使用这些值,用4种方法分别计算下面各个表达式的值。首先,假定所有变量都是整型,找到表达式右值,再找到它的左值,给出他所指定的内存位置的地址。接着,假定所有变量都是指向整型的指针,重复上述步骤。注意:在执行地址运算时,假定整形和指针的长度都是4字节。
变量 地址 内容 变量 地址 内容
a 1040 1028 o 1096 1024
c 1056 1076 q 1084 1072
d 1008 1016 r 1068 1048
e 1032 1088 s 1004 2000
f 1052 1044 t 1060 1012
g 1000 1064 u 1036 1092
h 1080 1020 v 1092 1036
i 1020 1080 w 1012 1060
j 1064 1000 x 1072 1080
k 1044 1052 y 1048 1068
m 1016 1008 z 2000 1000
n 1076 1056
#include
#include
#define byte_of_int 4
#define byte_of_pointer 4
typedef int * int_ptr;
typedef int int_alias;
int main( void ){
return EXIT_SUCCESS;
}



