Why can't I convert 'char**' to a 'const char* const*' in C?
The following code snippet (correctly) gives a warning in C and an error in C++ (using gcc & g++ respectively, tested with versions 3.4.5 and 4.2.1; MSVC does not seem to care):
char **a;
const char** b = a;
I can understand and accept this.
The C++ solution to this problem is to change b to be a const char * const *, which disallows reassignment of the pointers and prevents you from circumventing const-correctness (C++ FAQ).
char **a;
const char* const* b = a;
However, in pure C, the corrected version (using const char * const *) still gives a warning, and I don't understand why. Is there a way to get around this without using a cast?
To clarify:
1) Why does this generate a warning in C? It should be entirely const-safe, and the C++ compiler seems to recognize it as such.
2) What is the correct way to go about accepting this char** as a parameter while saying (and having the compiler enforce) that I will not be modifying the characters it points to? For example, if I wanted to write a function:
void f(const char* const* in) {
// Only reads the data from in, does not write to it
}
And I wanted to invoke it on a char**, what would be the correct type for the parameter?
Edit: Thank you to those who have responded, particularly those who addressed the question and/or followed up on my responses.
I've accepted the answer that what I want to do cannot be done without a cast, regardless of whether or not it should be possible.
I had this same problem a few years ago and it irked me to no end.
The rules in C are more simply stated (ie they don't list exceptions like converting char**
to const char*const*
). Consequenlty, it's just not allowed. With the C++ standard, they included more rules to allow cases like this.
In the end, it's just a problem in the C standard. I hope the next standard (or technical report) will address this.
> However, in pure C, this still gives a warning, and I don't understand why
You've already identified the problem -- this code is not const-correct. "Const correct" means that, except for const_cast and C-style casts removing const, you can never modify a const object through those const pointers or references.
The value of const-correctness -- const is there, in large part, to detect programmer errors. If you declare something as const, you're stating that you don't think it should be modified -- or at least, those with access to the const version only should not be able to modifying it. Consider:
void foo(const int*);
As declared, foo doesn't have permission to modify the integer pointed to by its argument.
If you're not sure why the code you posted isn't const-correct, consider the following code, only slightly different from HappyDude's code:
char *y;
char **a = &y; // a points to y
const char **b = a; // now b also points to y
// const protection has been violated, because:
const char x = 42; // x must never be modified
*b = &x; // the type of *b is const char *, so set it
// with &x which is const char* ..
// .. so y is set to &x... oops;
*y = 43; // y == &x... so attempting to modify const
// variable. oops! undefined behavior!
cout << x << endl;
Non-const types can only convert to const types in particular ways to prevent any circumvention of 'const' on a data-type without an explicit cast.
Objects initially declared const are particularly special -- the compiler can assume they never change. However, if 'b' can be assigned the value of 'a' without a cast, then you could inadvertantly attempt to modify a const variable. This would not only break the check you asked the compiler to make, to disallow you from changing that variables value -- it would also allow you break the compiler optimizations!
On some compilers, this will print '42', on some '43', and others, the program will crash.
Edit-add:
HappyDude: Your comment is spot on. Either the C langauge, or the C compiler you're using, treats const char * const * fundamentally differently than the C++ language treats it. Perhaps consider silencing the compiler warning for this source line only.
Edit-delete: removed typo
To be considered compatible, the source pointer should be const in the immediately anterior indirection level. So, this will give you the warning in GCC:
char **a;
const char* const* b = a;
But this won't:
const char **a;
const char* const* b = a;
Alternatively, you can cast it:
char **a;
const char* const* b = (const char **)a;
You would need the same cast to invoke the function f() as you mentioned. As far as I know, there's no way to make an implicit conversion in this case (except in C++).
链接地址: http://www.djcxy.com/p/28354.html上一篇: 投射void指针