可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
The following code compiles without warning on GCC but gives a warning in Visual Studio 2005.
const void * x = 0;
char * const * p = x;
x points to a constant object of unknown type, and p points to a constant pointer to char. Why should the assignment to p result in a warning?
Again, this is C, not C++. Thanks.
回答1:
It happens because when you make a pointer of one type point to another type, sometimes it is done unintentionally (bug), so the compiler warns you about it.
So, in order to tell the compiler that you actually intent to do it, you have to do explicit casting, like this:
const void * x = 0;
char * const * p = (char * const * )x;
P.S. At the first place I wrote "most of the times is done unintentionally", but AndreyT made me reconsider it when he rightfully said that void * exists specifically for that purpose.
回答2:
The C code is valid and a conforming compiler shouldn't warn as const
ness is correctly preserved and conversion of void *
to any pointer type (function pointers aside) is implicit.
A C++ compiler is supposed to warn about the implicit conversion, but a warning about discarding the const
qualifier is wrong and should be considered a compiler bug.
回答3:
What if x
would point to, say, a struct Thing
as opposed to a char
? In that case, you'd be doing something with unspecified behavior. GCC tends to let you do this because it assumes that you're smart enough not to shoot yourself in the foot, but there is good reason for the warning.
回答4:
You have to read the following from right to left.
char * const * p = x;
For Example:
P points to a const pointer of type char.
回答5:
const void * x = 0;
char * const * p = x;
At first I assumed you meant to take the address of x and wrote the code for that. Then I decided that x points to a pointer to char []. Both anyway, and it's still quite confusing:
#include <stdio.h>
int main()
{
char s [] = "Hello World!";
const void * x = s;
const char * const * const p = (const char * const *)&x;
printf("%s\n", *p);
/* won't compile
*p++; // increments x to point to 'e'
(**p)++; // increments 'H' to 'I'
*/
const char * y = s;
x = &y;
const char * const * const q = x;
printf("%s\n", *q);
/* won't compile
*q++;
(**q)++;
*/
return 0;
}
The extra const
before the char
in the declaration of p
prevents (**p)++
from compiling. However, the added const
before the declaration of q
(in GCC) shadows warning: dereferencing ‘void *’ pointer
with error: increment of read-only location ‘**q’
for (**q)++
. Hope that helps, it has helped me a little :-)
回答6:
warning C4090: 'initializing' : different 'const' qualifiers
You cannot cast const void
to char *const
or even char *
. By dereferencing p
, you can now modify *(char *)(*x)
. This is a little known subtlety about pointers in C.
A working type for p
would be:
char const **p = x;
And yes, I put const
on the right like a man.