为什么将地址传递给指针数组不会存储该唯一值?

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

Why doesn't passing an address to a pointer array store that unique value?

问题

我尝试创建一个指针数组,用来保存不同大小的字符串。我想要提示用户输入,将这些值存储在数组中,然后使用以下代码打印它们:

#include <stdio.h>

int main() {

    char *string_array[10];

    for (int x = 0; x < 2; x++)
    {
        char string[50];
        printf("Input Name of Fruit number %d\n", x);
        fgets(string, 50, stdin);
        string_array[x] = string;
    }

    for (int x = 0; x < 2; x++)
    {
        printf("%s\n", string_array[x]);
    }
    return 0;
}

我期望这段代码接受两次用户输入,并存储每个字符串的地址。然而,当我运行代码时,最后一次用户输入显示的是指针数组中每个地址的值。经检查,我发现每个地址都是相同的。

我猜测这是因为 string 变量每次都被实例化为相同的地址,或者尽管在每个循环中都被定义,但从未发生变化。这里发生了什么,阻止这段代码正常工作?

英文:

I'm trying to create a pointer array that holds strings of various sizes. I want to prompt the user for input, store the values in the array, and then print them using the following code:

#include &lt;stdio.h&gt;

int main() {

    char *string_array[10];

    for (int x = 0; x &lt; 2; x++)
    {
        char string[50];
        printf(&quot;Input Name of Fruit number %d\n&quot;, x);
        fgets(string, 50, stdin);
        string_array[x] = string;
    }

    for (int x = 0; x &lt; 2; x++)
    {
        printf(&quot;%s\n&quot;, string_array[x]);
    }
    return 0;
}

I expected this code to take in two user prompts and store the address of each string. However, when I run the code, the final user prompt represents the value stored at each address in the pointer array. On inspection, I found that every address is the same.

I presume this is because the string variable is instantiated to the same address every time, or is never changed despite being defined in each for loop. What's happening here with the addresses to prevent this code from working?

答案1

得分: 2

这个循环中的数组 `string` 具有块作用域。当块结束时,它将不复存在。因此,`string_array[0]` 和 `string_array[1]` 将指向不再存在的内存,访问该内存将引发未定义行为。

&gt; 1) 对象有其生存期,在生存期外就无法访问。
&gt; 
&gt; 2) 在对象生存期外引用该对象会产生未定义行为。
&gt; 3) 自动变量的生存期对应于其定义的块的执行。

**修复**:

如 @Weather Vane 所评论的:

&gt; 你正在存储相同缓冲区的相同地址,但当报告字符串时,该缓冲区已经超出作用域。你可以做的是复制:

string_array[x] = strdup(string);


另一个解决方案是使用 `malloc()` 分配内存并使用标准的 `strcpy()`。如果输入超出了块的原始长度,可以稍后使用 `realloc()` 调整内存大小。
英文:
for (int x = 0; x &lt; 2; x++)
{
        char string[50];
        printf(&quot;Input Name of Fruit number %d\n&quot;, x);
        fgets(string, 50, stdin);
        string_array[x] = string;
}

The array string in this loop has block scope. It ceases to exist when the block ends. So string_array[0] and string_array[1] will be pointing to memory that no longer exists, and accessing that memory would invoke undefined behaviour.

> 1) Objects have a lifetime outside of which they can't be accessed.
>
> 2) Referring to an object outside of its lifetime has undefined
> behaviour.
> 3) Automatic variables have a lifetime corresponding to the execution
> of the their block of definition.


Fix:

As commented by @Weather Vane:

> You are storing the same address of the same buffer, but when you
> report the strings, that buffer has gone out of scope. What you can do
> is to make a copy:

string_array[x] = strdup(string);

Another solution would be to allocate memory with malloc() and use standard strcpy(). The memory can later be resized with realloc() if the input exceeds the original length of the block.

答案2

得分: 1

为什么将地址传递给指针数组不会存储该唯一值?

问题出在这里。
string_array[x] 中的相同唯一值地址(string[]的地址)成功存储了3次。

只是在第一个for()块的每次迭代之后,该地址变为无效。

英文:

>Why doesn't passing an address to a pointer array store that unique value?

Question is amiss.
The same unique value address (of string[]) was stored successfully 3 times in string_array[x].

Is simply that after each iteration of the first for() block, that address was invalid.

答案3

得分: 0

我稍微修改了你的代码。使用 strcpy 来将一个字符串传递给另一个。请注意,由于 char string[50],你可以读取的最大字符串大小为50。

#include <stdio.h>
#include <string.h>

int main() {

    char string_array[10][50];
    char string[50];

    for (int x = 0; x < 2; x++)
    {
        printf("输入水果名称 %d\n", x);
        fgets(string, 50, stdin);
        strcpy(string_array[x], string);
    }

    for (int x = 0; x < 2; x++)
    {
        printf("%s\n", string_array[x]);
    }
    return 0;
}
英文:

I slightly modified your code. Use strcpy to pass a string to another. Note that 50 is the maximum string size you can read because of char string[50].

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int main() {

    char string_array[10][50];
    char string[50];

    for (int x = 0; x &lt; 2; x++)
    {
        printf(&quot;Input Name of Fruit number %d\n&quot;, x);
        fgets(string, 50, stdin);
        strcpy(string_array[x], string);
    }

    for (int x = 0; x &lt; 2; x++)
    {
        printf(&quot;%s\n&quot;, string_array[x]);
    }
    return 0;
}

huangapple
  • 本文由 发表于 2023年2月19日 19:25:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75499786.html
匿名

发表评论

匿名网友

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

确定