In the following code, copyThing()
is written so that its return value has the same type as its argument value:
extern void *copyThingImpl(const void *x);
#define copyThing(x) ((typeof(x)) copyThingImpl(x))
void foo(void);
void foo(void)
{
char *x = "foo";
char *y;
y = copyThing(x);
(void) y;
}
This uses the widely available typeof
operator. This works fine and compiles without warnings (e.g., gcc -Wall -O2 -c test.c
).
Now if we change x
to a const
pointer, we will run into light problems:
extern void *copyThingImpl(const void *x);
#define copyThing(x) ((typeof(x)) copyThingImpl(x))
void foo(void);
void foo(void)
{
const char *x = "foo";
char *y;
y = copyThing(x);
(void) y;
}
This causes a warning:
warning: assignment discards 'const' qualifier from pointer target type
which is correct, because (typeof(x))
is (const char *)
, so assignment to non-const
y
will drop the const
.
My understanding is that the typeof_unqual
operator that is new in C23 is supposed to be able to address this case. So I try
extern void *copyThingImpl(const void *x);
#define copyThing(x) ((typeof_unqual(x)) copyThingImpl(x))
void foo(void);
void foo(void)
{
const char *x = "foo";
char *y;
y = copyThing(x);
(void) y;
}
If I compile this with an appropriate C23-enabling option (e.g., gcc -Wall -O2 -std=c2x -c test.c
), I still get the same warning, from various gcc and clang versions.
Am I using this correctly? What is the point of typeof_unqual
if this doesn't work?