-1

I am testing gcc version 8.2

gcc seems to be treating long long int as int. Is there any way to fix this?

Here is the code:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <float.h>

int main(int argc, char** argv) {

    printf("INT_MAX     :   %d\n", INT_MAX);
    printf("INT_MIN     :   %d\n", INT_MIN);
    printf("LONG_MAX    :   %ld\n", (long) LONG_MAX);
    printf("LONG_MIN    :   %ld\n", (long) LONG_MIN);
    printf("UINT_MAX    :   %u\n", (unsigned int) UINT_MAX);
    printf("ULLONG_MAX   :   %lu\n", (unsigned long long int) ULLONG_MAX);
    printf("Big Integer   :   %lu\n", (unsigned long long int) 1234567890123456);

    printf("%d\n", sizeof(long long int));
    return 0;
}

output:

INT_MAX     :   2147483647
INT_MIN     :   -2147483648
LONG_MAX    :   2147483647
LONG_MIN    :   -2147483648
UINT_MAX    :   4294967295
ULLONG_MAX   :   4294967295
Big Integer   :   1015724736
8

C:\prog_c\c_pro>gcc --version gcc (MinGW.org GCC-8.2.0-5) 8.2.0 Copyright (C) 2018 Free Software Foundation, Inc...

dbush
  • 205,898
  • 23
  • 218
  • 273
user813801
  • 521
  • 2
  • 6
  • 23

2 Answers2

2

printf needs to know the difference between long and long long, and that's with the %lld (signed) or %llu (unsigned):

    printf("ULLONG_MAX  :   %llu\n", (unsigned long long int) ULLONG_MAX);
    printf("Big Integer :   %llu\n", (unsigned long long int) 1234567890123456);

This should work as you expect. Otherwise, printf is grabbing only part of the bits from the stack, giving the bad answers you were getting.

Furthermore, if you'd turn on compiler warnings it would have told you this:

long.c: In function ‘main’:
long.c:13:5: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘long long unsigned int’ [-Wformat=]
     printf("ULLONG_MAX  :   %lu\n", (unsigned long long int) ULLONG_MAX);
     ^
long.c:14:5: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘long long unsigned int’ [-Wformat=]
     printf("Big Integer :   %lu\n", (unsigned long long int) 1234567890123456);
     ^
long.c:16:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]

It's a really, really good idea to always turn on the warnings - with GCC I normally use -W -Wall - so it tells me what I'm getting wrong.

Compiler warnings are like SO but without the downvotes :-)

Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
  • used -W -Wall and now says "unknown conversion type character 'l' in format" after doing your fix of printf("ULLONG_MAX : %llu\n", (unsigned long long) ULLONG_MAX); – user813801 Dec 18 '19 at 21:27
  • Hmm, that's odd, because `%llu` should be correct. Are you sure it's pointing to that line? – Steve Friedl Dec 18 '19 at 21:29
  • c_pro2.c:15:32: warning: unknown conversion type character 'l' in format [-Wformat=] printf("ULLONG_MAX : %llu\n", (unsigned long long) ULLONG_MAX); – user813801 Dec 18 '19 at 21:31
  • Maybe this is relevant? https://stackoverflow.com/questions/23718110/error-unknown-conversion-type-character-l-in-format-scanning-long-long – Steve Friedl Dec 18 '19 at 21:38
  • this works https://stackoverflow.com/a/55586/813801 – user813801 Dec 20 '19 at 06:31
1

You're using the wrong format specifier to print.

An unsigned long long int requires the use of the %llu format specifier. You're using %lu instead, which is for unsigned long int. Mismatching the format specifier to the type invokes undefined behavior.

What's probably happening in this case is that the first 4 bytes of the unsigned long long value are being read as an unsigned long.

Print like this:

printf("ULLONG_MAX   :   %llu\n", (unsigned long long int) ULLONG_MAX);
printf("Big Integer   :   %llu\n", (unsigned long long int) 1234567890123456);

And you should see the expected results.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
dbush
  • 205,898
  • 23
  • 218
  • 273