3

I'm studying the basic concepts of the C Programming Language on a website called TutorialsPoint. Examples of source code on this website can include a "try it" button that opens up an on-line c programming environment with an on-line c compiler (GNU GCC version 4.7.2). In one example the sizeof() function is demonstrated. Here is the source code.

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

int main() {

  printf("Storage size for int : %d \n", sizeof(int));

  return 0;
}

Link to the lesson: TutorialsPoint - C Data Types

When this program is compiled and executed within the on-line programming environment, the following output is produced:

"Storage size for int : 4"

When I attempt to compile the same code on my computer using the GNU GCC version 5.2.1, I receive the following error message:

gcc sizeofExample.c
sizeofExample.c: In function 'main':
sizeofExample.c:6:10: warning: format '%d' expects argument of type 'int',
but argument 2 has type 'long unsigned int' [-Wformat=]
  printf("Storage size for int: %d \n", sizeof(int));
         ^

Here is my source code, just to be thorough:

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

int main()
{
  printf("Storage size for int : %d \n", sizeof(int));

  return 0;
}

I understand that this error is the result of a data type mismatch between the %d [int data type] and the sizeof(int) [long unsigned int].

Why does my compiler detect a data type mismatch, while TutorialsPoint's on-line compiler does not?

  • That's a warning, not an error. Gcc will still compile it for you. It's just going above and beyond and letting you know that the code is probably incorrect, even if it compiles. A lesser compiler might not do the additional analysis necessary to generate this warning – Pete Baughman Mar 02 '16 at 02:35
  • @PeteBaughman: Of course, the lesser compiler would just invoke undefined behavior in that case; `gcc` is going above and beyond, but the code is, by the standard, wrong, and could easily experience problems on big endian architectures or in cases where additional arguments are passed to `printf` and not all of them are passed in registers. – ShadowRanger Mar 02 '16 at 02:41
  • I didn't realize that the GCC was still compiling this code for me. This comment answers my question. I will be sure to heed the warning and use the correct data type in the printf() function. – Christian Westbrook Mar 02 '16 at 02:42
  • It's wrong, but it's wrong in a runtime way, not a compile-time way. Gcc is performing additional static analysis, but this is valid as far as a standards conforming compiler is concerned. You're passing a bad value in the string, but compiler doesn't have to care. Just like doing a divide by zero. Types check out ok, so compiler doesn't have to care. – Pete Baughman Mar 02 '16 at 02:44
  • `sizeof` yields a `size_t` result, not an `int`. The code uses a wrong format specifier. If they already fail at this, I strongly recommend to look for a different site. Or - better - read one of these old-fashioned things with the many letters, called "book". If their compiler does not complain about such simple errors, you might draw your own conclusions. – too honest for this site Mar 02 '16 at 02:48
  • @ShadowRanger: It is already a problem for typical 16 vs. 32 vs. 64 bit architectures. – too honest for this site Mar 02 '16 at 02:51
  • Olaf, I will be studying Starting Out with C++: From Control Structures through Objects by Tony Gaddis. I am currently well versed in Java, and have been wanting to explore another popular programming language, and as such will be studying C. I am currently in the middle of the semester in college at a university where most coursework uses Java. With very little free time on my hands, the C programming tutorials on TutorialsPoint have been a good beginning reference point. When I have more free time I plan on working through this textbook for in-depth study. – Christian Westbrook Mar 02 '16 at 02:55
  • 1
    @Olaf: It's undefined behavior, but it's not up to the compiler to identify it. From a standard conforming compiler's point of view, it's just an opaque C-style string followed by varargs; `gcc` special cases `printf` because it's relatively easy to do and a common source of errors, but standards conforming compilers aren't required to look for undefined behavior like this, it's undefined, so they can try to make it work, or not, or set fire to your house, as they choose. – ShadowRanger Mar 02 '16 at 02:57
  • @ChristianWestbrook: I thought you learn C. C++ ius a different language! Don't use a C++ book to learn C. If you want to put some effort in it, you can also ready the standard. It is not _that_ hard to understand. – too honest for this site Mar 02 '16 at 03:01
  • @ShadowRanger: I didn't say it was the compiler's job. But any halfway modern compiler **does** warn. A **tutorial** site's compiler can be expected to detect such simple errors very well. But the worst is that the code (according to the question text) originates from that site. – too honest for this site Mar 02 '16 at 03:06
  • @PeteBaughman: "but this is valid as far as a standards conforming compiler is concerned" - No! This is undefined behaviour and no way valid! And it is not the value which is wrong but the type – too honest for this site Mar 02 '16 at 03:06
  • @Olaf C++ grew out of C. They are very similar languages. I am learning both, starting with C and then moving to C++. What do you mean read the standard? Reference or link please? I'd be interested. – Christian Westbrook Mar 03 '16 at 03:03
  • The language standards! Are Wikipedia and google both down? While you are right for the first C++ version (it was a C preprocessor actually), you are not since >20 years now. Sorry, but I'm tired of this discussion; every newbie who makes his first steps starts with the same wrong assumptions - no offence. Just learn! – too honest for this site Mar 03 '16 at 03:09
  • I didn't realize you were referring to the ISO C programming language standards. I have 5 years of experience in the Java programming language, and hardly consider myself a "newbie making his first steps". My statement was correct; C++ did in fact grow out of C. I made no assumptions about how C++ has evolved past its conception. The Java programming language has a similar document called the Java Language Specifications. My collegiate computer science program has not made direct reference to these documents. I take no offense (not offence), as my situation has been misjudged. – Christian Westbrook Mar 03 '16 at 05:45

