为什么printf("%s",ptr)能够取消引用空格*?

And*_*sne 7 c pointers dereference

当我们谈论解除引用时,是否有必要*使用它?如果我们以其他方式访问指针的引用对象,可以将其视为取消引用指针,如:

char *ptr = "abc" ;
printf( "%c" , *ptr ); // Here pointer is dereferenced.
printf( "%s" , ptr );  // What about this one?
Run Code Online (Sandbox Code Playgroud)

这是我提问的第一部分.

现在,如果printf( "%s" , ptr )是解除引用的一个例子,那么也请回答我的问题的以下部分.

K&R说

"指向void的指针"用于保存任何类型的指针,但不能自行解除引用

因此,

char a = 'c' ;
char *p = &a ;
void *k = &a;
printf( "\n%c\n" , *p );
printf( "\n%c\n" , *k );
Run Code Online (Sandbox Code Playgroud)

不编译,编译器给出错误

在函数'main'中:警告:解除引用'void*'指针错误:无效使用void表达式

但是,如果我们使用

char *a = "c" ;
char *p = a ;
void *k = a;
printf( "\n%c\n" , *p );
printf( "\n%s\n" , k );
Run Code Online (Sandbox Code Playgroud)

它编译和工作.这意味着可以取消引用void指针 - 我们已经得到了对象指针.
如果是这种情况那么K&R上面提到的报价在这种情况下意味着什么呢?

谢谢你的时间.

小智 9

不,你所拥有的是"未定义的行为" - C语言标准没有说明会发生什么.在你的情况下,它"工作",但对于另一个用户/编译器/平台,它可能不会.你的陈述:

printf( "\n%s\n" , k );
Run Code Online (Sandbox Code Playgroud)

相当于:

int k = 42;
printf( "\n%s\n" , k );
Run Code Online (Sandbox Code Playgroud)

并且同样未定义.