7

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.

Andrew-Dufresne
  • 5,464
  • 7
  • 46
  • 68

2 Answers2

9

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.

  • I got your point. Thanks. What about the first part of question? Is `printf( "%s" , ptr )` also considered as dereferencing of a pointer? – Andrew-Dufresne Jul 28 '10 at 10:59
  • 1
    @andrew printf() will certainly have to dereference the pointer to do what it does for the "%s" formatter. OTOH, if you used the "%p" formatter on the same pointer, no deference is needed. –  Jul 28 '10 at 11:01
  • I don't know how the standard defines `printf` or if I'm missing something, but it is conceivable that the `void*` is casted to a `char*`, as `printf` can infer that it is a string by the `%s`. Then again, the problem could be a vararg problem. I don't feel like digging into it. – Thomas Eding Oct 25 '11 at 01:02
  • @ThomasEding: (Yes, I'm replying several years late.) There is no *cast* (which is an explicit operator that specifies a conversion). The language guarantees that `void*` and `char*` have the same representation. It doesn't guarantee that they're passed the same way to variadic functions, but it's very very likely that they are. The behavior is undefined. `printf` *assumes* that the argument is of type `char*`; since it isn't, the caller has lied to it, and its behavior is undefined.. – Keith Thompson Sep 02 '14 at 22:34
0

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.

mukunda
  • 2,908
  • 15
  • 21