B
Barry Schwarz
snip
At this points c contains the contents of p which is the address of
arrc[0].
When c is incremented at the end of each loop iteration, it increments
to the address of arrc[1], arrc[2], etc.
Given the values the c contains in each iteration, *c obviously
evaluates to 'c', 'o', 'm', 'p'. The loop will terminate when *c
evaluates to '/0'.
At this point, c contains the value in arrp[0] which is the adddress
of
the object a.
For the first iteration, *c evaluates to the contents of object a
which is 'a'.
Since this is the end of the loop, c is incremented. It now points
one char beyond the object a. While this is a legal value for c to
hold, it is not legal to dereference the value. Therefore, when the
test condition in the for statement is evaluated, the behavior is
undefined. Attempting to evaluate the *c in the printf statement also
invokes undefined b havior.
You seem to be fixated on the mistaken idea that since c starts out
with the contents of arrp[0], when you increment it it somehow
acquires the value of arrp[1]. As noted above, this is not the case.
That is because you do not provide a pointer to the array of
pointers. You only provide a pointer that contains the value of the
first pointer in the array. At no point do you ever access any of the
other pointers in the array.
Actually, the arrays behave exactly the same. It is your code that
treats them differently. In the first function, you assign c the
address of the array. In the second function, you assign c the value
of the first element. If you choose to treat things differently, you
cannot complain when they react differently.
Chances are, if you had used the function parameter, you would have
treated the arrays the same and not created the problem for yourself.
Here is very simplified version of the above code which prints the same
weired iteration. Look at the 2 printing functions:
#include <stdio.h>
void print_arrc(char* );
void print_arrp(char** );
int main(void)
{
char arrc[] = "comp";
char* arrp[5] = {0};
char a = 'a';
char b = 'b';
char c = 'c';
arrp[0] = &a;
arrp[1] = &b;
arrp[2] = &c;
print_arrc(arrc);
print_arrp(arrp);
return 0;
}
void print_arrc(char* p)
{
char* c = p;
At this points c contains the contents of p which is the address of
arrc[0].
for( ; c && *c; ++c )
When c is incremented at the end of each loop iteration, it increments
to the address of arrc[1], arrc[2], etc.
{
printf("Char Element: %c\n", *c);
Given the values the c contains in each iteration, *c obviously
evaluates to 'c', 'o', 'm', 'p'. The loop will terminate when *c
evaluates to '/0'.
}
printf("\n\n");
}
void print_arrp(char** arr)
{
char* c = *arr;
At this point, c contains the value in arrp[0] which is the adddress
of
the object a.
for( ; c && *c; ++c)
{
printf("Points to Element: %c\n", *c);
For the first iteration, *c evaluates to the contents of object a
which is 'a'.
Since this is the end of the loop, c is incremented. It now points
one char beyond the object a. While this is a legal value for c to
hold, it is not legal to dereference the value. Therefore, when the
test condition in the for statement is evaluated, the behavior is
undefined. Attempting to evaluate the *c in the printf statement also
invokes undefined b havior.
You seem to be fixated on the mistaken idea that since c starts out
with the contents of arrp[0], when you increment it it somehow
acquires the value of arrp[1]. As noted above, this is not the case.
}
printf("\n\n");
return;
}
Inside the print function: it works fine by taking a local pointer to
the /array of chars/ passed as argument
Inside the print function: it does not work by taking a local pointer to
the /array of pointers/ passed as argument
That is because you do not provide a pointer to the array of
pointers. You only provide a pointer that contains the value of the
first pointer in the array. At no point do you ever access any of the
other pointers in the array.
So an /array of char/ and an /array of pointers/ behave differently when
passed as arguments and accessed using local pointers.
Actually, the arrays behave exactly the same. It is your code that
treats them differently. In the first function, you assign c the
address of the array. In the second function, you assign c the value
of the first element. If you choose to treat things differently, you
cannot complain when they react differently.
Anyway, I don't see any point in using a local pointer as the passed
double-pointer is also local to the function. Trouble is I don't
understand the /Why/
Chances are, if you had used the function parameter, you would have
treated the arrays the same and not created the problem for yourself.