Thread: 2D char array and pointer

  1. #1
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    2D char array and pointer

    Is this okay:
    Code:
    #include <stdio.h>
    
    void testfunc(char **ray) {
    	printf("%c\n",ray[2][2]);		
    }
    
    
    int main () {
    	char *ray[5][12]={"this","that","and","more"};
    	testfunc((char**)ray);
    	return 0;
    }
    I have been doing it this way for awhile, since it's the only way to pass a "list" to a parameter "char **" without using malloc, and there is no way to assign a functional pointer to char list[5][12]. But today I am thinking that char *list[5][12] might not be what I hope that it is. Altho if it's not, I'm not sure what it would be...
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    No, because a char ** is not the same as a char [5][12] or some such. They may appear similar, but when you pass the pointer to char[5][12], you are actually passing a pointer to (*char)[12], not the address of an array of pointers to char.

    In this case, you must supply all but the left-most size, e.g.
    Code:
    void testfunc(char ray[][12]) {
    	printf("%c\n",ray[2][2]);		
    }


    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Further, this is an array of const char* pointers, not a 2D array, which makes it even more wrong.
    Of course, since it's an array of pointers, it just happens to work:
    Code:
    #include <stdio.h>
    
    void testfunc(const char** ray)
    {
    	printf("%c\n", ray[2][2]);		
    }
    
    int main ()
    {
    	const char* ray[] = { "this", "that", "and", "more" };
    	testfunc(ray);
    	return 0;
    }
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    Further, this is an array of const char* pointers, not a 2D array, which makes it even more wrong.
    The code posted is valid (besides the passing to the function part, that is), it initializes a set of 12-element arrays to the values given by the initializer list.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by matsp View Post
    No, because a char ** is not the same as a char [5][12] or some such. They may appear similar, but when you pass the pointer to char[5][12], you are actually passing a pointer to (*char)[12], not the address of an array of pointers to char.
    By (char*)[12], do you mean:
    • an array of twelve pointers
    • a pointer with the size of 12?

    If it is the former, then there really is not a problem (since all the elements will have the same "number", each element of (char*)[12] will be an element of *ray[5]. I suppose the stack size of **ray in testfunc() will be 12x instead of 5x.

    What I am mostly worried about is the notation *ray[5][12] implies I could actually have a 3Dish array (a 2D pointer array) and that the "elements" to which I am assigning strings may have sizeof(char*) and not 12. For example, I can now compile this with char *ray[5][12]:
    Code:
    printf("%s\n",ray[0][0][0]);
    where char ray[5][12] would produce a subscipted value error. It segfaults tho.

    SInce I don't seem to be producing an overflow (no GUI debugger...) with it, apparently *ray[5][12] is really a 2D char array (a "list") with a pointer to it? Just using ray[5][12] makes a **pointer impossible.

    To make a long story short: you don't see a potential overflow in main(), just a possible exceeding of boundaries in testfunc() with the number of elements?

    I'm guessing this is because it's easier for the compiler to use an array of pointers with 12 bytes assigned to each rather than to use a pointer to an array of elements with a size of 12 each. So there is no pointer to such a thing possible.

    ps. I really really want **char as the argument to testfunct()
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by matsp View Post
    The code posted is valid (besides the passing to the function part, that is), it initializes a set of 12-element arrays to the values given by the initializer list.

    --
    Mats
    Perhaps the code is correct, but I do question if it's intended. Clearly, it is an array of strings, and as thus, in its current form, should be an array of pointer or a 2D array.

    Quote Originally Posted by MK27 View Post
    By (char*)[12], do you mean:
    • an array of twelve pointers
    • a pointer with the size of 12?
    No, it's a pointer to an array of 12 elements of type char*.
    The actual type should be char (*)[5].

    Code:
    #include <stdio.h>
    
    void testfunc(char (*ray)[5])
    {
    	printf("%c\n", ray[2][2]);		
    }
    
    int main ()
    {
    	char ray[12][5] = {"this", "that", "and", "more"};
    	testfunc(ray);
    	return 0;
    }
    Last edited by Elysia; 02-10-2009 at 02:35 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Sorry, I missed the (very obvious) red star in the original post.

    Still, a 2D array is not a pointer to pointer. If you want to do that, then do what Elysia says.

    If you want a 2D array of char, and need a pointer to that [e.g. you want to modify the content of the strings in an array of strings], then you need to pass the length of the strings.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Elysia View Post
    Of course, since it's an array of pointers, it just happens to work:
    That's it. I just noticed it functions as a 3D array in main.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I imagine yours does, because array are laid out sequentially in memory. It just happens to work, but I would definitely say it's undefined.
    EDIT: It might just work because you have a pointer to the array (all arrays, 2D or whatever are essentially just one pointer anyway), and as the array is storing pointers, you have an extra pointer in the type and it... works. But if you change it to a 2D array or 3D array you will get trouble.
    Last edited by Elysia; 02-10-2009 at 02:50 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Hmmm...okay I just noticed this seems to work very nicely, it's only slightly more limited but it still saves a lot of potential malloc and strcpy. I suppose it is the same as just using char[][12] except I can use actual pointers in testfunc() (rather than a local copy):
    Code:
    #include <stdio.h>
    #include <string.h>
    
    typedef struct {
    	char X[256];
    } string;
    
    void testfunc(string *ray) {
    	printf("%s\n",(char*)&ray[2]);
    	strcpy((char*)&ray[3],"well done");
    }
    
    
    int main () {
    	string ray[4]={"this and that","more and","hello world"};
    	testfunc(ray);
    	printf("%s\n",(char*)&ray[3]);		
    	return 0;
    }
    You actually don't even need the (char*) casts. The only issue seems to be that -Wall claims:
    Code:
    test2.c: In function ‘main’:
    test2.c:14: warning: missing braces around initializer
    test2.c:14: warning: (near initialization for ‘ray[0]’)
    Is this significant and can I get out of it?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I believe it must be:
    Code:
    string ray[4] = { { "this and that" }, etc };
    One initializer for each struct in the array and one for each member in the struct.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    You can get rid of the warning by doing:
    Code:
    	string ray[4]={{"this and that"},{"more and"},{"hello world"}};
    Which is exactly what the compiler told you anyways.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Thanks again people.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  14. #14
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Perhaps you meant to print the string instead of the character it points to - and here's my 2c.
    Code:
    #include <stdio.h>
    
    void testfunc(const char *ray[][12])
    {
        printf("%s\n",ray[0][2]);
    }
    
    int main()
    {
        const char *ray[5][12]={"this","that","and","more"};
        testfunc(ray);
        return 0;
    }

  15. #15
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by itCbitC View Post
    Perhaps you meant to print the string instead of the character it points to - and here's my 2c.
    Perhaps you should have -- nevermind. Anyway all the code I posted works in the way I describe it as working, I wasn't asking for that kind of fix.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 07-11-2008, 07:39 AM
  2. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  3. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM
  4. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM
  5. convert long to pointer to char array
    By gazmack in forum C++ Programming
    Replies: 5
    Last Post: 09-26-2003, 11:33 AM

Tags for this Thread