2 D阵列的问题

时间:2012-09-21 11:20:19

标签: c arrays pointers 2d

我在C中编写了以下代码:

#include<stdio.h>

int  main()
{
  int a[10][10]={1};
  //------------------------
  printf("%d\n",&a);
  printf("%d\n",a);
  printf("%d\n",*a);
  //-------------------------
  printf("%d",**a);

  return 0;
}

使用上面3个printf语句,我得到了相同的值。在我的机器上它是2686384.但是最后一个声明我得到了1。

这不是出问题吗?这些陈述意味着:

  1. a的地址是2686384
  2. a中存储的值为2686384
  3. a指向的变量地址(即2686384)存储的值为2686384.
  4. 这意味着a必须像一个指向自身的变量......

    那么为什么*(*a) 1的输出?为什么不将其评估为*(*a)=*(2686384)=2686384

7 个答案:

答案 0 :(得分:2)

#include<stdio.h>

int  main()
{
  // a[row][col]
  int a[2][2]={ {9, 2}, {3, 4} };
  // in C, multidimensional arrays are really one dimensional, but
  // syntax alows us to access it as a two dimensional (like here).

  //------------------------
  printf("&a            = %d\n",&a);
  printf("a             = %d\n",a);
  printf("*a            = %d\n",*a);
  //-------------------------

  // Thing to have in mind here, that may be confusing is:
  // since we can access array values through 2 dimensions,
  // we need 2 stars(asterisk), right? Right.

  // So as a consistency in this aproach,
  // even if we are asking for first value,
  // we have to use 2 dimensional (we have a 2D array)
  // access syntax - 2 stars.

  printf("**a           = %d\n", **a );         // this says a[0][0] or *(*(a+0)+0)
  printf("**(a+1)       = %d\n", **(a+1) );     // a[1][0] or *(*(a+1)+0)
  printf("*(*(a+1)+1)   = %d\n", *(*(a+1)+1) ); // a[1][1] or *(*(a+1)+1)
  // a[1] gives us the value on that position,
  // since that value is pointer, &a[i] returns a pointer value
  printf("&a[1]         = %d\n", &a[1]);
  // When we add int to a pointer (eg. a+1),
  // really we are adding the lenth of a type
  // to which pointer is directing - here we go to the next element in an array.

  // In C, you can manipulate array variables practically like pointers.
  // Example: littleFunction(int [] arr) accepts pointers to int, and it works vice versa,
  //          littleFunction(int* arr) accepts array of int.

  int b = 8;
  printf("b             = %d\n", *&b);

  return 0;

}

答案 1 :(得分:1)

包含数组名称的表达式可以衰减到指向数组第一个元素的指针。因此即使a具有int[10][10]类型,它也可以衰减为int(*)[10]

现在,这种衰变发生在表达式*a中。因此表达式具有类型int[10]。重复相同的逻辑,这再次衰减到int*,因此**aint,而且它是数组a的第一个元素的第一个元素,即1

其他三个打印语句分别打印出数组的第一个元素的数组的地址,以及数组的第一个元素的第一个元素(当然所有相同的地址,只是不同的类型)。

答案 2 :(得分:1)

首先,关于数组的一个词......

除非它是sizeof_Alignof或一元&运算符的操作数0,或者是用于在声明中初始化另一个数组的字符串文字, >“{元素数组T”类型的>表达式将被转换(“衰减”)为“指向T的指针”类型的表达式,表达式的值将是数组中第一个元素的地址。

表达式&a具有类型“指向10个元素数组int”或int (*)[10][10]的10元素数组的指针。表达式a具有“10元素数组int的10元素数组”,按照上面的规则衰减为“指向int的10元素数组”,或者int (*)[10]。最后,表达式*a(相当于a[0])的类型为“10个元素的int数组”,再次按照上面的规则衰减到“int的指针}}”。

所有三个表达式都具有相同的值,因为数组的地址和第一个元素的地址是相同的:&a[0][0] == a[0] == {{ 1}} == *a == a。但是,表达式的类型是不同的,这在进行指针运算时很重要。例如,如果我有以下声明:

