2
#include<stdio.h>

int main(void) {

    int t;
    long long n = 4294967295;
    //printf("%lu",n);
    return 0;
}

Whenever I run the above code, the compiler shows the following warning

[Warning] this decimal constant is unsigned only in ISO C90

What's wrong in my code?

Dimitar
  • 4,402
  • 4
  • 31
  • 47
Muniyasamy V
  • 81
  • 1
  • 4
  • 9
  • Is the warning coming with `print` commented out? Because the mention of a constant has nothing to do with the variable passed to `printf`. – Weather Vane Jan 10 '17 at 00:35
  • It may be that the rules were different in C90. I Standard C (C11), decimal literals without `u` suffix are always of a signed type, whereas hex and octal literals alternate between signed and unsigned types. (Perhaps this once used to be the behaviour for decimal literals, too?) – Kerrek SB Jan 10 '17 at 00:38
  • `4294967295` is an `unsigned int` and some old compilers might object, you could try `4294967295ll`. – Weather Vane Jan 10 '17 at 00:38
  • check [this](http://stackoverflow.com/questions/2347936/cant-get-rid-of-this-decimal-constant-is-unsigned-only-in-iso-c90-warning) and [this](http://stackoverflow.com/questions/9941261/warning-this-decimal-constant-is-unsigned-only-in-iso-c90) – Anty Jan 10 '17 at 00:39
  • @WeatherVane: Not in standard C. – Kerrek SB Jan 10 '17 at 00:39
  • What version of C was used to compile: C90, C99, C11 or what? – chux - Reinstate Monica Jan 10 '17 at 01:52
  • @WeatherVane: Only non-decimal constants are converted to unsigned if that fits. Decimals are indeed always signed by default. – too honest for this site Jan 10 '17 at 02:44
  • @chux: Most likely either C99 or C11, according to the warning. – too honest for this site Jan 10 '17 at 02:45
  • @Olaf in C89 (likely C90 too) unsuffixed decimal constants can be `unsigned long`. – chux - Reinstate Monica Jan 10 '17 at 02:46
  • @chux: Yes, but then the warning would be pointless, wouldn't it? – too honest for this site Jan 10 '17 at 02:47
  • Note: the `printf` has a wrong conversion type specifier. For `long long` it should be `%lld`. Otherwise you invoke undefined behaviour. – too honest for this site Jan 10 '17 at 02:48
  • @olaf yes it would, hence OP's question and the peculiar warning. IAC, the question of compiler venison still remains for OP. – chux - Reinstate Monica Jan 10 '17 at 02:49
  • 1
    @chux I wonder about the message. As I see everything is fine, looks like an invalid warning to me. We should know the warning settings used. A correct warning would be if the `LL` constant was assigned to a smaller type, but here everything is fine (as long as `printf` is commented out). – too honest for this site Jan 10 '17 at 02:52
  • 2
    @olaf Agree. What we are missing is what compiler, its version and settings are unknown. – chux - Reinstate Monica Jan 10 '17 at 02:59
  • @chux I have seen this message in the past from gcc. The warning is correct information but spurious (the code is correct). It could be useful in other cases, e.g. `unsigned int y = (4294967295 + 1)/2;` changed value from C90 to C99 (for system with 32-bit int) – M.M Jan 10 '17 at 03:58
  • @Olaf with MSVC `sizeof 4294967295` is 4 therefore is considered as `unsigned int` and not `long long`. More non-compliance? – Weather Vane Jan 10 '17 at 08:10
  • @WeatherVane: I'm not surprised. FYI: http://port70.net/~nsz/c/c11/n1570.html#6.4.4.1p5 – too honest for this site Jan 10 '17 at 12:12
  • @M.M: I don't think it is correct to warn about the constant. It would be correct (and will be for `-Wconversion`) to emit a warning for the assignment to a smaller type, though. But here we have `long long` assigned to `long long`. Looks like a bug in the compiler. gcc 4.8.4 with `-Wall -Wextra -Wpedantic -Wconversion` (there might be redundancies) does not warn for C11, but warns for C90 about `long long` not existing in C90. – too honest for this site Jan 10 '17 at 12:18
  • @WeatherVane MSVC (approximately) complied to C90, they never made any effort to implement C99 or C11. I heard they might have started on that recently but I haven't been following – M.M Jan 10 '17 at 22:48
  • @M.M fortunately for MS they don't need to bother implementing variable length arrays, which are now optional! MSVC 2015 approximates to C99, I think, but no VLAs. – Weather Vane Jan 10 '17 at 22:55

2 Answers2

2

In ISO C the behaviour of 4294967295 changed between C90 and C99.

In C90, on normal systems this is an unsigned value, unsigned int (on 32-bit system) or unsigned long (on 16-bit system). However in C99 this is a signed long long on those systems.

You could disable this warning, or use an integer suffix to show that you understand the issue, e.g. 4294967295LL.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • Wouldn't the obvious advice be to use `4294967295U` to get an unsigned type? The width is never a problem, since it adjusts automatically as needed. The signedness is the beef of the matter. – Kerrek SB Jan 10 '17 at 01:20
  • 2
    @KerrekSB There are multiple ways... the intent is to set a value for a `long long`, so it seems natural to use the corresponding suffix. Disabling the warning is actually my preferred solution (and instead, warn on out-of-range conversion) – M.M Jan 10 '17 at 01:23
  • Oh, I see, the use case is to initialize a long long. Hm, it's a silly warning. It shouldn't show up in pedantic standards mode I'd hope. (Out of range isn't a warning, but ill-formed, I think.) – Kerrek SB Jan 10 '17 at 01:30
  • @KerrekSB out-of-range literals are ill-formed; I meant that code like OP's which is correct should get no warning, but for example `int x = 4294967295;` , which is implementation-defined, should get a warning, rendering it unnecessary for the literal to have its own warning – M.M Jan 10 '17 at 01:32
  • Note: Re; "out-of-range literals are ill-formed": Literally, `4294967295` is not a literal in C, but an integer constant. Code can take the address of a literal, but not `&4294967295`. – chux - Reinstate Monica Jan 10 '17 at 01:36
  • @chux I think "literal" is a better word for the thing we're talking about :P You're right that the C Standard calls them "constants" though (despite the fact that they do not have `const`-qualified type) – M.M Jan 10 '17 at 01:38
  • 1
    `const` does not make an object a constant in C. C does not have symbolic constants like C++. – too honest for this site Jan 10 '17 at 02:50
0

For long long int, you need %lld format specifier:

long long n = 4294967295;
printf("%lld", n);

Using wrong format specifier %lu for long long int type causes undefined behaviour.

artm
  • 17,291
  • 6
  • 38
  • 54