Thread: array of pointers/pointer arithmetic

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    7

    Unhappy array of pointers/pointer arithmetic

    Long time troll, first time poster... I have some problems understanding arrays containing pointers. Take this fragment for example:
    Code:
            char *a[3];
    	char d[50] = {'a', 'b', 'c'};
    
    	*(*(a + 0) + 0) = *(d + 0);
    	*(*(a + 0) + 1) = *(d + 1);
    	*(*(a + 0) + 2) = *(d + 2);
    	*(*(a + 0) + 3) = *(d + 3);
    
            printf("%c",*(*(a + 0) + 0));
    	printf("%c",*(*(a + 0) + 1));
    	printf("%c",*(*(a + 0) + 2));
    Which should print out "abc" without the quotes... The following explanation is shody at best so please bare with me...

    From what I understand, array 'a' contains three members of type pointer to a char array. The actual data contained in these 3 memory adresses are actually of type int, where an int represent the address of the actual char array. So take for example the line *(*(a + 0) + 0) = *(d + 0); ...
    Starting from the innermost parentheses, the code states--
    #1. (a + 0)..... take the starting memory adress of a, that is a[0], and add this to sizeof(type) multiplied by 0... So I am at the level of a[0] which once again contains a pointer to the first element of char array
    #2. *(a + 0) + 0..... Now take what a[0] points to, which is the starting address of the first char array, and deference the value, which should now give me the starting address of the single character at the beginning of the char array. Thus *(a + 0) + 1 should be the address of the second member of the char array and so on
    #3. *(*(a + 0) + 0) = *(d + 0)..... Finally, deference the address of the char array and give me it's value, which should be of type char, and assign d[i] as it's value;

    Now the above only works if I add nothing else to the program, that is-- when i try this with reading lines of text from a file all hell breaks loose. I suspect my pointer arithmetic and logic as detailed above is flawed. If i had to guess, I would say since I did not specify the array size when i declared the variable, the array only contains one single member, so adding sucessive members to char array will work in very limited situations and through side effects -- That is, I am printing the values from beyond my array but since there was nothing there and nothing will go in that address I got away with it.

    Now you can probably guess what I am trying to do here...
    Code:
            char *a[3];
    	char *b[3];
    	char *c[3];
    	
    	char **all[3] = {a,b,c};
    So with one line of code, say *(*(*(all + 1) + 2) + 10), I can tell the program to put whatever data into the 11th character position of array *b[2]. What seemed so simple at first really has me scratching my head. Any corrections to my faulty logic/ suggestions would be appreciated. Thank you.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > From what I understand, array 'a' contains three members of type pointer to a char array.
    So far, so good.
    However, the rest of it is off in the weeds somewhere.
    Your use of "int" is just plain wrong I'm afraid.

    The first problem is that although the type is correct, you didn't actually do something like
    a[0] = some_block_of_memory_of_type_char*
    before you did
    a[0][0] = aChar;

    For instance, in this particular code segment, you could do
    a[0] = malloc( 4 );


    > Now the above only works if I add nothing else to the program, that is-- when i try this with reading lines of text from a file all hell breaks loose.
    Yup, C will let you walk into a minefield, but won't necessarily blow you up at the first problem.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by tlpog View Post
    #2. *(a + 0) + 0..... Now take what a[0] points to, which is the starting address of the first char array, and deference the value, which should now give me the starting address of the single character at the beginning of the char array. Thus *(a + 0) + 1 should be the address of the second member of the char array and so on
    *(a + 0) + 1 adds 1 to whatever a[0] is pointing to; eg if a[0] points to the string "hello world" then *(a + 0) + 1 adds 1 to 'h' giving you the character 'i' which is not an lvalue. So *(a + 0) + 1 is not the address of the second member of the char array but (a + 0) + 1 is actually a[1].
    Ofcourse I'm assuming that you are on a machine with an ASCII character set not EBCDIC.
    Last edited by itCbitC; 11-09-2008 at 11:46 AM.

  4. #4
    Registered User
    Join Date
    Nov 2008
    Posts
    7
    thanks for the quick reply salem.. I definately suspected something to do with memory allocation... guess it's time for me to learn something new

  5. #5
    Registered User
    Join Date
    Nov 2008
    Posts
    7
    If i understand your comment itCbitC, you are saying *(a + 0) + 1 adds 1 to ASCI of 'h', which of course returns a junk value. Maybe I need a clarification of what this decleration : char *a[3]; ... really means. Now from my understanding a contains 3 members each a pointer. Each pointer points to the starting address of the char array. So by saying *(a + 0) + 1 I am saying add 0 to the top level, deference that value... so now we get the address of the char array and NOT the ASCI value which means i can continue with the pointer arithmetic? So saying *(a + 0) returns the base adress while *(a + 0) + 3 returns the base adress + 3... Did what i just say complete B.S?

  6. #6
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by tlpog View Post
    If i understand your comment itCbitC, you are saying *(a + 0) + 1 adds 1 to ASCI of 'h', which of course returns a junk value. Maybe I need a clarification of what this decleration : char *a[3]; ... really means. Now from my understanding a contains 3 members each a pointer.
    Yes that is correct.
    Quote Originally Posted by tlpog View Post
    Each pointer points to the starting address of the char array.
    Need not be an array of char...could be just one char.
    Quote Originally Posted by tlpog View Post
    So by saying *(a + 0) + 1 I am saying add 0 to the top level, deference that value... so now we get the address of the char array
    Yes you are getting the address of the char array by dereferencing it.
    If a[0] points to the string "hello" then *a[0] accesses the letter 'h' and *(a +0) + 1 adds one to the contents of a[0].
    I apologize if I confused you. I wound myself into knots too. Well that's what happens when one multitasks.
    Last edited by itCbitC; 11-09-2008 at 12:29 PM. Reason: goofed not!

  7. #7
    Registered User
    Join Date
    Nov 2008
    Posts
    7
    I screwed some based on your suggestions ItsC...

    Code:
    char *a[3] = {"AEI", "OUY", "JKL"};
    	printf("OUTPUT 1: %c\n", *a[0]); //Accesses the letter A
    	printf("OUTPUT 2: %c\n", *(a[0] + 1)); // Accesses a the string and adds 1
    	// then deferences it
    	printf("OUTPUT 3: %c\n", *(a[0] + 2)); // and again
    	
    	//But...
    	(*a[0]) = 'p';
    	printf("OUTPUT 4: %c\n", *a[0]); // doesn't work... i don't get output
    OUTPUT 1: A
    OUTPUT 2: E
    OUTPUT 3: I

    Does it mean the strings in a[3] are const? Since now i definately know there is memory allocated for the *a[0] spot.

    So based on the most recent comment...

    Code:
    *(*(a + 0) + 0) = 'p';
    	printf("OUTPUT 4: %c\n", *a[0]);
    still no dice... i am trying to say- #1. Take the array of a and add 0 to it so we get a[0] #2 defference that so we get the adresse of *a[0] #3 add 0 to that so we are point at the first element of *a[0] or the first element of the string AEI which is A #4 deference that value again so now we get the ASCI of A... which I assume if the type is not constant i can assign 'p' to
    Last edited by tlpog; 11-09-2008 at 01:01 PM. Reason: sorry, failed to see your edit

  8. #8
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by tlpog View Post
    I screwed some based on your suggestions ItsC...
    I apologize as I got somewhat mixed up with this roundabout way of initializing array elements.
    Quote Originally Posted by tlpog View Post
    Code:
    char *a[3] = {"AEI", "OUY", "JKL"};
    	printf("OUTPUT 1: %c\n", *a[0]); //Accesses the letter A
    	printf("OUTPUT 2: %c\n", *(a[0] + 1)); // Accesses a the string and adds 1
    	// then deferences it
            printf("OUTPUT 3: %c\n", *(a[0] + 2)); // and again
    This walks along the first string "AEI" and that's why the output 'E' is as expected. To print the letter B add 1 to A as in *a[0] + 1.
    Quote Originally Posted by tlpog View Post
    //But...
    (*a[0]) = 'p';
    printf("OUTPUT 4: %c\n", *a[0]); // doesn't work... i don't get output[/CODE]
    Can't do this because it's of the type const char.
    Quote Originally Posted by tlpog View Post
    OUTPUT 1: A
    OUTPUT 2: E
    OUTPUT 3: I

    Does it mean the strings in a[3] are const? Since now i definately know there is memory allocated for the *a[0] spot.
    Yes the strings in a[3] are const and sure enough there is memory allocated for storing each of those strings.

  9. #9
    Registered User
    Join Date
    Nov 2008
    Posts
    7
    Thank you salem and itC for the comments... I think I have enough info now to correct the problem. If i declare something like *a[3]; without initializing the variable with const data and later allocating memory to the arrays i should be able to modify each element of *a[i] with whatever data i choose

  10. #10
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by tlpog View Post
    Thank you salem and itC for the comments... I think I have enough info now to correct the problem. If i declare something like *a[3]; without initializing the variable with const data and later allocating memory to the arrays i should be able to modify each element of *a[i] with whatever data i choose
    Yes that approach lets you modify *a[i].

  11. #11
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by tlpog View Post
    Code:
    *(*(a + 0) + 0) = 'p';
    	printf("OUTPUT 4: %c\n", *a[0]);
    still no dice... i am trying to say- #1. Take the array of a and add 0 to it so we get a[0] #2 defference that so we get the adresse of *a[0] #3 add 0 to that so we are point at the first element of *a[0] or the first element of the string AEI which is A #4 deference that value again so now we get the ASCI of A... which I assume if the type is not constant i can assign 'p' to
    imho by stepwise dissecting the expression *(*(a + 0) + 0) as in
    a + 0 is a pointer to the first element of a ie a + 0 == &a[0].
    *(a + 0) applies dereferencing to obtain a[0].
    *(a + 0) + 0 points to the same place that a[0] is pointing to.
    *(*(a + 0) + 0) accesses the object that a[0] is pointing to ie 'A' in this case.

  12. #12
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by itCbitC View Post
    imho by stepwise dissecting the expression *(*(a + 0) + 0) as in
    a + 0 is a pointer to the first element of a ie a + 0 == &a[0].
    *(a + 0) applies dereferencing to obtain a[0].
    *(a + 0) + 0 points to the same place that a[0] is pointing to.
    We were doing fine up to right here. *(a+0) is a character a[0], adding 0 to it gives us the same character.
    Quote Originally Posted by itCbitC View Post
    *(*(a + 0) + 0) accesses the object that a[0] is pointing to ie 'A' in this case.
    And this is just an error.

  13. #13
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by tabstop View Post
    We were doing fine up to right here. *(a+0) is a character a[0], adding 0 to it gives us the same character.

    And this is just an error.
    care to explain if you please what you mean by the above statement??

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by itCbitC View Post
    care to explain if you please what you mean by the above statement??
    What it means is that I can't read. We have an array of char *, not of char as I had originally read it. So yes what you said is what we have. Sorry.

  15. #15
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    ah ha! yes I had made the same mistake earlier

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 11-25-2008, 01:50 AM
  2. 1-D array
    By jack999 in forum C++ Programming
    Replies: 24
    Last Post: 05-12-2006, 07:01 PM
  3. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM
  4. Array Program
    By emmx in forum C Programming
    Replies: 3
    Last Post: 08-31-2003, 12:44 AM
  5. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM