[C语言]sizeof和strlen在一维数组和二维数组中的计算问题

发布于:2022-11-09 ⋅ 阅读:(9) ⋅ 点赞:(0) ⋅ 评论:(0)

在做这类题时有几个点需要注意

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
3. 除此之外的所有数组名都表示首元素的地址
4. 推荐先自己看一看做一做再来核对一下
5. 头文件的引用在各个代码块省略,放在最后的完整代码
目录:
一维数组
二维数组
完整代码

一.一维数组

1.整型数组
int main()
{
	int a[] = { 1,2,3,4 };
	
	printf("%d\n", sizeof(a));		//16
	printf("%d\n", sizeof(a + 0));	//4/8  -  a+0是第一个元素的地址
	printf("%d\n", sizeof(*a));		//4	 -  *a是数组的第一个元素,sizeof(*a)计算的是第一个元素的大小
	printf("%d\n", sizeof(a + 1));	//4/8  -  a+1计算的是第二个元素的地址,sizoef计算的是第二个元素地址的大小
	printf("%d\n", sizeof(a[1]));   //4  -  计算的是第二个元素的大小

	printf("%d\n", sizeof(&a));		//4/8  -  &a是数组本身的地址,故sizeof计算的是地址
	printf("%d\n", sizeof(*&a));	//16  -  将地址解引用即为数组本身
	printf("%d\n", sizeof(&a + 1)); //4/8 -  数组地址+1.跳过一个数组,即指向4后面
	printf("%d\n", sizeof(&a[0]));	//4/8 -  第一个元素地址
	printf("%d\n", sizeof(&a[0] + 1));//4/8 - 第二个元素地址
	return 0;
}

地址的大小为4/8,在32位系统时是4,在64位系统是8

2.字符数组
例一

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6  数组的大小
	printf("%d\n", sizeof(arr + 0));//4/8   a的地址+0 == a的地址
	printf("%d\n", sizeof(*arr));//1   arr此时表示a的地址,解引用后为1
	printf("%d\n", sizeof(arr[1]));//1   计算b的大小
	
	printf("%d\n", sizeof(&arr));//4/8   数组的地址
	printf("%d\n", sizeof(&arr + 1));//4/8   &arr为数组地址,加一后跳过一个数组
	printf("%d\n", sizeof(&arr[0] + 1));//4/8   计算b的地址
	return 0;
}

注意该数组内并没有‘\0’

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//随机值
	printf("%d\n", strlen(arr + 0));//随机值
	printf("%d\n", strlen(*arr));//错误
	printf("%d\n", strlen(arr[1]));//错误
	printf("%d\n", strlen(&arr));//随机值
	printf("%d\n", strlen(&arr + 1));//随机值-6
	printf("%d\n", strlen(&arr[0] + 1));//随机值-1
	return 0;
}

>strlen函数当读取到‘\0’时结束,而数组内部没有’\0’,会向下读取从而产生随机值
>strlen函数接收的参数类型为const char* str, *arr即为a本身,传给strlen以ASCII码表示,即97,产生错误,arr[1]为b,同理产生不了正确的值
>&arr+1即跳过了一个数组的地址,最后长度等于&arr - 6,即 随机值 - 6,&arr[0]+1是b的地址
//注意在运行的时候产生错误的结果记得注释掉

例二

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));//7  数组最后一位是'\0'
	printf("%d\n", sizeof(arr + 0));//4/8  首元素地址
	printf("%d\n", sizeof(*arr));//1   a
	printf("%d\n", sizeof(arr[1]));//1   b
	printf("%d\n", sizeof(&arr));//4/8   arr地址
	printf("%d\n", sizeof(&arr + 1));//4/8   跳过一个数组的地址
	printf("%d\n", sizeof(&arr[0] + 1));//4/8   b地址
	return 0;
}

此数组最后一位为‘\0’

int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6
	printf("%d\n", strlen(*arr));//错误
	printf("%d\n", strlen(arr[1]));//错误
	printf("%d\n", strlen(&arr));//6
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//5
	return 0;
}

根据例一的strlen的题可以较轻松的得出结果
另外&arr+1因为跳过了数组,只能向后随机找到’\0’,故产生随机值

例三
字符指针

int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));//4/8   首元素地址
	printf("%d\n", sizeof(p + 1));//4/8   b的地址
	printf("%d\n", sizeof(*p));//1   a
	printf("%d\n", sizeof(p[0]));//1   a
	printf("%d\n", sizeof(&p));//4/8   p的地址
	printf("%d\n", sizeof(&p + 1));//4/8   跳过p后的地址
	printf("%d\n", sizeof(&p[0] + 1));//4/8 b的地址
	return 0;
}

