Pointer arithmetic for list of strings


 
Thread Tools Search this Thread
Top Forums Programming Pointer arithmetic for list of strings
# 1  
Old 05-25-2013
Pointer arithmetic for list of strings

When i want to use a list of strings
Code:
char *list[];

i never understand it well.

Here is an easy example. It took me long to figure it out, searching the web didn't help much:
Code:
#include <stdio.h>


int main(void)
{
        char *list[] = {"foo", "bar", "baz"};
        char **pl;
        int len = sizeof(list)/sizeof(&list);
        int i = 0;


        for (pl = list; i < len; i++) {
                printf("%s\n", *pl++);
        }

        /*segfault after baz 
        while ( *pl ) {
                printf("%s\n", *pl++); 
        }
       */

        /*      
        for (i = 0; i < len; i++) {
                printf("%s\n", list[i]); 
        }

        */

        return 0;
}
~

1) I don't understand why the size of len is computed that way.
2) If i loop with while over list instead of pl, i get a error complaining an lvalue would be required.
3) I would prefer to use pointer arithmetic, but i never get it sorted. If i use the index i instead it works

Thanks for explanations or a link where it is explained with examples.
# 2  
Old 05-25-2013
Here is a modified version of your code with a few changes and lots of comments added. Please read through the code, examine the output, and let me know if something is still confusing:
Code:
#include <stdio.h>

int main(void)
{       /* Note that list is terminated by a NULL pointer. */
        char *list[] = {"foo", "bar", "baz", NULL};
        char **pl;
        int i;
        /* The common way of setting the number of elements in an array is
        ** to divide the size of the array by the size of the 1st element
        ** in the array.
        */
        int len = sizeof(list)/sizeof(list[0]);

        /* When using 64 bit pointers, each pointer is 8 bytes long. */
        printf("sizeof(list) = %d, sizeof(list[0]) = %d, len = %d\n",
                (int)sizeof(list), (int)sizeof(list[0]), len);

        printf("\nPrinting list using *pl while i < len:\n");
        /* Set pl to the address of the first element in the array list.
        ** Note that in C "list" and "&list[0]" are synonyms.
        */
        for (pl = list, i = 0; i < len; i++, pl++) {
                /* Print the pointer to the pointer. */
                printf("pl = %p\t", pl);        /* &list[i] */
                /* Print the pointed to pointer. */
                printf("*pl = %p\t", *pl);      /* list[i]  */
                /* Print the string pointed to by the pointer to the pointer. */
                printf("%s\n", *pl ? *pl : "NULL pointer");
        }

        printf("\nPrinting list using *pl while *pl != NULL:\n");
        /* If list[]'s last element is not a NULL pointer, this loop will
        ** use random pointers following the array and try to interpret them
        ** as pointers to character strings.  If one of those random values
        ** points outside the address space of the process, we'll get a memory
        ** fault.
        */
        for(pl = list; *pl; printf("%s\n", *pl++));

        printf("\nPrinting list using list[i]:\n");
        for (i = 0; i < len; i++) {
                printf("list[%d] = %p\t", i, list[i]);
                printf("%s\n", list[i] ? list[i] : "NULL pointer");
        }

        return 0;
}

When compiled as a 64-bit application and run on OS X this produces:
Code:
sizeof(list) = 32, sizeof(list[0]) = 8, len = 4

Printing list using *pl while i < len:
pl = 0x7fff6de4db08	*pl = 0x10e24ee70	foo
pl = 0x7fff6de4db10	*pl = 0x10e24ee74	bar
pl = 0x7fff6de4db18	*pl = 0x10e24ee78	baz
pl = 0x7fff6de4db20	*pl = 0x0	NULL pointer

Printing list using *pl while *pl != NULL:
foo
bar
baz

Printing list using list[i]:
list[0] = 0x10e24ee70	foo
list[1] = 0x10e24ee74	bar
list[2] = 0x10e24ee78	baz
list[3] = 0x0	NULL pointer

These 2 Users Gave Thanks to Don Cragun For This Post:
# 3  
Old 05-25-2013
Thanks, that makes it clear, especially all the comments. Main problem seems to have been to set the last element to NULL.

Divide sizeof the list by sizeof the first element i can remember. It is still a bit unclear, but i guess i confuse the strlen of the first element with sizeof (if i change the strlen of an element and then use sizeof, i always get the same size, 4 in my case).

I don't understand why i get the error: lvalue required if i increment list itself.

The both slightly unclear questions are minor problems for me (only to fully understand it, out of interest). I guess and hope it will be more clear when i understand more about C.

Thanks again.
# 4  
Old 05-25-2013
Quote:
Originally Posted by tornow
Thanks, that makes it clear, especially all the comments. Main problem seems to have been to set the last element to NULL.

Divide sizeof the list by sizeof the first element i can remember. It is still a bit unclear, but i guess i confuse the strlen of the first element with sizeof (if i change the strlen of an element and then use sizeof, i always get the same size, 4 in my case).

I don't understand why i get the error: lvalue required if i increment list itself.

The both slightly unclear questions are minor problems for me (only to fully understand it, out of interest). I guess and hope it will be more clear when i understand more about C.

Thanks again.
The size of a pointer to a character is a constant in any particular program; whether that pointer points to a single character or to a nul-byte terminated string of 100 characters does not affect the size of the pointer.

In your program, list is the address where an array of pointers to characters is stored. The statement:
Code:
list++;

would be an attempt to move that array to a new location in memory. Since you can't do that, the C compiler won't allow it.

