开发者

Why printf( "%s" , ptr ) is able to dereference a void*?

开发者 https://www.devze.com 2023-01-09 18:18 出处:网络
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:

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 followi开发者_开发百科ng 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.


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消