指针如何使一维数组有效地变为二维?

huangapple go评论88阅读模式
英文:

How do pointers make a 1D array effectively 2D?

问题

以下是 C 编程中下面这行代码的含义:

```c
 char* list[3]={"pune","banglore","chennai"}

现在如果我只是创建了名为 list 的一维数组,它是如何存储城市的全名的?

我只是想了解上面这行代码,虽然它只有一维数组,却可以存储多个 char 的名字信息。


<details>
<summary>英文:</summary>

What does the below line of code mean in c Programming?  

char* list[3]={"pune","banglore","chennai"}


Now if I am just creating 1-D array named `list`, then how is it  storing the full names of the city?

I just want to understand how the above line of code, although it has 1-D array, still storing the 2-D information of names with multiple `char`.


</details>


# 答案1
**得分**: 2

`list` 是一个包含 `3` 个 `char *` 类型的数组。它是一个 `1D` 数组,包含指向字符串文字的 `char` 指针类型的元素。

`list` 在内存中的视图类似于这样:

      list                       
        +----+    +-+-+-+-+--+
 list[0]|    |--->|p|u|n|e|
      list                       
+----+    +-+-+-+-+--+
list[0]|    |--->|p|u|n|e|\0|
|    |    +-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+-+--+
list[1]|    |--->|b|a|n|g|l|o|r|e|\0|
|    |    +-+-+-+-+-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+--+
list[2]|    |--->|c|h|e|n|n|a|i|\0|
|    |    +-+-+-+-+-+-+-+--+
+----+
| | | +-+-+-+-+--+ +----+ +-+-+-+-+-+-+-+-+--+ list[1]| |--->|b|a|n|g|l|o|r|e|
      list                       
+----+    +-+-+-+-+--+
list[0]|    |--->|p|u|n|e|\0|
|    |    +-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+-+--+
list[1]|    |--->|b|a|n|g|l|o|r|e|\0|
|    |    +-+-+-+-+-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+--+
list[2]|    |--->|c|h|e|n|n|a|i|\0|
|    |    +-+-+-+-+-+-+-+--+
+----+
| | | +-+-+-+-+-+-+-+-+--+ +----+ +-+-+-+-+-+-+-+--+ list[2]| |--->|c|h|e|n|n|a|i|
      list                       
+----+    +-+-+-+-+--+
list[0]|    |--->|p|u|n|e|\0|
|    |    +-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+-+--+
list[1]|    |--->|b|a|n|g|l|o|r|e|\0|
|    |    +-+-+-+-+-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+--+
list[2]|    |--->|c|h|e|n|n|a|i|\0|
|    |    +-+-+-+-+-+-+-+--+
+----+
| | | +-+-+-+-+-+-+-+--+ +----+

`list` 并不存储字符串的 `2D` 信息,而是每个元素(即指针)指向一个字符串<sup>1)</sup>。

以下部分仅供参考,以防您仍然对 `list` 误解为 `2D` 数组或存储 `2D` 信息。

将 `list` 声明为 `2D` 数组:

```c
char list[3][9] = {"pune", "banglore", "chennai"};

现在,list 是一个 2D 数组。您可以将其内存视图视为以下方式:

     index   0 1 2 3 4 5 6 7 8 
      list  +-+-+-+-+-+-+-+-+-+
    list[0] |p|u|n|e|0|0|0|0|0|
            +-+-+-+-+-+-+-+-+-+
    list[1] |b|a|n|g|l|o|r|e|0|
            +-+-+-+-+-+-+-+-+-+
    list[2] |c|h|e|n|n|a|i|0|0|
            +-+-+-+-+-+-+-+-+-+

请注意,在这种情况下,用于初始化数组的字符串文字的字符被复制到数组内存中。但在前一种情况下(其中 list 是一个 char * 数组),字符串文字转换为指向其第一个元素的指针1)

根据 C11 标准#6.3.2.1p3 [强调已添加]

3 除非它是 sizeof 运算符、_Alignof 运算符、一元 & 运算符的操作数,或者是用于初始化数组的字符串文字,具有类型 "array of type" 的表达式会转换为具有类型 "pointer to type" 的表达式,指向数组对象的初始元素,且不是左值。

英文:

list is an array of 3 char * types. It's a 1D array of char pointers type, where it's each pointer is pointing to a string literal.

The in-memory view of list would be something like this:

      list                       
        +----+    +-+-+-+-+--+
 list[0]|    |---&gt;|p|u|n|e|
      list                       
