1

I am reading Beginning Programming with C for dummies came across a code I couldn't understand

#include <stdio.h>

int main(void) 
{
    printf("The total is %d\n", 16.0 + 17);
}

It show output as:

The total is 0

I thought that first 16.0 + 17 will automatically type cast to 16.0 + 17.0 = 33.0 then the fractional will be truncated while printing it's value and the final output will be:

The total is 33

Can you explain why the output comes out to be 0:

Stargateur
  • 24,473
  • 8
  • 65
  • 91
Jay Patel
  • 95
  • 8
  • 1
    If you Look at the signature of `printf` how should the compiler even know that a conversion might be required? – Gerhardh May 11 '18 at 07:17
  • Note that the symbol `℅` in your title is not the percentage `%` symbol. It is C / 0 instead of 0 / 0. – mch May 11 '18 at 07:30
  • 1
    You should enable all warnings in your compiler. With `gcc -Wall -Wextra -g` using [GCC](http://gcc.gnu.org/), you'll be warned (because the compiler "knows" about `printf`, thru some `__attribute__` mentioned in some system header) – Basile Starynkevitch May 11 '18 at 08:49

2 Answers2

3

The declaration of printf is like this:

int printf(const char *format, ...);

It takes variable length arguments where the first one format is mandatory. But it can't know the types of later arguments in advance, i.e. during compile time. So in order to determine type for later arguments, i.e. to know how many bytes it has to read from memory, how to interpret those bytes etc., it entirely depends on format specifier present in format string.

And this is the reason that the format specifier and actual type must match. Otherwise it will be undefined behavior and anything may happen in that case.

taskinoor
  • 45,586
  • 12
  • 116
  • 142
2

C (also C++) has concept of undefined behavior (UB). There are certain things you aren't allowed to do according to language rules. If you violate such rules, then you can't expect any reasonable outcome. %d expects int, if you pass it a float (or say double), you enter area of undefined behavior. Get familiar with UB.

In the end you need to get familiar with all rules which cause UB (there are more than 100 things which cause UB in the standard); but since you are now learning C, it is not required you get to know all of them, just know thing like UB exists.

Giorgi Moniava
  • 27,046
  • 9
  • 53
  • 90
  • so will UB will depend on the compiler? Thanks BTW – Jay Patel May 11 '18 at 06:32
  • 1
    @JayPatel yes, it could. – Giorgi Moniava May 11 '18 at 06:33
  • Answer is partially OK. Core is: variable arguments C functions are not type safe, there is no cast double to int (but cast is possible) – Jacek Cz May 11 '18 at 06:36
  • @Giorgi Moniava what will happen if I pass an int value to a float format specifier (%f) will it show UB or will it work perfectly? – Jay Patel May 11 '18 at 06:37
  • 3
    @JayPatel it is also UB in same way. That's the point, you need to get familiar and learn those rules, there is no other way. Sometimes they might not seem logical at all, but those are rules. – Giorgi Moniava May 11 '18 at 06:38
  • 1
    "Personally I think UB is a disadvantage to C and C++ because of so many rules you need to remember, and compiler not being able to always detect violations. There were reasons to have UB apparently, but from safety point of view, they make programming in C and C++ tricky."... you serious ? – Stargateur May 11 '18 at 08:50
  • @Stargateur Why would I post something if I wasn't serious? Also next time you might want to directly propose your counter arguments, instead of those kind of remarks. PS. To free C from undefined behavior is something people more knowledgeable in this field have also considered: https://blog.regehr.org/archives/1180 – Giorgi Moniava May 11 '18 at 09:13
  • 1
    @GiorgiMoniava "Also next time you might want to directly propose your counter arguments" comment are not here for that, I just want to ask you if you were really serious, come to C room if you want argue. The blog article and what you say and the blog you link is primary opinion based and shouldn't be write on an answer on SO. – Stargateur May 11 '18 at 11:38
  • @Stargateur No I don't want to come to chat, the blog post makes that clear enough. I posted few words which are more or less apparent that the more rules language has the more cumbersome it is to use it, if I have violated some SO policy, point me to that and I will delete that paragraph. – Giorgi Moniava May 11 '18 at 12:05
  • 1
    @GiorgiMoniava "the blog post makes that clear enough" so you are not argue, you just assume the blog is right and don't want to discute about it, so "Also next time you might want to directly propose your counter arguments" you don't care in fact. "the more rules language has the more cumbersome it is to use it, if I have violated some SO policy" not a policy but don't be surprise that people like me will argue about this, that why on SO advise to avoid it. To argue with the blog post, just read [this](https://blog.regehr.org/archives/1180#comment-16431) comment. – Stargateur May 11 '18 at 12:10
  • @Stargateur OK let's finish up because you know comments are not for extended discussion. The reason I showed you blog post was to merely highlight that the idea to free C from UB is not meaningless and many people have thought about it - *and that's it*. – Giorgi Moniava May 11 '18 at 12:44
  • This answer isn't an answer to the question at all, it's just wrong. taskinoor answer is 100% correct.. compiler does deal with type conversions at compile time but printf deals with variable arguments at runtime, it's a basic c question with a specific answer, either you know it or you don't .. This answerer simply does not know c very well. – little_birdie May 14 '18 at 15:40
  • @little_birdie The answer just states that what OP has is undefined behavior. Do you say opposite? If yes, check this: https://stackoverflow.com/questions/16864552/what-happens-when-i-use-the-wrong-format-specifier, or read the standards. taskinoor's answer just tries to explain why this could have been labeled as undefined behavior in the C standard. – Giorgi Moniava May 14 '18 at 15:56
  • The question asks why. The answer "it is undefined behavior" is not an answer to the question, for two reasons. First, because it does not explain why.. and yes there is a specific and easily understood answer to "why". And second, because actually this behavior of printf is not "undefined" c language behavior because printf is not a feature of the c language. It is merely a function in the library that happens to use the variable argument lists feature of c.., and the behavior of variable argument lists is documented and how they work are understood. – little_birdie May 14 '18 at 16:04
  • @little_birdie Check "section 7.19.6.1 p9 of the C99 standard:" which says it is undefined behavior and come back then. Second, you said this answer is wrong, which is false, given my previous sentence. Yes taskinoors answer might involve more explanations but it doesn't make this answer wrong. Please carefully read what I wrote in this comment, I am not going to go into endless discussion with you, I have other things to do too. – Giorgi Moniava May 14 '18 at 16:07