You could allocate space for an array of pointers (such as by using malloc() or mmap()), set up a pointer to a pointer that points to the start of that newly allocated space, copy pointers into that space and increment that pointer to a pointer. You could allocate more space for a copy of that array of pointers and copy the array to the new space, etc., but that is a different lesson.
This User Gave Thanks to Don Cragun For This Post:
# 5  
Old 05-25-2013
Ok, thanks a lot. You explained it very good. I ran into the problem a couple of times, but nothing i found really made it clear. I think i got it now.
# 6  
Old 05-26-2013
After Don's explanations, this is probably not necessary, but here it is in case it helps: comp.lang.c FAQ :: 6.2 :: But I heard that char a[] was identical to char *a.

Regards,
Alister
# 7  
Old 05-26-2013
No, any additional info is very welcome. Both, pointers and the whole subject of memory, is very hard for me, in general.

Reading the FAQ about name[3] and *name i think this: I am quite sure that i read somewhere (K&R?) that the compiler immediatly translates the one to the other ( i think indexed to pointers). All i can find in my book is this: "There is one difference between and array name and a pointer that must be kept in mind. A pointer is a variable, pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal"

I am not sure, but i think what i wrote above, that list++ gives me an lvalue error, is related? After Don's explanation: In your program, list is the address where an array of pointers to characters is stored. The statement: list++ would be an attempt to move that array to a new location in memory. Since you can't do that, the C compiler won't allow it."
i seem to be sure, but it won't hurt to ask if i am right.

side note: I am never sure about the right terminology. Please correct me if i use terms wrong.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. UNIX for Beginners Questions & Answers

How to pass strings from a list of strings from another file and create multiple files?

Hello Everyone , Iam a newbie to shell programming and iam reaching out if anyone can help in this :- I have two files 1) Insert.txt 2) partition_list.txt insert.txt looks like this :- insert into emp1 partition (partition_name) (a1, b2, c4, s6, d8) select a1, b2, c4, (2 Replies)
Discussion started by: nubie2linux
2 Replies

2. Programming

unidirectional linked list pointer problem

I am trying to test some operations on a directed list. However, the declaration of a pointer is giving me trouble. I seem to have done something incorrectly because I get an error: "listtest.c:29: warning: 'p' may be used uninitialized in this function" Can anyone help? This is my code... (6 Replies)
Discussion started by: bluetxxth
6 Replies

3. Shell Programming and Scripting

Take a list if strings from a file and search them in a list of files and report them

I have a file 1.txt with the below contents. -----cat 1.txt----- 1234 5678 1256 1234 1247 ------------------- I have 3 more files in a folder -----ls -lrt------- A1.txt A2.txt A3.txt ------------------- The contents of those three files are similar format with different data values... (8 Replies)
Discussion started by: realspirituals
8 Replies

4. UNIX for Dummies Questions & Answers

Delete strings in file1 based on the list of strings in file2

Hello guys, should be a very easy questn for you: I need to delete strings in file1 based on the list of strings in file2. like file2: word1_word2_ word3_word5_ word3_word4_ word6_word7_ file1: word1_word2_otherwords..,word3_word5_others... (7 Replies)
Discussion started by: roussine
7 Replies

5. Shell Programming and Scripting

Strings to integers in an arithmetic loop

Hi all, Could someone please advise what is the correct syntax for my little script to process a table of values? The table is as follows: 0.002432 20.827656 0.006432 23.120364 0.010432 25.914184 0.014432 20.442655 0.018432 20.015243 0.022432 21.579517 0.026432 18.886874... (9 Replies)
Discussion started by: euval
9 Replies

6. Programming

Pointer Arithmetic In C

I have a fundamental question on C pointer arithmetry.. Suppose i have a c string pointer already pointing to a valid location, Can I just do a charptr = charptr +1; to get to the next location, irregardless if my program is 32 or 64 bits? or should i do it this way: charptr =... (1 Reply)
Discussion started by: Leion
1 Replies

7. Programming

linked list node with pointer to struct

Suppose to have: struct Tstudent { string name, surname; int matriculation_num; }; struct Tnode { Tstudent* student; Tnodo* next; } L;I want to deference that "student" pointer. For example, I tried with: *(L->student).matriculation_numbut it not worked, as terminal... (4 Replies)
Discussion started by: Luke Bonham
4 Replies

8. Shell Programming and Scripting

ksh-script "arithmetic syntax error" comparing strings

Hi all, Iīve already searched the forum but canīt find what i am doing wrong. I am trying to compare two variables using ksh under red hat. The error I get is: -ksh: .: MDA=`md5sum /tmp/ftp_dir_after_transfer | cut -d' ' -f1 ` MDB=`md5sum /tmp/ftp_dir_before_transfer | cut -d' ' -f1 `... (3 Replies)
Discussion started by: old_mike
3 Replies

9. Programming

pointer arithmetic vs. strlen() & strnlen()?

I have been getting some flack recently for my use of strlen() and strnlen(). Honestly I have always just taken their functionality for granted as being the easiest way of getting the length of a string. Is it really so much better to do pointer arithmetic? What am I gaining besides more... (3 Replies)
Discussion started by: jjinno
3 Replies

10. Programming

pass a pointer-to-pointer, or return a pointer?

If one wants to get a start address of a array or a string or a block of memory via a function, there are at least two methods to achieve it: (1) one is to pass a pointer-to-pointer parameter, like: int my_malloc(int size, char **pmem) { *pmem=(char *)malloc(size); if(*pmem==NULL)... (11 Replies)
Discussion started by: aaronwong
11 Replies
Login or Register to Ask a Question