0

Trying to print a long in C++ on 32-bit machine. I'm getting an unexpected output.

From this code:

long n = 5330111323L;
printf("n = %ld\n", n);
printf("can print? %s\n", LONG_MAX < 5330111323L ? "yes" : "NO");
printf("LONG_MAX = %ld\n", LONG_MAX);

I'm getting this:

enter image description here

The C# output is fine.

This:

long n = 5330111323L;
    Console.WriteLine(n);

print:

5330111323

Both use 32-bit compilers. Why am I getting this C++ output?

Jack
  • 16,276
  • 55
  • 159
  • 284

5 Answers5

2

There is a mistake in the condition, it should be :

LONG_MAX > 5330111323L ? "yes" : "NO"

n can be (correctly) printed if it is lower than LONG_MAX, because in all cases, n will be lower or equal to LONG_MAX if n has been declared as long.

edit: note you can use >= too

Pierre
  • 1,162
  • 12
  • 29
  • 1
    Wouldn't `>=` actually be better than `>`? – Paulo1205 Dec 29 '15 at 15:39
  • 1
    Also notice that if `n` has been explicitly declared as `long`, it will always, by definition, be `<=LONG_MAX`. – Paulo1205 Dec 29 '15 at 15:41
  • One of the problems with his code is that he makes direct comparisons with integer literal constants, which can get expanded as needed -- and occasionally without warning -- by the compiler. – Paulo1205 Dec 29 '15 at 15:49
  • I didn't understand what you wrote :/ – Pierre Dec 29 '15 at 15:50
  • When you write `LONG_MAX > 5330111323L`, you're not necessarily comparing two `long`s. If `5330111323L` is larger then the maximum possible `long`, the compiler may silently promote it to `long long`, regardless of the ‘L’ suffix that someone might suppose that forces it unto being interpreted as `long`. Forcing a constant unto a type only happens when promoting small integer literals to bigger types. – Paulo1205 Dec 29 '15 at 16:21
  • So, in C++11, for example, `auto a=1;` will make `a` an `int`, but `auto b=1L;` will explicitly make `b` a `long`. OTOH, `auto c=9876543210;`, even without any suffix, will make `c` to have an integer type larger than 32 bits (possibly `long long` on 32-bit systems, and `long` on 64-bit ones). – Paulo1205 Dec 29 '15 at 16:22
1

In C# long is a 64 bit data type. It doesn't matter that you compile on 32 bits it is still 64 bits in size. In C++ All we know about long is that it has to hold as much or more than an int and it is at least 32 bits. If you use a long long in c++ that is guaranteed to be at least 64 bits which will match what you have in C#. Again it is 64 bits even if you compile in 32 bits in C++.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
1

sizeof(long) is not fixed anywhere and there is no even 'customary' size for it, and using this type is actually not recommended (there are checkers which even issue an error every time long is used). In particular, on your system it is clear long is 32 bit in size.

On a side note, size of the long (or any other non-pointer type for this matter) has no relationship to 32 vs 64 bit mode.

On the third note, your check is logically incorrect. You should be printing 'yes' when LONG_MAX is bigger than the number.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • The size of `long` is somewhat fixed, in that it must be at least 32 bits. I don't know by whom it is "not recommended"; it's appropriate whenever you need an integral type that holds at least 32 bits. – Pete Becker Dec 29 '15 at 15:50
  • @PeteBecker, int is a good type which can hold at least 32 bit. What's more important, it usually holds 32 bit exactly, which is helpful. Long has no benefits over int, and just adds confusion (many people, like OP, tend to believe it is *longer* than int). This is why it is not recommended to use it - to avoid unnceccessary confusion. – SergeyA Dec 29 '15 at 16:07
  • 1
    `int` is only required to hold at least 16 bits. – Pete Becker Dec 29 '15 at 16:08
  • @PeteBecker, techincally - yes. Practically I have NEVER seen a compiler with 16bit ints. Even cppreference has it: `However, on 32/64 bit systems it is almost exclusively guaranteed to have width of at least 32 bits (see below).` – SergeyA Dec 29 '15 at 16:17
  • @SergeyA, You're lucky, then. Some of us had, in a distant past, C and C++ compilers for MS-DOS and 16-bit Windows. Some of us even had it for 8-bit CP/M-80. But you don't need a time capsule to get a compiler that have shorter than 32 bits `int`s: think of micro-controllers and embedded processors. – Paulo1205 Dec 29 '15 at 16:51
  • @Paulo1205, fair enough. I can admit I am spoiled by 32bit/64 archs. Still, checkers I mentioned exist. – SergeyA Dec 29 '15 at 16:58
0

In C++, integer literal constants that are to large to fit their original types can be automatically interpreted as a longer type, even if they have the wrong suffix.

#include <iostream>

int main(){
    auto a=9876543210;  // ‘L’ or ‘LL’ suffix missing.
    int  b=a;           // Not even a warning
    int  c=9876543210;  // warning: "implicit constant conversion", even without suffix!
    std::cout << a << '\n' << b << '\n' << c << '\n';
}
Paulo1205
  • 918
  • 4
  • 9
0

What do you think , which is bigger 5330111323(user input) or 2147483647(LONG_MAX)?

You are actually trying to print a value which is outside the long range on your system Which is an invitation to undefined behavior .

BTW , Improve below condition in your program .

printf("can print? %s\n", LONG_MAX > 5330111323L ? "yes" : "NO"); //
SACHIN GOYAL
  • 955
  • 6
  • 19