C语言中字符串sizeof输出异常:为何长度不符合预期
问题解答:scanf写入数组后sizeof结果不符合预期
问题重现
代码
#include <stdio.h> int main(){ char word[]=""; scanf("%s",word); printf("%s: %d\n", word, sizeof(word)); }
输入
Hello
输出
Hello: 1
问题原因
- 数组大小由编译期确定:
char word[] = "";会让编译器创建一个大小为1的字符数组,仅用来存储字符串结束符'\0'。sizeof是编译期运算符,它的值完全由编译时的数组定义决定,和运行时数组内实际存储的内容无关,所以不管你往里面写入多少字符,sizeof(word)永远返回1。 - 缓冲区溢出属于未定义行为:用
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
相关产品推荐
相关产品推荐

