我有一个非常奇怪的指针示例,这需要您的帮助。通常,指针用于指向变量(请参见下面的第一个示例(,但是当指向数组时。我不明白为什么它不再需要延期获得数组(请参见下面的第二个示例(
printf("TEST: %in", x[i]);// I expect this should be *x[i]
这确实非常奇怪。只是一个c惯例还是如何解释?
编辑::由于许多人提供了一个明确的答案,所以我想包括另一个小的后续问题,因为你们所有人都提到x [i] [j]对于2维数组?它等同于什么?是否需要取消给予?
带有正常变量
int j = 4;
int* pointerj=&j;//pointerj holds address of j or points to j
printf("%d",*pointerj); returns the value that pointer j points to
带有数组:
#include <stdio.h>
#include <stdlib.h>
int *function(unsigned int tags) {
int i;
int *var;
var = (int*)malloc(sizeof(int)*tags); // malloc is casted to int* type , allocated dynamical memory, it returns a pointer!
//so now var holds the address to a dynamical array.
for (i = 0; i < tags; i++) {
var[i] = i;
}
return var;
}
int main() {
int *x;
int i;
x = function(10);
for (i = 0; i < 10; i++) {
printf("TEST: %in", x[i]);// I expect this should be *x[i]
}
free(x); x = NULL;
return 0;
}
不明白为什么它不再需要删除来获得数组(element(
好吧,您是删除,它只是不使用dereference oterator *
。
阵列订阅操作员[]
在此处担任删除。引用C11
,第§6.5.2.1章
后缀表达式,然后在方括号中表达式
[]
是一个下标 数组对象元素的名称。下标操作员[]
的定义 是E1[E2]
与(*((E1)+(E2)))
相同。由于转换规则 如果E1
是一个数组对象(等效地,将指向指向二进制+
操作员 数组对象的初始元素(和E2
是一个整数,E1[E2]
指定E2
-THE1
的元素(从零计数(。
这是句法糖。表达式x[i]
和*(x+i)
等效。后来满足您的期望,而第一个则掩盖了解雇操作员,但要做的是您所期望的完全相同的工作。
也就是说,也密切关注数据类型。您所期望的是,沿*x[i]
线的某些内容将是无效的,因为它归结为``((x i(((。现在,
-
x
是类型int []
(整数数组,它衰减到整数指针( -
x+i
为您提供了int
类型结果的指针。 - 将内部解雇操作员应用于它,导致
int
。 - 外部
*
,现在将尝试在类型int
(而不是指针(的操作数上操作,并且此操作将是句法错误,因为解雇操作员的约束表示,
Unary
*
操作员的操作数应具有指针类型。
在C11
中,第§6.5.3.2章。
回答其他问题:
让我再次使用该报价,这是第2章,第6.5.2.1章
。连续的下标运算符指定多维数组对象的元素。 如果
E
是n
-Dimensional Array(n ≥ 2)
,尺寸i × j × . . . × k
,则是E
(用作用作 除了lvalue(被转换为指向(n − 1)
二维数组的指针 尺寸j × . . . × k
。如果一元*
操作员明确应用于此指针,或者 由于订阅而隐含的结果是引用的(n − 1)
-维 阵列,如果用作LVALUE,则将其本身转换为指针。它跟随 由此,数组以行 - 序列顺序存储(最后一个下标不同(。考虑声明定义的数组对象
int x[3][5];
此处
x
是int
s的3 × 5
数组;更确切地说,x
是三个元素对象的数组,每个对象是一个 五个int的阵列。在表达式x[i]
(等效于(*((x)+(i)))
(中,x
首先转换为 指向五个INT的初始数组的指针。然后根据x
的类型调整i
,从概念上讲 需要将i
乘以指向指向的对象的大小,即五个int
的数组 对象。添加结果并应用间接式以产生五个int的阵列。当在 表达式x[i][j]
,该数组又转换为第一个INT的指针,因此x[i][j]
产生int
。
这还可以。不 *那里。
如果您有指针int *a
,则指向一系列有效数据,例如:
int *a;
int arr[5] = {1, 2, 3, 4, 5];
a = arr;
通过使用a[0]
,您已经取消了指针,并且不需要*
,因为a[0]
与*(a + 0)
相同。
您可以走得更远,甚至更复杂的读者代码。
您可以在示例中使用i[x]
而不是x[i]
。为什么? x[i]
等于*(x + i)
,但也等同于*(i + x)
,这是c。
它即使使用数字,例如x[3]
或3[x]
也会给您相同的结果。
在c中,做x [i]在i [x]上是等效的(是的(。您的编译器通过:
对此进行编译*(x i(,您可以检索自己喜欢的符号。
x i是一个指针,您可以从x开始,然后i。结果考虑了指针的类型(0xff与char*的地址不同于int*(。
您误解了如何误解阵列工作。确实,当使用诸如int
之类的变量时,您应该通过
int x;
int *p2x = &x
但是使用数组时,它有点不同。int y[SOME_SIZE];
是内存中字节的一部分,*y
将带您进入该内存位置中的第一个元素,并将其解释。y[0]
也会做同样的事情。*y[0]
将首先在y[0]
中取值,然后尝试将其解释...不是您通常想要的:(
对您的问题的简单答案是:
数组的名称是指向数组的第一个元素。