hermetik
hermetik

Reputation: 115

Understanding Array of Character String Pointers

I a am trying to understand the results I am receiving when referencing the pointer 'p'. I have placed comments in-line, stating what I believe is happening.

#include <stdio.h>

main()
{
    char *words[] = { "hello", "world" };
    char **p = words;              // p is now pointing to words[0]?

    ++p; // p now points to "world"

    printf("%s\n", *p);            // Prints the character string 'world', pointed to by p
    printf("%c\n", *p[0]);         // Returns 'w'
    printf("%c\n", *p[1]);         // Should return 'o'? Returns garbage
    printf("%c\n", *++p[0]);       // Returns 'o'?
}

My understanding is that after:

char **p = words;

That p now points to the first character pointed to by words[0], i.e., the 'h' in 'hello'. Then after:

++p

p now points to the first character pointed to by the pointer at words[1], i.e., the 'w' in 'world'.

The results:

world
w
<blank space>
o

If *p[0] returns the character 'w'. Then, why does *p[1] return garabage? I am trying to understand how the contents pointed to by the pointers in *words is organized in memory, then, where p is pointing to after each call.

Update

By changing the following lines:

    printf("%d\n", *p[0]);         
    printf("%d\n", *p[1]);         
    printf("%d\n", *++p[0]);      

The results are now:

119 // 'w'
1   // 'SOH' -- Start of heading
111 // 'o'

Now, what exactly is the SOH character, in this context?

Upvotes: 0

Views: 81

Answers (2)

R Sahu
R Sahu

Reputation: 206697

There is some misunderstanding.

The memory layout after:

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

will look something like:

words[0]    words[1]
|           |
v           v
+-----------+-----------+
|   ptr1    |    ptr2   |
+-----------+-----------+


ptr1
+---+---+---+---+---+------+
| h | e | l | l | o | '\0' |
+---+---+---+---+---+------+

ptr2
+---+---+---+---+---+------+
| w | o | r | l | d | '\0' |
+---+---+---+---+---+------+

You said:

char **p = words;              // p is now pointing to world[0]?

If you meant words[0], then you are correct.

You also said,

That p now points to the first character pointed to by words[0]

That is not correct. The type of p is char**. You could say *p points to the first character pointed to by words[0].

Regarding the output of the program...

You have a line:

++p;

This line changes p so that it points to words[1].

The line

printf("%c\n", *p); // Should return 'w'? But returns garbage

is cause for undefined behavior since the type of *p is not an int that represents a char. Type of *p is char*, not char.

The line

printf("%c\n", *p[0]);         // Returns 'w'

prints w since p[0] is equal to ptr2. As you can see from the memory layout, *ptr2 evaluates to 'w'. Hence, you get w in the output.

The line

printf("%c\n", *p[1]); // Should return 'o'? Returns garbage

is also cause for undefined behavior.

Due to operator precedence, *p[1] is equivalent to *(p[1]), which is equivalent to *(*(p+1)). Since p already points to words[1], (p+1) points to invalid memory.

Upvotes: 1

&#212;rel
&#212;rel

Reputation: 7632

You should use warning to show you basic error

a.c:10:5: warning: format ‘%c’ expects argument of type ‘int’, but argument 2 has type ‘char *’ [-Wformat]

*p is a pointer to a char. Try:

printf("%s\n", *p); 


printf("%c\n", *p[1]);

Here p[1] can be the third element of words as there is no third element you read garbage value.

For ++p[0] p[0] points to "world" with ++ this point to "orld" then with * you print the first char so o.

To undrestand pointer you can use print with %p to see your pointed adress.

Upvotes: 0

Related Questions