Reputation: 236
Suppose I have some code like this:
void foo (void *ptr) {
const struct some *azaza = (const struct some *)ptr;
azaza->some_field = 123; // inadvertently assignment => error
// ...
Is the const
specifier really needed in cast?
EDIT: foo
is callback function with a particular prototype that I can't change (it's not in my code).
Upvotes: 3
Views: 114
Reputation: 5613
If I understand your question, you want the instance to be protected by const, and you are asking is it sufficient to write:
const struct some *azaza = (struct some *)ptr;
Rather than
const struct some *azaza = (const struct some *)ptr;
I would say that it is, as the const attribute can be automatically applied by the compiler, but it can't be taken away. If this were C++ this would be the minimum sufficient code, but as others have mentioned, in C it is sufficient to write:
const struct some *azaza = ptr;
As C allows a void pointer to be cast to any other pointer type, and then the constness can be inferred. However, I think the C++ mandate makes for clearer readable code.
Note that if you already have a const pointer, you can't assign it to a non-const pointer without "casting away" the const. To match the C++ spec I would tend to put in 2 casts, though C would accept either one on its own:
void foo (const void *ptr) {
struct some *azaza = (struct some *)(void*)ptr;
azaza->some_field = 123; // intentional overwrite!
// ...
Upvotes: 0
Reputation: 1581
if the value pointed by ptr
was declared as const, then what you are trying to do is undefined behaviour. you should not change const values. you can remove const with cast and modify value only if it was not declared with const initially.
int modify(void *ptr) {
some_t *value = ptr;
value->member = 0; // here where UB could happen
}
int main(void)
{
some_t obj0 = {0};
const some_t obj1 = {0};
modify(&obj0); // OK
modify(&obj1); // leads to undefined behaviour
return 0;
}
otherwise, if it's not declared with const, why just not to:
struct some *azaza = ptr;
Upvotes: 0
Reputation: 620
It depends what you are trying to do. Your code snippet is confusing for the following reasons:
The function takes a non-const pointer, which means the function may wish to change the contents pointed-to by 'ptr'.
Then, upon entering the function, you cast 'ptr' to a const pointer. So now the compiler believes that the function has no intention of modifying the contents pointed to by ptr. It is thus normal for an error to occur when the program invokes:
azaza->some_field = 123; // not allowed !
Depending on your intent, you can write the function in one of two forms:
Option #1: The function does not intend to modify what's pointed-to by ptr:
void foo( const void * ptr ) {
const struct some * azaza = (const struct some *) ptr ;
// ... do something other than writing to 'azaza', for example:
printf("Some field: %d\n", azaza->some_field ) ;
}
Option #2: The function does intend to modify what's pointed-to by ptr:
void foo(void * ptr ) {
struct some * azaza = (struct some *) ptr ;
// ... write to 'azaza', for example:
azaza->some_field = 123 ;
}
Upvotes: 0
Reputation: 5055
In your specific case you don't even need a cast. In case of void *
cast is needed only when dereferencing. So it is sufficient to do:
const struct some *azaza = ptr;
But for the sake of interest,
#gcc test.c
:
// 1)
const struct some *azaza = ptr;
azaza->some_field = 123; // error: assignment in read-only object
// 2)
struct some *azaza = (const struct some *)ptr; // (!)warning: initialization discards ‘const’ qualifier
azaza->some_field = 123;
#gcc test.c -pedantic-errors
:
// 1)
const struct some *azaza = ptr;
azaza->some_field = 123; // error: assignment in read-only object
// 2)
struct some *azaza = (const struct some *)ptr; // error: initialization
// discards ‘const’ qualifier
azaza->some_field = 123;
To sum up:
const
in cast.const
only in cast (for some odd reason ._.) and without -pedantic-errors
- an accidently assignment will not result in an error what is fraught with consequences.Upvotes: 6