7

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

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 在这种情况下是什么意思?

谢谢你的时间。

4

2 回答 2

9

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

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

相当于:

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

并且同样未定义。

于 2010-07-28T10:52:54.367 回答
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因为%c格式标记。

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

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

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

一个不同的坏例子:

char *a = "ce";
int b = (int)a;
printf( "\n%s\n" , b );

您也不能取消引用整数,但我告诉printf它是 a char*,所以它可以工作。

于 2014-12-03T04:21:21.117 回答