C语言二维数组初始化和作形参时常见的坑

1、int二维数组初始化方式

int A[2][3] = { 1, 2, 3, 4, 5, 6};
对应顺序是
A[0][0]=1; A[0][1]=2; A[0][2]=3;
A[1][0]=4; A[1][1]=5; A[1][2]=6;

int A[2][3] = { 1, 2, 3, 4};
其中剩余的未赋值元素编译器自动初始化为0。
数组元素值对应顺序是
A[0][0]=1; A[0][1]=2; A[0][2]=3;
A[1][0]=4; A[1][1]=0; A[1][2]=0;

int A[2][3] = { { 1, 2, 3}, { 4}};
其中剩余的未赋值元素编译器自动初始化为0。
数组元素值对应顺序是
A[0][0]=1; A[0][1]=2; A[0][2]=3;
A[1][0]=4; A[1][1]=0; A[1][2]=0;

int A[][3] = { { 1, 2, 3}, { 4}};
省略行数,切记列数无法省略。其中剩余的未赋值元素编译器自动初始化为0。
数组元素值对应顺序是
A[0][0]=1; A[0][1]=2; A[0][2]=3;
A[1][0]=4; A[1][1]=0; A[1][2]=0;

2、char二维数组初始化方式

char A[2][3] = { 'a', 'b', 'c', 'd'};
其中未初始化的部分,编译器自动初始为'0'NULL)。
printf("%s\n", A);
输出"abcd"

char A[2][3] =  { { 'a'}, { 'd', 'e', 'f'}};
其中未初始化的部分,编译器自动初始为'0'NULL)。
printf("%s\n", A);
输出"a",输出第一行时遇到结束符导致停止输出。

char A[2][3] = { { 'a', 'b', 'c'}, { 'd', 'e', 'f'}};
printf("%s\n", A);
输出"abcdef"
    
char A[][3] = { { 'a', 'b'}, { 'd'}};
省略行数,切记列数无法省略。
printf("%s\n", A);
输出"ab"

3、二维数组作为形参

想要在函数中传递一个一维数组作为参数,必须以下面三种方式来声明函数形式参数,这三种声明方式的结果是一样的,因为每种方式都会告诉编译器将要接收一个整型指针

方式1,形式参数是一个指针
void myFunction1(int *param)

方式2,形式参数是一个已定义大小的数组
void myFunction2(int param[10])

方式3,形式参数是一个未定义大小的数组
void myFunction3(int param[])

int param[3] = { 0};
myFunction1(param);
myFunction2(param);
myFunction3(param);
int *param2;
myFunction1(param2);
myFunction2(param2);
myFunction3(param2);

就函数而言,一维数组作为形参时的长度是无关紧要的,因为 C 不会对形式参数执行边界检查。

同样的方式也可以传递一个多维数组作为形式参数?

方式1,形式参数是一个指针
void myFunction1(int **param)

方式2,形式参数是一个已定义大小的数组
void myFunction2(int param[2][10])
void myFunction2(int param[2][3])

方式3,形式参数是一个未定义一维宽度的数组
void myFunction3(int param[][3])

方式4
void myFunction4(int (*a)[3])

方式5
void myFunction5(int *a[3])

int param[2][3] = { 0};
myFunction1(param);
错误,[Error] cannot convert 'int (*)[3]' to 'int**' for argument '1' to 'void myFunction(int**)'int param[2][3]中param其实是"int (*)[3]"类型,不是"int**"类型,这两者不能混用
myFunction2(param);
二维宽度为10的错误,[Error] cannot convert 'int (*)[3]' to 'int (*)[10]' for argument '1' to 'void myFunction2(int (*)[10])',可以理解为"int (*)[3]""int (*)[10]"不是一种类型
为3的正确,二维数组作为函数形参会进行边界检查,所以第二个维度必须一致
myFunction3(param);
myFunction4(param);
myFunction5(param);
错误,注意如果是int *a[3],因为"[]"的优先级比"*"高,所以会导致该形参被编译器识别为"int**"

int **param2 = (int **)malloc(sizeof(int *) * 2);
myFunction1(param);
myFunction2(param);
myFunction3(param);
myFunction4(param);
myFunction5(param);
只有myFunction1和myFunction5正确,其余的形参都不是"int**"类型
注意myFunction5中的"a[3]"类似一维数组作形参的效果,不管数组大小都被当作"int *"

4、综合例子

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

// 二维数组作为函数的形式参数会进行边界检查,所以第二个维度必须为5 
void example(char acHello[][5])
{ 
	printf("%d\n", sizeof(char (*)[5])); // 输出8
	printf("%d\n", sizeof(acHello)); // 输出8,为sizeof(char (*)[5]),指针为8 
	printf("%d\n", strlen(acHello[0])); // 输出9,因为acHello[0]并没有'\0'结束符,所以是acHello的总长度 
	acHello[0][0] = 'c';
	return;
}

int main(void)
{ 
	char str[] = "\\\\";
	printf("%d\n", sizeof(str)); // 输出3,\\其实是转义,所以2个'\'加字符串自带的1个'\0'是3 
	printf("%d\n", strlen(str)); // 输出2,即2个'\' 
	
	char *str2 = "\\\\";
	printf("%d\n", sizeof(str2)); // 输出8,str是char*类型的指针,指针在64位下都是8 
	printf("%d\n\n", strlen(str2)); // 输出2,即2个'\' 

	char str3[2][3] = { "qw", "er"};
	printf("%c ", *(*(str3 + 0) + 0));
	printf("%c ", *(*(str3 + 0) + 1));
	printf("%c ", *(*(str3 + 1) + 0));
	printf("%c\n", *(*(str3 + 1) + 1));

	printf("%c ", *(str3[0] + 0));
	printf("%c ", *(str3[0] + 1));
	printf("%c ", *(str3[1] + 0));
	printf("%c\n", *(str3[1] + 1));

	printf("%c ", str3[0][0]);
	printf("%c ", str3[0][1]);
	printf("%c ", str3[1][0]);
	printf("%c\n\n", str3[1][1]);
	// *(str3 + 0)等效于str3[0],*(*(str3 + 0) + 0)等效于str3[0][0] 

	char *szStr = "abcde";
	printf("%c\n", szStr[0]); // 输出a 
	printf("%llu\n", szStr); // 输出4210713,该值为"abcde"这个常串中字符a所在的地址
	szStr += 2;
	printf("%c\n", szStr[0]); // 输出c 
	printf("%llu\n\n", szStr); // 输出4210715,该值为"abcde"这个常串中字符c所在的地址

	char dqq[][10] = { { 'h', 'e', 'l', 'l', 'o'}, { 'q', 'w', 'e'}};
	printf("%s\n", dqq); // 输出hello,因为第一维多的部分被自动初始化为'\0',所以输出的时候截断了 
	printf("%s\n", dqq[1]); // 将第二维输出,所以是输出qwe
	printf("%c\n\n", dqq[1][0]); // 输出q

	char acHello[][5] = { { 'h', 'e', 'l', 'l', 'o'}, { 'h', 'e', 'l', 'l'}};
	example(acHello);
	printf("%s\n\n", acHello); // 输出cellohell,由于是传的指针,所以第一个字符被修改为c

	return 0;
}
    原文作者:陈小星_绛菱纱影
    原文地址: https://blog.csdn.net/A657997301/article/details/109725541
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