C语言字符串无需内存分配?mmc-utils中print_str实现疑问
解答:C语言字符串字面量的内存机制
我在处理mmc-utils的do_erase函数时看到如下代码:
int do_erase(int nargs, char **argv) { int dev_fd, ret; char *print_str; __u8 ext_csd[512], checkup_mask = 0; __u32 arg, start, end; ... if (strcmp(argv[1], "legacy") == 0) { arg = 0x00000000; print_str = "Legacy Erase"; } else if (strcmp(argv[1], "discard") == 0) { arg = 0x00000003; print_str = "Discard"; } else if (strcmp(argv[1], "secure-erase") == 0) { print_str = "Secure Erase"; checkup_mask = EXT_CSD_SEC_ER_EN; } ... if ((checkup_mask & ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]) != checkup_mask) { fprintf(stderr, "%s is not supported in %s\n", print_str, argv[4]); ret = -ENOTSUP; goto out; } out: printf(" %s %s!\n\n", print_str, ret ? "Failed" : "Succeed"); close(dev_fd); return ret; }
我无法理解该函数未对print_str进行栈或堆内存分配却能正常工作的原因。虽然栈上有字符串指针,但C语言在运行时不存在自动栈分配的“魔法”吧?该代码编译运行均无问题,想请教原理,同时确认:C语言中使用字符串是否真的无需内存分配?
核心原理:字符串字面量的存储机制
C语言中,像"Legacy Erase"、"Discard"这类用双引号包裹的字符串字面量,在编译阶段就会被编译器处理:
- 它们会被存储到程序的**只读数据段(.rodata)**中,这个区域属于程序可执行文件的一部分,程序启动后会被加载到内存里,生命周期和整个程序一致。
- 代码中
print_str = "Legacy Erase";这行,并不是把字符串内容复制到栈或堆上,而是把只读数据段中该字符串的起始地址赋值给栈上的指针变量print_str。
关于内存分配的澄清
C语言中使用字符串并非都不需要内存分配,分两种情况:
- 字符串字面量:如代码中的用法,编译时已分配在只读段,运行时只需用指针指向它即可,不需要手动调用
malloc或在栈上开辟数组。 - 动态生成/可变字符串:比如需要接收用户输入、拼接字符串、修改内容的场景,就必须手动分配内存——要么用栈上的字符数组(如
char buf[256];),要么用malloc/calloc在堆上分配空间。
代码合法性说明
这段代码完全合法,因为print_str始终指向只读数据段中有效的字符串地址,这些字符串在程序运行期间一直存在,不会出现野指针或内存非法访问的问题。后续用printf、fprintf输出时,本质是通过指针访问只读段里的字符串内容,自然能正常工作。
内容的提问来源于stack exchange,提问作者led
相关产品推荐
相关产品推荐

