关于sizeof和strlen知多少

"这篇博客详细探讨了C语言中sizeof()和strlen()的区别,以及指针和数组的相关概念。sizeof()计算的是变量所占内存的字节数,而strlen()计算的是字符串的实际长度(不包括'')。此外,文章还讲解了指针常量和常量指针的不同,并提供了大量练习题来区分一维、二维整型数组和字符数组的用法。最后,博主分享了一段代码,解释了指针运算后的内存访问情况。"
摘要由CSDN通过智能技术生成

 

一、sizeof()和strlen()的区别

1.sizeof()是一个单目操作符,并非函数,它计算的是参数所占空间的大小即字节数(注意:字符串通常以'\0'结尾,所以在计算字符串所占空间的大小时,也要包含'\0')

2.strlen()是一个函数,用于计算字符串实际长度(计算字符串的实际长度不包含'\0',假如定义了一个字符数组 char arr[]="helloworld",‘\0’是数组的最后一个元素,虽然我们看不到,但它也是字符串的一部分,但我们实际看到的是“helloword”,所以实际长度的意思就是我们实际看到的字符串的长度,不应包含'\0')

二、其他概念

1.指针和数组的区别

为了方便计算后面的练习,首先还应该弄清楚指针和数组的区别

其实,指针和数组完全是两个不相干的概念,所以说它俩有什么区别是很不科学的。

容易让我们混淆的原因在于:

       数组本身就只有取下标运算,但是在一些情况下又会隐式转化为指针(在C语言中):

     ①函数传参

     ②加减运算

     ③解引用

     ④比较操作

     然而指针又能[]取下标,行为上非常类似数组

2.int* const p和const int* p的区别

①int * const p等价于const * int p,其中p的内容不能被修改,即p中保存的地址不能被修改,所以下面的运行结果是错误的(为了方便记忆,想出了一个可能不太恰当的方法去理解,*没有紧跟p所以就表示p这个指针变量本身,也就是p变量的内容不能被改变)

int a = 5;
int b = 10;
int* const p = &a; //p保存的地址不能被修改
p = &b;
printf("%d\n", *p);

②const int* p,其中p所指的内容不能被修改,所以下面的运行结果是错误的(为了方便记忆,想出了一个可能不太恰当的方法去理解,*紧跟p相当于对指针p解引用,也就是p所指向的内容不能被改变)

int a = 5;
int b = 10;
const int* p = &a; //p中保存的地址所指向的内容不能被修改,即a的值不能被修改
*p = 20;
printf("%d\n", *p);

三、练习

1.一维整型数组的练习

int arr[] = { 1, 2, 3, 4 };

arr是一个长度为4的整形数组,在32位系统下,一个int 占4个字节,指针类型占4个字节。下面我们按照32位系统去练习~(16位操作系统下一个int占 2个字节,指针类型占2个字节;64位系统下int占4个字节,指针类型占8个字节)

①sizeof()

printf("%d\n", sizeof(arr));//数组名表示首元素的地址,因为数组中的元素在内存中是连续存放的,所以我们可以通过首元素的地址访问整个数组,即要求整个数组所占的空间大小,即sizeof(arr)=4*4=16
printf("%d\n", sizeof(arr + 0));//前面提到数组名+操作会触发隐式转换,arr表示首元素的地址,隐式转换成为指向首元素的指针,即sizeof(int*)=4
printf("%d\n", sizeof(*arr));//数组名表示首元素的地址,*使其隐式转化成为指针int*,对其解引用就是sizeof(int)=4
printf("%d\n", sizeof(arr + 1));//32位系统下,指针类型一律占4个字节,sizeof(int *)=4
printf("%d\n", sizeof(arr[1]));//数组的第二个元素所占空间的大小即sizeof(int)=4
printf("%d\n", sizeof(&arr));//对数组的首元素的地址取地址得到一个数组指针即sizeof(int(*)[4])=4
printf("%d\n",sizeof(*&arr));//根据操作符的优先级和结合性,&arr得到数组指针int(*)[4],再对其解引用得到int[4],即sizeof(int[4])=16
printf("%d\n", sizeof(&*arr));//首先触发隐式转换得到int*,解引用得到int,再对其取地址得到int*,即sizeof(int*)=4
printf("%d\n", sizeof(&arr + 1));//sizeof(int(*)[4]+1)=4,指针类型~
printf("%d\n", sizeof(&arr[0]));//sizeof(int *)=4,指针类型~
printf("%d\n", sizeof(&arr[0] + 1));//sizeof(int *)=4	指针类型~

2.二维整形数组的练习

int arr[3][4] = { 0 };

①sizeof()

printf("%d\n", sizeof(arr)); //sizeof(int[3][4]))=12*4=48
printf("%d\n", sizeof(arr[0]));//sizeof(int[4])=4*4=16
printf("%d\n", sizeof(arr[0]+1));//sizeof(int*[4])=4
printf("%d\n", sizeof(&arr[0]+1));//sizeof(int**[4])=4
printf("%d\n", sizeof(arr[0][0]));//sizeof(int)=4
printf("%d\n", sizeof(*arr[0]));//sizeof(int)=4
printf("%d\n", sizeof(*arr));//sizeof(int[4])=4*4=16
printf("%d\n", sizeof(*(arr + 1)));//sizeof(int[4])=16
printf("%d\n", sizeof(&arr[0] + 1));//sizeof(int*[4])=4
printf("%d\n", sizeof(*(arr[0]) + 1));//sizeof(int)=4

3.字符数组的练习(1)

char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };

注意:上面字符数组,初始化时没有‘\0’

            只有char arr[]="abcdef"初始化时才会自动加'\0'

①sizeof()

printf("%d\n", sizeof(arr));//sizeof(char[6])=6
printf("%d\n", sizeof(arr + 0));//sizeof(char*)=4
printf("%d\n", sizeof(*arr));//sizeof(char)=1
printf("%d\n", sizeof(arr+1));//sizeof(char*)=4
printf("%d\n", sizeof(arr[1]));//sizeof(char)=1
printf("%d\n", sizeof(&arr));//sizeof(char(*)[6])=4
printf("%d\n", sizeof(*&arr)); //sizeof(char[6])=6
printf("%d\n", sizeof(&*arr)); //sizeof(char*)=4
printf("%d\n", sizeof(&arr[1]+1));//sizeof(char*)=4
printf("%d\n", sizeof(&arr + 1));//sizeof(char(*)[6])=4

②strlen()

注意:strlen()计算的是字符串的实际长度

printf("%d\n", strlen(arr));//???未定义行为
printf("%d\n", strlen(arr+0));//strlen(char*)???未定义行为
printf("%d\n", strlen(*arr));//strlen(arr[0])???
printf("%d\n", strlen(arr[1]));//???
printf("%d\n", strlen(&arr));//???
printf("%d\n", strlen(&arr + 1));//???
printf("%d\n", strlen(&arr[0]) + 1);//???

4.字符数组的练习(2)

char arr[] = "abcdef";

注意:此时,我们数组中保存的是一个字符串,以'\0'结尾

①sizeof()

printf("%d\n", sizeof(arr));//sizeof(char[7])=7
printf("%d\n", sizeof(arr+0));//sizeof(char*)=4
printf("%d\n", sizeof(*arr));//sizeof(char)=1
printf("%d\n", sizeof(arr[1]));//sizeof(char)=1
printf("%d\n", sizeof(&arr[0]+1));//sizeof(char*)=4
printf("%d\n", sizeof(&arr));//sizeof(char(*)[7])=4
printf("%d\n", sizeof(*&arr));//sizeof(char[7])=7
printf("%d\n", sizeof(&*arr));//sizeof(char*)=4
printf("%d\n", sizeof(&arr+1));//sizeof(char(*)[4])=4

②strlen()

printf("%d\n", strlen(arr));//6
printf("%d\n", strlen(arr+1));//5
printf("%d\n", strlen(&arr+1));//类型不匹配
printf("%p\n", strlen(&arr));//6  类型不匹配  strlen(char(*)[7])=6
printf("%d\n", strlen(&arr[0]));//strlen(char*arr[7])=6
printf("%d\n", strlen(*&arr));//char(*)[7]->char[7]  strlen(char[7])=6
printf("%d\n", strlen(&*arr));//char*arr[0]->char arr[0]->char *arr[0] strlen(char *arr[0])=6
printf("%d\n", strlen(&arr[1]+1));//char* arr[1]->char* arr[2] strlen(char* arr[2])=4 

5.指向字符串首元素的指针的练习

char* p = "abcdef";

注意:此时p是一个指针变量,指向字符串的首元素,其中的内容就是字符串首元素的地址

①sizeof()

printf("%d\n", sizeof(p));//sizeof(char*)=4
printf("%d\n", sizeof(p + 1));//sizeof(char*)=4
printf("%d\n", sizeof(*p));//sizeof(char)=1
printf("%d\n", sizeof(p[0]));//sizeof(char)=1
printf("%d\n", sizeof(&p));//sizeof(char**)=4
printf("%d\n", sizeof(&p[1]+1));//sizeof(char*)=4
printf("%d\n", sizeof(*&p));//sizeof(char*)=4
printf("%d\n", sizeof(&*p));//sizeof(char**)=4

②strlen()

printf("%d\n",strlen(p));//strlen(char*[0])=6	
printf("%d\n", strlen(p + 1));//strlen(char*[1])=5
printf("%d\n", strlen(*p));//strlen(char[0]) 类型不匹配
printf("%d\n", strlen(p[1]));//类型不匹配
printf("%d\n", strlen(&p));//类型不匹配
printf("%d\n", strlen(&p[1] + 1));//strlen(char *p[2])=4
printf("%d\n", strlen(*&p));//strlen(char*)=6
printf("%d\n", strlen(&*p));//strlen(char*)=6

6.其他题目

求如下代码的输出结果

#include<stdio.h>
#include<windows.h>

int main()
{ 
   int a[4] = { 1, 2, 3, 4 };
   int* ptr1 = (int*)(&a + 1);
   int* ptr2 = (int*)((int)a + 1);
   printf("%x,%x", ptr1[-1], *ptr2);
   system("pause");
   return 0;
}

关于ptr1[-1]:通过上面大量的练习,我们可以知道&a是一个数组指针int(*a)[4],再对其+1,表示跳过整个数组,ptr1指向数组最后一个元素后面的位置,也是一个特殊位置,所以ptr[-1]实际上就是数组最后一个元素,即4

关于*ptr2:数组名a表示的是数组首元素的地址,(int)a表示将这个地址强制转化成为int型,假设数组的首元素的地址为0x100,那么(int)a的结果就为0x100,再对其+1结果为0x101,最终ptr2这个指针指向的是0x101,对其打印,因为被强制类型转换为(int *)型,所占4个字节,所以向后读取四个字节 如下图所示:

 

最终得到 00 00 00 02

按照小端字节序(高位在高地址),得到输出结果  2000000

 

以上就是自己对于sizeof()和strlen()的一些理解,描述的有点粗糙,有什么不对的地方大家可以指出来哦~~

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值