C数组和指针:等价的指向数组元素的指针

3

编辑:之前提出的类似问题并没有涉及到与此问题相关的一些观点。

在Kernighan和Ritchie的ANSI C书籍中,他们说以下两种写法是等价的:

  • a[i]
  • *(a+i)

我不明白对于占用多个地址空间的元素(例如结构体)来说,这怎么可能是正确的。

请解释一下?编辑:感谢所有的回答,但我还是不太理解。看起来我和@CucumisSativus有同样的困惑,因为他的回答和评论中都提到了这个问题。

假设sizeof(*a)是3。如果由于某种原因我想访问a中第一个元素的中间字节,我认为应该这样做:*(a+1)

假设a的地址是10,每个元素的大小是20。我们想要获取指向第二个元素的指针。据我所知,我们可以这样做:p = (10 + 20)。我认为这等价于&a[1]

我真的很难解释我不理解的地方!!


请查看此链接:http://stackoverflow.com/questions/21544177/array-of-structures-and-pointer-arithmetic - tesseract
数组下标运算符 [] 在标准中已经被定义,没有太多需要解释的。 - Yu Hao
它被称为“指针算术”,在学习C语言时至少会咬你一次。 - Stefano Sanfilippo
你说的“多个地址空间”是什么意思?你是在指K&R中可以找到的“地址空间”的某个定义吗? - n. m.
5个回答

6

C语言中,指针算术运算与普通整数算术运算有所不同。将整数i加到指针p上会使内存地址增加i * sizeof(*p),即i乘以指向类型的大小

有趣但实际上没什么用的一点是:由于p[i]的定义为*(p+i),表达式i[p]也等效于相同的表达式…


3
+运算符并不是指在地址空间中的下一个元素。
增量由涉及的数据类型的大小定义。因此,如果a是指向整数的指针,则a + 1将引用下一个int,如果a是指向struct的指针,则a + 1将引用下一个 struct

不是指向地址空间中的下一个元素。它是指向同类型指针的下一个元素的起始点。 - Grijesh Chauhan
@GrijeshChauhan 是的。通过地址空间,我指的是体系结构的字长,这也是OP所考虑的。 - axiom

1
假设我们有一个整数指针和一个字符指针,如下所示:
int *a; char *b;
现在假设a存储在位置10000,b存储在位置20000。
通过执行以下操作:
*(a+1) : It will return the value contained in address 10004 i.e. (10000+4)
*(b+1) : It will return the value contained in address 20001 i.e. (20000+1)

原因:

指针加法不同于普通算术加法。如果将1添加到整数指针中,则该指针会沿着整数的大小向前移动到一个位置。因此,在这种情况下,它会将指针提前到10004。由于字符只有1个字节长,所以它会将指针提前1个字节。


0

a+i在伪代码中的翻译大致如下

  *(a+i*sizeof(variableType))

4
不,将 *(a+i) 输入代码中等同于 a[i] - 如果你输入 *(a+i*sizeof(*a)),除非 sizeof(*a) 等于 1,否则会超过范围。 - Arkku
@Arkku 对,我写的更像是伪代码而不是纯粹的C语言。但你说得对,我表述不够清晰。 - CucumisSativus
2
你代码的问题在于它是合法的 C 代码。如果您编写伪代码,请在答案中明确说明或使用一个清晰明了的(完全不相关的)句法。 - Stefano Sanfilippo

0

我读了更多的K&R,并找到了拼图的缺失部分,使我能够理性地解释发生的事情。(是否正确仍有待讨论!)

根据我的理解,以下内容是无效的:

p = (10 + 20)
  • 鉴于引用的话:“指针和整数不能互换。零是唯一的例外。”
  • 我理解这意味着 *(a+i) 不执行直接的整数算术。
  • 我相信这种行为是由表达式中指针的存在所决定的。

再次引用K&R以及其他回答我的问题的人,涉及:

  1. 一个指针和
  2. 一个或多个整数

的算术运算的确切行为如下定义:"n根据p指向的对象的大小进行缩放,该大小由p的声明确定"

我意识到让我感到困惑的原因是:过去我曾经能够使用 printf() 输出指针的实际地址值。我相信这是“未定义的行为”,我使用的编译器碰巧通过将指针视为整数来处理它。

同样,根据上述两个编号的要点以及使用它们的定义,我认为将两个指针相加(相同类型的)会导致未定义的行为,更确切地说,将两个不同类型的指针相加。

要获取整数的第n个字节,请参见this question

K&R随后补充说以下是合法的指针操作:

  • 将一个指针赋值给另一个指针(相同类型)
  • 添加或减去指针和整数
  • 从另一个指针中减去一个指针(到相同数组)
  • 比较指针(到相同数组)
  • 分配/比较为0

所有其他指针算术都是非法的。


“n根据p指向的对象的大小进行缩放,这取决于p的声明。” 这正是我和Arrku所说的。 - axiom
是的,正如我在我的回答中所说,“引用K&R和其他人对我的问题提供的答案”,因此我承认了您的回复。让我理解的是K&R的另一个引用:“指针和整数不可互换”。我仍然给了您的答案+1。 - Jodes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接