3D数组中**和*之间的区别

时间:2019-07-03 20:01:48

标签: c multidimensional-array

下面显示的两个代码都给出相同的输出,即** a和* a(在printf中)。为什么会这样?

我对多维数组不是很好,我尝试了各种博客来理解,但仍然失败。我不明白两种情况下的输出如何相同。预先谢谢你。

两种情况的输出都是 abcdefghijklm

// CODE 1
int main() 
{

  char a[2][3][3] = {'a','b','c','d','e','f','g', 
                    'h','i','j','k','l','m'};
  printf("%s ", **a); 
  return 0; 
} 

///代码2

int main()     {

  char a[2][3][3] = {'a','b','c','d','e','f','g', 
                    'h','i','j','k','l','m'};
  printf("%s ", *a); 
  return 0; 
} 

1 个答案:

答案 0 :(得分:0)

这很有趣。

请记住,数组元素是连续布置的-a在内存中看起来像这样:

   +---+
a: |'a'| a[0][0][0]
   +---+ 
   |'b'| a[0][0][1]
   +---+
   |'c'| a[0][0][2]
   +---+
   |'d'| a[0][1][0]
   +---+
   |'e'| a[0][1][1]
   +---+
   |'f'| a[0][1][2]
   +---+
   |'g'| a[0][2][0]
   +---+
   |'i'| a[0][2][1]
   +---+
   |'j'| a[0][2][2]
   +---+
   |'k'| a[1][0][0]
   +---+
   |'l'| a[1][0][1]
   +---+
   |'m'| a[1][0][2]
   +---+
   | 0 | a[1][1][0]
   +---+
   | 0 | a[1][1][1]
   +---+
    ...

由于您提供的初始化程序数量少于数组可容纳的大小(12对18),因此其余元素被初始化为0(这在以后很重要)。

首先,介绍一些数组背景:

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

数组下标操作a[i]定义*(a + i)-给定起始地址a,偏移量i 元素(不是字节!),然后取消引用结果。这意味着*a == *(a + 0) == a[0]

那么,这如何适用于您的代码?

表达式 a的类型为“ char的3元素数组的3元素数组的2元素数组。如果a不是sizeof或一元&运算符的操作数,则该表达式“衰减”以键入“指向{{1}的3元素数组的3元素数组的指针” }”,表达式的值是数组第一个元素的地址-char

表达式&a[0]解引用该指针,并且表达式的类型为“ *a的3元素数组的3元素数组”。同样,此表达式不是char或一元sizeof操作数的操作数,因此它被转换为“指向&的3元素数组的指针”,其值是地址数组第一个元素的值,即char。从&(*a)开始,这也可以视为*a == a[0]

表达式&a[0][0]取消引用**a(其类型为“指向*a的3元素数组的指针”)的结果,表达式的类型为“ 3元素char的数组”。同样,此表达式不是char或一元sizeof运算符的操作数,因此它会“拒绝”键入“指向&的指针”。

巧合的是char所期望的。 %s转换说明符希望其自变量具有类型%s,并指向字符序列中的第一个,后跟一个0值的终止符。还记得我之前说过数组的其余6个元素将初始化为0吗?也许毫无意义,您已经在<{1}中存储了 string

因此,这就是获得char *的输出的原因。但是a为什么也能工作?

数组的地址与数组的第一个元素的地址-**a相同(您可以从上面的ASCII文字中看到)。 *a 类型是错误的-是&a[0] == &a[0][0] == &a[0][0][0]而不是*a-因此严格来说,行为是不确定的,但其 value (至少其逻辑值)与char (*)[3]相同。不同的指针类型可能具有不同的表示形式,因此可能存在一个平台,其中char *的表示形式可能与**a的表示形式不同,从而使此代码无法正常工作。但是,在类似char (*)[3]的平台上,所有指针类型都具有相同的表示形式,因此char *的值与x86的值的解释方式相同。