-
指针总是和地址一样吗?
通常是,但不总是。考虑用字而不是字节划分内存的计算机。字可以包含36位、64位,或者更多位。如果假设36位的字,那么内存将有如下的显示:
当用字划分内存时,每个字都有一个地址。通常整数占一个字长度,所以指向整数的指针可以就是一个地址。但是,字可以存储多于一个的字符。例如,36位的字可以存储6个6位的字符:
或者4个9位的字符:
由于这个原因,可能需要用不用于其他指针的格式存储指向字符的指针。指向字符的指针可以由地址(存储字符的字)加上一个小整数(字符在字内的位置即偏移量)组成。
在一些计算机上,指针可能是“偏移量”而不完全是地址。例如,Intel微处理器(用于IBM PC和其他产品)具有复杂的模式,模式中的地址有时用单独的16位数(偏移量)表示,有时用两个16位数(段:偏移量对)表示。偏移量不是真正的内存地址:CPU必须把它和存储在特殊寄存器中段的值联合起来。
用于IBM PC家族的C语言编译器通过提供两种指针的方式处理Intel的分段结构:近指针(16位偏移量)和远指针(32位段)。由于这个原因,PC编译器通常保留单词near和far用于指针变量的声明。 -
如果指针可可以指向程序中的数据,那么使指针指向程序代码是否可能?
可能。例如后续将介绍到的指向函数的指针。 -
是否存在显示指针的值得方法?
调用printf函数,在格式串中采用转换%p;具体细节在讲输入输出的博客中给出。 -
对于指针的算术运算,如果指针是地址,那么这是否意味着诸如p+j这样的表达式是把加上j后的地址存储在p中呢?
不是的。标量用于指针算术运算的整数要依赖于指针的类型。例如,如果p的类型是int*,那么p+j通常既可以用2×j+p,也可以用4×j+p,依据就是int型的值要求的是2个字节还是4个字节。但是,如果p的类型位double*,那么p+j可能是8×j+p,因为double类型的值通常都是8个字节长。 -
指针运算只对指向数组的数组元素才有意义,这是什么意思?
根据C语言的标准,对于并非指向数组的指针,指针的运算是未定义的。这并不意味着不能这样做,只是意味着不能保证发生什么。 -
编写处理数组的循环时,使用数组下标和指针算术运算,哪种更好一些呢?
因为它依赖于所使用的机器和编译器本身,所以这个问题没有简单的答案。在早期PDP-11机器上的C语言,指针算术运算会产生执行较快的程序。在当今的机器上,采用现今的编译器,数组下标方法常常是很好的,而且有时甚至更好。底线是,学习这两种方法,然后采用对你现在正在编写的程序更自然的方法。 -
为什么在形式参数的声明中*a和a[ ]是一样的?
上述两种形式都说明期望实际参数是指针。在这两种情况下(特别是指针算术运算和数组下标运算)可能在a上的操作时相同的。而且,在这两种情况下,可以在函数内给a本身赋予新的值。 -
当函数有数组a作为形式参数时,*a和a[ ]哪种格式声明形式参数更好呢?
*a比a[ ]更通用,没有特别具体的原因说明。 -
已经看到C语言中数组和指针之间的紧密联系。是否可以精确地称他们是可互换的呢?
不可以。数组型形式参数和指针形式参数是可以互换的。但是作为数组变量不同于指针变量,从技术上说,数组的名字不是指针。更准确地说,需要时C语言编译器会把数组的名字转换成指针。 -
从某些地方读到i[a]和a[i]是一样的,这是真的吗?
是真的,对于编译器而言i[a]等同于*(i + a),也就是*(a + i),而*(a + i)也就是a[i]
。 -
说明了如何使用指针处理二维数组地行中的元素。用类似的方法处理列中的元素是否可行?
是可行的。但是不像行处理那么容易。因为数组是按行存储的,而不是按列。下面这个循环清楚地表明数组a中列i的元素:
int a[NUM_ROWS][NUM_COLS],i,(*p)[NUM_COLS];
for(p = a; p < = &a[NUM_ROWS-1]; p++)
(*p)[i] = 0;
已经声明了p是指向长度为NUM_COLS的数组的指针,且此数组的元素为整型的。在表达式(*p)[NUM_COLS]中要求*p
周围有圆括号,如果没有圆括号,那么编译器将会把p作为指针的数组而不是指向数组的指针来处理了。
指针的数组、指向数组的指针有什么区别?指向数组的指针是一个int *类型的指针,而指针的数组是一个int[ ]类型的数组,在参数传递时指针的数组和指向数组的指针应该是没区别的,但在for循环中,用到判断条件p <= &a[NUM_ROWS - 1];
指针的数组p映射到内存空间中存储指针的物理内存地址的值,无法和二维数组中元素的地址的值做判断。
表达式p++在下一行开始时提前处理p。在表达式(*p)[i]
中,*p
表示数组a
的完整一行,所以(*p)[i]
选择了此行i列的元素。在(*p)[i]
中的圆括号是必须的,因为编译器把*p[i]
解释为*(p[i])
。
- 如果a是二维数组,为什么可以给find_largest函数传递a[0]而不是数组a本身呢?a和a[0]不是都指向同一位置(数组开始的位置)吗?
他它们是指向同一位置,作为实际情况,两者都指向元素a[0][0]
。但是,编译器注意到a的类型为int **
(这不是find_largest函数所希望的),而a[0]得类型为int *。关于类型得这种考虑实际是很好的。如果C语言不是如此挑剔,可能会使编译器注意不到所有得指针错误。
警告
问题11的回答可能有错误,编程验证指针数组和指向数组的指针的区别以及对for循环语句的影响。