// 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: