| In message <
[email protected]>
| (e-mail address removed) wrote:
|
|> I have some code where I am using certain literal values cast to stdint
|> types like uint32_t, uint64_t, etc. In gcc versions below 3.3 it's working
|> OK.
|>
|> Here's an example:
|>
|> (uint64_t) 0x5555555555555555U
|>
|> In gcc 3.3.1, it doesn't like this, saying that the literal is out of range
|> for "unsigned long" (well, yeah, that would be true).
|
| It should still accept it. If it's too large for "unsigned long" then the
| type is "unsigned long long". This is covered in section 6.4.4.1 of C99.
|
| On reflection, that diagnostic makes it sound as if the compiler is in C90
| mode - check this. You really want to be in C99 mode if you want to use
| long longs in a coherent fashion.
I will double check that with the person who was compiling it. It worked by
default for me on gcc 3.2.2 but it failed for him by default on gcc 3.3.1.
|> What is the proper way to write a literal when you want the type to be of a
|> specific stdint type, as opposed to the generic int types like long and
|> long long?
|
| There are macros in <stdint.h> for this:
|
| UINT64_C(0x5555555555555555)
|
| This actually corresponds to uint_least64_t, although if you have a 64-bit
| type then obviously uint_least64_t == uint64_t.
I'll look into using these.
|> Is there even a way to do it without a bunch of #if's to check sizes and
|> figure out whether to use L or LL appendage to the literal?
|
| You shouldn't normally have to. Just write the constant (maybe with a U
| suffix to force unsigned), and the type will expand automatically to fit
| the constant - it will be int, long or long long. You only need to worry
| about L suffixes (or the _C macros) if you want to force the constant to be a
| larger type than it would otherwise be. For example, on a platform with
| 16-bit int, 32-bit long, 64-bit long long:
|
| 4000 int 4000L long int
| 40000 long int 400000L long int
| 4000000000 long long int 4000000000L long long int
|
| Decimal constants are always signed, unless they have a U suffix. Octal or
| hex constants are normally signed, unless they need to be unsigned to fit
| into a smaller type:
|
| 0x2000 int 0x2000U unsigned int
| 0x4000 int 0x4000U unsigned int
| 0x8000 unsigned int 0x8000U unsigned int
| 0x10000 long 0x10000U unsigned long
| 0x20000 long 0x20000U unsigned long
| 0x80000000 unsigned long 0x80000000U unsigned long
| 0x100000000 long long 0x100000000U unsigned long long
|
| For a C90 compiler with a long long extension, this is more complicated;
| C90's constant type rules do not include long long, so you have to mess
| with suffixes to override the standard C90 behaviour. Don't go there - use
| C99.
|
| In C99 it should be perfectly fine to write
|
| (..._t) 0x........
|
| with no suffix. The constant will automatically assume a suitable type to
| accurately represent the value, and the cast will convert the value to the
| required type. The only scope for failure is if the value doesn't actually
| fit in the specified type.
It fix under gcc 3.2.2 so it should be OK. Thanks for the leads. I'll dig
in and maybe report a bug to the gcc people if it continues to look like it.