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

发布于 2024-09-11 23:05:52 字数 917 浏览 3 评论 0 原文

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

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

这是我问题的第一部分。

现在 if 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 在这种情况下意味着什么?

感谢您抽出时间。

When we talk about dereference, is it necessary that * should be used in it? If we access the referent of the pointer in some other way, can it be considered as dereferencing a pointer or not, like:

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

That is the first part of my question.

Now if printf( "%s" , ptr ) is an example of dereferencing then kindly answer the following part of my question too.

K&R says

a "pointer to void" is used to hold
any type of pointer but cannot be
dereferenced itself

Hence,

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

Does not compile, complier gives error

In function ‘main’: warning:
dereferencing ‘void *’ pointer error:
invalid use of void expression

But if we use

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

It compiles and works. Which means void pointer can be dereferenced - we have got the object pointer is referring to.
If that's the case then what does K&R above mentioned quote means in this context?

Thanks for your time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

万劫不复 2024-09-18 23:05:52

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

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

相当于:

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

并且同样未定义。

No. what you have is "undefined behaviour" - the C language standard does not say what should happen. In your case, it "works", but for another user/compiler/platform it might not. Your statement:

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

is equivalent to:

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

and is equally undefined.

‘画卷フ 2024-09-18 23:05:52

在给出的示例中:

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

发生了什么,在第一个 printf 中,值“c”是通过取消引用 char 指针传入的,printf 只知道您给了它一个 < code>char 因为 %c 格式标记。

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

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

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

另一个不好的例子:

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

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

In the example given:

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

What is happening, in the first printf, the value 'c' is passed in from dereferencing the char pointer, printf only knows you gave it a char because of the %c format tag.

Now, a void* is just a raw pointer that has an unknown type, you can't dereference it because the compiler does not know what type to read from it unless you cast it to something else.

In the second printf, the void* pointer is passed in. printf just sees it as a plain number, and has no idea what it is until it reads the formatting tag given. By using %s, you are telling the printf function that you actually passed in a char*, so it casts it accordingly and reads it properly as a string, i.e. it dereferences a char* pointer--not a void* pointer.

It's valid code, as long as the void* pointer points to a null-terminated char array. If the void* pointer is pointing to something different, the printf function will still happily try to read it as a char* pointer (if you specify %s) and cause undefined behavior.

A different bad example:

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

You can't dereference an integer either, but I told printf that it's a char*, so it works.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文