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

本文详细介绍了C语言中二维数组的初始化方式,包括不同情况下的元素赋值与默认初始化。同时,探讨了二维数组作为函数参数时的传递规则,分析了各种函数形参声明方式的影响,并通过示例代码展示了如何在函数中正确操作二维数组。此外,还提供了一个综合示例,演示了二维数组在实际编程中的应用。
摘要由CSDN通过智能技术生成

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;
}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值