让int * ptr,array[10]; ptr= array;
。现在阵列的连续位置中的每个存储器单元具有固定的大小。如果第一个单元的地址是1234,那么下一个单元必须是1238地址。但是我们使用指针*(ptr+1)
来访问它。
我很困惑。任何来源或答案?感谢。
答案 0 :(得分:5)
来自C11 standard:§6.5.2.1
post fi x表达式后跟方括号[]中的表达式是下标 指定数组对象的元素。下标运算符[]的定义 是E1 [E2]与(*((E1)+(E2)))相同。由于转换规则 应用于二进制+运算符,如果E1是一个数组对象(等效地,指向 数组对象的初始元素),E2是整数,E1 [E2]表示E2 E1的元素(从零开始计数)。
E.G。你正在做的基本上是[]
已经做了什么
同样(相同的标准)解释了为什么指针会在你注意到的时候递增:§6.5.6
当指针中添加或减去具有整数类型的表达式时, result具有指针操作数的类型。如果指针操作数指向的元素 一个数组对象,并且该数组足够大,结果指向一个偏移的元素 原始元素使得结果和原始的下标不同 数组元素等于整数表达式。换句话说,如果表达式P指向 数组对象的第i个元素,表达式(P)+ N(等效地,N +(P))和 (P)-N(其中N具有值n)分别指向第i + n和第i-n个元素 数组对象,只要它们存在。而且,如果表达式P指向最后一个 数组对象的元素,表达式(P)+1指向一个过去的最后一个元素 数组对象,如果表达式Q指向一个数组对象的最后一个元素, 表达式(Q)-1指向数组对象的最后一个元素。如果两个指针 操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素 数组对象的元素,评估不得产生溢出;否则, 行为未定。如果结果指向一个超过数组对象的最后一个元素的那个,那么 不得用作被评估的一元*运算符的操作数。
答案 1 :(得分:3)
编译器知道ptr
是一个指向4字节类型的指针,因此它知道ptr+1
在内存中还有4个字节。
如果你想了一下,很明显这一定是这样的,否则如果你不知道系统中整数(例如)的大小就无法编写可移植代码。
此外,数组索引正是封面下的指针算法 - 即array[3]
与*(array + 3)
完全相同
答案 2 :(得分:1)
当索引指针时,编译器知道索引应该按单元的大小前进,在这种情况下,指针是4个字节。
答案 3 :(得分:1)
指针算法考虑指向类型的大小。例如,如果ptr
的值为1234
,因为ptr
的类型为int*
,则p + 1
的值为1234 + 1 * sizeof(int) == 1234 + 1 * 4 = 1238
(假设sizeof(int) == 4
)。
答案 4 :(得分:0)
+运算符的右操作数,让我们称之为x,不是你移动指针的实际数量。因为int是4个字节,所以编译器知道实际跳到x * 4。
答案 5 :(得分:0)
指针运算的单位是指向对象,而不是字节。
如果p
指向int
个对象,则p+1
,p+2
和p+3
指向连续的int
个对象,而不是连续的字节。如果p
指向大型结构,则它们指向结构的连续实例。
编译器在幕后完成工作,将指针算法转换为机器地址算法。因此,它会根据需要将偏移量乘以从对象单位转换为字节单位。
答案 6 :(得分:0)
我的猜测是根据你(ptr + 1)
应该给你1235
,但显然不是。{1}}
除了其他人提供的关于为什么会添加4
并为您提供1238
的答案之外,如果它在1235
您1235
给了{{1}},请考虑一下没有整数元素(即数组的第二个元素)。
但是你的指针应该指向一个整数。因此它不会以这种方式运作。
答案 7 :(得分:0)
指针算术与普通算术不同。在指针算术中,一个参数必须是指针类型,另一个必须是整数类型:
intA + intB
:正常算术,结果是总和。intA + pointerB
:指针算术,执行的计算是sizeof(*pointerB)*intA + pointerB
pointerA + intB
:指针算术,执行的计算是pointerA + sizeof(*pointerA)*intB
pointerA + pointerB
:非法 pointerA[intB]
只是案例2(pointerA + intB
)的简写,这就是为什么它等同于intB[pointerA]
(解析为案例3),但这仅用于IOCCC