Thread: Multi-dimensjonal (char) array

  1. #1
    Registered User
    Join Date
    Nov 2009
    Posts
    111

    Multi-dimensjonal (char) array

    Ok, I'm struggling a bit again. This time it's the concept of multi-dimensional char arrays.

    A one-dimensional array works like this:
    Code:
    char str[15];
    string(str);
    
    void string(char *str) {
    	printf("%s\n", str);
    }
    However, when I create a multi-dimensional array and try to pass it to a function in the same way, like this:
    Code:
    void mstring(char *);
    
    char mstr[5][10];
    string(mstr);
    
    void mstring(char *mstr) {
    	// something
    }
    I get the following warnings:

    Code:
    warning: passing argument 1 of ‘mstring’ from incompatible pointer type (points to the line with the function call, string(mstr);)
    note: expected ‘char *’ but argument is of type ‘char (*)[10]’ (points to the prototype for the mstring function)
    I'm _beginning_ to grasp the concept of pointers, but there's still a long way to go. However, I'm not sure if a two-dimensional array is a pointer to a pointer, or a pointer with pointers to arrays?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by cnewbie1
    However, I'm not sure if a two-dimensional array is a pointer to a pointer, or a pointer with pointers to arrays?
    mstr is an array of 5 arrays of 10 char. It is neither a pointer to a pointer nor a pointer with pointers to arrays. However, it can be converted to a pointer to an array of 10 char. This is still different from a pointer to a pointer, and certainly different from a pointer to a char.

    For example:
    Code:
    void foo(char (*y)[10]);
    
    int main(int argc, char *argv[])
    {
        char x[5][10];
        foo(x);
        return 0;
    }
    
    void foo(char (*y)[10])
    {
        y[0][0] = '\0';
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    It's a question of how you envision it...

    If you have: char Strings[10][50]

    You have 10 buffers (or lines) of 50 characters each.

    Strings points to the first line first character Strings[0][0].

    Strings[1] is actually a pointer to the second buffer, first character.

    Strings[3][30] is the character at the 4th buffer, 31st position.

    If it looks like I'm missing by one... I am. Don't forget that C arrays always index from 0, not 1.
    Last edited by CommonTater; 10-21-2010 at 04:38 AM.

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by CommonTater View Post
    Strings points to the first line first character Strings[0][0].
    No, it does not.

    Strings is not a pointer to char, and also cannot be implicitly converted to a pointer to char, so cannot point at Strings[0][0].

    If you want evidence of that, you will find that the test
    Code:
    if (Strings == &(Strings[0][0])) {}
    will not even compile.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    Registered User
    Join Date
    Nov 2009
    Posts
    111
    Ah, thanks a heap. So simple, really - I should've examined the warning(s) more closely.

    I was confusing arras/pointers, of course, with that last question. Probably because of the relationship between arrays and pointers.

  6. #6
    Registered User
    Join Date
    Nov 2009
    Posts
    111
    But, there's more:

    When returning arrays from functions, this works:
    Code:
    char *string2(char *);
    
    char buf[15];
    char str2 = *string2(buf);
    printf("%s\n", buf);	
    
    char *string2(char *buf) {
    	strcpy(buf, "Textstring 2");
    	return buf;
    }
    However, doing the same thing with a 2-dimensional array doesn't work:
    Code:
    char *mstring2(char (*)[10]);
    
    char mbuf[5][10];
    char mstr2 = *mstring2(mbuf);
    
    char *mstring2(char (*buf)[10]) {
            // Do something...fill the arrays...
    	return buf;
    }
    This gives:
    Code:
    warning: return from incompatible pointer type

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by cnewbie1
    However, doing the same thing with a 2-dimensional array doesn't work:
    I suggest that you make use of a typedef, e.g.,
    Code:
    #include <stdio.h>
    
    typedef char string_type[10];
    
    string_type *foo(string_type *y);
    
    int main(void)
    {
        string_type x[5];
        string_type *r = foo(x);
        printf("%c\n", r[0][0]);
        return 0;
    }
    
    string_type *foo(string_type *y)
    {
        y[0][0] = 'C';
        return y;
    }
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Nov 2009
    Posts
    111
    Thanks, laserlight. Typedef it is, then. I'm guessing, since you're suggesting that, it's not possible to pass a multi-dimensional array like I tried?

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by CommonTater View Post
    Strings[1] is actually a pointer to the second buffer, first character.
    You're thinking of an array of pointers - in this case, the entire array is one contiguous block of data.

    Code:
    int main( void )
    {
        const int rows = 13, cols = 2;
        char data[ rows ][ cols ];
        int ltr = 'a';
        for( int rdx = 0; rdx < rows; ++rdx )
        {
            for( int cdx = 0; cdx < cols; ++cdx )
            {
                data[ rdx ][ cdx ] = ltr++;
            }
        }
    /*
        Out of bounds?
    */    
        data[ 0 ][ 'j' - 'a' ] = '!';
        for( int rdx = 0; rdx < rows; ++rdx )
        {
            for( int cdx = 0; cdx < cols; ++cdx )
            {
                putchar( data[ rdx ][ cdx ] );
            }
            putchar( '\n' );
        }
    }
    Last edited by Sebastiani; 10-21-2010 at 04:12 PM. Reason: cleanup
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    Registered User
    Join Date
    Oct 2010
    Posts
    5
    just put an asterisk before mstr. multidimensional arrays are address of address of (address of) something.


    Code:
    void mstring(char *);
    
    char mstr[5][10];
    mstring(*mstr);   <----- there you go
    
    void mstring(char *mstr) {
    	// something
    }

  11. #11
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Quote Originally Posted by scout
    multidimensional arrays are address of address of (address of) something.
    This is not true. Arrays are not pointers. A multidimensional array is an array of array (of array ...).

    It's true that in almost all circumstances, an array decays into a pointer. But as has been mentioned, an array of array does not decay into a pointer to pointer; it decays into a pointer to an array. A multidimensional array is one of the cases where the difference between a pointer and an array is important.

  12. #12
    Registered User
    Join Date
    Nov 2009
    Posts
    111
    scout: That works with a void method, as mentioned further up. But with a char method, receiving and returning a multi-dimensional array, I cannot get it to work that way. Using a typedef, however, worked beautifully.

  13. #13
    Registered User
    Join Date
    Oct 2010
    Posts
    5
    Quote Originally Posted by cnewbie1 View Post
    scout: That works with a void method, as mentioned further up. But with a char method, receiving and returning a multi-dimensional array, I cannot get it to work that way. Using a typedef, however, worked beautifully.
    mstring2 takes a multidimensional array and returns the same multidimensional array address (the mstr2 becomes a single array though). just play with it and hopefully it'll help. . yeah the typedef solution is sweet.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    char *mstring2(char *);
    
    int main(void)
    {
        char mbuf[5][10];
        char *mstr2 = mstring2(*mbuf);  // takes a multidimensional array and returns multidimensional array (address)
       
                printf("%p\n", mstr2);               // check if equal
                printf("%p\n", &mbuf[0][0]);         // 
          
        printf("this should be 49 = %d\n",mbuf[4][9]);
        printf("this should be 1 = %d\n",mbuf[0][1]);
        char k = 'k';
        char p = 'p';
        *(mstr2+(4*10)+9) = 3;                      
        *(mstr2+(0*10)+1) = k;
        *(mstr2+(1*10)+1) = p;
        printf("this should be 3 = %d\n",mstr2[49]);
        printf("this should be 3 = %d\n",mbuf[4][9]);
        printf("this should be k = %c\n",mbuf[0][1]);
        printf("this should be p = %c\n",mbuf[1][1]);
    
        getchar();
        return 0;
    }
    
    char *mstring2(char *k) {
        
        for (int i=0;i<50; i++)
        {
            *(k+i) = i;
        }
    	return k;
    }
    Last edited by scout; 10-23-2010 at 06:27 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ ini file reader problems
    By guitarist809 in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2008, 06:02 AM
  2. newbie needs help with code
    By compudude86 in forum C Programming
    Replies: 6
    Last Post: 07-23-2006, 08:54 PM
  3. Obtaining source & destination IP,details of ICMP Header & each of field of it ???
    By cromologic in forum Networking/Device Communication
    Replies: 1
    Last Post: 04-29-2006, 02:49 PM
  4. NULL terminating a multi dim char array
    By NickESP in forum C++ Programming
    Replies: 2
    Last Post: 02-05-2003, 03:43 PM