char*与int*数组初始化差异及相关代码疑问解析
C语言指针与printf相关疑问解答
先确认你的理解
你对char *d = "sadwad"的描述有部分准确,但需要修正细节:字符串字面量"sadwad"会被编译器处理成以'\0'结尾的连续char数组,char *d是指向这个数组首元素(也就是字符's')的指针。注意这里的字符是连续存储在内存块里的,不是“链式指向”——链式是链表那种分散节点的结构,而字符串字面量是连续的内存区域,靠最后的'\0'标记结束。
问题1:为什么printf用d而非*d,不会打印首字符的地址?
这完全是printf格式控制符的规则决定的:
- 当你用
%s作为格式符时,要求对应的参数必须是指向char类型的指针。printf会从这个指针指向的地址开始,逐个输出字符,直到碰到'\0'才停止。 - 如果想打印指针
d本身的地址,得用%p格式符,比如写printf("%p", d);,这时候才会输出指针存储的地址值。 - 要是你想打印首字符,那才需要用
*d配合%c格式符,比如printf("%c", *d);,这样会输出's'。
问题2:第二段代码崩溃的原因
你觉得两段代码逻辑一致是误解,二者本质完全不同:
- 字符串字面量的特殊性:
"sadwad"是C语言合法的表达式,编译器会在程序的只读数据段为它分配一块内存,存储成带'\0'的char数组,所以char *d = "sadwad"是让指针指向一个合法的、可访问的内存地址,完全没问题。 - 第二段代码的致命错误:
int *d = {32,454,652,12};这种写法是非法的。{32,...}是数组初始化器,不能直接赋值给指针。编译器会把初始化器里的第一个值32当成指针的地址,也就是让d指向内存地址0x20(十进制32)——这是一个系统保留的、用户程序无权访问的无效地址。- 当你执行
d[0]时,相当于*(d + 0),也就是试图访问0x20这个地址的内存,直接触发内存访问违规,导致程序崩溃。
- 额外提一句:两段代码里重复定义了变量
d,这本身就是编译错误,不过你遇到的崩溃是运行时问题,核心原因还是指针被赋值了无效地址。
内容的提问来源于stack exchange,提问作者Abdalrahman Maher
相关产品推荐
相关产品推荐

