You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环输入名字时指针指向同一内存致内容覆盖的C语言问题求解

问题分析与修复方案

你的判断完全正确:问题出在两个指针指向了同一块内存区域。enteredName是循环内部的局部数组,它存储在栈内存中,每次循环迭代时,这块内存的地址会被重复利用。因此first和second最终都指向这块栈内存,最后输入的内容会覆盖之前的,导致打印结果重复。

修复测试程序

要解决这个问题,需要为每个输入的名字分配独立的堆内存,确保每个指针指向不同的内存块。可以通过malloc+strcpy实现,或者用更便捷的strdup(自动分配内存并复制字符串,主流编译器均支持)。

修复后的测试代码(malloc+strcpy版本)

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

int main(void)
{
    char* first = NULL;
    char* second = NULL;

    for (int i = 0; i < 2; i++)
    {
        char enteredName[20];
        printf("Please enter a name: ");
        scanf("%s", enteredName);

        // 为名字分配内存(+1是为了存储字符串结束符'\0')
        char* nameCopy = malloc(strlen(enteredName) + 1);
        if (nameCopy == NULL) {
            perror("malloc failed");
            // 释放已分配的内存避免泄漏
            if (first) free(first);
            exit(EXIT_FAILURE);
        }
        strcpy(nameCopy, enteredName);

        if (i == 0)
        {
            first = nameCopy;
        }
        else
        {
            second = nameCopy;
        }
    }
    printf("First: %s\n", first);
    printf("Second: %s\n", second);

    // 释放堆内存
    free(first);
    free(second);
    return 0;
}

修复后的测试代码(strdup简化版本)

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

int main(void)
{
    char* first = NULL;
    char* second = NULL;

    for (int i = 0; i < 2; i++)
    {
        char enteredName[20];
        printf("Please enter a name: ");
        scanf("%s", enteredName);

        // strdup自动分配内存并复制字符串
        char* nameCopy = strdup(enteredName);
        if (nameCopy == NULL) {
            perror("strdup failed");
            if (first) free(first);
            exit(EXIT_FAILURE);
        }

        if (i == 0)
        {
            first = nameCopy;
        }
        else
        {
            second = nameCopy;
        }
    }
    printf("First: %s\n", first);
    printf("Second: %s\n", second);

    free(first);
    free(second);
    return 0;
}

实现完整程序(输入到"done"停止,支持任意数量名字)

要支持任意数量的名字,需要使用动态扩容的指针数组,因为无法提前预知用户输入的数量。以下是完整实现:

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

#define INITIAL_CAPACITY 4  // 数组初始容量

int main(void)
{
    // 动态指针数组,存储每个名字的堆内存地址
    char** names = malloc(INITIAL_CAPACITY * sizeof(char*));
    if (names == NULL) {
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }

    int nameCount = 0;       // 已输入的名字数量
    int currentCapacity = INITIAL_CAPACITY;
    char enteredName[20];

    printf("Enter names (type 'done' to finish):\n");
    while (1) {
        printf("Name %d: ", nameCount + 1);
        scanf("%s", enteredName);

        // 输入"done"则结束循环
        if (strcmp(enteredName, "done") == 0) {
            break;
        }

        // 数组容量不足时,扩容为原来的2倍
        if (nameCount >= currentCapacity) {
            currentCapacity *= 2;
            char** temp = realloc(names, currentCapacity * sizeof(char*));
            if (temp == NULL) {
                perror("realloc failed");
                // 清理已分配的所有内存,避免泄漏
                for (int i = 0; i < nameCount; i++) {
                    free(names[i]);
                }
                free(names);
                exit(EXIT_FAILURE);
            }
            names = temp;
        }

        // 为当前名字分配独立内存并复制
        char* nameCopy = strdup(enteredName);
        if (nameCopy == NULL) {
            perror("strdup failed");
            // 清理已分配内存
            for (int i = 0; i < nameCount; i++) {
                free(names[i]);
            }
            free(names);
            exit(EXIT_FAILURE);
        }

        names[nameCount++] = nameCopy;
    }

    // 打印所有输入的名字
    printf("\nAll entered names:\n");
    for (int i = 0; i < nameCount; i++) {
        printf("%d. %s\n", i + 1, names[i]);
    }

    // 释放所有堆内存:先释放每个名字的内存,再释放指针数组
    for (int i = 0; i < nameCount; i++) {
        free(names[i]);
    }
    free(names);

    return 0;
}

关键要点说明

  • 动态数组管理:用char**类型的指针数组存储每个名字的地址,初始分配固定容量,容量不足时用realloc扩容(通常翻倍,减少扩容次数)。
  • 独立内存分配:每个名字都通过strdup(或malloc+strcpy)分配独立的堆内存,确保指针不会指向同一块内存。
  • 内存泄漏防护:所有堆内存都要在程序结束前释放;如果内存分配失败,要先清理已分配的内存再退出程序。

内容的提问来源于stack exchange,提问作者Carsdan Dvorachek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:30:20