473,467 Members | 1,992 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

making literals be a stdint size

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). 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? 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?

--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------
Nov 13 '05 #1
8 4380
in comp.lang.c i read:
(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). 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?


in addition to kevin's response (use the macros, though they shouldn't be
necessary), which is right on the money, i'll add that since you don't
mention exact width types wider than 64 bits and since long long must be at
least 64 bits a suffix of ULL should also work for an extended-c90
compiler.

--
a signature
Nov 13 '05 #2
On Tue, 26 Aug 2003 04:57:29 +0100 Nick Austin <ni**********@nildram.co.uk> wrote:
| On 25 Aug 2003 22:37:01 GMT, ph**************@ipal.net 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
|
| ITYM,
| 0x5555555555555555ULL
|
| Nick.

And if the cast size happens to be that of a long, not long long, on the
given platform, how does that affect it? And what if a platform has a
uintXX_t type which is larger than long long?

--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------
Nov 13 '05 #3
ph**************@ipal.net writes:
On Tue, 26 Aug 2003 04:57:29 +0100 Nick Austin <ni**********@nildram.co.uk> wrote:
| On 25 Aug 2003 22:37:01 GMT, ph**************@ipal.net 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
|
| ITYM,
| 0x5555555555555555ULL
| ppp
| Nick.

And if the cast size happens to be that of a long, not long long, on the
given platform, how does that affect it?
0x5555555555555555 will fit into an unsigned long long. It will
also fit into a uint64_t. Casts preserve value, so there is no
problem that I see.
And what if a platform has a
uintXX_t type which is larger than long long?


What if it does? I don't understand the problem you see.
--
"I should killfile you where you stand, worthless human." --Kaz
Nov 13 '05 #4
On Tue, 26 Aug 2003 12:27:26 +0100 Kevin Bracey <ke**********@tematic.com> wrote:
| In message <bi********@enews4.newsguy.com>
| ph**************@ipal.net 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.

--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------
Nov 13 '05 #5
On 26 Aug 2003 19:30:16 GMT those who know me have no need of my name <no****************@usa.net> wrote:
| in comp.lang.c i read:
|
|> (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). 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?
|
| in addition to kevin's response (use the macros, though they shouldn't be
| necessary), which is right on the money, i'll add that since you don't
| mention exact width types wider than 64 bits and since long long must be at
| least 64 bits a suffix of ULL should also work for an extended-c90
| compiler.

There are two issues:

1. If ULL is used, but long long is 128 bits on that platform,
the for a value only needing 64 bits, this might cause more
memory to be used to store the constant somewhere and convert
it in runnable code.

2. If long long is 64 bits, but the machine supports 128 bits,
and ther eis a uint128_t (in C99), then how to you express a
constant for that.

GCC 3.3.1 complains that (uint64_t) 0x5555555555555555U is too large for
unsigned long. Sure, I can make it be ULL. But I shouldn't have to.
I think GCC is broken. I just wanted to make sure.

--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------
Nov 13 '05 #6
On 26 Aug 2003 23:12:30 -0700 Ben Pfaff <bl*@cs.stanford.edu> wrote:

| Now I am just confused. Where did a 128-bit type come into the
| picture. Your original question, as I understood it, was "how do
| I write a uint64_t constant". (uint64_t) 0x5555555555555555ULL
| is a way to do that.

The question is how do I write a constant (I used the wrong term
literal before) which is a specific stdint size, WITHOUT specifying
what size that is in terms of long or long long. The reason is so
I can make that constant portable.
| The ULL suffix isn't even necessary. 0x5555555555555555 is a
| valid constant of some integer type by itself; casting it to
| uint64_t will convert it into an uint64_t having the same value.

Then gcc 3.3.1 is broken. I had specified 0x5555555555555555U
with the cast in front of (uint64_t) and it said the value was out
of range for "unsigned long".
|> I want to know the officially/formally correct way to write the
|> constant in full 128 bit glory.
|> An earlier following said 6.4.4.1 of C99 requires a constant be
|> of a type that fits it. That should solve the problem I would
|> think. The catch is that gcc 3.3.1 is broken based on someone
|> I know compiling my library on their machine with gcc 3.3.1.
|
| Here is what 6.4.4.1 of C99 says about this. Maybe it will
| clarify the issue for you.
|
| $ The type of an integer constant is the first of the corresponding
| $ list in which its value can be represented.
| $
| $ Octal or Hexadecimal
| $ Suffix Decimal Constant Constant
| $
| $ none int int
| $ long int unsigned int
| $ long long int long int
| $ unsigned long int
| $ long long int
| $ unsigned long long int

