0

I am learning C from this website. However, when I come up to this tutorial, I seem to be getting strange outcomes. The site recommended to try to make the code without looking at the example first, so I tried entering this code.

#include <stdio.h>
int main()
{
    printf("The \"long\" keyword is pretty useful!\n");

    int a=5;
    long int la=5;
    long long int lla=5;
    double b=5;
    long double lb=5;
    printf("%d (as a normal int) is %d bytes big!\n", a, sizeof(a));
    printf("%d (as a long int) is %d bytes big!\n",la, sizeof(la));
    printf("%d (as a long long int) is %d bytes big!\n",lla, sizeof(lla));
    printf("%lf (as a normal double) is %d bytes big!\n",b, sizeof(b));
    printf("%lf (as a long double) is %d bytes big!\n"),lb, sizeof(lb);
}

and I get this response

The "long" keyword is pretty useful!
5 (as a normal int) is 4 bytes big!
5 (as a long int) is 4 bytes big!
5 (as a long long int) is 0 bytes big!
5.000000 (as a normal double) is 8 bytes big!
5.000000 (as a long double) is 8 bytes big!

It didn't make any sense, so eventually I looked at the example, and saw that it didn't declare any numbers, just the variables. Skipping a mistake I made regarding calling for a variable when there's no set number, I tried doing this instead:

    int a;
    long int la;
    long long int lla;
    double b;
    long double lb;
    printf("A normal int is %d bytes big!\n", sizeof(a));
    printf("A long int is %d bytes big!\n", sizeof(la));
    printf("A long long int is %d bytes big!\n", sizeof(lla));
    printf("A normal double is %d bytes big!\n", sizeof(b));
    printf("A long double is %d bytes big!\n"), sizeof(lb);

to which I get the outcome:

The "long" keyword is pretty useful!
A normal int is 4 bytes big!
A long int is 4 bytes big!
A long long int is 8 bytes big!
A normal double is 8 bytes big!
A long double is 8 bytes big!

Which is almost the intended outcome, except "long int" is 4 bytes big, the same size as a normally declared int, for some unknown reason. Same with "long double".

Eventually, I decided to just copy/paste the example the website gave, to make sure if I'm making a mistake or not, which is this:

    #include <stdio.h>
    int main() {
        int a;
        long b;   // equivalent to long int b;
        long long c;  // equivalent to long long int c;
        double e;
        long double f;
        printf("Size of int = %ld bytes \n", sizeof(a));
        printf("Size of long int = %ld bytes\n", sizeof(b));
        printf("Size of long long int = %ld bytes\n", sizeof(c));
        printf("Size of double = %ld bytes\n", sizeof(e));
        printf("Size of long double = %ld bytes\n", sizeof(f));

        return 0;
    }

And the site says the example should return

Size of int = 4 bytes 
Size of long int = 8 bytes
Size of long long int = 8 bytes
Size of double = 8 bytes
Size of long double = 16 bytes

But for me, it returns:

Size of int = 4 bytes
Size of long int = 4 bytes
Size of long long int = 8 bytes
Size of double = 8 bytes
Size of long double = 12 bytes

This is the only part that I can't seem to find the answer as to why it's not returning the same as what the site says.

I have no clue as to why it's doing this, nor why my first attempt seemed to not return the "sizeof" parts correctly (especially the third line, that returns that a long long int is 0 bytes big.) Does anyone know?

