指针疑难点问答

  1. 指针总是和地址一样吗?
    通常是,但不总是。考虑用字而不是字节划分内存的计算机。字可以包含36位、64位,或者更多位。如果假设36位的字,那么内存将有如下的显示:
    在这里插入图片描述
    当用字划分内存时,每个字都有一个地址。通常整数占一个字长度,所以指向整数的指针可以就是一个地址。但是,字可以存储多于一个的字符。例如,36位的字可以存储6个6位的字符:
    在这里插入图片描述
    或者4个9位的字符:
    在这里插入图片描述
    由于这个原因,可能需要用不用于其他指针的格式存储指向字符的指针。指向字符的指针可以由地址(存储字符的字)加上一个小整数(字符在字内的位置即偏移量)组成。
    在一些计算机上,指针可能是“偏移量”而不完全是地址。例如,Intel微处理器(用于IBM PC和其他产品)具有复杂的模式,模式中的地址有时用单独的16位数(偏移量)表示,有时用两个16位数(段:偏移量对)表示。偏移量不是真正的内存地址:CPU必须把它和存储在特殊寄存器中段的值联合起来。
    用于IBM PC家族的C语言编译器通过提供两种指针的方式处理Intel的分段结构:近指针(16位偏移量)和远指针(32位段)。由于这个原因,PC编译器通常保留单词near和far用于指针变量的声明。

  2. 如果指针可可以指向程序中的数据,那么使指针指向程序代码是否可能?
    可能。例如后续将介绍到的指向函数的指针。

  3. 是否存在显示指针的值得方法?
    调用printf函数,在格式串中采用转换%p;具体细节在讲输入输出的博客中给出。

  4. 对于指针的算术运算,如果指针是地址,那么这是否意味着诸如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个字节长。

  5. 指针运算只对指向数组的数组元素才有意义,这是什么意思?
    根据C语言的标准,对于并非指向数组的指针,指针的运算是未定义的。这并不意味着不能这样做,只是意味着不能保证发生什么。

  6. 编写处理数组的循环时,使用数组下标和指针算术运算,哪种更好一些呢?
    因为它依赖于所使用的机器和编译器本身,所以这个问题没有简单的答案。在早期PDP-11机器上的C语言,指针算术运算会产生执行较快的程序。在当今的机器上,采用现今的编译器,数组下标方法常常是很好的,而且有时甚至更好。底线是,学习这两种方法,然后采用对你现在正在编写的程序更自然的方法。

  7. 为什么在形式参数的声明中*a和a[ ]是一样的?
    上述两种形式都说明期望实际参数是指针。在这两种情况下(特别是指针算术运算和数组下标运算)可能在a上的操作时相同的。而且,在这两种情况下,可以在函数内给a本身赋予新的值。

  8. 当函数有数组a作为形式参数时,*a和a[ ]哪种格式声明形式参数更好呢?
    *a比a[ ]更通用,没有特别具体的原因说明。

  9. 已经看到C语言中数组和指针之间的紧密联系。是否可以精确地称他们是可互换的呢?
    不可以。数组型形式参数和指针形式参数是可以互换的。但是作为数组变量不同于指针变量,从技术上说,数组的名字不是指针。更准确地说,需要时C语言编译器会把数组的名字转换成指针

  10. 从某些地方读到i[a]和a[i]是一样的,这是真的吗?
    是真的,对于编译器而言i[a]等同于*(i + a),也就是*(a + i),而*(a + i)也就是a[i]

  11. 说明了如何使用指针处理二维数组地行中的元素。用类似的方法处理列中的元素是否可行?
    是可行的。但是不像行处理那么容易。因为数组是按行存储的,而不是按列。下面这个循环清楚地表明数组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])

  1. 如果a是二维数组,为什么可以给find_largest函数传递a[0]而不是数组a本身呢?a和a[0]不是都指向同一位置(数组开始的位置)吗?
    他它们是指向同一位置,作为实际情况,两者都指向元素a[0][0]。但是,编译器注意到a的类型为int **(这不是find_largest函数所希望的),而a[0]得类型为int *。关于类型得这种考虑实际是很好的。如果C语言不是如此挑剔,可能会使编译器注意不到所有得指针错误。

警告
问题11的回答可能有错误,编程验证指针数组和指向数组的指针的区别以及对for循环语句的影响。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值