3 Answers3

5

sizeof produces a size_t result (an unsigned quantity which is usually 4 bytes on 32 bit systems, and 8 bytes on 64 bit systems). You should use an appropriate printf format code, in this case %zu (z means "width equivalent to size_t", u meaning "unsigned value"). That should work correctly on all systems (aside from a very few incredibly archaic systems that don't support the z size modifier).

The on-line compiler probably doesn't complain because either:

  1. It's not performing the in depth printf format code checking gcc does or
  2. It's a 32 bit compiler, and size_t and int are the same size (though differing in signedness) so there isn't a size mismatch there, while your local gcc is a 64 bit compiler, and the sizes differ.
  3. The compiler simply doesn't display warnings in order to keep output simple for beginners.

Note that gcc is only warning, not erroring out, so the code will finish compilation and run. Usually warnings indicate a problem though, so it was a good thing to investigate further.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • Or it just doesn't display warnings like most online compilers (which is silly). – Fantastic Mr Fox Mar 02 '16 at 02:50
  • @Ben: Good point. I don't use them much, so I'm not aware how strict they may be. For non-legacy code, I always turn the warnings up (and usually make them errors) precisely to catch nonsense like this at compile time before it bites me in harder to diagnose ways at run time. – ShadowRanger Mar 02 '16 at 02:52
  • I absolutely agree, also +1, not sure why someone down voted this? – Fantastic Mr Fox Mar 02 '16 at 02:53
2

This is a warning not an error so the compilation is finishing and producing an executable file, but GCC is warning you of something that might cause bad behavior. As for why TutorialPoint doesn't show this warning, a similar online compiler website ideone.com also doesn't throw this warning. You can see here that Ideone uses the GCC compiler. Online websites commonly suppress warnings to simplify their output for users. It is always a good idea to fix warnings, to do so in this case you would use:

printf("Storage size for int : %zu \n", sizeof(int));

This can potentially save you Undefined Behaviour problems from mismatched printf types reading more memory then they should . Read more about this here.

Community
  • 1
  • 1
Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
1

Why does my compiler detect a data type mismatch

Because printf expects %zu (instead of %d) for sizeof(type)

artm
  • 17,291
  • 6
  • 38
  • 54
  • Why does the on-line compiler not expect %zu for sizeof(type)? – Christian Westbrook Mar 02 '16 at 02:38
  • I don't use on-line compiler so can't comment on that. The standard compiler (ie gcc) would give you a warning if you use `%d`: wwarning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’` – artm Mar 02 '16 at 02:40