此时p指向a前面的地址
对于此类字符指针,p[0]等价于*(p+0)
下面一个简单的图示便于理解
字符指针

int main()
{
	char* p = "abcdef";
	printf("%d\n", strlen(p));//6  a地址
	printf("%d\n", strlen(p + 1));//5  b地址
	printf("%d\n", strlen(*p));//错误
	printf("%d\n", strlen(p[0]));//错误
	printf("%d\n", strlen(&p));//随机值
	printf("%d\n", strlen(&p + 1));//随机值
	printf("%d\n", strlen(&p[0] + 1));//5  b地址
	return 0;
}

这一题相信经过前面的吸收已经没有什么大问题了,唯一需要注意的是&p&p+1产生的随机值并没有不变的明确关系,由上图可知指针p所占用的4个字节不能确定是否含有‘\0’,唯一可以确定的是前者值一定大于后者。

二.二维数组

二维数组需要注意的点
1.二维数组的首元素就是第一行
>若a为数组,a[0]就是第一行数组名,可以看作是一个一维数组(以a[0][0]为首元素)

int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48   3*4*sizeof(int)

	printf("%d\n", sizeof(a[0][0]));//4   第一行第一个元素

	printf("%d\n", sizeof(a[0]));//16   第一行的大小

	printf("%d\n", sizeof(a[0] + 1));//4/8  第一行第二个元素的大小 
	//解释:a[0]并不属于sizeof(数组)和&数组的情况,此时可以看过是第一行的一维数组,此时一维数组名即首元素的地址,+1成为第一行第二个元素的地址

	printf("%d\n", sizeof(*(a[0] + 1)));//4  对第一行第二个元素的解引用

	printf("%d\n", sizeof(a + 1));//4/8   第二行的地址
	//解释:a并不属于sizeof(数组)和&数组的情况,作为第一行的地址,+1为第二行的地址

	printf("%d\n", sizeof(*(a + 1)));//16   第二行的大小
	//解释:a+1为第二行地址,解引用为第二行的大小/也可以将*(a+1)等价于a[1]

	printf("%d\n", sizeof(&a[0] + 1));//4/8   第二行的地址
	//解释:a[0]是第一行数组名,&a[0]为第一行地址,+1后为第二行地址,等价于sizeof(a+1)

	printf("%d\n", sizeof(*(&a[0] + 1)));//16   第二行大小
	//解释:将上一行的地址解引用

	printf("%d\n", sizeof(*a));//16  第一行的大小
	//a并不属于sizeof(数组)和&数组的情况,相当于首元素地址,解引用计算为第一行大小

	printf("%d\n", sizeof(a[3]));//16  第四行的数组大小(假设存在)
	//解释:sizeof()并不会计算其中的表达式,a[3]相当于一个int [4]类型,可以看作一维数组

	return 0;
}

解释注释在对应的代码下面

三.完整代码

#define _CRT_SECURE_NO_DEPRECATE 1

#pragma warning(disable:4996)

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

//一维数组
 
//1.整型数组
int main()
{
	int a[] = { 1,2,3,4 };

	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));		
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));

	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));
 return 0;
}


//2.字符数组
//例一
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));

}


int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
	return 0;
}


//例二
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", siezof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));
	return 0;
}


int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
	return 0;
}


//例三 - 字符指针
int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));
	printf("%d\n", sizeof(p + 1));
	printf("%d\n", sizeof(*p));
	printf("%d\n", sizeof(p[0]));
	printf("%d\n", sizeof(&p));
	printf("%d\n", sizeof(&p + 1));
	printf("%d\n", sizeof(&p[0] + 1));
	return 0;
}


int main()
{
	char* p = "abcdef";
	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p + 1));
	printf("%d\n", strlen(*p));
	printf("%d\n", strlen(p[0]));
	printf("%d\n", strlen(&p));
	printf("%d\n", strlen(&p + 1));
	printf("%d\n", strlen(&p[0] + 1));
	return 0;
}


//二维数组
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a[0][0]));
	printf("%d\n", sizeof(a[0]));
	printf("%d\n", sizeof(a[0] + 1));
	printf("%d\n", sizeof(*(a[0] + 1)));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(*(a + 1)));
	printf("%d\n", sizeof(&a[0] + 1));
	printf("%d\n", sizeof(*(&a[0] + 1)));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a[3]));

	return 0;
}

在运行的时候不要忘了将会产生错误的代码注释掉哦