C生万物 | 从浅入深理解指针【最后部分】(一)

简介: C生万物 | 从浅入深理解指针【最后部分】(一)
  • 接下来我们开始我们指针的最后一个部分,来加深对指针的印象~~

sizeof和strlen的对比

sizeof

  • 在学习操作符的时候,我们学习了sizeofsizeof 计算变量所占内存内存空间大小的,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。
  • 我们就来开始学习了解sizeof~~
  • 其中size_t其实专门是设计给sizeof的,表示sizeof的返回值类型
  • sizeof计算的不可能是负数吧,所以size_t是为sizeof来设计的~~

列如:

int main()
{
  int a = 10;
  printf("%d\n", sizeof(a));
  printf("%d\n", sizeof(int));
  return 0;
}

  • 如果这里是变量,括号是可以省略的
  • 如果是类型就是,就不能省略

  • 这里算出的4就是占用4个字节
  • sizeof 只关注占用内存空间的大小,不在乎内存中存放什么数据,我们一会来详细看~~

strlen

strlenC语言库函数,功能是求字符串长度。函数原型如下:

size_t strlen ( const char * str );

它统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数。

strlen 函数会一直向后找\0 字符,直到找到为止,所以可能存在越界查找。

我们来看下面的代码

int main()
{
  char arr2[] = "abc";
  printf("%d\n", strlen(arr2));
  return 0;
}
  • 这里的strlen算出的是几?3
  • 我们还可以通过调试窗口看一下是怎么存放的~~

  • 可以看到这里内存监视窗口的61就是97,0就是\0strlen是统计\0之前的字符串的个数,结果是3

  • 那我在字符串的中间手动加一个\0会算出几呢?
char arr2[] = "ab\0c";
printf("%d\n", strlen(arr2));
  • 可以看到结果是3

  • 那字符串没有\0它的结果是什么呢?
char arr1[] = { 'a', 'b', 'c' };
printf("%d\n", strlen(arr1));
  • 我们可以看到结果是15,其实是随机值,我也不知道多会会遇到\0

  • 下面我们来对比一下strlensizeof

strlen:

  • sizeof是操作符
  • sizeof计算操作数所占内存的大小,单位是字节
  • 不关注内存中存放什么数据

sizeof:

  • strlen是库函数,使用需要包含头文件string.h
  • srtlen是求字符串长度的,统计的是\0之前字符的个数
  • 关注内存中是否有\0,如果没有\0,就会持续往后找,可能会越界
  • sizeof在计算大小的时候,其实是根据类型推算的
  • 那么下面打印的是什么呢?
short s = 10;
int i = 2;
int n = sizeof(s = i + 4);
printf("%d\n", n);
printf("%d\n", s);
  • 我们来看结果~~

  • 为什么是2和10呢?我们来分析一下~~
  • 创建了一个短整型s,占两个字节,i是整形,占四个字节
  • 这里的i+4得出的结果我要放到s类型,我一个4个整形的放到两个整形的空间,这要发生截断,截断之后就是s说了算,所以就是2个字节。
  • 那么第二个,表达式放到sizeof内部不会真实计算的,不参与计算!!!所以原来的值就会打印什么值~~
  • 那么有同学会问,表达式不参与计算,那上面那个为什么会是2呢?其实是sizeof是根据类型推断出来的,s = i + 4不会执行,其中 i + 4算出的就是整形类型的,整形类型的结果要放到shot类型的,所以就是short类型,就是2个字节,你懂了吗~~

如果还没有理解的话,我们来看一些笔试题,来加深一下印象~~

数组和指针笔试题解析

一维数组

  • 我们先来看这里,下面打印的是什么呢?可以先自己分析一下,然后我们来挨个分析~~
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;
}
  • 你要知道的就是数组名即为首元素地址,不过有两个例外:
  • sizeof(数组名) —— 数组名表示整个数组,计算的是整个数组的大小,单位是字节
  • &数组名 —— 数组名表示数组名表示整个数组,取出的是整个数组的地址。
  • sizeof内部单独放了一个数组名,数组名表示整个数组的大小,数组内有4个元素,每个元素4个字节,所以就是16
printf("%d\n", sizeof(a));
  • 这个地方的数组名的a并没有放到sizeof内部,也没有&,所以a就是首元素的地址,是地址,大小就是4/8个字节
printf("%d\n", sizeof(a + 0));
  • a就是数组首元素的地址,a==&a[0],*a 其实就是第一个元素,也就是a[0],大小就是4个字节
printf("%d\n", sizeof(*a));
  • a就是数组首元素的地址(&a[0] -->int*), a+1–> &a[1],a+1就是第二个元素的地址,所以结果就是4/8
printf("%d\n", sizeof(a + 1));
  • 计算第2个元素的大小,单位是字节 结果就是4
printf("%zd\n", sizeof(a[1]));
  • &a 取出的是数组的地址,但是数组的地址也是地址,是地址大小就是4 / 8 个字节
printf("%zd\n", sizeof(&a));
  • 这里&a是取出数组的地址,然后再解引用,也就是相当于抵消了,&a是一个数组指针,也就是int(*p)[4] = &a,*p访问一个数组的大小,p+1就是跳过一个数组的大小,结果是16
printf("%d\n", sizeof(*&a));
  • &a+1是跳过整个数组后的地址,是地址大小就是4/8个字节,结果就是4/8
printf("%zd\n", sizeof(&a + 1));
  • &a+1是跳过整个数组后的地址,是地址大小就是4/8个字节,结果就是4/8
printf("%zd\n", sizeof(&a + 1));
  • 我们在vs上验证一下,这个是32位平台下打印的~~

  • 这个是在64位下运行的~~

C生万物 | 从浅入深理解指针【最后部分】(二):https://developer.aliyun.com/article/1426866

相关文章
C生万物 | 从浅入深理解指针【最后部分】(二)
C生万物 | 从浅入深理解指针【最后部分】(二)
|
3月前
|
存储 C++
C生万物 | 从浅入深理解指针【第三部分】(转移表的实现)
C生万物 | 从浅入深理解指针【第三部分】(转移表的实现)
C生万物 | 从浅入深理解指针【第二部分】(二)
C生万物 | 从浅入深理解指针【第二部分】(二)
|
3月前
|
编译器
C生万物 | 从浅入深理解指针【第二部分】(一)
C生万物 | 从浅入深理解指针【第二部分】 前言: 如果没有看过第一部分的话,推荐先看第一部分,然后再来看第二部分~~
C生万物 | 从浅入深理解指针【第四部分】(qsort的使用和模拟实现)
C生万物 | 从浅入深理解指针【第四部分】(qsort的使用和模拟实现)
|
3月前
|
机器学习/深度学习 安全 程序员
C生万物 | 从浅入深理解指针【第一部分】(二)
C生万物 | 从浅入深理解指针【第一部分】(二)
|
9天前
|
存储 C语言
C语言 — 指针进阶篇(下)
C语言 — 指针进阶篇(下)
16 0
|
9天前
|
存储 C语言 C++
C语言 — 指针进阶篇(上)
C语言 — 指针进阶篇(上)
8 0
|
24天前
|
存储 人工智能 编译器
C语言指针详解
指针运算,指针和数组,二级指针
C语言指针详解
|
24天前
|
存储 C语言
C语言第二十四弹---指针(八)
C语言第二十四弹---指针(八)

热门文章

最新文章