Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
1D数组与2D数组在c中打印字符串_C_Arrays_Pointers - Fatal编程技术网

1D数组与2D数组在c中打印字符串

1D数组与2D数组在c中打印字符串,c,arrays,pointers,C,Arrays,Pointers,我知道要打印字符串,我们使用 char *pt = "Hi there"; printf("%s", pt); 或 其中,数组名的作用类似于指向第一个元素地址的指针 然而,当我们得到一个2D数组时,例如,要打印一个字符串,我们必须先取消对数组的引用,然后才能打印字符串 char b[2][10]; strcpy(b[0], "banana"); strcpy(b[1], "apple"); printf("%s", *(b+1)); 我想知道为什么在打印字符串之前必须先取消对数组的引用,因为

我知道要打印字符串,我们使用

char *pt = "Hi there";
printf("%s", pt);

其中,数组名的作用类似于指向第一个元素地址的指针

然而,当我们得到一个2D数组时,例如,要打印一个字符串,我们必须先取消对数组的引用,然后才能打印字符串

char b[2][10];
strcpy(b[0], "banana");
strcpy(b[1], "apple");
printf("%s", *(b+1));
我想知道为什么在打印字符串之前必须先取消对数组的引用,因为在第一种情况下,我们可以通过向printf提供字符数组的地址来打印字符串。


然而,在第二种情况下,我们已经有了第二个字符串“apple”的地址,那么为什么我们必须先取消对指针(b+1)的引用,然后才能打印里面的值呢?

C中的多维数组有点微妙。您认为
b
b[0]
解析为相同的物理地址是正确的,但它们具有不同的数据类型,例如,这会影响指针添加的工作方式。另外,请注意
*(b+1)
b[1]
相同


数组
b
衰减为类型
char(*)[10]
,它是指向10
char
数组的指针。因此,如果向其中添加一个,它将添加
10*sizeof(char)
。但是
b[0]
会衰减为类型
char*
,因此如果向其中添加一个,它会添加
sizeof(char)
。解引用实际上并没有转化为内存操作,而是更像一个类型转换。

回答得好,但“解引用实际上并没有转化为内存操作,而是更像一个类型转换。”因为它和该段第一句所说的有些冲突。有点不对劲。它确实以一种类似于强制转换的方式工作,但它当然也是一种内存操作(引用)。它提供了一个指向字符数组
type char(*)[10]
的指针,正如您所说。@DavidC.Rankin好的,关键是从
b
b[0]
时不会生成任何代码。地址相同,但类型不同。请记住,当访问
b[i][j]
时,只执行一次内存加载,而不是两次(就像一维数组一样)。这就是我要说的。例如,这与指向
char
的指针数组不同,后者需要两次内存加载才能访问。这就是为什么我投票支持你,但放弃了评论。我知道你在说什么,但我试图找出一种方法,不让不知道的人挠头说“我在解引用,但这不是一个内存操作,更像是一个cast…”这是完全正确的,但解引用提供了存储在地址中的值,在本例中,它恰好是一个数组(在数组数组中)的开始,在所谓的2D数组中。我想最让人心痛的是“非内存操作”。@DavidC.Rankin
b[0]
没有存储在内存中,也不会生成代码。记住,二维数组是压缩的。内存中没有存储指针。它们与指针数组非常不同,尽管对它们的引用在语法上是相同的。所以
char x[2][10]
是一个由20个
char
组成的压缩序列,但是
char*x[2]
是一个由两个
char*
组成的数组,
char**x
是指向
char*
的单个指针。所有三个都可以作为
x[i][j]
访问,但第一个是单次加载,第二个是两次加载,第三个最多是三次加载(如果
x
在内存中)。每次撤销都是另一个地址或值的加载。(当然,我们正在考虑取消引用的结果)。我想最重要的一点是,每次取消引用都会提供一个新的地址、类型或值。关键是要知道,给定手头的对象,解引用的行为如何。获取指向行的指针可以将每一行视为一个字符数组。无论是通过
b[0]
还是通过
&b[0][0]
完成,结果都是相同的,但第一个指针指向行,第二个指针指向类型。我想这是一个明确的,因为它需要。干得好。您可以编写
printf(“%s”,b[1])
由于
b
是一个二维数组,
b[1]
是一个一维数组,它与您现在的第一个示例完全相同
char b[2][10];
strcpy(b[0], "banana");
strcpy(b[1], "apple");
printf("%s", *(b+1));