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

C语言中字符串sizeof输出异常:为何长度不符合预期

问题解答:scanf写入数组后sizeof结果不符合预期

问题重现

代码

#include <stdio.h>

int main(){
    char word[]="";
    scanf("%s",word);

    printf("%s: %d\n", word, sizeof(word));
}

输入

Hello

输出

Hello: 1

问题原因

  1. 数组大小由编译期确定:char word[] = "";会让编译器创建一个大小为1的字符数组,仅用来存储字符串结束符'\0'。sizeof是编译期运算符,它的值完全由编译时的数组定义决定,和运行时数组内实际存储的内容无关,所以不管你往里面写入多少字符,sizeof(word)永远返回1。
  2. 缓冲区溢出属于未定义行为:用scanf("%s", word)往大小为1的数组里写入包含结束符共6个字符的"Hello",已经超出数组的内存范围,属于缓冲区溢出。这种行为是C标准定义的未定义行为——虽然程序看起来能打印出"Hello",但实际上已经非法修改了数组之外的内存,可能导致程序崩溃、数据篡改甚至安全问题。

解决方案(满足无静态大小、不引入字符串头文件要求)

利用GCC编译器的扩展特性%ms,让scanf自动为输入字符串分配足够内存,再手动遍历计算实际占用大小(包含结束符):

#include <stdio.h>

int main(){
    char *word = NULL;
    // %ms 让scanf自动分配内存存储输入,地址存入word指针
    scanf("%ms", &word);
    
    if (word != NULL) {
        // 手动遍历计算字符串长度(含结束符)
        int actual_size = 0;
        while (word[actual_size] != '\0') {
            actual_size++;
        }
        actual_size++; // 加上结束符'\0'的大小
        
        printf("%s: %d\n", word, actual_size);
        
        // 释放scanf分配的内存,使用GCC内置函数避免引入stdlib.h
        __builtin_free(word);
    }
    return 0;
}

说明

  • %ms是GCC的扩展格式符,你的环境为GCC 13.2.0,完全支持该特性。
  • 手动遍历计算长度无需引入<string.h>的strlen函数,符合要求。
  • 必须释放内存避免泄漏,使用__builtin_free可无需引入<stdlib.h>。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 06:26:09