23

I'm new to C programming, I encountered a problem.
In case of complicated declarations i found this

int *daytab[13]; // daytab is an array of 13 pointers to int

which means daytab is the name of the array and the name of the array points to the first element of the array. The array name is not compatible with pointer manipulation like daytab++ etc (correct me if I'm wrong).

But I found this code written in Dennis Ritchie

main(int argc, char * argv[]) {
    while( --argc > 0 )                    
        printf("%s%s",*++argv,(argc>1) > " " : "");

    printf("\n");
    return 0;
}

How can they manipulate argv? Is it not the array name?

GSerg
  • 76,472
  • 17
  • 159
  • 346
akash
  • 1,801
  • 7
  • 24
  • 42
  • It is a pointer to an (char) array of all the parameters that were passed by system to your application, argc contains the count of same – Hanky Panky May 21 '13 at 09:20
  • 1
    In the line containing `printf` - shouldn't that last bit be `(argc>1) ? " " : ""`? The free-standing '>' doesn't appear to be right. To me it looks like it's supposed to put a blank between the arguments as they print, but no blank after the last arg. – Bob Jarvis - Слава Україні May 21 '13 at 12:05
  • 1
    I'm absolutely shocked that four years on there's no reference to the [Clockwise Spiral Rule](http://c-faq.com/decl/spiral.anderson.html) for interpreting C variable declarations. Oh, wait... :-) – Bob Jarvis - Слава Україні Jun 21 '17 at 23:15
  • 1
    An excellent resource to interpret C variable declarations http://cseweb.ucsd.edu/~ricko/rt_lt.rule.html – Ambareesh Jul 25 '21 at 03:02

7 Answers7

31

The parameter char * argv[] decays to a pointer, char ** argv. You can equally well write the function signature for main() as:

int main(int argc, char ** argv)

You can do what you like with the pointer argv within main(), so argv++ for example just bumps argv to point at argv[1] rather than argv[0].

argv ---> argv[0] ---> "program"
          argv[1] ---> "arg1"
          argv[2] ---> "arg2"
           ...          ...
          argv[argc] == NULL
Paul R
  • 208,748
  • 37
  • 389
  • 560
5

When a program starts, it gets it's argument in the main function. That's why you ususally write.

int main(int argc, char *argv[])

This simply means that argv is a pointer to as many argument strings as indiciated by argc (== argument count). Since argv decays to char **argv you can also increase it, or you it otherwise like a pointer.

So if you want to print all arguments from the commandline:

int main(int argc, char *argv[])
{
   for(int i = 0; i < argc; i++)
       printf("%s\n", argv[i]);

   for(int i = 0; i < argc; i++)
       printf("%s\n", argv++);

    return 0;
}
Devolus
  • 21,661
  • 13
  • 66
  • 113
  • 1
    Note that this code does not do the same thing as the code posted by OP. Note carefully the use of the pre-increment and pre-decrement operators in the original code, and the effect of operator precedence. Share and enjoy. – Bob Jarvis - Слава Україні May 21 '13 at 11:52
5

argv is an array of char*. Doing ++argv means accessing the next cell of the array. The * indicates we want the value of the cell, not the address.

ibi0tux
  • 2,481
  • 4
  • 28
  • 49
4

The declaration char *argv[] is an array (of undetermined size) of pointers to char, in other words an array of strings.

And all arrays decays to pointers, and so you can use an array as a pointer (just like you can use a pointer as an array). So *++argv first increases the "pointer" to point to the next entry in the array argv (which the first time in the loop will be the first command line argument) and dereferences that pointer.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
2

The parameter declaration looks similar to the declaration of an array but in fact (because it is a function parameter) it isn't one. The C FAQ explains that well.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
0

argc and argv are the parameters passed to the main function of the program.

argc in an integer holding the number of parameters, and argv is a pointer to a string array holding the actual parameters. Each element referenced by argv are separated by whitespace.

Maciek Czarnik
  • 5,950
  • 2
  • 37
  • 50
AcId
  • 458
  • 2
  • 12
-1

What is done here is pointer arithmetic.

The pointer is not really changed.

The pointer's adress is used, incremented temporarily and then used for output.

Because the operator ++ is placed before the argv, the adress is first taken, then incremented, and then dereferenced to get the char* behind this adress.

But it is not the adress itself, which gets changed, just the offset, from where the printf will read.

Ok ?

icbytes
  • 1,831
  • 1
  • 17
  • 27
  • 5
    The pointer very much **is** being changed, using the pre-increment operator. But, y'know, this is C, not some namby-pamby computer science language that aims to protect us from ourselves. You want to alter your procedure arguments? Hey, go for it! We are C! We are tough! We are strong! We are(*$(*&(*#ADDRESS EXCEPTION AT MEMORY LOCATION 0 – Bob Jarvis - Слава Україні May 21 '13 at 11:39
  • Sorry for being that late. Wtf. I thought all the time,.that this preincrement operator just helps to get the "place before", and would not really alter the pointer itself, meaning, just for the access during runtime. Ok, i need to read once more, i would say (must admit). – icbytes Jun 21 '17 at 20:51