I'm struggling a little bit with pointer arithmetic. In the below example, let's assume argc is 3 and argv is an array of pointers, each of which are pointing to the individual character strings: find -nx pattern.
When the while runs, and this line is invoked:
(*++argv)[0] == '-'
the primary expression operators (e.g. () []) are evaluated first. They are evaluated left to right. So first we evaluate what's in the parenthesis (). Within the parenthesis, we have two unary operators (++ *). Unary operators are evaluated right to left. So first we increment the pointer to point to the first index of the character string '-nx' from 'find'. The first index holds value '-'. Then we use the unary dereference indirection operator to return the value held at the pointer, which is the character '-'. But then we use the subscript operator on a character '-' which doesn't seem right. Any ideas?
In this context, char * argv[] equals to char** argv, which means (*++argv) will return a char*.
Using then operator[] you will be checking the first letter to see if it's a minus.
Edit: In fact line 14 is the unclear one. c = *++argv[0];
Can be translated to c = *++(*argv);
This should be already clear, but just in case think of this.
argv[0] points to -x
So we increase the value of argv[0], pointing to the character AFTER the minus. ++(argv[0]);
And we copy it to c c = *++(argv[0]);
As you can see, argv is an array of char pointers.
1) Step 1. we use pointer arithmetic to increment to the second char pointer in array of char pointers. Now the second char pointer should be pointing to the first element in the char array '-nx'.
(++argv)
2) Step 2. We use dereference operator to refer to the value that the second char pointer is pointing to which should be that '-' character.
(*++argv)
But you are saying that (*++argv) will return a char pointer. Isn't the ++argv pointer airthmetic? Which means that it increments to the second pointer, which itself is pointing to the first element of char array? And if so, dereferencing that memory should return the char '-' itself?
Consider this wider example (i'm now on PC so it's easier for me to explain this):
argv is of type char**.
argv[0] points to "hello" of type char* .
argv[1] points to "-world" of type char* .
In the first while:
(*++argv)[0] == '-'
argv is incremented, so it will point to argv[1] from now on, for the entire length of the program.
argv at this point is still of type char**.
argv is then dereferenced, giving you a char*. Remember, dereferencing only removes one pointer at a time from the type (from char* to char, from char** to char*, from char*** to char**, and so on. In this example, from char** to char*).
Then operator[] is called on the given char*, giving you the minus sign (as the minus sign is on the first position, index 0, of the received char*.
Found the minus sign you go down in the deeper while. c = *++argv[0]
For easiness' sake let's translate this into c = *++(argv[0])
as noted above.
argv[0], as we said before, is argv[1] as argv has been permanently incremented.
So argv[0] is a char* to "-world".
Same thing here (only remove one pointer from the type, from char** to char*).
Now, the char* given from argv[0] itself is incremented.
Which leads, from "-world" it becomes "world".
Then it gets dereferenced, and gives you the letter 'w'.
while (--argc > 0 && (*++argv)[0] == '-')
while (c = *++argv[0])
I don't think it's a pointer arithmetic problem, it think you're trying to do too much in each statement.
Ok, (*++argv)[0] == '-' does what you want because argv starts off pointing to the program name, so you pre-increment it. You could write it as **(++argv) == '-' to further your quest for terseness.
You should realise that early C compilers didn't have the optimisations that we use with confidence today. So the code was assembler like. You shouldn't do that now, you should write clear code that is obvious.
The second while loop is the problem.
The first loop identifes a string that starts with -. You now need to traverse that string, so you need a loop that visits the characters in turn. So it should look like:
1 2 3
char* c; /* declare here as we appear to be using C */
while (--argc > 0 && **(++argv) == '-')
for (c = *argv + 1; *c; ++c)
*argv is the address of the - in that string. *argv + 1 is the address of the next character along. The loop keeps going until it sees the null terminator.