2

I have started learning C++ from Josh Lospinoso's C++ Crash Course.

I am unable to wrap my mind around 'types'.

What is the difference between long long int a=50 and int a =50LL ? To me, they both look like long long int

I tried to run this:

#include<cstdio>
int main() {
    long long int a=50;
    int b=50LL;
    printf("a is %lld and b is %lld",a,b);
}

and got :

a is 50 and b is 18042367336513586

So there is something wrong with either the format specifier or int b=50LL

On changing the format specifier of b to %d. I get:

a is 50 and b is 50

So does this mean that b is the default 'int' ? If yes, what is the role of LL then?

On surfing about types, I came across this. So I tried running this:

#include <iostream>
#include <typeinfo>

int main(){
    long long int a = 50;
    int b = 50LL;
    std::cout << typeid(a).name() << std::endl;
    std::cout << typeid(b).name() << std::endl;

    return 0;
}

which gave

x
i

So they are indeed of different types (?). But Why?

Wolgwang
  • 133
  • 8
  • 2
    Mismatching `printf` format specifier and argument type leads to *undefined behavior*. The variable `b` is an `int`, you should use a format specifier that matches it. – Some programmer dude Jul 24 '23 at 12:15
  • 1
    No the `int a=50LL;` will still be an `int`. If you can use C++20 consider using std::format (instead of printf), and if you can use C++23 use [std::print](https://en.cppreference.com/w/cpp/io/print) – Pepijn Kramer Jul 24 '23 at 12:15
  • 1
    The problem with first value of `b` is in `printf`. You use format specifier for `long long int ` and load normal `int` in stack. Then function `printf` uses random values following bytes of `int` (50). Probably you have ignored warnings. – i486 Jul 24 '23 at 12:15
  • 3
    `int` is not `long long int`. They are different types. When you do `int b = 50LL;` the **50LL** gets converted from a long long int to an int. – Eljay Jul 24 '23 at 12:15
  • 1
    Instead of using runtime typeid, check your types with a compile time assert and [](https://en.cppreference.com/w/cpp/header/type_traits). E.g. `static_assert(std::is_same_v);` and you will see that `a` is not a `long long` but an `int` too – Pepijn Kramer Jul 24 '23 at 12:18
  • @i486 I didn't get any warning. [Image](https://i.stack.imgur.com/px40I.png) – Wolgwang Jul 24 '23 at 12:19
  • 1
    Printing an `int` (i.e. `b` in your code) using the `%lld` format gives undefined behaviour. – Peter Jul 24 '23 at 12:20
  • @Wolgwang -- You lied to `printf` and told it that `b` is a `long long int` when it actually is an `int`. And since you used `cout`, you could have simply outputted `std::cout << a << " " << b;` and saw they had the same *value*. – PaulMcKenzie Jul 24 '23 at 12:20
  • Don't use `printf`. `std::cout << "a is " << a << " and b is " << b << '\n';` – Pete Becker Jul 24 '23 at 12:21
  • 1
    *I didn't get any warning.* Do you even have warnings turned on? If you don't turn them on, you don't get them. In the olden days, we'd use a **lint** program to find problems, but since then the lint functionality has been rolled into the compiler itself (because we have faster machines and more memory). – Eljay Jul 24 '23 at 12:23
  • @Eljay How to turn that on? (I am a noob, sorry ) – Wolgwang Jul 24 '23 at 12:25
  • 1
    `g++ -Wall -Wextra test.cpp` or `clang++ -Weverything test.cpp` – Eljay Jul 24 '23 at 12:25
  • try `unisgned x = -1;` and `int y = -1;`. `-1` is signed in both cases, but `x`s value will be diffferent. – 463035818_is_not_an_ai Jul 24 '23 at 12:49
  • What an unfortunate choice in naming. Are you sure you want to take a course in making C++ crash? – user4581301 Jul 24 '23 at 17:29
  • @user4581301 Sorry, but how is the choice in naming unfortunate? – Wolgwang Jul 25 '23 at 02:04
  • "C++ Crash Course" Generally you don't want to write programs that crash. – user4581301 Jul 25 '23 at 02:06

2 Answers2

6
long long int a=50;

This declares a long long int variable, and initializes it to 50.

int a =50LL;

This declares an int variable, and initializes it to 50. The constant value 50 is lexically specified as a long long integer constant, which gets converted to an int, for the purpose of initializing a (accomplishing absolutely nothing useful, by itself, whatsover).

So the difference is that you end up with either a long long int or an int variable named a. In both cases they are initialized to 50.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
1

The problem is the call to printf, not the initialization.

%lld is the wrong conversion specification for variable b, which has type int. Use %d instead.

  • %lld means output a value of type long long int in decimal format (rather than hex or octal).
  • %d means output a value of type int in decimal format (rather than hex or octal).

The garbage output is explained by the different sizes of int and long long int.

As you wrote it, printf is going to the address where b is stored, and grabbing 8 bytes, which is (usually) the size of long long int. It should be grabbing only 4 bytes, which is (usually) the size of int.

Here is the correct program:

#include<cstdio>
int main() {
    long long int a = 50LL;
    int b = 50;
    printf("a is %lld and b is %d", a, b);
}

On Microsoft Visual C++, the invalid program actually runs correctly after automatically being fixed by the compiler. Here are the warnings it generated:

1>main.cpp(5,12): warning C4477: 'printf' : format string '%lld' requires an argument of type '__int64', but variadic argument 2 has type 'int'
1>main.cpp(5,12): message : consider using '%d' in the format string
1>main.cpp(5,12): message : consider using '%I32d' in the format string

By the way, the initializer used for b is a poor choice, but perfectly valid. C++ silently performs a narrowing conversion that discards the high-order bits.

int b = 50LL;  // poor form, but legal
int b = 50;    // better form
tbxfreeware
  • 547
  • 1
  • 9