How to increment array of pointers to strings

B

barncat

I am trying to increment the pointer of this array, similar to
incrementing *argv[]:
*++argv
printf("%s\n", *argv); /* now prints the arg at argv[1]; */
--
code:
char *args[8];
args[0] = "x";
args[1] = "y";
args[2] = "z";

/* if i use:
args++; or
*args++;
i get error:
xxx.c:18: error: wrong type argument to increment
*/
 
B

Ben Bacarisse

barncat said:
I am trying to increment the pointer of this array, similar to
incrementing *argv[]:
*++argv
printf("%s\n", *argv); /* now prints the arg at argv[1]; */
--
code:
char *args[8];
args[0] = "x";
args[1] = "y";
args[2] = "z";

/* if i use:
args++; or
*args++;
i get error:
xxx.c:18: error: wrong type argument to increment
*/

When [] appear in a parameter declaration, it really means *. I.e. argv
is really a char ** object. Your args is actually an array, so to get
the same effect you need a pointer to the first element of it and then
you can work with that. Of course, there's no reason to use a pointer
at all. An index will work just as well.
 
B

barncat

When [] appear in a parameter declaration, it really means *.  I.e. argv
is really a char ** object.  Your args is actually an array, so to get
the same effect you need a pointer to the first element of it and then
you can work with that.  Of course, there's no reason to use a pointer
at all.  An index will work just as well.

Thanks. The array is actually a ptr to an array of strings, like:
char *name[] = { "one","two","three" };
which yes, i guess is different than **argv.
sorry, i am just confused trying to learn. I guess i could make it an
** object like argv and work with it that way.

thanks
 
D

Denis McMahon

I am trying to increment the pointer of this array, similar to
incrementing *argv[]:
*++argv
printf("%s\n", *argv); /* now prints the arg at argv[1]; */
--
code:
char *args[8];
args[0] = "x";
args[1] = "y";
args[2] = "z";

/* if i use:
args++; or
*args++;
i get error:
xxx.c:18: error: wrong type argument to increment
*/

You're declaring an array of pointers to char. Try walking through the
following code:

#include <stdio.h>

int main(int argc, char *argv[])
{
char * args[8];
int i,j;

args[0] = "tiger";
args[1] = "dog";
args[2] = "horse";
args[3] = "pig";
args[4] = "cougar";
args[5] = "lion";
args[6] = "elephant";
args[7] = "leopard";

i = 0;

while (i < 8)
{
j = -1;
while (args[++j] != 0x00);
printf("%s has length %d\n",args[i++],j);
}

return 0;
}

Rgds

Denis McMahon
 
B

Ben Bacarisse

barncat said:
When [] appear in a parameter declaration, it really means *.  I.e. argv
is really a char ** object.  Your args is actually an array, so to get
the same effect you need a pointer to the first element of it and then
you can work with that.  Of course, there's no reason to use a pointer
at all.  An index will work just as well.

It's best to snip sig blocks, even short ones. The way you indicate who
wrote what is usually to have an attribution lines at the top (see, up
there?).
Thanks. The array is actually a ptr to an array of strings, like:
char *name[] = { "one","two","three" };

No, that is an array of (pointers to the start of) strings. When you
write the array name 'name' in most contexts it is converted to a
pointer to the first element. This is where people often get confused.
On it's own, this:

name

is indeed an expression of type char ** -- a pointer to the first
character pointer in the array. But it is a pointer _value_, not a
pointer _object_. It can't be incremented any more than 5 can be
incremented.
which yes, i guess is different than **argv.

Yes, it is. Please forgive the above if you've already "got it" but
your phrase "the array is actually a ptr" suggested that you had not
quite got there yet.
sorry, i am just confused trying to learn. I guess i could make it an
** object like argv and work with it that way.

If you make it a char ** object then there won't be anywhere for the
(pointers to the) strings. You need both: an array to hold the pointers
to the strings, and a char ** that you can increment that points to each
of the char * pointers in the array one after the other.
 
K

Keith Thompson

