C语言第二十三弹---指针(七)

✨个人主页:熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】

指针

1、sizeof和strlen的对比

1.1、sizeof

1.2、strlen

[1.3、sizeof 和 strlen的对比](#1.3、sizeof 和 strlen的对比)

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

2.1、⼀维数组

2.2、二维数组

总结


1、sizeof和strlen的对比

1.1、sizeof

在学习操作符的时候,我们学习了 sizeof , sizeof 计算变量所占内存空间大小的 , 单位是
字节 ,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。
sizeof 只关注占注内存空间的大小,不在乎内存中存放什么数据。
比如:

#include <stdio.h>
int main()
{
	int a = 10;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof a);
	printf("%d\n", sizeof(int));
	return 0;
}

注:变量可以不加括号,类型必须加圆括号(小括号)。

1.2、strlen


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

size_t strlen ( const char * str );

注:strlen需要包含头文件#include<string.h>,可以在cplusplus旧版本搜索,前面函数章节有详细讲解查库函数的两个工具。
统计的是从 strlen 函数的参数 str 中这个地址开始向后, \0 之前字符串中字符的个数。
strlen 函数会⼀直向后找 \0 字符,直到找到为止,所以 可能存在越界查找。

#include<string.h>
#include <stdio.h>
int main()
{
 char arr1[3] = {'a', 'b', 'c'};
 char arr2[] = "abc";
 printf("%d\n", strlen(arr1));
 printf("%d\n", strlen(arr2));
 
 printf("%d\n", sizeof(arr1));
 printf("%d\n", sizeof(arr2));
 return 0;
}


为什么strlen(arr1)是15呢?按照我们正常思维是不是应该为3呢?
听小林娓娓道来,首先需要知道strlen是如何进行计算的,计算的是首地址到'\0'直接的字符个数,arr1数组是通过单引号进行初始化的,初始化几个元素就是几个元素,其中没有包含\0,因此在计算字符串长度时,遇到'\0'才停止,但是此处不知道什么为'\0',所以该长度为随机值(编译器不同答案就可能不一样)。
那有uu会说为什么strlen(arr2)就是3呢?
这就考到我们之前需要字符串时讲的一个知识点,双引号包裹的字符串在末尾会自动加上'\0',因此在计算arr2的长度时,在字符c之后遇到'\0'就会停止,也就能计算正确字符串长度。
为什么sizeof(arr2)是4呢?按照正常思维是不是应该为3呢?
首先我们需要知道sizeof是如何进行计算的,sizeof计算的是占用内存空间的大小,单位为字节,上述我们刚刚讲到双引号包裹的字符串在末尾会自动加上'\0',因此arr2中的元素有abc\0四个,根据数组不加大小的原则,实际为几个字节那么数组就占用几个字节,因此arr2占用的大小为4字节,即sizeof(arr2)为4。

1.3、sizeof 和 strlen的对比

sizeof strlen
1. sizeof是操作符 2. sizeof计算操作数所占内存的大小, 单位是字节 3. 不关注内存中存放什么数据 1. strlen是库函数,使用需要包含头⽂件 string.h 2. srtlen是求字符串长度的,统计的是 \0 之前字符的个数 3. 关注内存中是否有 \0 ,如果没有 \0 ,就会持续往后找,可能会越界

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

2.1、⼀维数组

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));

sizeof计算操作数所占内存的大小, 单位是字节

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

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

//数组名单独放在sizeif内部代表的是整个数组大小(数据类型大小*数据个数),因此为16字节

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

//数组名不是单独放在sizeof内部,因此数组名为数组首元素地址,+0还是此地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。

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

//数组名为首元素地址,*a则为数组第一个元素,类型为int,因此为4字节

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

//数组名不是单独放在sizeof内部,因此数组名为数组首元素地址,+1则向后移动一个int类型大小位置,但还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。

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

//a[1]为数组第二个元素,类型为int,因此为4字节

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

//&a为整个数组的地址,但是实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。

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

//&a为整个数组的地址,解引用则为整个数组,因此此处为整个数组大小,即16字节

//也可以理解为*和&可以相互抵消,就是数组名单独在sizeof内部

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

//&a为整个数组的地址,+1即向后走整个数组大小步,但是实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。

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

//a[0]为第一个元素,&a[0]为第一个元素的地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。

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

//a[0]为第一个元素,&a[0]为第一个元素的地址,+1则向后走int类型大小步,但是实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。

2.2、二维数组

int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));

sizeof计算操作数所占内存的大小, 单位是字节

int a[3][4] = {0};
printf("%d\n",sizeof(a));
//数组名单独放在sizeof内部代表整个数组大小(数据元素类型大小*元素个数,即4*3*4),因此为48字节。
printf("%d\n",sizeof(a[0][0]));
//a[0][0]为第一行第一列的元素,类型为int,因此大小为4字节。
printf("%d\n",sizeof(a[0]));
//a[0]单独放在sizeof内部代表整行元素,大小为4*4字节
printf("%d\n",sizeof(a[0]+1));
//a[0]为首行第一个元素地址,+1为第二行第一个元素地址,但实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(*(a[0]+1)));
//a[0]为首行第一个元素地址,+1为第二行第一个元素地址,解引用则为第二行首元素,int类型,4字节。
printf("%d\n",sizeof(a+1));
//a为首元素地址,在二维数组中,首元素地址为首行地址,+1则为第二行地址,但实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(*(a+1)));
//a为首元素地址,在二维数组中,首元素地址为首行地址,+1则为第二行地址,解引用则为第二行元素大小,4*4字节。
printf("%d\n",sizeof(&a[0]+1));
//&a[0]为首行的地址,+1位第二行的地址,但实质还是地址,地址在x64(64位)环境为8字节,x86(32位)环境为4字节。
printf("%d\n",sizeof(*(&a[0]+1)));
//&a[0]为首行的地址,+1位第二行的地址,解引用则为第二行的大小,4*4字节。
printf("%d\n",sizeof(*a));
//a为首元素地址,在二维数组中,首元素地址为首行地址,解引用则为首行的大小,4*4字节。
printf("%d\n",sizeof(a[3]));
//a[3]为第四行的地址,单独放在sizeof内部代表整行元素,虽然越界了,但是sizeof只看类型,大小为4*4字节。

总结

本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

相关推荐
Heisenberg~1 小时前
详解八大排序(五)------(计数排序,时间复杂度)
c语言·数据结构·排序算法
Elihuss2 小时前
ONVIF协议操作摄像头方法
开发语言·php
lb36363636364 小时前
分享一下arr的意义(c基础)(必看)(牢记)
c语言·知识点
Swift社区5 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht5 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht5 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20245 小时前
Swift 数组
开发语言
南东山人6 小时前
一文说清:C和C++混合编程
c语言·c++
stm 学习ing6 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc7 小时前
《Python基础》之字符串格式化输出
开发语言·python