[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Silly _Generic trick: const_cast(T, exp

Joel C. Salomon

5/20/2011 5:50:00 PM

Untested, but I think this should work:

#ifdef __cplusplus
#define const_cast(T, exp) const_cast<T>(exp)
#else
#define const_cast(T, exp) _Generic((exp), const T : (T)(exp))
#endif

void foo(void) {
const int i = 42;

// &i is compatible with `const int *` = `int const *`
int *pi = const_cast(int *, &i);

// pi is compatible with `const int const *` = `int const *`
int const *pci = const_cast(int const *, pi);

// fails: types incompatible
double *pd = const_cast(double *, &i);
} /* d--n google groups*/

Disgusting, no? ;)

(Even if this works, it won't be too hard to make it break. Typedef'd pointers will do it: `const vptr` = `void * const` != `void const *`.)

I've got another yucky hack brewing: a reinterpret_cast that casts everything *except* qualifiers.

--Joel
8 Answers

China Blue Veins

5/20/2011 6:04:00 PM

0

> I've got another yucky hack brewing: a reinterpret_cast that casts everything
> *except* qualifiers.

enum {MSBfirst=0, PDP11=2, LSBfirst=3};
#define nativebyteorder \
(((union{char b[4]; uint32_t n;}) \
{.b={MSBfirst, 1,PDP11, LSBfirst}}).n & 0xFF)
#define nativeMSBfirst (nativebyteorder==MSBfirst)
#define nativeLSBfirst (nativebyteorder==LSBfirst)
#define nativePDP11 (nativebyteorder==PDP11)

--
I remember finding out about you, | Accept no substitutions.
Everyday my mind is all around you, | I'm whoever you want me to be.
Looking out from my lonely room | Annoying Usenet one post at a time.
Day after day. | At least I can stay in character.

jt

5/20/2011 10:48:00 PM

0

Joel C. Salomon <joelcsalomon@gmail.com> wrote:
> Untested, but I think this should work:

> #ifdef __cplusplus
> #define const_cast(T, exp) const_cast<T>(exp)
> #else
> #define const_cast(T, exp) _Generic((exp), const T : (T)(exp))
> #endif

What's '_Generic' meant to do? Without knowing that there's no
way to figure out what this is meant to do (or what you expect
it to do).

> I've got another yucky hack brewing: a reinterpret_cast that casts
> everything *except* qualifiers.

I 'm not yet convinced that dragging C++ stuff into C will
work (or will be beneficial). A bit more of context of what
you intent to get from that might be useful...

Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://t...

Ben Pfaff

5/20/2011 10:55:00 PM

0

"Joel C. Salomon" <joelcsalomon@gmail.com> writes:

> Untested, but I think this should work:
>
> #ifdef __cplusplus
> #define const_cast(T, exp) const_cast<T>(exp)
> #else
> #define const_cast(T, exp) _Generic((exp), const T : (T)(exp))
> #endif

I use:

/* Expands to a void expression that checks that POINTER is an
expression whose type is a qualified or unqualified version of
a type compatible with TYPE (a pointer type) and, if not,
causes a compiler warning to be issued (on typical compilers).

Examples:

int *ip;
const int *cip;
const int **cipp;
int ***ippp;
double *dp;

// None of these causes a warning:
CHECK_POINTER_HAS_TYPE (ip, int *);
CHECK_POINTER_HAS_TYPE (ip, const int *);
CHECK_POINTER_HAS_TYPE (cip, int *);
CHECK_POINTER_HAS_TYPE (cip, const int *);
CHECK_POINTER_HAS_TYPE (dp, double *);
CHECK_POINTER_HAS_TYPE (dp, const double *);
CHECK_POINTER_HAS_TYPE (cipp, const int **);
CHECK_POINTER_HAS_TYPE (cipp, const int *const *);
CHECK_POINTER_HAS_TYPE (ippp, int ***);
CHECK_POINTER_HAS_TYPE (ippp, int **const *);

// None of these causes a warning either, although it is unusual to
// const-qualify a pointer like this (it's like declaring a "const int",
// for example).
CHECK_POINTER_HAS_TYPE (ip, int *const);
CHECK_POINTER_HAS_TYPE (ip, const int *const);
CHECK_POINTER_HAS_TYPE (cip, int *const);
CHECK_POINTER_HAS_TYPE (cip, const int *const);
CHECK_POINTER_HAS_TYPE (cipp, const int **const);
CHECK_POINTER_HAS_TYPE (cipp, const int *const *const);
CHECK_POINTER_HAS_TYPE (ippp, int ***const);
CHECK_POINTER_HAS_TYPE (ippp, int **const *const);

// Provokes a warning because "int" is not compatible with "double":
CHECK_POINTER_HAS_TYPE (dp, int *);

// Provoke warnings because C's type compatibility rules only allow
// adding a "const" qualifier to the outermost pointer:
CHECK_POINTER_HAS_TYPE (ippp, const int ***);
CHECK_POINTER_HAS_TYPE (ippp, int *const**);
*/
#define CHECK_POINTER_HAS_TYPE(POINTER, TYPE) \
((void) sizeof ((TYPE) (POINTER) == (POINTER)))

/* Given expressions A and B, both of which have pointer type,
expands to a void expression that causes a compiler warning if
A and B are not pointers to qualified or unqualified versions
of compatible types.

Examples similar to those given for CHECK_POINTER_HAS_TYPE,
above, can easily be devised. */
#define CHECK_POINTER_COMPATIBILITY(A, B) ((void) sizeof ((A) == (B)))

/* Equivalent to casting POINTER to TYPE, but also issues a
warning if the cast changes anything other than an outermost
"const" or "volatile" qualifier. */
#define CONST_CAST(TYPE, POINTER) \
(CHECK_POINTER_HAS_TYPE (POINTER, TYPE), \
(TYPE) (POINTER))

--
Ben Pfaff
http://be...

Joel C. Salomon

5/20/2011 11:29:00 PM

0

On 05/20/2011 06:48 PM, Jens Thoms Toerring wrote:
> Joel C. Salomon <joelcsalomon@gmail.com> wrote:
>> Untested, but I think this should work:
>
>> #ifdef __cplusplus
>> #define const_cast(T, exp) const_cast<T>(exp)
>> #else
>> #define const_cast(T, exp) _Generic((exp), const T : (T)(exp))
>> #endif
>
> What's '_Generic' meant to do? Without knowing that there's no
> way to figure out what this is meant to do (or what you expect
> it to do).

If `exp` is type-compatible with `const T` -- i.e., `exp` is itself of
type `T` or `const T` -- then cast it to type T. Otherwise the (C1x)
compiler will complain of incompatible types.

As the `#ifdef __cplusplus` documents, this is *intended* to be a
work-alike clone of C++'s `const_cast<>`.

>> I've got another yucky hack brewing: a reinterpret_cast that casts
>> everything *except* qualifiers.
>
> I'm not yet convinced that dragging C++ stuff into C will
> work (or will be beneficial). A bit more of context of what
> you intent to get from that might be useful...

Oh, I don't know that it's a *good* idea; I was just opening up the
discussion. Given all the arguments that C++ puts forward for its
`*_cast<>` -- findable with grep, control over exactly what is being
cast away, etc. -- and assuming that C1x gives us the tools to do
something similar, what say we come up with a prototype and discuss it?

--Joel

Ian Collins

5/20/2011 11:54:00 PM

0

On 05/21/11 11:29 AM, Joel C. Salomon wrote:
> On 05/20/2011 06:48 PM, Jens Thoms Toerring wrote:
>> Joel C. Salomon<joelcsalomon@gmail.com> wrote:
>>> Untested, but I think this should work:
>>
>>> #ifdef __cplusplus
>>> #define const_cast(T, exp) const_cast<T>(exp)
>>> #else
>>> #define const_cast(T, exp) _Generic((exp), const T : (T)(exp))
>>> #endif
>>
>> What's '_Generic' meant to do? Without knowing that there's no
>> way to figure out what this is meant to do (or what you expect
>> it to do).
>
> If `exp` is type-compatible with `const T` -- i.e., `exp` is itself of
> type `T` or `const T` -- then cast it to type T. Otherwise the (C1x)
> compiler will complain of incompatible types.

So where do we get hold of a C1x compiler?

--
Ian Collins

Keith Thompson

5/20/2011 11:55:00 PM

0

jt@toerring.de (Jens Thoms Toerring) writes:
> Joel C. Salomon <joelcsalomon@gmail.com> wrote:
>> Untested, but I think this should work:
>
>> #ifdef __cplusplus
>> #define const_cast(T, exp) const_cast<T>(exp)
>> #else
>> #define const_cast(T, exp) _Generic((exp), const T : (T)(exp))
>> #endif
>
> What's '_Generic' meant to do? Without knowing that there's no
> way to figure out what this is meant to do (or what you expect
> it to do).

It's a new feature in the upcoming C201X standard.

See <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n15..., section
6.5.1.1. (I'm not sure whether that's the latest and/or best C201X
draft.)

[...]

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Ian Collins

5/20/2011 11:59:00 PM

0

On 05/21/11 10:48 AM, Jens Thoms Toerring wrote:
> Joel C. Salomon<joelcsalomon@gmail.com> wrote:
>> Untested, but I think this should work:
>
>> #ifdef __cplusplus
>> #define const_cast(T, exp) const_cast<T>(exp)
>> #else
>> #define const_cast(T, exp) _Generic((exp), const T : (T)(exp))
>> #endif
>
> What's '_Generic' meant to do? Without knowing that there's no
> way to figure out what this is meant to do (or what you expect
> it to do).
>
>> I've got another yucky hack brewing: a reinterpret_cast that casts
>> everything *except* qualifiers.
>
> I 'm not yet convinced that dragging C++ stuff into C will
> work (or will be beneficial). A bit more of context of what
> you intent to get from that might be useful...

They would be useful for one of the main reasons they are useful in C++:
you can grep for them! An awful lot of casts in C code are necessary
and they can mask errors. An easy way to spot them is a big help.

--
Ian Collins

Keith Thompson

5/21/2011 12:30:00 AM

0

Ian Collins <ian-news@hotmail.com> writes:
> On 05/21/11 11:29 AM, Joel C. Salomon wrote:
>> On 05/20/2011 06:48 PM, Jens Thoms Toerring wrote:
>>> Joel C. Salomon<joelcsalomon@gmail.com> wrote:
>>>> Untested, but I think this should work:
>>>
>>>> #ifdef __cplusplus
>>>> #define const_cast(T, exp) const_cast<T>(exp)
>>>> #else
>>>> #define const_cast(T, exp) _Generic((exp), const T : (T)(exp))
>>>> #endif
>>>
>>> What's '_Generic' meant to do? Without knowing that there's no
>>> way to figure out what this is meant to do (or what you expect
>>> it to do).
>>
>> If `exp` is type-compatible with `const T` -- i.e., `exp` is itself of
>> type `T` or `const T` -- then cast it to type T. Otherwise the (C1x)
>> compiler will complain of incompatible types.
>
> So where do we get hold of a C1x compiler?

I'm sure they'll become available as quickly as C99 compilers did.

--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.ne...
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"