20

I have following array, that I need to operate by hand on bitmaps.

const unsigned int BITS[32] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 
                               2048, 4096, 8192, 16384, 32768, 65536, 131072, 
                               262144, 524288, 1048576, 2097152, 4194304, 
                               8388608, 16777216, 33554432, 67108864, 134217728, 
                               268435456, 536870912, 1073741824, 2147483648};

Unfortunately, when compiled I get

warning: this decimal constant is unsigned only in ISO C90

How can I remove this?

5
  • See this similar question : stackoverflow.com/questions/2347936/… Commented Feb 28, 2010 at 23:33
  • Why are you doing this? If you think a lookup table is going to be faster than simply computing these values as needed, think again... Commented Aug 17, 2011 at 5:08
  • @Nemo I am working on a chess engine where looking up attacks for a piece is much faster than calculating, what are you trying to say? Commented Oct 1, 2020 at 14:55
  • @AryanParekh: This particular lookup table can be replaced by a single left-shift instruction, so it's dumb. Obviously a sufficiently complex function will take longer to compute than to look up in a table. (Although since CPUs improve faster than memory does, every year more things are faster to compute than to look up.) Commented Oct 1, 2020 at 15:14
  • @Nemo No sorry I am wrong, I didn't see the pattern in the values in the question earlier😂. But for sure the engine I am working on needs 8 shits max and an intersection for each shift for 1 piece. And when there are 2 pieces a lookup table can save time Commented Oct 1, 2020 at 16:33

3 Answers 3

24

Integer literals in C are, by default, of type "signed int" (edit: but see comments for caveats). The last number there is too large to be represented as a signed 32-bit integer, and so you need to tell the compiler that it's an unsigned integer by suffixing it with "U", as:

2147483648U

Note that you can also add a suffix of "L" to make it a "long", but on many systems that's still 32-bit and thus irrelevant.

Also, there's a much less error-prone (and easier-to-read) way to write this code, with the bit-shift operator:

const unsigned int BITS[32] = {1U, 1U<<1, 1U<<2, 1U<<3, 1U<<4,
                               /* and so on */
                               1U<<31};

Or, writing in hexadecimal, if you don't like bit shifts for some reason:

const unsigned int BITS[32] = {0x1, 0x2, 0x4, 0x8, 0x10, 0x20,
                               /* and so on */
                               0x80000000U};
Sign up to request clarification or add additional context in comments.

7 Comments

Why compiler treats it then as an int, rather then automatically turn it into uint? Especially, that it exactly knows in what type it will be stored.
In a lot of cases you can't know what type a constant is (for instance, as a function argument in a varargs function) so it has to be specified explicitly. It's confusing to have the type be implied some times and need to be specified explicitly in others, and also confusing to have the same constant be different types on systems with different int sizes. Also, because C never does type inference of that sort, adding it for this one case would complicate the parser quite a lot without significant benefit.
@gruszczy: In C89/90 an unsuffixed decimal constant must be interpreted as int, long or unsigned long (whichever fits first). In C99 it must be interpreted as int, long or long long (whichever fits first). This what the compiler is trying to say by this warning. Apparently, on this platform long has the same size as int. The compiler is basically saying: "maybe you were trying to create a signed long connstant or maybe even a long long constant, but by the C89/90 rules I have to make it unsigned long.
OK, thanks. And by the way: version with operators is indeed better. I didn't know, I could do that outside of a function, in an array initializer. Thanks a lot.
In fact, the situation is quite a bit complicated. It's not as easy as "it's always signed int": There are differences between all of C90, C99 and C++ and there are different treatment of hex/oct and decimal literals. It's all causing a big headache.
|
7

Your constant has to be specified as unsigned too, use

2147483648UL

(UL = Unsigned Long), or simply

2147483648U

for an unsigned int.

As your code is right now, a constant, which is by default a plain int, and hence signed, is assigned to an unsigned int, which generates your warning.

2 Comments

Pedandically speaking, the error isn't that from the fact the (plain int) constant is assigned to an unsigned int; the assignment is irrelevant. The error is because the value of "2147483648" is too large to be a signed int, and so there's an overflow in generating the signed int constant in the first place.
Actually, the real reason for the warning is that the compiler has to choose unsigned long for the constant type. (Note, again, this constant is not unsigned int, it is unsigned long.) And it has to choose it in C89/90 specifically, instead of choosing a larger signed type (which it might support) or following C99 rules and choosing long long. This is what the warning is about and why it refers to ISO C90. In C99, for example, an unsuffixed decimal constant would never be given an unsigned type.
1

Not necessary to define data type as unsigned just type;

int variable_name=2147483648U;

else just convert decimal value to hex...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.