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

为何C语言中两种char*指针读取字符串的方法一可行一失效?

问题根源:两个方法都存在未定义行为,只是“运气”不同

首先得明确:你的两个方法本质上都是错误的,方法1能“符合预期运行”纯粹是巧合,不是代码正确。核心问题出在你声明的char *str;是一个未初始化的野指针——它没有指向任何合法的、可写的内存区域。

为什么会出现这种诡异的差异?

不管是方法1还是方法2,你直接通过str+len往指针指向的地址写数据,都是在操作随机的非法内存:

  • 方法1“正常”:只是刚好这个野指针指向的地址,在当前运行环境下是暂时可写的,而且后续的printf没有破坏这块内存,所以看起来输出正常。但换个编译器、换个操作系统,或者稍微修改一下代码,它立刻就会崩溃或者输出乱码。
  • 方法2“无法运行”:这次野指针指向的内存不可写,或者readString函数执行完后,栈上的相关数据被覆盖了,导致printf找不到有效字符串。
  • 加int useless=-1;后又能运行:这改变了栈的布局,让未初始化的str刚好落在了一块暂时空闲的栈内存区域,又是一次随机的巧合,完全不代表问题被解决了。

正确的写法应该怎么做?

你需要给指针分配合法的内存空间,有两种常用方式:

方式1:使用固定大小的字符数组

#include <stdio.h>
int readString(char *str, char delimiter, int maxLen) {
    int len = 0;
    // 限制读取的字符数,防止缓冲区溢出
    while (len < maxLen - 1 && scanf("%c", &str[len]) == 1 && str[len] != delimiter) {
        len++;
    }
    // 处理分隔符(如果需要保留的话)
    if (str[len] == delimiter) {
        len++;
    }
    // 确保字符串以'\0'结尾
    str[len] = '\0';
    return len;
}
int main() {
    // 分配足够大的栈内存数组,比如100字节
    char str[100];
    int len = readString(str, '.', sizeof(str));
    printf("%s", str);
    return 0;
}

方式2:动态分配内存

如果需要不确定大小的字符串,可以用malloc动态分配(记得用完后释放):

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

#define INIT_SIZE 32

int readString(char **str, char delimiter) {
    int len = 0;
    int capacity = INIT_SIZE;
    // 初始化动态内存
    *str = malloc(capacity * sizeof(char));
    if (*str == NULL) {
        perror("malloc failed");
        return -1;
    }
    char c;
    while (scanf("%c", &c) == 1 && c != delimiter) {
        // 如果内存不够,扩容
        if (len >= capacity - 1) {
            capacity *= 2;
            char *temp = realloc(*str, capacity * sizeof(char));
            if (temp == NULL) {
                perror("realloc failed");
                free(*str);
                return -1;
            }
            *str = temp;
        }
        (*str)[len++] = c;
    }
    // 处理分隔符(如果需要保留的话)
    if (c == delimiter) {
        (*str)[len++] = c;
    }
    (*str)[len] = '\0';
    return len;
}

int main() {
    char *str = NULL;
    int len = readString(&str, '.');
    if (len != -1) {
        printf("%s", str);
        free(str); // 记得释放动态内存
    }
    return 0;
}

额外提醒

  • 直接使用scanf("%c")时要注意输入缓冲区的换行符,可能需要先用getchar()清空。
  • 永远不要使用未初始化的指针进行写操作,这是C语言中最常见的bug来源之一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:37:59