复习部分内容(仅图片和部分代码)

文章详细解释了C语言中sizeof和strlen这两个操作符的工作原理,以及它们在处理数组、指针和字符串时的不同行为。着重展示了sizeof用于计算内存占用大小,而strlen用于计算字符串长度的例子。
摘要由CSDN通过智能技术生成

int main()
{
	int a[] = { 1,2,3,4 };

	printf("%d\n", sizeof(&a + 1));//4/8
	//&a取出的是数组的地址
	//&a-->  int(*)[4]
	//&a+1 是从数组a的地址向后跳过了一个(4个整型元素的)数组的大小
	//&a+1还是地址,是地址就是4/8字节
	//
	printf("%d\n", sizeof(&a[0]));//4/8
	//&a[0]就是第一个元素的地址
	//计算的是地址的大小
	printf("%d\n", sizeof(&a[0] + 1));//4/8
	//&a[0]+1是第二个元素的地址
	//大小是4/8个字节
	//&a[0]+1 ---> &a[1]
	//

	printf("%d\n", sizeof(a));//16
	//sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节
	printf("%d\n", sizeof(a + 0));//4
	//a不是单独放在sizeof内部,也没有取地址,所以a就是首元素的地址,a+0还是首元素的地址
	//是地址,大小就是4/8个字节
	printf("%d\n", sizeof(*a));//4
	//*a中的a是数组首元素的地址,*a就是对首元素的地址解引用,找到的就是首元素
	//首元素的大小就是4个字节
	printf("%d\n", sizeof(a + 1));
	//这里的a是数组首元素的地址
	//a+1是第二个元素的地址
	//sizeof(a+1)就是地址的大小
	printf("%d\n", sizeof(a[1]));//4
	//计算的是第二个元素的大小
	printf("%d\n", sizeof(&a));//4/8
	//&a取出的数组的地址,数组的地址,也就是个地址
	printf("%d\n", sizeof(*&a));//16
	//&a----> int(*)[4]
	//&a拿到的是数组名的地址,类型是 int(*)[4],是一种数组指针
	//数组指针解引用找到的是数组
	//*&a ---> a
	//
	//2.
	//&和*抵消了
	//*&a ---> a
	//
	return 0;
}

 这里每个sizeof后面变量的含义和结果说明如下:

printf("%d\n", sizeof(&a + 1));//4/8 

&a是a数组的地址,地址加1之后得到的是下一个地址,因为地址是指针类型,指针类型在32位系统和64位系统下都为4/8字节。

printf("%d\n", sizeof(&a[0]));//4/8

&a[0]是数组第一个元素的地址,地址类型与上面一致,结果为4/8字节。

printf("%d\n", sizeof(&a[0] + 1));//4/8 

&a[0]+1得到的是数组第二个元素的地址,结果与上面二者相同。

printf("%d\n", sizeof(a));//16

a是数组名,sizeof计算整个数组占用的空间,这里a有4个int元素,每个int为4字节,所以总大小为4 * 4 = 16字节。

printf("%d\n", sizeof(a + 0));//4

a+0还是a,这里a decay成指针,指针类型为4/8字节。

printf("%d\n", sizeof(*a));//4

*a是数组第一个元素,sizeof计算元素本身大小,int为4字节。

printf("%d\n", sizeof(a + 1));//4/8

a+1得到的是下一个数组的地址,也是指针类型,结果与上面相同。

printf("%d\n", sizeof(a[1]));//4 

a[1]是第二个元素,结果与*a相同。

printf("%d\n", sizeof(&a));//4/8

&a是数组的地址,地址类型为4/8字节。

printf("%d\n", sizeof(*&a));//16

&a是数组地址,*&a解引用得到的是数组本身,所以结果与sizeof(a)相同。

