当我们谈论取消引用时,是否有必要使用*
?如果我们以其他方式访问指针的指示对象,可以将其视为取消引用指针,如:
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上面提到的报价在这种情况下意味着什么?
感谢您的时间。
答案 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
,所以它可以正常工作。