L7vanmatre
  • 13
  • 2
  • 2
    The C specification does not specify exact sizes for integer types. – Robert Harvey Jan 20 '20 at 20:59
  • 2
    See [here](https://en.wikipedia.org/wiki/C_data_types). In most cases, int sizes are stated as *minimums.* So different compiler implementations may have different sizes for some types. – Robert Harvey Jan 20 '20 at 21:00
  • 1
    The copy/paste code is using `%ld` for the `sizeof` arguments. Your code uses `%d`. Neither is correct. The correct conversion specifier is `%zu`. – user3386109 Jan 20 '20 at 21:03
  • Chances are, that the site example is executed on unix x86_64 (where long int is 64-bit), while you are either on x86_32 or on windows (32 or 64 bit) (where long int is 32-bit only) – Ctx Jan 20 '20 at 21:12
  • @RobertHarvey I see. So if I'm understanding correctly, different compilers/systems will put a different size on each data type, and the only thing that C really specifies is the minimal amount of space a certain type will take up? – L7vanmatre Jan 22 '20 at 00:37
  • @user3386109 Roger that. I've changed the relative things to %zu. Thank you! – L7vanmatre Jan 22 '20 at 00:45
  • @Ctx I'm not sure, as I couldn't find a place where they specified on the site. But you may very well be right. Reading the other answers/comments, it seems that could change some stuff regarding the output. – L7vanmatre Jan 22 '20 at 00:45

2 Answers2

4

The problem is that you're using the wrong formats to print long int and long long int. %d is only for int, not the longer variants.

Because the format you're using is incorrect, you're getting undefined behavior. It's not printing the size of long long int correctly because it extracted the parameters incorrectly, that's why it shows 0 there.

    printf("%d (as a normal int) is %ld bytes big!\n", a, sizeof(a));
    printf("%ld (as a long int) is %ld bytes big!\n",la, sizeof(la));
    printf("%lld (as a long long int) is %ld bytes big!\n",lla, sizeof(lla));

See How to printf long long

You're also supposed to use %zu for size_t values, but in practice it usually works with %ld. You should always check the compiler warnings. The compiler will issue a warning when you use the wrong format specifier. You need to make sure that you enable those warnings, and fix them.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    I believe, that the main question of the OP is the differing "Size of long int". A question, that you do not answer (yet?) – Ctx Jan 20 '20 at 21:08
  • I've added some more detail about why it says `0`. – Barmar Jan 20 '20 at 21:09
  • 1
    @Ctx He's getting `5 (as a long long int) is 0 bytes big!` That's the 0 I'm talking about. – Barmar Jan 20 '20 at 21:24
  • @Barmar Ah, ok you are right, I just read the blocks below where he asks, why the two last codeblocks yield different results. – Ctx Jan 20 '20 at 21:26
  • Thank you! The third "printf" line now correctly posts as 8 bytes after I used %lld instead, and I switched to %zu for sizeof(). However, the second "printf" (long int) line still says that it's 4 bytes big where the tutorial says it should post as 8. Additionally, printf line 5 still doesn't say the long long double is worth 16 bytes; still says 8. Also, my compiler doesn't seem to provide any warnings regarding such stuff, unless if I need to manually turn something on. (As a test, I tried to put 10000000000 on the ints, and it gave me a warning for overflows) – L7vanmatre Jan 22 '20 at 00:25
  • I have a few other new details about the implementations on the answers, but I'm new to Stack Overflow, so I'm not sure if I should edit the main post to include the other issues or post it as a different issue, as comments seem too constricting to give adequate information, at least in this case. – L7vanmatre Jan 22 '20 at 00:26
  • If they're very close to the original question, you can edit the question. But if they're new problems, you should post a new question. – Barmar Jan 22 '20 at 15:15
  • The size of types is implementation-dependent. `long int` could be only 4 bytes on your system. – Barmar Jan 22 '20 at 15:17
  • Alright. It makes me unsure since it was something that's in the original post, but something I got new information on, but I also didn't really ask about that information specifically, but it has to do with why the information is different on the 5th line. Feels like it could be something, but as far as the SO rules that I've seen so far are, it looks like it could be either from my perspective. – L7vanmatre Jan 22 '20 at 19:49
1

Your first try:

printf("%d (as a long long int) is %d bytes big!\n",lla, sizeof(lla));

has the problem that you're passing a long long int and a size_t to printf(), but your format specifier is %d, which indicates the parameters are ints. The correct format specifiers are %lld (long long int) and %zu (size_t). The result is undefined behavior, and the program can do anything in response (though usually, it'll either crash or print nonsense).

Your second try

printf("A long int is %d bytes big!\n", sizeof(la));

is close enough to correct that you're running into a different issue: the sizes of data types varies between processors, compilers, and operating systems. Based on the results you and the tutorial are seeing, I'm guessing you're using MSVC on (probably 64-bit) Windows, while the tutorial is using GCC on 64-bit Linux.

This difference is one of the reasons the sizeof operator exists. The C standard doesn't specify exact sizes for the basic data types, only minimums. Compilers are allowed to increase the sizes for speed, compatibility, or other reasons.

Mark
  • 2,792
  • 2
  • 18
  • 31
  • I see, so basically, the "long int" on my system might not be 8 bytes like the tutorial says? Also, I'm using Code::Blocks 17.12 on 64-bit Windows 10, if that helps. I figured I should use the same program that the tutorial was using. – L7vanmatre Jan 22 '20 at 00:29
  • Exactly. When Microsoft was deciding how to support 64-bit CPUs in Windows, they decided that "long int" would be 4 bytes in both 32-bit and 64-bit Windows. Linux and MacOS both went the other way, with "long int" being 4 bytes on 32-bit systems and 8 bytes on 64-bit systems. – Mark Jan 22 '20 at 00:35