barncat said:
Thanks. The array is actually a ptr to an array of strings, like:
char *name[] = { "one","two","three" };
which yes, i guess is different than **argv.
sorry, i am just confused trying to learn. I guess i could make it an
** object like argv and work with it that way.

Given the above declaration, name is a pointer to the first element
of an array of char*, where each char* happens to point to (the
first character of) a string. (A pointer to an array is not the same
as a pointer to the array's first element.)

Remember: in spite of several features of C that seem to conspire
to make you think otherwise, arrays are not pointers, and pointers are
not arrays.

Recommended reading: section 6 of the comp.lang.c FAQ,
<http://www.c-faq.com>.
 
M

Morris Keesan

barncat said:
Thanks. The array is actually a ptr to an array of strings, like:
char *name[] = { "one","two","three" };
which yes, i guess is different than **argv.
sorry, i am just confused trying to learn. I guess i could make it an
** object like argv and work with it that way.

Given the above declaration, name is a pointer to the first element
of an array of char*, where each char* happens to point to (the
first character of) a string. (A pointer to an array is not the same
as a pointer to the array's first element.)

Um, ... no. Given the above declaration, name is not any kind of pointer.
It's an array of (char *).

In most cases, when name appears in an expression it will be *converted*
to a pointer to the first element of the array, but name is most definitely
an array, and not a pointer.
Remember: in spite of several features of C that seem to conspire
to make you think otherwise, arrays are not pointers, and pointers are
not arrays.

Remember: even though in usage they usually get converted to pointers,
arrays are not pointers.
 
K

Keith Thompson

pete said:
Keith said:
barncat said:
Thanks. The array is actually a ptr to an array of strings, like:
char *name[] = { "one","two","three" };
which yes, i guess is different than **argv.
sorry, i am just confused trying to learn.
I guess i could make it an
** object like argv and work with it that way.

Given the above declaration, name is a pointer to the first element
of an array of char*, where each char* happens to point to (the
first character of) a string.

It almost seems as though you are saying that
given the above declaration, that (name) is a pointer.

OOPS!

Yes, that's what I was saying, and I wrong.

Memo to self: Engage brain before posting.

Correction: name is an *array* of pointers; each element is of type
char* and points to (the first character of) a string.
 
K

Keith Thompson

Morris Keesan said:
barncat said:
Thanks. The array is actually a ptr to an array of strings, like:
char *name[] = { "one","two","three" };
which yes, i guess is different than **argv.
sorry, i am just confused trying to learn. I guess i could make it an
** object like argv and work with it that way.

Given the above declaration, name is a pointer to the first element
of an array of char*, where each char* happens to point to (the
first character of) a string. (A pointer to an array is not the same
as a pointer to the array's first element.)

Um, ... no. Given the above declaration, name is not any kind of pointer.
It's an array of (char *).

D'oh! You're right, of course. Dumb mistake on my part.
In most cases, when name appears in an expression it will be *converted*
to a pointer to the first element of the array, but name is most definitely
an array, and not a pointer.
Yup.


Remember: even though in usage they usually get converted to pointers,
arrays are not pointers.

Right.
 
B

barncat

D'oh!  You're right, of course.  Dumb mistake on my part.



Right.


Thanks All! My brain hurts after reading and tyring to understand
your explanations. I think i get this now, or at least my program
works now :) Thanks again
 
S

Shao Miller

Thanks All!  My brain hurts after reading and tyring to understand
your explanations. I think i get this now, or at least my program
works now :)  Thanks again
Something else to make your brain hurt: An array has elements of a
fixed size. :) So you cannot have an array of strings of different
length. With pointers to strings, those pointers have a fixed size.
You can have an array of those, then.

char *name[] = { "one","two","three" };

Spiral your way outward beginning towards the right of 'name'. You
hit '[]'. "'name' is an array." You circle back over and hit 'char
*'. "'name' is an array of 'char *'."

Your element count is unspecified between '[]'. The initializer list
will determine the count. The count is 3. "'name' is an array of
'char *' with 3 elements."

The initializer list will determine the initial values.