+----+    +-+-+-+-+--+
list[0]|    |---&gt;|p|u|n|e|\0|
|    |    +-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+-+--+
list[1]|    |---&gt;|b|a|n|g|l|o|r|e|\0|
|    |    +-+-+-+-+-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+--+
list[2]|    |---&gt;|c|h|e|n|n|a|i|\0|
|    |    +-+-+-+-+-+-+-+--+
+----+    
| | | +-+-+-+-+--+ +----+ +-+-+-+-+-+-+-+-+--+ list[1]| |---&gt;|b|a|n|g|l|o|r|e|
      list                       
+----+    +-+-+-+-+--+
list[0]|    |---&gt;|p|u|n|e|\0|
|    |    +-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+-+--+
list[1]|    |---&gt;|b|a|n|g|l|o|r|e|\0|
|    |    +-+-+-+-+-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+--+
list[2]|    |---&gt;|c|h|e|n|n|a|i|\0|
|    |    +-+-+-+-+-+-+-+--+
+----+    
| | | +-+-+-+-+-+-+-+-+--+ +----+ +-+-+-+-+-+-+-+--+ list[2]| |---&gt;|c|h|e|n|n|a|i|
      list                       
+----+    +-+-+-+-+--+
list[0]|    |---&gt;|p|u|n|e|\0|
|    |    +-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+-+--+
list[1]|    |---&gt;|b|a|n|g|l|o|r|e|\0|
|    |    +-+-+-+-+-+-+-+-+--+
+----+    +-+-+-+-+-+-+-+--+
list[2]|    |---&gt;|c|h|e|n|n|a|i|\0|
|    |    +-+-+-+-+-+-+-+--+
+----+    
| | | +-+-+-+-+-+-+-+--+ +----+

list is not storing 2D information of string but it's each element (which is a pointer) pointing to a string<sup>1)</sup>.


Below part included, just in case, if you still confused and thinking of list as 2D array or storing 2D information.

Declaration of list as 2D array:

char list[3][9] = {&quot;pune&quot;,&quot;banglore&quot;,&quot;chennai&quot;};

Now, the list is a 2D array.
You can think of it's in-memory view something like this:

 index   0 1 2 3 4 5 6 7 8 
  list  +-+-+-+-+-+-+-+-+-+
list[0] |p|u|n|e|0|0|0|0|0|
        +-+-+-+-+-+-+-+-+-+
list[1] |b|a|n|g|l|o|r|e|0|
        +-+-+-+-+-+-+-+-+-+
list[2] |c|h|e|n|n|a|i|0|0|
        +-+-+-+-+-+-+-+-+-+

Note that, in this case the string literals used to initialize array, the characters of string literals are copied to array memory. But in the former case (where list is an array of char *), the string literal converted to pointer to its first element<sup>1)</sup>.


From C11 Standards#6.3.2.1p3 [emphasis added]

>3 Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type ''array of type'' is converted to an expression with type ''pointer to type'' that points to the initial element of the array object and is not an lvalue. ....

答案2

得分: 0

这是一个指向char的一维指针数组。
指向char的指针是C语言中最接近"字符串"的表示方式,即指向一系列以0终止符标示结尾/长度的字符的第一个字符的指针。这也是类似"pune"这样的字符串被存储/表示的方式。

这个数组有三个条目,并用"字符串"初始化。
最终它包含指向字符序列的指针,这些指针应被视为只读,因为你不应该对它们进行写入。

在显示的代码中,似乎缺少一个最终的;,但我认为这只是你故意选择复制粘贴内容而没有理解困难。

英文:

It is a 1D array of pointers to char.
Pointers to char are the closest C comes to "strings", i.e. pointers to the first of a sequence of characters which have their end/length indicated with a 0-terminator. That happens to be the way things like &quot;pune&quot; are stored/represented.

That array, which has three entries, gets initialised with "strings".
It ends up containing pointers to character sequences which should be considered read-only, as you are not supposed to write to them.

In the shown code a final ; seems to be missing, but I think that is just your intentional choice of copy-paste content and you do not have any trouble of understanding there.

答案3

得分: 0

"pune", "banglore" 和 "chennai" 被称为字符串字面值。字符串字面值是 C 字符串。C 字符串是一个包含所有字符和终止空字符(通常是\0,其整数值为零)的字符数组。字符串数组不能被您的程序修改。

在 C 中,数组会衰减为指针(当您在表达式中使用数组时,它会衰减为指向数组第一个元素的指针)。这在这里发生了。

char *list[3] = {"pune", "banglore", "chennai"} 定义了指向 char 的一维指针数组,并用字符串字面值的首字符引用初始化它。这等同于以下代码:

const char arr1[] = "pune";
const char arr2[] = "banglore";
const char arr3[] = "chennai";
char* list[3] = {arr1, arr2, arr3};

