2

So I'm learning C. I'm trying to mess around on a web-based IDE called https://replit.com/languages/c .

I decided I would learn to code a counter function that goes from 1 to 100(using a for loop iterator). I did this successfully with the following code:

#include <stdio.h>
int main (void) {
  for (int i = 1; i < 101; i++)
    {
      printf("%i\n", i);
    }

}

This code does exactly what I wanted. So I decided to learn more and break the code. I removed the data argument "i" in the print statement and proceeded to run the code again to see what happens.

#include <stdio.h>
int main (void) {
  for (int i = 1; i < 101; i++)
    {
      printf("%i\n");  <-- notice int variable i is removed
    }

}

Unsurprisingly, the console gave me a warning "warning: more '%' conversions than data arguments". This made perfect sense to me. What doesn't make sense is the output. The code ran with the warning and spit out the following in the console:

-921955384
0
0
0
0
0
...

I'm assuming it printed 99 more 0's after the large negative integer in question, and then terminated. I did not count all the 0's. Why the negative integer?

When I ran the program again, it printed:

1818314744
0
0
0
0
0
...

A third run prints the following:

-725290120
0
0
0
... 

Fourth:

clang-7 -pthread -lm -o main
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
clang-7: error: linker command failed with exit code 1 (use -v to see invocation)
exit status 1

So my question is: Why does it output the negative integer? Why is it changing/incrementing from positive to negative until its too big for it's integer type? Why all the 0's if there's not a data argument for my "%"? Why the error?

It seems like it has to do storage size and respective value ranges given a specific integer type. I got this info from CS50 and the Integer Type table at https://www.tutorialspoint.com/cprogramming/c_data_types.htm ... So I changed the code in the for loop to a Long integer type:

#include <stdio.h>
int main (void) {
  for (long i = 1; i < 101; i++)
    {
      printf("%i\n");
    }

}

It never errors out, so I thought I was onto something. But when I go BACK to int integer type to recreate the initial error on the 4th run, it never shows that error message from the fourth time I ran it. It keeps going. In fact it actually shows me a different initial integer... It started with 885981032(different number from first time around which was a negative number), then gave me -1940014968, then -42383224, then 1313794568, then 1348629208, then -303298488.... No error message... All using normal int type and not long.

What in the world is going on with this output? Why could I not recreate the error when going back to int? Fourth run just kept showing more numbers as opposed to the first time it spit out an error on the fourth run. What are the negative numbers? How are they incrementing? Why the 99 0's?

I'm just very curious as to what's going on behind the scenes here.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    The `printf` function at run time believes your `%i` and neither knows nor cares whether you actually passed a value to use. It will use whatever is in the memory location (or register) where it is *expecting* to find a value. It is the compiler which warns you about this, and the resultant behavior is *undefined*. – Weather Vane Aug 06 '21 at 19:13
  • 2
    The language makes this undefined behavior, so in principle anything can happen. In practice, what it probably does is print out the contents of whatever register or memory location would otherwise be used for passing the argument. Surrounding code may be using that register or memory location for other stuff, so you might well expect it to change between calls. – Nate Eldredge Aug 06 '21 at 19:13
  • 1
    See: [Undefined, unspecified and implementation-defined behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) – John Kugelman Aug 06 '21 at 19:14
  • 1
    See: [Does “Undefined Behavior” really permit *anything* to happen?](https://stackoverflow.com/questions/32132574/does-undefined-behavior-really-permit-anything-to-happen) – John Kugelman Aug 06 '21 at 19:16
  • So this is memory management stuff? Is the initial number changing on each run because "surrounding code may be using that register or mem location for other stuff?" Do the links and Nates description explain why I cannot re-create the error message? Sorry, it seems concise and accurate but the language used kind of goes over my head. I need to learn a lot more about CS and C. – anthonyarmend Aug 06 '21 at 19:24
  • 2
    C doesn't require variadic functions to be able to determine how many arguments were supplied when the code is running. The compiler checks for a mismatch when the format string is a literal, but it still generates runnable code. – Barmar Aug 06 '21 at 19:30
  • From John's link: "Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message)." - this sounds like the reason I can't re-create the error message(is that accurate?) but does this also explain why I'm getting different integers on the first increment of int i? – anthonyarmend Aug 06 '21 at 19:36
  • 1
    If there was a definable result, then it wouldn't be undefined... The 'permissible' is a red herring. What happens isn't really relevant, but suppose... you start running red lights. Do you think it is definable, or even relevant, *which* vehicle you are going to have a collision with (if any)? The answer is to respect the red light, not to figure out the consequences. – Weather Vane Aug 06 '21 at 19:42
  • 3
    The "error message" didn't come from running your program, it came from running the compiler without any input. – Ben Voigt Aug 06 '21 at 19:53
  • 1
    You are getting different integers because `printf` is using data that wasn't placed there for that purpose. The result is indeterminate. It might be the same, or different, or crash the program. It is undefined. – Weather Vane Aug 06 '21 at 19:55
  • 1
    Yes, as @BenVoigt says, "Fourth" is totally unrelated to the others. You simply forgot to include the name of your source file on the command line, so the compiler tried to compile an empty program consisting only of the pthread library, which obviously doesn't work because it has no `main` function. You might want to take it out of your question as it has nothing to do with `printf`. – Nate Eldredge Aug 06 '21 at 19:57
  • I think I understand what you're saying Nate, but I'm not sure. I say this because I did not change the code at all in that web compiler and thus I don't think I really forgot to include the name of my source file as you say. I just pressed run on what happened to be the 4th time, and it threw the error. Sorry if I'm missing your point or missing a basic concept here. – anthonyarmend Aug 06 '21 at 20:01
  • 1
    @anthonyarmend: Well, the command line is right there in what you posted, and the source filename isn't included. Maybe this is a bug in the replit web interface, but anyway I am sure it hasn't got anything to do with your printf question. – Nate Eldredge Aug 06 '21 at 20:10
  • Does this answer your question? [Undefined, unspecified and implementation-defined behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) – the busybee Aug 06 '21 at 20:15
  • 1
    As a general rule, by deliberately "breaking" code to cause undefined behavior, you *might* learn something about the inner workings of your particular compiler and system; but you'll generally need a good working knowledge of your system's assembly language, ABI, and so forth. What you will *not* learn is anything about the C language per se. – Nate Eldredge Aug 06 '21 at 21:21

0 Answers0