'"one"' itself has type 'char[4]' (but do not attempt to modify its
contents, in general). When used as an initializer value, '"one"'
yields a 'char *' to the first element ('o'). '"two"' yields a
pointer to its 't', etc. Thus, you have your 'char *' elements for
your 'name' array.

Visually, it might look like this in memory:

First string literal, nul-terminated:
00: ['o'] 01: ['n'] 02: ['e'] 03: [0]

Second string literal, nul-terminated:
04: ['t'] 05: ['w'] 06: ['o'] 07: [0]

Third string literal, nul-terminated:
08: ['t'] 09: ['h'] 10: ['r'] 11: ['e'] 12: ['e'] 13: [0]

The 'name' array of 'char *' with 3 elements:
14: [00] ??: [04] ??: [08]

'??' because the address depends on the size of a 'char *'. This is
merely an example, obviously. :) (The addresses are silly in that
they start at 0 and happen to be "cooked" to be contiguous.)

Hope it helps.
 
E

Eric Sosman

Thanks All! My brain hurts after reading and tyring to understand
your explanations. I think i get this now, or at least my program
works now :) Thanks again
Something else to make your brain hurt: An array has elements of a
fixed size. :) So you cannot have an array of strings of different
length.[...]

Actually, you can. Keeping in mind the definitions of "string"
and "string length,"

char array[][6] = { "forty", "two" };
assert (strlen(array[0]) != strlen(array[1])); // woops!
assert (sizeof(array[0]) == sizeof(array[1])); // granted ...
 
S

Shao Miller

Thanks All!  My brain hurts after reading and tyring to understand
your explanations. I think i get this now, or at least my program
works now :)  Thanks again
Something else to make your brain hurt: An array has elements of a
fixed size. :)  So you cannot have an array of strings of different
length.[...]

     Actually, you can.  Keeping in mind the definitions of "string"
and "string length,"

        char array[][6] = { "forty", "two" };
        assert (strlen(array[0]) != strlen(array[1]));  // woops!
        assert (sizeof(array[0]) == sizeof(array[1]));  // granted ...
Thanks, Eric. :) Let's change it to:

"Something else to make your brain hurt: An array has elements of a
fixed size. :) So you cannot have an array of arrays of 'char' with a
different number of elements for each sub-array."

Of course, one could argue that your array above is _more_ than an
array of strings, due to the padding after the second element. ;)
That is to say, if just one of the strings is long and the others
shorter, the entire array will have lots of padding, so one should be
aware of that.
 
K

Keith Thompson

Shao Miller said:
Thanks All!  My brain hurts after reading and tyring to understand
your explanations. I think i get this now, or at least my program
works now :)  Thanks again
Something else to make your brain hurt: An array has elements of a
fixed size. :)  So you cannot have an array of strings of different
length.[...]

     Actually, you can.  Keeping in mind the definitions of "string"
and "string length,"

        char array[][6] = { "forty", "two" };
        assert (strlen(array[0]) != strlen(array[1]));  // woops!
        assert (sizeof(array[0]) == sizeof(array[1]));  // granted ...
Thanks, Eric. :) Let's change it to:

"Something else to make your brain hurt: An array has elements of a
fixed size. :) So you cannot have an array of arrays of 'char' with a
different number of elements for each sub-array."

Of course, one could argue that your array above is _more_ than an
array of strings, due to the padding after the second element. ;)
That is to say, if just one of the strings is long and the others
shorter, the entire array will have lots of padding, so one should be
aware of that.

Strictly speaking, there's no such thing as an "array of strings". A
string isn't a data type; it's a data format.

In the above, ``array'' is an array of arrays of char; each element is
of type char[6] and *contains* a string.

Consider:

char array[][6] = { "forty", "two" };
/* Is ``array'' an array of strings? */
memcpy(array[0], "abcdef", 6);
memcpy(array[1], "uvwxyz", 6);
/* It certainly isn't now. */

An array of foo is an array of foo regardless of its current contents.
For "foo" = "string", that doesn't work.
 

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

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,163
Latest member
Sasha15427
Top