1

I've the following code :

#include <stdio.h>
int main(int argc, char* argv[]){
    int a = argv[1]?atoi(argv[1]):10;
    int b = argv[2]?atoi(argv[2]):20;
    printf("a = %d, b = %d\n", a, b);
    return 0;
}

If I do not provide any command line inputs, the values in "a" and "b"
should be 10 and 20 respectively, but what happens instead is "a" gets value as 10 whereas "b" gets 0.
I cant understand why this is happening, since I am doing exactly same
thing in both cases.

Thanks.

Abhishek Choubey
  • 883
  • 6
  • 16
  • 4
    Because you are invoking Undefined Behaviour. If no command line args are provided then the code MUST NOT access those `arg` entries. They are not all guaranteed to be NULL in that case. Only `argv[argc]` is defined to be NULL by the C standard. – kaylum Feb 19 '16 at 05:47
  • 2
    In the third and fourth lines, try changing `argv[1]` and `argv[2]` to `(argc>1)` and `(argc>2)` – r3mainer Feb 19 '16 at 05:49
  • I tried checking if argv[1] and argv[2] are null, turns out argv[2] is not null even when I dont provide any inputs on command line. Thanks. – Abhishek Choubey Feb 19 '16 at 05:59

2 Answers2

7

The runtime (often thru crt0 & kernel) guarantees (per C99 or POSIX standards) that (for main's arguments argc & argv) :

  • argc is positive

  • argv is a valid non NULL pointer to an array of argc+1 pointers

  • argv[argc] is the NULL pointer

  • for each i between 0 and argc-1 included, argv[i] is a (valid non NULL) pointer to a zero-terminated string

  • hence access to argv[j] with j>argc (or j<0) is undefined behavior (UB) - so explaining what happens is only possible by diving into implementation details...

  • the valid argv[i] are not pointer aliases, so if i & j are both between 0 and argc-1 included, and i != j, argv[i] != argv[j]

therefore, your code is wrong when argc==1 because accessing argv[2] is forbidden (UB).

You should code:

int main(int argc, char* argv[]){
    int a = (argc>1)?atoi(argv[1]):10;
    int b = (argc>2)?atoi(argv[2]):20;

Be very scared of undefined behavior (see also the references here). Sadly, a program with UB might sometimes appear to "work" (that is might not crash). But at other times bad things may happen. So you should imagine the worst.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
6

If I do not provide any command line inputs, the values in "a" and "b" should be 10 and 20 respectively.

No, if you don't provide any command-line inputs, you're accessing beyond the end of the argv array and anything can happen (including your program crashing and burning).

Your checks should be:

int a = argc > 1 ? atoi(argv[1]) : 10;
int b = argc > 2 ? atoi(argv[2]) : 20;

That's what argc is for, to tell you how many entries argv has in it that you can access.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875