基于数组、指针的sizeof和strlen

一.基础知识:

①一般情况下数组名arr代表首元素地址,除了两个情况:

Ⅰ.sizeof(数组名)表示整个数组的大小

Ⅱ.&(数组名)表示取出整个数组的地址

②strlen是库函数,是求字符串长度的,关注的是字符串中的'\0',计算的是'\0'之前出现的字符的个数,strlen 的参数必须是一个指向字符串的指针(const char*),而不是单个字符或整数。

③sizeof是操作符,只关注占用内存空间的大小,不在乎内存中放了什么

④地址的内存大小占4/8个字节

二.基于这些我们来练习一下下面这些题

Ⅰ.char arr[] = { 'a','b','c','d','e','f' };
    printf("%d\n", sizeof(arr));由基础知识——①——Ⅰ和③知这里计算的是整个数组占用内存空间的大小,有6个字符,每个字符是1个字节,所以是6
    printf("%d\n", sizeof(arr+0));arr不是单独在sizeof里面,所以表示首元素'a'的地址,+0还是首元素的地址,是4/8
    printf("%d\n", sizeof(*arr));对首元素的地址解引用,表示'a'的大小,a是字符,占1个字节
    printf("%d\n", sizeof(arr[1]));是第二个元素占用内存空间的大小,也就是b的大小,占1个字节
    printf("%d\n", sizeof(&arr));由基础知识——①——Ⅱ和③、④知这里计算的是整个数组的地址占用内存空间的大小,地址内存是4/8
    printf("%d\n", sizeof(&arr+1));&arr表示取出整个数组的地址,+1表示跳过整个数组,指向数组最后一个元素'f'后面的地址,地址内存是4/8
    printf("%d\n", sizeof(&arr[0]+1));&arr[0]表示取出第一个元素的地址,+1——>第二个元素的地址,地址为4/8

    printf("%d\n", strlen(arr));由基础知识——②,因为不知道这个数组的'\0'在哪里,所以'\0'之前出现的字符的个数是随机值
    printf("%d\n", strlen(arr+0));arr不是单独在sizeof里面,所以表示首元素'a'的地址,和strlen(arr)一样
    printf("%d\n", strlen(*arr));报错,表示对数组首元素地址解引用,为strlen('a'),由基础知识——②知直接调用 strlen('a') 是不合法的,会导致编译错误或未定义行为。
    printf("%d\n", strlen(arr[1]));报错,表示strlen('b'),由基础知识——②知直接调用 strlen('a') 是不合法的,会导致编译错误或未定义行为。
    printf("%d\n", strlen(&arr));取出整个数组的地址,也是从数组首元素开始向后数到'\0'字符的个数,由基础知识——②,因为不知道这个数组的'\0'在哪里,所以'\0'之前出现的字符的个数是随机值
    printf("%d\n", strlen(&arr+1));比上一个随机值小6,因为跳过了一整个数组的地址,从'f'后面的地址开始向后数到'\0'结束
    printf("%d\n", strlen(&arr[0]+1));比上面第一个随机值小1取出首元素的地址,+1表示第二个元素的地址,即从'b'向后,为随机值

 char arr[] = "abcdef";
    printf("%d\n", sizeof(arr));整个数组的大小,字符串后面隐藏的\0,所以一共有7个字符,每个字符1个字节,共7个字节
    printf("%d\n", sizeof(arr + 0));arr不是单独在sizeof里面,所以表示首元素a的地址,+0还是首元素地址,地址是4/8
    printf("%d\n", sizeof(*arr));首元素地址解引用,是字符a,大小是1个字节
    printf("%d\n", sizeof(arr[1]));是第二个元素b的大小,1个字节
    printf("%d\n", sizeof(&arr));取出整个数组的地址,地址是4/8
    printf("%d\n", sizeof(&arr + 1));跳过整个数组,指向'\0'后面的元素的地址,地址就是4/8
    printf("%d\n", sizeof(&arr[0] + 1));第二个元素b的地址,地址就是4/8

    printf("%d\n", strlen(arr));从首元素向后数直到'\0'结束,有6个字符
    printf("%d\n", strlen(arr + 0));从首元素向后数直到'\0'结束,有6个字符
    printf("%d\n", strlen(*arr));报错,表示对数组首元素地址解引用,为strlen('a'),由基础知识——②知直接调用 strlen('a') 是不合法的,会导致编译错误或未定义行为。
    printf("%d\n", strlen(arr[1]));报错,表示strlen('b'),由基础知识——②知直接调用 strlen('a') 是不合法的,会导致编译错误或未定义行为。
    printf("%d\n", strlen(&arr));取出整个数组的地址,也就是首元素的地址,即首元素往后数字符个数直到'\0'结束,是6
    printf("%d\n", strlen(&arr + 1));跳过整个数组,指向'\0'后面的元素的地址,从这开始往后数字符个数直到'\0'结束,由基础知识——②,因为不知道后面的'\0'在哪里,所以'\0'之前出现的字符的个数是随机值
    printf("%d\n", strlen(&arr[0] + 1));取出首元素地址,+1表示第二个元素的地址,从这里向后直到'\0'有5个字符

 char* p = "abcdef";将首元素a的地址方p中
    printf("%d\n", sizeof(p));p是指针变量,本质是地址,4/8
    printf("%d\n", sizeof(p + 1));若p是0x0012ff40,那么p+1就是0x0012ff41,是地址,4/8
    printf("%d\n", sizeof(*p));对地址p解引用,表示指针指向的a,字符a的大小是1个字节
    printf("%d\n", sizeof(p[0]));——>  *(p+0)——>*p
    printf("%d\n", sizeof(&p));取出p的地址,而p是指针变量,所以&p是二级指针,也是地址,4/8
    printf("%d\n", sizeof(&p + 1));取出p的地址,+1表示指向p的下一个内存空间的地址,地址就是4/8
    printf("%d\n", sizeof(&p[0] + 1));&p[0]是a的地址,+1表示b的地址,地址是4/8

    printf("%d\n", strlen(p));p存a的地址,所以是从a的地址向后数直到'\0'之间的字符个数,为6
    printf("%d\n", strlen(p + 1));a的地址+1,就是b的地址,所以是从b的地址向后数直到'\0'之间的字符个数,为5
    printf("%d\n", strlen(*p));报错,对a的地址解引用,为a,由基础知识——②知直接调用 strlen('a') 是不合法的,会导致编译错误或未定义行为。
    printf("%d\n", strlen(p[0]));报错,为a,由基础知识——②知直接调用 strlen('a') 是不合法的,会导致编译错误或未定义行为。
    printf("%d\n", strlen(&p));是取p的地址,p的地址我们不知道是多少,所以'\0'在哪也不清楚,是随机值                                                                                 注意p的地址和p存的a的地址不一样
    printf("%d\n", strlen(&p + 1));p是个指针变量,是4个字节,取出p的地址再+1,表示p的地址的第4个字节后面的地址向后数到'\0'之间的字符个数,后面的'\0'在哪也不清楚,是随机值 ,而我们不知道这4个字节中有无'\0'所以不能判断这个随机值和上一个随机值的联系
    printf("%d\n", strlen(&p[0] + 1));&p[0]是a的地址,+1是指向b的地址,所以是从b的地址向后数直到'\0'之间的字符个数,为5

