指针进阶(3) -- 关于sizeof和strlen的详细总结(上)

简介: 指针进阶(3) -- 关于sizeof和strlen的详细总结(上)

1.知识准备


数组和指针的定义:

数组和指针

数组 - 能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型

指针 - 地址/指针变量,大小是4/8个


数组和指针的关系:

数组是数组,指针是指针,二者不等价

1.数组名是数组首元素的地址,这个地址就可以存放在指针变量中

2.我们就可以使用指针变量来遍历数组


🚀数组名的注意事项:

1.通常情况:

大部分情况下数组名是数组首元素的地址


2.例外

1.sizeof(数组名) - 数组名表示整个数组,计算的是整个数组的大小


2.&数组名 - 数组名表示整个数组,取出的是数组的地址


2.指针和数组笔试题解析


注意:编译环境是x86环境!,sizeof是一个操作符,和+- * /类似


整型数组的sizeof

int a[]={1,2,3,4}的sizeof的使用

#include<stdio.h>
int main(){
int a[] = {1,2,3,4};
    printf("%d\n",sizeof(a));//1
    printf("%d\n",sizeof(a+0));//2
    printf("%d\n",sizeof(*a));//3
    printf("%d\n",sizeof(a+1));//4
    printf("%d\n",sizeof(a[1]));//5
    printf("%d\n",sizeof(&a));//6
    printf("%d\n",sizeof(*&a));//7
    printf("%d\n",sizeof(&a+1));//8
    printf("%d\n",sizeof(&a[0]));//9
    printf("%d\n",sizeof(&a[0]+1))//10
    return 0;
}


接下来我将尽力解释每一行的含义

1.sizeof(a)

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

数组4个元素,每个元素是int类型,一个int类型4个字节,   4*4=16 byte

sizeof(a)就是数组名单独放在sizeof内部,计算的是数组的总大小, 单位是字节

运行结果:

17518841df6d438ca49f5249557f2393.png


2.sizeof(a + 0)

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

a+0,数组名(a)没有单独放在sizeof内部,这里属于参与运算变成地址了

             ||

a (首元素地址) + 0 == a(数组第一个元素地址) 这里并没有跳过任何距离,+0等于没加

所以大小为4个字节

运行结果:

f99d5b729e0543c39c0b0a2ff8114c95.png


3.sizeof(*a)

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

a是数组首元素的地址 --> &a[0]

*a -> *&a[0] -> a[0]  ==> * 和 & 可以互相抵消

个人理解:

因为a是数组首元素的地址,可以写成&a[0],即*a==*&a[0],所以*a可以表示为: *&a[0]

整体思想:

&a[0]是取出这个元素所在的内存空间的对应唯一的地址,而 *地址,是对地址解引用,找到那块空间对应的元素,而数组a的类型是int,所以它每个元素的数据类型也是int,所占内存空间字节是4 byte ,所以打印的结果为4

运行结果:

d2abf17471594ff781c005cbfb9f8781.png


4.sizeof(a + 1)

a是数组首元素的地址 -- int* ,a+1 跳过一个整型,是第二个元素的地址

运行结果:

346ab7cf62814fe1bfb1a6d027e3e05b.png


5.sizeof(a[1])

a[1]表示数组第二个元素,一个int大小就是4/8个字节

运行结果:

b9bd3be7858e4e919f94f87b77631228.png

6.sizeof(&a)

&a - 取出的是数组的地址,但是数组的地址也是地址,是地址大小就是4/8个字节

&a存起来:

int (*pa)[4]= &a --> 去掉pa,该指针类型为int (*)[4]

运行结果:

68dcfd951ab74a439e5011118d16453e.png

7.sizeof(*&a)

* 和 & 可以互相抵消,所以*&a==a,等于没有操作

个人理解:当对指针解引用的时候,访问几个字节取决于指针的类型

当是一个整型指针的时候,解引用访问的是一个整型,

当是一个字符指针的时候,解引用访问的是一个字符,

当是一个数组指针的时候,解引用访问的是一个数组,a[4],其类型是int,有4个元素,所以大小为16byte

运行结果:

b6fca2af802144fa9cf73490dc64c2c2.png


8. sizeof(&a + 1)

优先级是靠近的先算&a,先取地址,再解引用,跟优先级无关

区别:

数组名取地址取到的是整个数组的地址,从值上来看整个数组的地址和数组首元素地址的值相同,区别就是数组首元素地址+1时,跳过一个元素,整个数组地址+1时,跳过整个数组