int main()
{
	char str[] = "Hello";//没有\0
	//char str[] = {'a','b','c'};//没有\0
	//int str[] = { 1,2,3,4};
	printf("sizeof(str) = %d\n", sizeof(str)); // 6
	printf("strlen(str) = %d\n", strlen(str)); // 5

}
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));//6
	//sizeof(数组名)
	printf("%d\n", sizeof(arr + 0));//4/8
	//arr + 0 是数组首元素的地址
	printf("%d\n", sizeof(*arr));//1
	//*arr就是数组的首元素,大小是1字节
	//*arr --> arr[0]
	//*(arr+0) --> arr[0]
	printf("%d\n", sizeof(arr[1]));//1
	printf("%d\n", sizeof(&arr));//4/8
	//&arr是数组的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&arr + 1));//4/8
	//&arr + 1是数组后的地址
	//
	printf("%d\n", sizeof(&arr[0] + 1));//4/8
	//&arr[0] + 1是第二个元素的地址
	//
	return 0;
}
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", strlen(arr));//随机值,结尾没有\0
	printf("%d\n", strlen(arr + 0));//随机值

//	printf("%d\n", strlen(*arr));//--> strlen('a');-->strlen(97);//野指针
//	printf("%d\n", strlen(arr[1]));//-->strlen('b')-->strlen(98);

	printf("%d\n", strlen(&arr));//随机值
	printf("%d\n", strlen(&arr + 1));//随机值-6
	printf("%d\n", strlen(&arr[0] + 1));//随机值-1

	return 0;
}

 

int main()
{
	//char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };

	char arr[] = "abcdef";
	//strlen是求字符串长度的,关注的是字符串中的\0,计算的是\0之前出现的字符的个数
	//strlen是库函数,只针对字符串
	//sizeof只关注占用内存空间的大小,不在乎内存中放的是什么
	//sizeof是操作符
	//
	//[a b c d e f \0]
	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6
	//printf("%d\n", strlen(*arr));//err
	//printf("%d\n", strlen(arr[1]));//err
	printf("%d\n", strlen(&arr));//6
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//5
//
//
	//[a b c d e f \0]
	printf("%d\n", sizeof(arr));//7
	printf("%d\n", sizeof(arr + 0));//4/8
	printf("%d\n", sizeof(*arr));//1
	printf("%d\n", sizeof(arr[1]));//1
	printf("%d\n", sizeof(&arr));//4/8
	printf("%d\n", sizeof(&arr + 1));//4/8跳过一个数组
	printf("%d\n", sizeof(&arr[0] + 1));//4/8跳过第一个元素

 

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]));
	//a[0]是第一行这个一维数组的数组名,单独放在sizeof内部,a[0]表示第一个整个这个一维数组
	//sizeof(a[0])计算的就是第一行的大小
	printf("%d\n", sizeof(a[0] + 1));
	//a[0]并没有单独放在sizeof内部,也没取地址,a[0]就表示首元素的地址
	//就是第一行这个一维数组的第一个元素的地址,a[0] + 1就是第一行第二个元素的地址
	printf("%d\n", sizeof(*(a[0] + 1)));
	//a[0] + 1就是第一行第二个元素的地址
	//*(a[0] + 1))就是第一行第二个元素
	printf("%d\n", sizeof(a + 1));//4/8
	//a虽然是二维数组的地址,但是并没有单独放在sizeof内部,也没取地址
	//a表示首元素的地址,二维数组的首元素是它的第一行,a就是第一行的地址
	//a+1就是跳过第一行,表示第二行的地址
	printf("%d\n", sizeof(*(a + 1)));//16
	//*(a + 1)是对第二行地址的解引用,拿到的是第二行
	//*(a+1)-->a[1]
	//sizeof(*(a+1))-->sizeof(a[1])
	//
	printf("%d\n", sizeof(&a[0] + 1));//4/8
	//&a[0] - 对第一行的数组名取地址,拿出的是第一行的地址
	//&a[0]+1 - 得到的是第二行的地址
	//
	printf("%d\n", sizeof(*(&a[0] + 1)));//16
	printf("%d\n", sizeof(*a));//16
	//a表示首元素的地址,就是第一行的地址
	//*a就是对第一行地址的解引用,拿到的就是第一行
	//
	printf("%d\n", sizeof(a[3]));//16
	printf("%d\n", sizeof(a[0]));//16

	//int a = 10;
	//sizeof(int);
	//sizeof(a);

 这个程序主要使用sizeof操作符打印出不同情况下变量和表达式的大小。

