字符串数组初始化规则疑问及首元素未初始化致段故障问题
问题1:为何仅首元素被设为"anything"而非全部?
C语言的数组初始化规则明确:当对数组进行部分初始化时,未被显式指定初始值的元素会被自动执行值初始化——对于指针类型,值初始化的结果是NULL;对于整数类型,值初始化的结果是0。
你之前熟悉的int x[10] = { 0 };能让所有元素变为0,是因为0是int类型的零值,值初始化规则会把其余未指定的元素都填充为该类型的零值。但char *words[10] = { "anything" };中,你只给首元素指定了字符串常量的地址,其余元素会被值初始化为指针的零值NULL,而非自动复制首元素的值。C语言没有语法支持用单个初始值自动填充整个数组,必须显式处理。
问题2:为何未初始化首元素会引发段错误?
你定义的char *words[10];是栈上的局部数组,局部变量如果不进行初始化,其内存中的内容是随机的垃圾值——也就是所谓的「野指针」。当你用printf("%s", words[i])时,%s格式符要求传入一个指向有效字符串的指针,而野指针指向的是非法内存地址(可能是未分配的内存、已释放的内存或者内核空间),访问这类地址会触发操作系统的内存保护机制,直接抛出Segmentation fault错误。
而当你写char *words[10] = { "anything" };时,除首元素外的其余元素被自动初始化为NULL,GCC的printf实现对NULL的%s参数会特殊处理,打印出(null)而非访问非法内存,因此不会崩溃。
实现预期输出的方法
如果你想让数组所有元素都指向"anything",可以通过循环显式赋值:
#include <stdio.h> int main() { char *words[10]; const char *str = "anything"; for (int i = 0; i < 10; i++) { words[i] = str; } for (int i = 0; i < 10; i++) { printf("Word %d: %s\n", i, words[i]); } return 0; }
或者在初始化列表中显式列出所有元素(适合数组长度较小的情况):
char *words[10] = { "anything", "anything", "anything", "anything", "anything", "anything", "anything", "anything", "anything", "anything" };
内容的提问来源于stack exchange,提问作者Salty Sodiums

