qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] block: Explicitly specify 'unsigned long long'


From: Laszlo Ersek
Subject: Re: [Qemu-devel] [PATCH] block: Explicitly specify 'unsigned long long' for VHDX 64-bit constants
Date: Fri, 14 Mar 2014 17:17:20 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.3.0

On 03/14/14 16:36, Richard W.M. Jones wrote:
> On Fri, Mar 14, 2014 at 06:50:37AM -0400, Jeff Cody wrote:
>> On 32-bit hosts, some compilers will warn on too large integer constants
>> for constants that are 64-bit in length.  Explicitly put a 'ULL' suffix
>> on those defines.
>> -#define VHDX_FILE_SIGNATURE 0x656C696678646876  /* "vhdxfile" in ASCII */
>> +#define VHDX_FILE_SIGNATURE 0x656C696678646876ULL  /* "vhdxfile" in ASCII */
> 
> I think it's better to use this C99-defined feature (from <stdint.h>):
> 
> #define VHDX_FILE_SIGNATURE UINT64_C(0x656C696678646876)

Here's some pointing to the standard(s)...

"Unsigned long long" is a gnu-ism for C89. It's a standard part of C99.
Last time I checked, qemu used the gnu89 dialect on all build hosts
except SunOS.

So, when you use an integer constant like 0x656C696678646876, that
constant is undefined in C89. Namely,
- 6.1.3.2 "integer constants" (in C89) describes the "ladder" only up to
"unsigned long int" (unsuffixed hexadecimal),
- ULONG_MAX need not be higher than (2^32-1) (5.2.4.2.1 "sizes of
integral types <limits.h>"), which in fact happens to be the case in an
-m32 build,
- 6.1.3.2 "integer constants" (in C89) doesn't say anything about
"extended integer types" (C99 does mention those),
- in gnu89 dialect, gcc decides not to pick "long long unsigned" on its
own for this constant (IOW gcc doesn't elect to "fill in" this undefined
behavior for you even in gnu89 dialect).

So, in gnu89 you really have no other choice than saying "long long
unsigned" yourself (in this instance with the ULL suffix).

In C99 this is not an issue, because the ladder goes up to "long long
unsigned" (see 6.4.4.1 Integer constants), and that type must be able to
represent (2^64-1) minimally (5.2.4.2.1 Sizes of integer types <limits.h>).

The "problem" with the proposed UINT64_C() is that it's C99 only. If we
used C99 rather than gnu89, there would be no need for using UINT64_C(),
the constant would simply work.

(UINT64_C() might be part of gnu89 too, but then the ULL suffix, which
is also gnu89, is just shorter.)

In one sentence, the 0x656C696678646876 constant falls in the

  gnu89 \ c89

relative complement set for -m32, and gcc simply opts against
automatically picking the "unsigned long long" type (which otherwise
belongs to the same relative complement set of language features too),
and leaves the behavior undefined.

(That's my thinking at least.)

Laszlo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]