分段引用char数组时出错
#include int main(void) { char * p= "strings are good"; printf("%s",*p); return 0; }
有人可以告诉我为什么我在这里得到分段错误?
有人可以告诉我为什么我在这里得到分段错误?
C11:7.21.6格式化输入/输出function:
如果转换规范无效,则行为未定义.282)如果任何参数不是相应转换规范的正确类型,则行为未定义。
3.4.3
1使用不可移植或错误的程序结构或错误数据时, 未定义的行为行为,本国际标准不对此作出任何规定。
2 注意可能的未定义行为包括完全忽略不可预测的结果,在转换或程序执行期间以环境特征(有或没有发出诊断消息)的文档方式行为,终止翻译或执行(与发出诊断信息)。
*p
是char
类型。 %s
期望char *
类型的参数。 这将调用未定义的行为 。 在这种情况下,一切都可能发生 有时您可能会得到预期的结果,有时则不会。 这也可能导致程序崩溃或分段错误(这种情况就是这种情况)。
对于%s
,您需要传递sting / literal的起始地址。
更改
printf("%s",*p);
至
printf("%s",p);
这是问题所在:
printf("%s",*p);
printf
将解析const char *
格式字符串,在您的情况下: "%s"
,并推断除格式之外的第一个参数也将是char *
。
现在,因为你取消引用指针,你传递一个char( char
,没有*
)
现在,如果将char的大小与char 指针的大小进行比较:
printf("%d vs %d\n", sizeof(p), sizeof(*p));
你会看到一个char指针是4(或64位的8)乘以char的大小。
考虑一下你实际上在做什么,强制printf
将char的值强制转换为指针,然后使用该指针读取字符串:
const char *p = "foobar"; printf("%p\nWhereas you wanted: %p\n", (void *) *p, (void *) p);
输出:
0x66 //not a valid pointer, too small Whereas you wanted: 0x80485c8 //<-- actual address may vary
解决方案:
printf("%s\n", p);
不要取消引用指针,只是按原样传递它。
只是一个小技巧:学会喜欢存储类修饰符const
。 在这种情况下,这是一个有用的提醒:
char *p; //some code p = "a string"; //more code, or passing p to a function that attempts to do: p[0] = 'A';//ERROR!!
鉴于:
const char *p;//I can SEE p points to a constant p = "a string"; p[0] = 'A';//error, the declaration of p tells me why
const
是一个视觉提示,无论你要用p
做什么,你都应该记住它指向一个常数 ,并且无法编辑该值。
您在printf格式的输出中将单个字符串作为字符串类型(%s)传递。 将其更改为p