[snip]

| $ If an integer constant cannot be represented by any type in its
| $ list, it may have an extended integer type, if the extended

OK, so this should work:

(uint128_t) 0x55555555555555555555555555555555U

on a platform where uint128_t is implemented, and long long is the same
size as uint64_t.

It was my goal to specify a number in terms of a specific size because it
involved playing with bits. And I not only didn't want to have to make the
code figure out if it was long long, I wante dto handle uintXX_t that was
not even equivalent to any traditional integer type.

A machine might have:
8 bits -> char, int8_t
16 bits -> short, int16_t
32 bits -> int, int32_t
64 bits -> long, int64_t
128 bits -> long long, int128_t
256 bits -> int256_t
I just want to have constants that adapt and GCC appeared broken but I wanted
to double check that first before pointing fingers.

--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------
Nov 13 '05 #7
ph**************@ipal.net writes:
On 26 Aug 2003 23:12:30 -0700 Ben Pfaff <bl*@cs.stanford.edu> wrote:

| The ULL suffix isn't even necessary. 0x5555555555555555 is a
| valid constant of some integer type by itself; casting it to
| uint64_t will convert it into an uint64_t having the same value.

Then gcc 3.3.1 is broken. I had specified 0x5555555555555555U
with the cast in front of (uint64_t) and it said the value was out
of range for "unsigned long".


Have you tried this while invoking GCC 3.3.1 in its "try to be
C99 compliant mode"? (It's a real question; I don't know what it
will do.)
--
"...what folly I commit, I dedicate to you."
--William Shakespeare, _Troilus and Cressida_
Nov 13 '05 #8
On 27 Aug 2003 23:27:04 -0700 Ben Pfaff <bl*@cs.stanford.edu> wrote:
| ph**************@ipal.net writes:
|
|> On 26 Aug 2003 23:12:30 -0700 Ben Pfaff <bl*@cs.stanford.edu> wrote:
|>
|> | The ULL suffix isn't even necessary. 0x5555555555555555 is a
|> | valid constant of some integer type by itself; casting it to
|> | uint64_t will convert it into an uint64_t having the same value.
|>
|> Then gcc 3.3.1 is broken. I had specified 0x5555555555555555U
|> with the cast in front of (uint64_t) and it said the value was out
|> of range for "unsigned long".
|
| Have you tried this while invoking GCC 3.3.1 in its "try to be
| C99 compliant mode"? (It's a real question; I don't know what it
| will do.)

Yes. It works that way. But then I have to make it so that option is not
used with older versions that don't understand it.

What seems to work fine overall is wrapping all the constants in the
INTxx_C() macros.

--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------
Nov 13 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Scott David Daniels | last post by:
I am trying to figure out how to get 2.4a2 to build a python extension. GCC 2.2.95 does not have a stdint.h, but 3.2.3 does. These two are the only gcc versions I have on my box. Does anyone...
6
by: J. Campbell | last post by:
I'm wondering if there are any compelling reasons NOT to use the types defined in stdint.h in c-programms? Please refer to this thread:...
20
by: GS | last post by:
The stdint.h header definition mentions five integer categories, 1) exact width, eg., int32_t 2) at least as wide as, eg., int_least32_t 3) as fast as possible but at least as wide as, eg.,...
6
by: William Ahern | last post by:
So, GCC 4.01 is giving errors that GCC 3.3 did not, and I'm thinking they've gone overboard with their new type checking infrastructure. Here's the supposedly offending code (no laughing or...
4
by: copx | last post by:
I wonder how portable the exact width types defined by stdint.h are. I guess target platforms are not required to actually have all those types, right? What happens in that case?
351
by: CBFalconer | last post by:
We often find hidden, and totally unnecessary, assumptions being made in code. The following leans heavily on one particular example, which happens to be in C. However similar things can (and...
11
by: santosh | last post by:
Hello all, Conversion macros along the name of INT8_C, INT16_C etc, are defined in stdint.h to convert their argument into suitable representations for their corresponding types, i.e. int8_t,...
130
by: euler70 | last post by:
char and unsigned char have specific purposes: char is useful for representing characters of the basic execution character set and unsigned char is useful for representing the values of individual...
7
by: copx | last post by:
Do the standards say anything about size limits for string literals (min size, max size)? I want to know this to make sure that my code is portable. The program in question is ANSI C89, but I would...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.