肯尼斯·里科《C和指针》第6章 指针(1)-CSDN博客
肯尼斯·里科《C和指针》第6章 指针(2)-CSDN博客
肯尼斯·里科《C和指针》第6章 指针(3)-CSDN博客
肯尼斯·里科《C和指针》第6章 指针(4)实例-CSDN博客
6.17 问题
1.如果一个值的类型无法简单地通过观察它的位模式来判断,那么机器是如何知道应该怎样对这个值进行操纵的?
ans(书):机器无法做出判断。编译器根据值的声明类型创建适当的指令,机器只是盲目地执行这些指令而已。
2.C为什么没有一种方法来声明字面值指针常量呢?
[C++]一文让我理解什么是字面值常量 - 知乎 (zhihu.com)
指针常量与非指针常量在本质上是不同的,因为编译器负责把变量赋值给计算机内存中的位置,程序员事先无法知道某个特定的变量将存储到内存中的哪个位置。因此,你通过操作符获得一个变量的地址而不是直接把它的地址写成字面值常量的形式。例如,如果希望知道变量xyz的地址,我们无法书写一个类似oxff2044ec这样的字面值,因为我们不知道这是不是编译器实际存放这个变量的内存位置。事实上,当一个函数每次被调用时,它的自动变量(局部变量)可能每次分配的内存位置都不相同。因此,把指针常量表达为数值字面值的形式几乎没有用处,所以C语言内部并没有特地定义这个概念。《C和指针》
我大三一定要选修编译器。。。
3.假定一个整数的值是244,为什么机器不会把这个值解释为一个内存地址呢?
这个应该跟第一题的答案差不多。
4.在有些机器上,编译器在内存位置零存储0这个值,对NULL指针进行解引用操作时将访问这个位置。这种方法会产生什么后果?
ans(书):这是很危险的。首先,解引用一个NULL指针的结果因编译器而异,所以程序不应该这样做。允许程序在这样的访问之后还能继续运行是很不幸的,因为这时程序很可能并没有正确运行。
5.表达式(a)和(b)的求值过程有没有区别?如果有的话,区别在哪里?假定变量offset的值为3。
尝试运行了一下两个结果。
结合之前学习的内容,我们知道p += 3才能把指针的位置向前三个单位,从下面这个运行结果也可以看出:相差12,也就是3*4(bytes)。但无论是前者还是后者,都符合这一点。
但还是有区别的,p=p+offset,因为编译器是从右往左读的,所以先把offset读3,而p=p+3则没有这一步。
6.下面的代码段有没有问题?如果有的话,问题在哪里?
int array[ARRAY_SIZE];
int *pi;
for(pi=&array[0];pi<&array[ARRAY_SIZE];)
*++pi=0;
ans(书):有两个错误。对增值后的指针进行解引用时,数组的第一个元素并没有被清零。另外,若指针在越过数组的右边界以后仍然进行解引用,它将把其他某个内存地址的内容清零。注意,pi在数组之后立即声明。如果编译器恰好把它放在紧跟数组后面的内存位置,结果将是灾难性的。当指针移到数组后面的那个内存位置时,那个最后被清零的内存位置就是保存指针的位置。这个指针(现在变成了零)因为仍然小于&array[ARRAY_SIZE],所以循环将继续执行。指针在它被解引用之前增值,所以下一个被破坏的值就是存储于内存位置4的变量(假定整数的长度为4字节)。如果硬件并没有捕捉到这个错误并终止程序,这个循环将继续下去,指针在内存中继续前行,破坏它遇见的所有值。当再一次到达这个数组的位置时,它就会重复上面这个过程,从而导致一个微妙的无限循环。
所以改成*pi++=0就可以了?