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

时间:2010-07-28 10:50:03

标签: c pointers dereference

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

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

这是我提问的第一部分。

现在,如果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 );

不编译,编译器给出错误

  

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

但是如果我们使用

char *a = "c" ;
char *p = a ;
void *k = a;
printf( "\n%c\n" , *p );
printf( "\n%s\n" , k );

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

感谢您的时间。

2 个答案:

答案 0 :(得分:9)

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

printf( "\n%s\n" , k );

相当于:

int k = 42;
printf( "\n%s\n" , k );

并且同样未定义。

答案 1 :(得分:0)

在给出的例子中:

char *a = "c";
char *p = a;
void *k = a;
printf( "\n%c\n" , *p );
printf( "\n%s\n" , k );

正在发生的事情,在第一个printf中,值'c'从解除引用char指针传入,printf只知道你给了它char因为{ {1}}格式标记。

现在,%c只是一个具有未知类型的原始指针,您无法取消引用它,因为编译器不知道要从中读取什么类型,除非您将其转换为其他类型。

在第二个printf中,void*指针被传入。void*只是将其视为普通数字,并且在读取给定的格式化标记之前不知道它是什么。通过使用printf,您告诉printf函数您实际传递了%s,因此它会相应地转换它并将其作为字符串正确读取,即它取消引用char*指针 - - 不是char*指针。

只要void*指针指向以null结尾的void*数组,它就是有效的代码。如果char指针指向不同的东西,void*函数仍然会愉快地尝试将其作为printf指针读取(如果指定char*)并导致未定义的行为

另一个不好的例子:

%s

您也不能取消引用整数,但我告诉char *a = "ce"; int b = (int)a; printf( "\n%s\n" , b ); 它是printf,所以它可以正常工作。