C-指针和数组的微妙概念



我有一个非常奇怪的指针示例,这需要您的帮助。通常,指针用于指向变量(请参见下面的第一个示例(,但是当指向数组时。我不明白为什么它不再需要延期获得数组(请参见下面的第二个示例(

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 -TH E1的元素(从零计数(。

这是句法糖。表达式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章

连续的下标运算符指定多维数组对象的元素。 如果En -Dimensional Array (n ≥ 2),尺寸i × j × . . . × k,则是E(用作用作 除了lvalue(被转换为指向(n − 1)二维数组的指针 尺寸j × . . . × k。如果一元*操作员明确应用于此指针,或者 由于订阅而隐含的结果是引用的(n − 1)-维 阵列,如果用作LVALUE,则将其本身转换为指针。它跟随 由此,数组以行 - 序列顺序存储(最后一个下标不同(。

考虑声明定义的数组对象

  int x[3][5];

此处xint 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]中取值,然后尝试将其解释...不是您通常想要的:(

对您的问题的简单答案是:

数组的名称是指向数组的第一个元素。

相关内容

  • 没有找到相关文章

最新更新