为了更符合规范(因为您不能修改字符串字面值),应该声明为:

const char *list[3] = {"pune", "banglore", "chennai"};
英文:

&quot;pune&quot;, &quot;banglore&quot; and &quot;chennai&quot; are called string literals. String literal is C sting. C string is a char array containing all the characters plus terminating null character (which is usually \0 [and it has zero integer value]). String arrays cannot be modified by your program.

Arrays in C decay to pointers (when you use array in expression it decays to pointer to the first element of the array). It happens here.

char *list[3]={&quot;pune&quot;,&quot;banglore&quot;,&quot;chennai&quot;} defines 1D array of pointers to char and initializes it with references to first characters of the string literals. It is equivalent to.

const char arr1[] = &quot;pune&quot;;
const char arr2[] = &quot;banglore&quot;;
const char arr3[] = &quot;chennai&quot;;
char* list[3]={arr1, arr2, arr3}

To be more cont correct (as you can't modify the string literals) it should be declared as:

const char *list[3]={&quot;pune&quot;,&quot;banglore&quot;,&quot;chennai&quot;};

答案4

得分: 0

char* list[3]={"pune","banglore","chennai"}

当一个字符串文字,比如 `“pune”`,出现在源代码中时,将为它创建一个静态字符数组。该数组包含字符串的字符(“p”,“u”,“n”和“e”)以及一个终止空字符(代码0)。

`char * list[3]` 声明了一个包含三个元素的数组。每个元素都是一个 `char *`。`char *` 是指向 `char` 的指针。

`={"pune","banglore","chennai"}` 意味着用表达式 `“pune”`,`“banglore”`  `“chennai”` 来初始化数组。`“pune”` 用于初始化 `list[0]`,`“banglore”` 用于初始化 `list[1]`,`“chennai”` 用于初始化 `list[2]`。

当数组在表达式中被用作除了 `sizeof` 操作数、一元 `&` 操作数或用于初始化数组以外的地方时,它会自动转换为指向其第一个元素的指针。在这里,`“pune”` 被用于初始化 `list[0]`,它是一个指针(`char *`),而不是数组。因此,由 `“pune”` 表示的数组会被转换为指向其第一个元素 p”的指针,然后 `list[0]` 被初始化为该指针。

因此,`list[0]` 被设置为指向 `“pune”` 的第一个元素。类似地,`list[1]` 被设置为指向 `“banglore”` 的第一个元素,`list[2]` 被设置为指向 `“chennai”` 的第一个元素。

所以 `list` 不是一个二维数组。它是一个指向 `char` 的指针的一维数组。它所指向的 `char` 由编译器在内存中安排。它们不一定以某种有序的方式排列,比如一个数组。

## 脚注 ##

&lt;sup&gt;1&lt;/sup&gt; 在编译器优化期间,该数组的内容可能会被合并到程序中,而单独的数组可能会被消除,具体取决于情况。
英文:

> char* list[3]={"pune","banglore","chennai"}

When a string literal, like &quot;pune&quot;, appears in source code, a static array of characters is created for it.<sup>1</sup> That array contains the characters of the string (“p”, “u”, “n”, and “e”) and a terminating null character (code 0).

char * list[3] declares an array of three elements. Each element is a char *. A char * is a pointer to a char.

={&quot;pune&quot;,&quot;banglore&quot;,&quot;chennai&quot;} says to initialize the array with the expressions &quot;pune&quot;, &quot;banglore&quot;, and &quot;chennai&quot;. &quot;pune&quot; is used to initialize list[0], &quot;banglore&quot; is used to initialize list[1], and &quot;chennai&quot; is used to initialize list[2].

When an array is used in an expression other than as the operand of sizeof, as the operand of unary &amp;, or to initialize an array, it is automatically converted to a pointer to its first element. Here, &quot;pune&quot; is being used to initialize list[0], which is a pointer (char *), not an array. So the array represented by &quot;pune&quot; is converted to a pointer to its first element, “p”, and then list[0] is initialized with that pointer.

So list[0] is set to point to the first element of &quot;pune&quot;. Similarly, list[1] is set to point to the first element of &quot;banglore&quot;, and list[2] is set to point to the first element of &quot;chennai&quot;.

So list is not a two-dimensional array. It is a one-dimensional array of pointers to char. The char it points to are in memory arranged by the compiler. They are not necessarily in some orderly arrangement like an array.

Footnote

<sup>1</sup> During compiler optimization, the contents of this array might be incorporated into the program and the separate array might be eliminated, depending on circumstances.

huangapple
  • 本文由 发表于 2023年7月31日 19:09:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76803027.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定