Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

uint32_t is not the same as long unsigned int ?

46 views
Skip to first unread message

wolfgang bauer

unread,
Jan 3, 2020, 10:50:38 PM1/3/20
to
Hi

A Question about Datatypes:


uint32_t x;

printf("%lu\n", x);

That results in this warning:

warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type
'uint32_t {aka unsigned int}'


So the compiler states: uint32_t is unsigned int.
I thought, uint16_t is unsigned int.


I thought, "int" is 16 Bit. And so "long int" should be 32 Bit.

Am i wrong with that ?

If it is important for the answer: I'm working here with Linux 64-Bit, CodeLite / gcc.



James Kuyper

unread,
Jan 3, 2020, 11:19:05 PM1/3/20
to
On 1/3/20 10:50 PM, wolfgang bauer wrote:
> Hi
>
> A Question about Datatypes:
>
>
> uint32_t x;
>
> printf("%lu\n", x);
>
> That results in this warning:
>
> warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type
> 'uint32_t {aka unsigned int}'
>
>
> So the compiler states: uint32_t is unsigned int.
> I thought, uint16_t is unsigned int.
>
>
> I thought, "int" is 16 Bit. And so "long int" should be 32 Bit.
>
> Am i wrong with that ?

Yes. char, signed char, and unsigned char must have at least 8 bits.
short, unsigned short, int, and unsigned int must have at least 16 bits.
long and unsigned long must have at least 32 bits.
long long and unsigned long long must have at least 64 bits.
However, any of those types can have more than the minimum number of
bits. The exact sized typedefs from <cstdint> are optional, but if
supported, must have exactly the specified number of bits - so you
should not make assumptions about which standard types they are typedefs
for.
The actual requirements are in terms of the required range of values
that each standard integer type must be able to represent, and are
incorporated by reference from the C standard. I've converted those
ranges into bit counts to better match your question.

> If it is important for the answer: I'm working here with Linux 64-Bit, CodeLite / gcc.

One a 64-bit machine, long is often a 64-bit type, with int being a 32
bit type.

wolfgang bauer

unread,
Jan 3, 2020, 11:36:26 PM1/3/20
to
04.01.20 , 05:18 , James Kuyper:

>> uint32_t x;

>> printf("%lu\n", x);

>> I thought, "int" is 16 Bit. And so "long int" should be 32 Bit.
>>
>> Am i wrong with that ?
>
> Yes. char, signed char, and unsigned char must have at least 8 bits.
> short, unsigned short, int, and unsigned int must have at least 16 bits.
> long and unsigned long must have at least 32 bits.
> long long and unsigned long long must have at least 64 bits.


>> If it is important for the answer: I'm working here with Linux 64-Bit, CodeLite / gcc.
>
> One a 64-bit machine, long is often a 64-bit type, with int being a 32
> bit type.

If I remove the "l" from "lu" in the print-function, no warning appear.

This fits to your explanation.

And so printf("sizeof int %d\n", sizeof(int)) has 4 as result. So on a 32-Bit machine it would be 2.

Thank you for this helpful answer.



Robert Wessel

unread,
Jan 4, 2020, 1:19:19 AM1/4/20
to
On Sat, 4 Jan 2020 05:36:17 +0100, wolfgang bauer <sch...@gmx.de>
wrote:
On most 32-bit implementations, sizeof(int) is 4. sizeof(int) being 2
was common on 16-bit implementations.

Barry Schwarz

unread,
Jan 4, 2020, 1:29:31 AM1/4/20
to
On Sat, 4 Jan 2020 05:36:17 +0100, wolfgang bauer <sch...@gmx.de>
wrote:

Firstly, sizeof evaluates to a size_t which need not be int. Printing
it with %d is not portable, could lead to undefined behavior, and some
compilers will diagnose this. Either use %zu which is designed for
size_t or cast the value to a type that matches your format, in this
case int.

Secondly, on a 32-bit machine, sizeof(int) will almost always be 4. It
may be 2 on a 16-bit machine. It really depends on what the compiler
writer decided to do.

If your code depends on an int having a particular size, test for it
and abort if you don't get the value you want. Alternately, you could
use the exact size typedef for what you need. If the typedef is not
available, your code will not compile, identifying the problem
immediately. If it does compile, you know you are using the size you
want.

--
Remove del for email

Keith Thompson

unread,
Jan 4, 2020, 2:56:58 AM1/4/20
to
James Kuyper <james...@alumni.caltech.edu> writes:
[...]
> The actual requirements are in terms of the required range of values
> that each standard integer type must be able to represent, and are
> incorporated by reference from the C standard. I've converted those
> ranges into bit counts to better match your question.

A quibble: the required ranges of values for the standard integer types
are copied from the C standard, but are not incorporated by reference.

> One a 64-bit machine, long is often a 64-bit type, with int being a 32
> bit type.

True, but Microsoft's compiler has 32-bit long even on 64-bit machines.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
[Note updated email address]
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Jorgen Grahn

unread,
Jan 4, 2020, 3:37:51 AM1/4/20
to
On Sat, 2020-01-04, wolfgang bauer wrote:
> Hi
>
> A Question about Datatypes:
>
>
> uint32_t x;
>
> printf("%lu\n", x);
>
> That results in this warning:
>
> warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type
> 'uint32_t {aka unsigned int}'

Others have already explained the larger picture, but concretely:

