printing array of pointers

B

Barry Schwarz

snip
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.
 
S

Seebs

Here is very simplified version of the above code which prints the same
weired iteration. Look at the 2 printing functions:

It's not weird. It's been explained to you precisely.

Do you actually perceive the words in the posts you're responding to?
Has it occurred to you that these words might have meaning?
void print_arrp(char** arr)
{
char* c = *arr;

This extracts the first member of the array.
for( ; c && *c; ++c)
{
printf("Points to Element: %c\n", *c);
}

This loops through trying to print multiple characters pointed to by the
first argument.
So an /array of char/ and an /array of pointers/ behave differently when
passed as arguments and accessed using local pointers.
Probably.

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/

What's to understand? You pass in a variable arr, which points to the
first of several pointers to characters. You extract the first of these,
so you now have a pointer 'c' which points to the first set of characters.
You then iterate over c. You're iterating over that first pointer in
the array.

If you want to iterate over the array, don't iterate over something other
than the array, such as its first member.

You may find this easier to understand if you do:

char *arr[] = { "hello", "world", 0 };

Then the iteration over characters will give you h e l l o rather than
garbage.

Your function does:
char *c = arr[0]; /* points to "hello" */
(loop on c, printing h e l l o)

Mine iterated on arr, printing hello world.

-s
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top