Reputation: 43
In the following:
struct adt { void * A; };
int new_adt(const void * const A)
{
struct adt * r = malloc(sizeof(struct adt));
r->A = A;
}
I get:
warning: assignment discards qualifiers from pointer target type
I know I can use
memcpy(&(r->A), &A, sizeof(void *));
to workaround it, but I must ask: Is there any alternative?
By using const void * const
I pretend to say that no changes will be made to the input. Also, now that I think of it, const void *
would suffice, wouldn't it? (Since I can't change the pointer so that it affects the caller)
Thanks for taking the time to read.
Upvotes: 4
Views: 9993
Reputation: 6586
If you never want to modify A
through its pointer from adt
, then you should make that pointer const as well, i.e.:
struct adt {
const void * A;
};
That will make the error go away.
If you do want to modify A
through adt
, then new_adt
should take a non-const pointer.
Edit: A more general note, which may help:
The const
keyword, in general, applies to the type immediately to its left. However, if there is no type to its left, it will apply to the type to the right. So:
const int * A
is the same as int const * A
(the const
applies to the int
, not to the pointer), but in int * const A
, the const applies to the pointer, not to the int.
There is a more comprehensive explanation on Wikipedia: const-correctness. The 'Pointers and References' section of that page includes an example which covers the various combinations of const and non-const that you can apply to a pointer.
Upvotes: 6
Reputation: 6770
By using const void * const I pretend to say that no changes will be made to the input.
You have not pretended to say that no changes will be made to the input, you have explicitly told the compiler that you have guaranteed that no changes will be made to the input.
You MUST NOT do what you are doing.
Upvotes: 7
Reputation: 9903
You can cast the const away:
r->A = (void *) A;
The issue, though, is less about how to avoid the warning and more about what you're trying to do. The compiler is warning you because you're telling the compiler that "A" is not writable, but you're trying to store it in a location that defines it as writable. That's generally not OK, semantically.
Imagine that "A" points to a location in your binaries data section; trying to write to it, after casting the const away, will most probably cause a segfault.
So, really, think about what you're trying to do more closely before trying to work around the compiler warning. They're warnings for a good reason.
Upvotes: 3