If you insist on combining std::printf and the fixed-width integer
types, you need to use the PRI... macros from <cinttypes>,
particularly:

#define PRIu32 "u"

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Keith Thompson

unread,
Jan 4, 2020, 5:16:38 AM1/4/20
to
Jorgen Grahn <grahn...@snipabacken.se> writes:
> On Sat, 2020-01-04, wolfgang bauer wrote:
>> A Question about Datatypes:
>>
>>
>> uint32_t x;
>>
>> printf("%lu\n", x);
>>
>> That results in this warning:
>>
>> warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type
>> 'uint32_t {aka unsigned int}'
>
> Others have already explained the larger picture, but concretely:
>
> If you insist on combining std::printf and the fixed-width integer
> types, you need to use the PRI... macros from <cinttypes>,
> particularly:
>
> #define PRIu32 "u"

*OR* you can convert to a type that you know is wide enough and that
printf handles directly:

uint32_t x;
std::printf("x = %lu\n", (unsigned long)x);

Or, of course:

std::cout << "x = " << x << "\n";

wolfgang bauer

unread,
Jan 4, 2020, 9:15:16 AM1/4/20
to


Till now I was not aware of some details.

Thank you all, for shedding some light onto it.




James Kuyper

unread,
Jan 4, 2020, 9:48:44 AM1/4/20
to
On 1/4/20 2:56 AM, Keith Thompson wrote:
> James Kuyper <james...@alumni.caltech.edu> writes:
> [...]
>> The actual requirements are in terms of the required range of values
>> that each standard integer type must be able to represent, and are
>> incorporated by reference from the C standard. I've converted those
>> ranges into bit counts to better match your question.
>
> A quibble: the required ranges of values for the standard integer types
> are copied from the C standard, but are not incorporated by reference.

In my copy of n4567.pdf, 18.3.3 says:

"1 Table 31 describes the header <climits>.
2 The contents are the same as the Standard C library header <limits.h>"

18.3.3p2 is precisely the kind of wording that "incorporated by
reference" means to me. What does it mean to you?

The "description" in table 31 is the only place that the C++ standard
that all of the *_MIN and *_MAX macros are referred to. The meanings of
those macros and the maximum and minimum (respectively) permitted values
for those macros which are only given in the C standard. If you read
only the C++ standard, you might not even realize that it imposes any
limits on the sizes of integer types, however indirectly.

Keith Thompson

unread,
Jan 4, 2020, 5:48:51 PM1/4/20
to
You're right. N4567 3.9.1 [basic.fundamental] paragraph 3 says:

The signed and unsigned integer types shall satisfy the constraints
given in the C standard, section 5.2.4.2.1.

My earlier post was based on N4842, which is a working draft for C++20
(and happens to be the document that I had open at the time). In that
draft, 6.8.1 [basic.fundamental] paragraph 3 includes a table showing
the minimum widths of the 5 signed integer types:

Type Minimum width N
signed char 8
short 16
int 16
long 32
long long 64

The widths are sufficient to specify the ranges, since unlike the
current edition of the C++ standard, N4842 mandates 2's-complement
for signed integers, including the extra negative value:

The range of representable values for a signed integer type is
−2**(N−1) to 2**(N−1) − 1 (inclusive), where N is called the *width*
of the type.
...
An unsigned integer type has the same object representation,
value representation, and alignment requirements (6.7.6) as
the corresponding signed integer type. For each value x of a
signed integer type, the value of the corresponding unsigned
integer type congruent to x modulo 2**N has the same value of
corresponding bits in its value representation.

(expressions tweaked to avoid superscripts).

Of course N4842 is not a standard, and I should have checked the current
edition.

James Kuyper

unread,
Jan 4, 2020, 9:40:02 PM1/4/20
to
It hadn't occurred to me that this might be something they were planning
to change. I wonder if they're planning to change any other features
from "incorporate by reference" to "copy wording with modifications"?

Keith Thompson

unread,
Jan 4, 2020, 10:43:17 PM1/4/20
to
James Kuyper <james...@alumni.caltech.edu> writes:
> On 1/4/20 5:48 PM, Keith Thompson wrote:
[...]
>> You're right. N4567 3.9.1 [basic.fundamental] paragraph 3 says:
>>
>> The signed and unsigned integer types shall satisfy the constraints
>> given in the C standard, section 5.2.4.2.1.
>>
>> My earlier post was based on N4842, which is a working draft for C++20
>> (and happens to be the document that I had open at the time). In that
>> draft, 6.8.1 [basic.fundamental] paragraph 3 includes a table showing
>> the minimum widths of the 5 signed integer types:
>>
>> Type Minimum width N
>> signed char 8
>> short 16
>> int 16
>> long 32
>> long long 64
>>
>> The widths are sufficient to specify the ranges, since unlike the
>> current edition of the C++ standard, N4842 mandates 2's-complement
>> for signed integers, including the extra negative value:
[snip]
> It hadn't occurred to me that this might be something they were planning
> to change. I wonder if they're planning to change any other features
> from "incorporate by reference" to "copy wording with modifications"?

I don't know. In this particular case the C++ requirements are
diverging from the C requirements.

Alf P. Steinbach

unread,
Jan 5, 2020, 12:09:33 AM1/5/20
to
We're ruled by "they".

- Alf

James Kuyper

unread,
Jan 5, 2020, 8:51:01 PM1/5/20
to
"They" are the ISO C++ committee.
0 new messages