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

C语言:调用void函数后字符串指针变量值丢失的问题

问题:void版本星期字符串函数无法正确传递结果的原因

问题场景

你需要实现一个void dayWeekStr(DatePtr date, char *buffer)函数,将日期对应的星期字符串存入传入的buffer中。你最初的实现是在函数内通过switch给buffer赋值字符串常量,main函数中传入未初始化的字符指针strDay,但运行后main里无法获取到正确的星期字符串——函数内部打印buffer是对的,但回到main后strDay为空。而改成返回char*的版本却能正常运行。

有问题的void版函数代码

void dayWeekStr(DatePtr date,char *buffer)
{
    switch (dayWeek(date))
    {
        case 0:
            buffer="Sunday";
            break;
        case 1:
            buffer="Monday";
            break;
        case 2:
            buffer="Tuesday";
            break;
        case 3:
            buffer="Wednesday";
            break;
        case 4:
            buffer="Thursday";
            break;
        case 5:
            buffer="Friday";
            break;
        case 6:
            buffer="Saturday";
            break;
        default:
            printf("ERROR\n");
            break;
    }
}

对应的main函数代码片段

char *strDay;
dayWeekStr(date1,strDay);
printf("Date: %s, %s\n",strDay,s);

核心原因

这是C语言值传递机制导致的:

  1. 当你把strDay传入dayWeekStr时,传递的是strDay这个指针变量的副本——函数里的buffer是一个新的指针变量,只是和strDay指向同一个地址(但这里strDay未初始化,本身就是野指针,指向随机内存)。
  2. 你在函数里执行buffer="Sunday",只是把buffer这个副本的指向改成了字符串常量"Sunday"的地址,但main里的strDay根本没被修改,它还是原来的野指针状态,所以打印时输出为空甚至可能崩溃。
  3. 而返回char*的版本能正常运行,是因为函数返回了字符串常量的地址,main里的strDay直接接收了这个地址,自然能访问到正确的字符串。

另外,main里的char *strDay;是未初始化的野指针,本身就存在内存访问风险,这也是问题的一个诱因。

正确的void版本实现

要让void版本的函数正确传递结果,有两种常见方案:

方案1:调用者提供足够大的缓冲区,用字符串复制

让main函数提前分配好足够容纳最长星期字符串的缓冲区(比如数组),函数内部用strcpy把字符串复制到缓冲区里:

#include <string.h> // 必须包含string.h头文件以使用strcpy

void dayWeekStr(DatePtr date, char *buffer)
{
    // 用数组存储星期字符串,比switch更简洁
    const char *weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
    int day_num = dayWeek(date);
    
    if (day_num >= 0 && day_num <= 6) {
        strcpy(buffer, weekdays[day_num]);
    } else {
        strcpy(buffer, "ERROR");
    }
}

对应的main函数修改:

// 定义足够大的字符数组作为缓冲区,避免野指针问题
char strDay[20]; 
dayWeekStr(date1, strDay);
printf("Date: %s, %s\n", strDay, s);

方案2:函数内部分配内存,传递指针的指针

如果需要动态分配内存,需要传递指针的指针(char **buffer),这样函数才能修改main里指针变量的指向:

#include <string.h>
#include <stdlib.h> // 包含malloc所需的头文件

void dayWeekStr(DatePtr date, char **buffer)
{
    const char *weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
    int day_num = dayWeek(date);
    
    if (day_num >= 0 && day_num <= 6) {
        // 分配足够存储字符串的内存(+1是为了存结束符'\0')
        *buffer = malloc(strlen(weekdays[day_num]) + 1);
        strcpy(*buffer, weekdays[day_num]);
    } else {
        *buffer = malloc(6); // "ERROR"加结束符共6个字符
        strcpy(*buffer, "ERROR");
    }
}

对应的main函数修改:

char *strDay = NULL;
dayWeekStr(date1, &strDay);
printf("Date: %s, %s\n", strDay, s);
// 使用完毕后必须释放内存,避免内存泄漏
free(strDay);
strDay = NULL;

内容的提问来源于stack exchange,提问作者Frank S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 07:01:26