passing 2D array in C – some mistakes and tips

// This is an example source file which is used to show common
// mistakes and tips when passing 2D array as a parameter to a
// function call in C/C++ programming.
// Feb 19, 2011
// dave.tian@alcatel-lucent.com

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define PRINT_ADDR( _var)                                      
        do                                                     
        {                                                      
                printf("addr of var     : 0x%xn", (_var));    
                printf("addr of var[0]  : 0x%xn", (_var)[0]); 
                printf("addr of var[1]  : 0x%xn", (_var)[1]); 
        }                                                      
        while(0);

void subFunc1( char **string)
{
        // SegV
        // Like the gcc’s warning:
        // warning: passing arg 1 of `subFunc1′ from incompatible pointer type
        // Pointer to pointer of char is NOT parameter type of 2-D array
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
}

void subFunc2( char string[][100])
{
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
}

void subFunc3( char *string[2])
{
        // SegV
        // Like the gcc’s warning:
        // warning: passing arg 1 of `subFunc3′ from incompatible pointer type
        // ‘char *string[2]’ is a 1-D array of char pointer with length 2.
        // The address of this case is the same like subFunc1.

        char *str2[2];
        printf("Declaration: char *str2[2];n");
        PRINT_ADDR( str2)
        printf("sizeof(str2)=%d, sizeof(str2[0])=%d, sizeof(str2[1])=%dn",
                sizeof(str2), sizeof(str2[0]), sizeof(str2[1]));

        printf("Processing parameter passing-byn");
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
}

void subFunc4( char (*string)[2])
{
        // Wired Output
        // Like the gcc’s warning:
        // warning: passing arg 1 of `subFunc4′ from incompatible pointer type
        // ‘char (*string)[2]’ here means a pointer to 1-D char array with length 2.
        // ‘string[0]’ is the exact char pointer of ‘msg[0]’, however,
        // ‘string[1]’ is the next char pointer of the next 1-D char arrray with length 2.
        // Below gives the right way to get the pointer of the second string.
        // And subFunc5 shows the right way to use this parameter.

        char (* str2)[2];
        printf("Declaration: char (* str2)[2];n");
        PRINT_ADDR( str2)
        printf("sizeof(str2)=%d, sizeof(str2[0]=%d, sizeof(str2[1])=%dn",
                sizeof(str2), sizeof(str2[0]), sizeof(str2[1]));

        printf("Processing parameter passing-byn");
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
        printf("String 2: %sn", (string[0]+100));
}

void subFunc5( char (*string)[100])
{
        PRINT_ADDR( string)
        printf("String 1: %sn", string[0]);
        printf("String 2: %sn", string[1]);
}

static char msg[2][100];

int main( int argc, char **argv)
{
        if ( argc != 2)
        {
                printf("Pleaes input the function number from 1~4n");
                return 1;
        }

        unsigned int funcNumber = strtoul( argv[1], NULL, 10);

        snprintf( msg[0], (100-1), "%s", "This is the first string");
        snprintf( msg[1], (100-1), "%s", "This is the second string");
        printf("string 1: %snString 2: %sn", msg[0], msg[1]);
        printf("sizeof(char)=%d, sizeof(char *)=%dn", sizeof(char), sizeof(char *));

        switch( funcNumber)
        {
                case 1:
                        printf("Call for subFunc1n");
                        subFunc1( msg);
                        break;
                case 2:
                        printf("Call for subFunc2n");
                        subFunc2( msg);
                        break;
                case 3:
                        printf("Call for subFunc3n");
                        subFunc3( msg);
                        break;
                case 4:
                        printf("Call for subFunc4n");
                        subFunc4( msg);
                        break;
                case 5:
                        printf("call for subFunc5n");
                        subFunc5( msg);
                        break;
                default:
                        printf("Invalid function number %d; valid number is 1~4n", funcNumber);
                        return 1;
        }

        return 0;
}

The output running on a Linux machine is like below:

/home/daveti/Ctest: ./multiDarray
Pleaes input the function number from 1~4
/home/daveti/Ctest: ./multiDarray 1
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
Call for subFunc1
addr of var     : 0x8049d20
addr of var[0]  : 0x73696854
addr of var[1]  : 0x20736920
Memory fault
/home/daveti/Ctest: ./multiDarray 2
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
Call for subFunc2
addr of var     : 0x8049d20
addr of var[0]  : 0x8049d20
addr of var[1]  : 0x8049d84
String 1: This is the first string
String 2: This is the second string
/home/daveti/Ctest: ./multiDarray 3
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
Call for subFunc3
Declaration: char *str2[2];
addr of var     : 0xbf8a0f80
addr of var[0]  : 0xb7e840e4
addr of var[1]  : 0xb7f5a160
sizeof(str2)=8, sizeof(str2[0])=4, sizeof(str2[1])=4
Processing parameter passing-by
addr of var     : 0x8049d20
addr of var[0]  : 0x73696854
addr of var[1]  : 0x20736920
Memory fault
/home/daveti/Ctest: ./multiDarray 4
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
Call for subFunc4
Declaration: char (* str2)[2];
addr of var     : 0xb7f16160
addr of var[0]  : 0xb7f16160
addr of var[1]  : 0xb7f16162
sizeof(str2)=4, sizeof(str2[0]=2, sizeof(str2[1])=2
Processing parameter passing-by
addr of var     : 0x8049d20
addr of var[0]  : 0x8049d20
addr of var[1]  : 0x8049d22
String 1: This is the first string
String 2: is is the first string
String 2: This is the second string
/home/daveti/Ctest: ./multiDarray 5
string 1: This is the first string
String 2: This is the second string
sizeof(char)=1, sizeof(char *)=4
call for subFunc5
addr of var     : 0x8049d20
addr of var[0]  : 0x8049d20
addr of var[1]  : 0x8049d84
String 1: This is the first string
String 2: This is the second string
/home/daveti/Ctest:

About daveti

Interested in kernel hacking, compilers, machine learning and guitars.
This entry was posted in Programming and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.