int a[3][4] = { 0 };二维数组
    printf("%d\n", sizeof(a));整个二维数组的大小,是3×4×4=48
    printf("%d\n", sizeof(a[0][0]));是第一行第一列元素的大小,为4
    printf("%d\n", sizeof(a[0]));a[0]是第一行这个一维数组的数组名,单独放sizeof内部表示第一行这整个一维数组,它的大小为4×4=16
    printf("%d\n", sizeof(a[0]+1));不是单独在sizeof中和在&后面,所以是首元素地址,就是第一行这个一维数组的第一列元素的地址,arr[0] 会自动转换为指向第一行首元素的指针,类型是 int*。arr[0] + 1 指向的地址是第一个元素 1 的地址加上 sizeof(int),表示第一行第二个元素的地址,地址是4/8
    printf("%d\n", sizeof(*(a[0]+1)));由上一条知a[0]+1是第一行第二个元素的地址,解引用就是第一行第二个元素,int类型大小是4
    printf("%d\n", sizeof(a+1));arr 会自动转换为指向数组首元素的指针。对于二维数组,首元素是一个一维数组(int[4]),因此 arr 会自动转换为指向一维数组的指针,类型是 int (*)[4]arr + 1 指向的地址是第一行的地址加上 sizeof(int[4]),即加上一行的大小。地址是4/8
    printf("%d\n", sizeof(*(a+1)));对第二行地址解引用,得到第二行。按指针运算来说*(a+1)=a[1],为4×4=16
    printf("%d\n", sizeof(&a[0]+1));对第一行数组名取地址,+1得第二行地址,地址是4/8
    printf("%d\n", sizeof(*(&a[0]+1)));对第二行地址解引用得到第二行,为4×4=16
    printf("%d\n", sizeof(*a));a二维数组首元素的地址,即第一行地址,对第一行解引用得到第一行,为4×4=16
    printf("%d\n", sizeof(a[3]));第4行,虽然这个数组没有4行,但是每行有4个int类型,sizeof其实是根据类型分析的,不是真的访问第4行,为4×4=16       

sizeof根据类型访问:             

eg:int a=10;sizeof(int)=sizeof(a)=4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值