sizeof后括号里的参数的意思如下:

1. a: 整个三维数组a的大小,即3×4×sizeof(int) bytes。 

2. a[0][0]: 数组a第一个子数组中的第一个元素int的大小,即sizeof(int) bytes。

3. a[0]: 数组a第一个子数组的大小,即4×sizeof(int) bytes。 

4. a[0]+1: 第一个子数组第一个元素的地址加1之后的地址,它也是int类型,所以大小是sizeof(int) bytes。 

5. *(a[0]+1): 解引用第一个子数组第一个元素地址加1之后的内容,也是一个int,大小是sizeof(int) bytes。

6. a+1: 数组a的地址加1之后的地址,它是一个指向数组的指针,大小是指针的大小,即sizeof(int*) bytes。

7. *(a+1): 解引用数组a地址加1之后的内容,它指向第二个子数组,大小依然是整个数组a的大小。

8. &a[0]+1: 第一个子数组地址加1之后的地址,也是一个指向数组的指针,大小是sizeof(int*) bytes。 

9. *(&a[0]+1): 解引用第一个子数组地址加1之后的内容,指向第二个子数组,大小是整个数组a的大小。

10. *a: 解引用数组a,它是一个指向第一个子数组的指针,大小是指针大小sizeof(int*) bytes。

11. a[3]: 访问第四个不存在的子数组,编译时错误。

12. a[0]: 第一个子数组,大小是4×sizeof(int) bytes。

 

int main()
{
	char* p = "abcdef";//p里只是a的地址
	printf("%d\n", sizeof(p));//a的地址
	printf("%d\n", sizeof(p + 1));//b的地址
	printf("%d\n", sizeof(*p));//a的大小
	printf("%d\n", sizeof(p[0]));//a的大小
	printf("%d\n", sizeof(&p));//指针的指针
	printf("%d\n", sizeof(&p + 1));//指针的指针(地址)末尾
	printf("%d\n", sizeof(&p[0] + 1));//b的地址

	printf("%d\n", strlen(p));
	printf("%d\n", strlen(p + 1));
	//printf("%d\n", strlen(*p));//err
	//printf("%d\n", strlen(p[0]));//err
	printf("%d\n", strlen(&p));//随机;在指针(4个字节)头往后数;
	//这里计算&p时是按地址类型4个字节4个字节的往后数。strlen函数需要一个以null结尾的字符串作为参数,
	//而&p是指向指针p的地址,它的大小通常是4个字节(32位系统)或8个字节(64位系统),
	//而不是字符串的长度。因此,strlen(&p)不会返回正确的字符串长度。
	printf("%d\n", strlen(&p + 1));//随机;从p末尾开始数
	printf("   %d\n    ", strlen(&p[0] + 1));//5

	return 0;
}

 对于这些strlen调用:

1. printf("%d\n", strlen(p));
   这里p是指向第一个字符的指针。strlen函数需要一个指向字符串的指针作为参数。所以p直接传给strlen,strlen将使用p指向的地址开始计算字符串长度。

2. printf("%d\n", strlen(p + 1));  
   p+1指向字符串中的第二个字符。strlen将从这个地址开始计算长度。

3. printf("%d\n", strlen(*p));
   *p是一个字符,strlen需要字符串地址,所以这里会报错。

4. printf("%d\n", strlen(p[0]));  
   p[0]也是一个字符,同样会报错。

5. printf("%d\n", strlen(&p));
   &p获取p指针的地址。strlen需要字符串地址,一个指针地址不是字符串地址,所以也会报错。

6. printf("%d\n", strlen(&p + 1));
   &p获取指针地址。&p+1指向下一个指针变量地址,不是字符串地址,也会报错。

7. printf("%d\n", strlen(&p[0] + 1));
   &p[0]获取第一个字符地址,&p[0]+1指向第二个字符地址,这里strlen可以正确工作,计算从第二个字符开始的字符串长度。

总之,strlen函数需要一个指向字符串的指针作为参数,其他情况如字符,指针地址等都不符合函数定义,会报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值