&a

然后int (*ap0)[10][10] = &a; int (*ap1)[10] = a; int *ip = *a; 会提前ap0++指向ap0的下一个10x10数组,int会提前ap1++指向下一个10元素数组ap1(或int)和a[1]会提前ip++指向下一个ipint)。

&a[0][1]相当于**a,相当于*a[0]。这是a[0][0]的第一个元素的,其类型为a,值为int(请注意 {{ 1}}被初始化为1;所有剩余的元素都被初始化为a[0][0])。

请注意,您应该使用1打印出指针值:

0

答案 3 :(得分:0)

首先,如果要打印指针值,请使用%p - 如果您使用的是64位机器,则int几乎肯定小于指针。

**a双重解引用实际上是int**的内容,因此您最终会得到第一个子数组的第一个元素:1。

答案 4 :(得分:0)

如果您将a定义为T a[10](其中T是某个typedef),那么简单的简单a表示数组开头的地址,与&a[0]相同。它们都有T*类型。

&a也是数组开头的地址,但它的类型为T**

在存在多维数组的情况下,事情变得更加棘手。要查看正在发生的事情,使用typedef将事情分解为更小的块更容易。所以,你有效地写了

typedef int array10[10];
array10 a[10];

[向读者练习:a的类型是什么? (它 int**)]

**a正确评估数组int中的第一个a

答案 5 :(得分:0)

来自C99标准

考虑声明

定义的数组对象
int x[3][5];

这里x是3×5的整数数组;更确切地说,x是一个由三个元素对象组成的数组,每个元素对象是一个由五个整数组成的数组。在表达式x [i]中,它等价于(*((x)+(i))), x首先转换为指向初始数组为5个整数的指针。然后根据x的类型调整i,这在概念上需要将i乘以指针所指向的对象的大小,即五个int对象的数组。添加结果并应用间接以产生五个整数的数组。当在表达式x [i] [j]中使用时,该数组又被转换为指向第一个int的指针,因此x [i] [j]产生一个int。

所以,

初始数组仅为x [0] [0]。

所有x,&amp; x和* x将指向x [0] [0]。

答案 6 :(得分:0)

不,你的代码没有任何问题。只是他们想你的方式......我想的越多,我就越难意识到这是解释,所以在我进入这个之前,请记住以下几点:

  1. 数组不是指针,不要那么想,它们是不同的类型。
  2. []是一名运营商。它是一个移位和参数运算符,所以当我写printf("%d",array[3]);时,我正在移动和引用
  3. 所以一个数组(让我们考虑一下维度)就在内存中的某个地方:

    int arr[10] = {1};
    //Some where in memory---> 0x80001f23
                                [1][1][1][1][1][1][1][1][1][1]
    

    所以,如果我说:

    *arr; //this gives the value 1
    

    为什么呢?因为它与arr[0]相同,它给出了地址的值,这是数组的开头。这意味着:

    arr; // this is the address of the start of the array
    

    那么这给了我们什么呢?

    &arr; //this will give us the address of the array. 
          //which IS the address of the start of the array
          //this is where arrays and pointers really show some difference
    

    所以arr == &arr;。数组的“作业”是保存数据,数组不会“指向”任何其他内容,因为它拥有自己的数据。期。另一方面,指针的作用是指向其他东西:

    int *z;     //the pointer holds the address of someone else's values
    z = arr;    //the pointer holds the address of the array
    z != &z;    //the pointer's address is a unique value telling us where the pointer resides
                //the pointer's value is the address of the array
    

    修改 还有一种思考方式:

    int b;   //this is integer type
    &b;      //this is the address of the int b, right?
    
    int c[]; //this is the array of ints
    &c;      //this would be the address of the array, right?
    

    所以这是可以理解的:

    *c;   //that's the first element in the array
    

    这行代码告诉你什么?如果我尊重c,那么我得到一个int。这意味着普通c是一个地址。因为它是数组的开头,所以它是数组的地址,因此:

    c == &c;