4

我用 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。

这意味着a必须是一个指向自身的变量......

那为什么输出是*(*a)1呢?为什么不评价为*(*a)=*(2686384)=2686384?

4

7 回答 7

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;

}
于 2014-02-01T02:53:48.850 回答
1

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

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

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

于 2012-09-21T11:30:49.343 回答
1

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

除非它是sizeof,_Alignof或一元运算符的操作数 0 &,或者是用于在声明中初始化另一个数组的字符串文字,否则“N-element array of”类型的表达式T将被转换(“decay”)为类型为“pointer to T”的表达式,表达式的值将是数组中第一个元素的地址。

表达式&a的类型为“指向 10 元素数组的 10 元素数组的指针int”,或int (*)[10][10]. 该表达式a的类型为“10 元素数组的 10 元素数组int”,根据上面的规则衰减为“指向 10 元素数组的指针int”,或者int (*)[10]。最后,表达式*a(相当于a[0])的类型为“10-element array of int”,再次按照上面的规则衰减为“pointer to int”。

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

int (*ap0)[10][10] = &a;
int (*ap1)[10]     =  a;
int *ip            = *a;

thenap0++将前进ap0指向 的下一个 10x10 数组intap1++将前进ap1到指向int(or a[1]) 的下一个 10 元素数组的指针,并ip++前进ip到指向下一个int( &a[0][1])。

**a等价于*a[0]等价于a[0][0]。这是和 的第一个元素的a,具有类型int和值1(请注意, a[0][0]初始化为1;所有其余元素都初始化为0)。

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

printf("&a = %p\n", &a);
printf(" a = %p\n",  a);
printf("*a = %p\n", *a);
于 2012-09-21T11:55:46.963 回答
0

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

**a是双重取消引用实际上是 a int**,所以你最终得到第一个子数组的第一个元素是:1。

于 2012-09-21T11:29:12.783 回答
0

从 C99 标准

考虑由声明定义的数组对象

int x[3][5];

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

所以,

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

所有 x、&x 和 *x 都将指向 x[0][0]。

于 2012-09-21T11:49:21.517 回答
0

如果定义aT a[10](where Tis some typedef),那么简单朴素的a意思就是数组的起始地址,同&a[0]. 他们都有 type T*

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

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

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

[练习给读者:什么是类型a?(不是 int**)]

**a正确计算为int数组中的第一个a

于 2012-09-21T11:37:18.873 回答
0

不,您的代码没有任何问题。就像你在想的那样……我想得越多,我就越难以解释,所以在我开始讨论之前,请记住以下几点:

  1. 数组不是指针,不要那样想它们,它们是不同的类型。
  2. [] 是一个运算符。这是一个移位和顺从运算符,所以当我写作时,printf("%d",array[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;
于 2012-09-21T11:53:31.113 回答