&a+1 地址跳过一个数组,还是指向内存里面的,是地址就是4/8个byte

&a[0]是取出数组首元素地址 <==> &a是数组的地址

注意:

&a[0]和a(数组名)是等价的

运行结果:

7681538cd13c413eb911f66be1ba9e72.png

图解:

eaca12184fb044ea9768a5435660f065.png

9.sizeof(&a[0] )

数组第一个元素的地址

运行结果:

33985b3572c94e16801af313971db72b.png

10.sizeof(&a[0] + 1)

数组第二个元素的地址

运行结果:

f8d73ffcd12f410ebde171b1e0a8d355.png


字符数组的sizeof和strlen


char arr[]={'a','b','c','d','e','f'}的sizeof的使用

预备知识:

1.sizeof计算的是占用内存空间的大小,单位是字节,不关注内存中到底存放的是什么

2.sizeof不是函数,是操作符

3.strlen是函数

4.strlen是针对字符串的,求的是字符串的长度,本质上是统计 \0 之前出现的字符个数

//字符数组
#include<string.h>
int main()
{
  char arr[] = { 'a','b','c','d','e','f'};
  printf("%d\n", sizeof(arr));//6
  printf("%d\n", sizeof(arr + 0));//arr+0是数组首元素地址
  printf("%d\n", sizeof(*arr));//*arr是首元素的,计算的是首元素的大小
  printf("%d\n", sizeof(arr[1]));//1
  printf("%d\n", sizeof(&arr));//&arr是数组的地址 4/8
  printf("%d\n", sizeof(&arr + 1));//&arr + 1跳过一个数组后的地址 4/8
  printf("%d\n", sizeof(&arr[0] + 1));//4/8 第二个元素的地址
  return 0;
}

1.sizeof(arr)

数组名单独放在sizeof()内部,是数组的地址,这个数组是没有放'\0'的,所以仅仅只有6个元素,所以计算的是整个数组的大小,为6byte

运行结果:

2e81433e41ac4c1f8f04b4ef430d1877.png

2.sizeof(arr + 0)

数组名arr,没有单独放在sizeof()内部,arr+0就是数组首元素地址是地址字节大小就是4/8byte

运行结果:

1f9c00feabee407f93c44a7a5d126fda.png


3.sizeof(*arr)

*arr是首元素,计算的是首元素的大小,而一个char类型大小就1byte

运行结果:

8789d4e3c32f40658d3b1cfc51c9f8dc.png

4.sizeof(arr[1])

char类型数组第二个元素,字节大小是1byte

运行结果:

daec97cb74e7411b9cfe982f92ed108c.png

5.sizeof(&arr)

&arr,是取出char a数组的地址,是地址大小就是4/8byte

运行结果:

9b06fb771d0d4956943934a6a20a2686.png

6.sizeof(&arr + 1)

&arr + 1跳过一个数组后的地址,字节大小是4/8

运行结果:

fdecbd862e4a4e2ea75ec75e1ddfb7da.png

7.sizeof(&arr[0] + 1)

字符数组第二个元素的地址,字节大小是4/8

运行结果:

11f63a2527224c8f9f95694173cb1265.png

相关文章
|
3月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
3月前
|
C语言
指针进阶(回调函数)(C语言)
指针进阶(回调函数)(C语言)
|
3月前
|
存储 C语言 C++
指针进阶(函数指针)(C语言)
指针进阶(函数指针)(C语言)
|
3月前
|
编译器 C语言
指针进阶(数组指针 )(C语言)
指针进阶(数组指针 )(C语言)
|
3月前
|
搜索推荐
指针进阶(2)
指针进阶(2)
39 4
|
3月前
指针进阶(3)
指针进阶(3)
32 1
|
3月前
|
C++
指针进阶(1)
指针进阶(1)
35 1
|
3月前
|
存储 安全 编译器
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
C++进阶之路:何为引用、内联函数、auto与指针空值nullptr关键字
32 2
|
3月前
|
Java 程序员 Linux
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
探索C语言宝库:从基础到进阶的干货知识(类型变量+条件循环+函数模块+指针+内存+文件)
36 0
|
3月前
|
存储 安全 编译器
C++进阶之路:探索访问限定符、封装与this指针的奥秘(类与对象_上篇)
C++进阶之路:探索访问限定符、封装与this指针的奥秘(类与对象_上篇)
27 0