C语言--指针终章

 

目录

 

1. sizeof和strlen的对⽐

1.1 sizeof

1.2 strlen

1.3 sizeof 和 strlen的对⽐

 2. 数组和指针的理解——题目理解

2.1.sizeof

代码1:

代码2:

代码3:

代码4:

代码5(二维数组):

2.2:strlen

代码1:

代码2: 

代码3:

代码4(模拟实现strlen的三种方式):


冰冻三尺,非一日之寒

1. sizeof和strlen的对⽐

1.1 sizeof

 sizeof 计算变量所占内存内存空间⼤⼩的,单位是 字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩。

sizeof 只关注占⽤内存空间的⼤⼩,不在乎内存中存放什么数据。
⽐如:
#inculde <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 函数的参数 str 中这个地址开始向后, \0 之前字符串中字符的个数。
strlen 函数会⼀直向后找 \0 字符,直到找到为⽌,所以可能存在越界查找。
#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;
}

1.3 sizeof 和 strlen的对⽐

 2. 数组和指针的理解——题目理解

2.1.sizeof

代码1:

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };//数组有几个元素
	printf("%zd\n", sizeof(a));//16 -- sizeof(数组名)的场景
	printf("%zd\n", sizeof(a + 0));//a是首元素的地址-类型是int*,a+0还是首元素的地址,是地址大小就是4/8
	printf("%zd\n",sizeof(*a));//a是首元素的地址,*a就是首元素,大小就是4个字节
	//*a == a[0] == *(a+0)
	printf("%zd\n",sizeof(a + 1));//a是首元素的地址,类型是int*,a+1跳过1个整型,a+1就是第二个元素的地址,4/8
	printf("%zd\n",sizeof(a[1]));//a[1]就是第二个元素,大小4个字节
	printf("%zd\n",sizeof(&a));//&a是数组的地址,数组的地址也是地址,是地址大小就是4/8个字节
	printf("%zd\n",sizeof(*&a));//1.*& 互相抵消了,sizeof(*&a)= sizeof(a)-16
	//2. &a 是数组的地址,类型是int(*)[4],对数组指针解引用访问的是数组,计算的是数组的大小 -16
	printf("%zd\n",sizeof(&a + 1));//&a+1是跳过整个数组后的那个位置的地址,是地址就是4/8个字节
	printf("%zd\n", sizeof(&a[0] + 1));//&a[0]+ 1 -- 数组第二个元素的地址,大小是4/8个字节
	printf("%zd\n",sizeof(&a[0]));//首元素的地址,大小4/8个字节
	return 0;
}

代码2:

#include<stdio.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", sizeof(arr));//数组名单独放在sizeof内部,计算的是数组的大小,单位是字节--6
	
    printf("%d\n", sizeof(arr + 0));//arr是数组名表示首元素的地址,arr+0还是首元素的地址,是地址就是4/8个字节
	
    printf("%d\n", sizeof(*arr));//arr是首元素的地址,*arr就是首元素,大小就是1个字节
	//*arr --  arr[0] -- *(arr+0)等价
	
    printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,大小也是1个字节
	
    printf("%d\n", sizeof(&arr));//&arr是数组地址,数组的地址也是地址,大小是4/8
	//&arr -- char(*)[6]
	
    printf("%d\n", sizeof(&arr + 1));//&arr+1,跳过整个数组,指向了数组后边的空间,4/8个字节
	
    printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,是地址就是4/8字节

	return 0;
}

代码3:

include<stdio.h>
int main()
{
	char arr[] =  "abcdef" ;
	printf("%d\n", sizeof(arr));//arr是数组名,单独放在sizeof内部,计算的是数组中大小,是7个字节

	printf("%d\n", sizeof(arr + 0));//arr表示数组首元素的地址,srr+0还是首元素的地址,是地址就是4/8

	printf("%d\n", sizeof(&arr));//arr表示数组首元素的地址,*arr就是首元素。大小是1字节

	printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,大小是1个字节

	printf("%d\n", sizeof(&arr));//&arr是数组的地址,+1是跳过整个数组,还是地址,是地址就是4/8字节

	printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]+1是第二个元素的地址,大小是4/8个字节

	return 0;
}

代码4:

#include<stdio.h>
int main()
{
	const char* p = "abcdef";
	printf("%d\n", sizeof(p));//p是指针变量,我们计算的是指针变量的大小,4/8个字节

	printf("%d\n", sizeof(p + 1));//p+1是b的地址,是地址大小就是4/8个字节

	printf("%d\n", sizeof(*p));//p的类型是const char*,*p就是char类型了,1个字节

	printf("%d\n", sizeof(p[0]));//1.p[0] --> *(p+0) --> *p --> 'a',大小是1字节
	//2.把常量字符串想象成数组,p可以理解为数组名,p[0]就是首元素

	printf("%d\n", sizeof(&p));//取出的是p的地址,地址的大小就是4/8字节

	printf("%d\n", sizeof(&p + 1));//&p+1是跳过p指针变量后的地址,是地址就是4/8字节

	printf("%d\n", sizeof(&p[0] + 1));//4/8 &p[0]-取出字符串首字符的地址,+1是第二个字符的地址,大小是4/8字节

	return 0;
}

代码5(二维数组):

#include<stdio.h>
int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//a是数组名,单独放在sizeof内部,计算的是数组打大小,单位是字节-48 =3*4*sizeof(int)

	printf("%d\n", sizeof(a[0][0]));//a[0][0] 是第一行第一个元素,大小4个字节

	printf("%d\n", sizeof(a[0]));//a[0]第一行的数组名,数组名单独放在sizeof内部了,计算的是数组的中大小 16 个字节

	printf("%d\n", sizeof(a[0] + 1));//a[0]第一行的数组名,但是a[0]并没有单独放在sizeof内部,所以这里的数组名a[0]就是
	//数组首元素的地址,就是&a[0][0],+1后是a[0][1]的地址,大小是4/8个字节

	printf("%d\n", sizeof(*(a[0] + 1)));//*(a[0] + 1)表示第一行第二个元素,大小就是4(int类型)

	printf("%d\n", sizeof(a + 1));//a作为数组名并没有单独放在sizeof内部,a表示数组数组首元素的地址,是二维数组首元素的地址,也就是
	//第一行的地址,a+1,跳过一行,指向了第二行,a+1是第二行的地址,a+1是数组指针,是地址大小就是4/8个字节

	printf("%d\n", sizeof(*(a + 1)));//1.a+1是第二行的地址,*(a+1)就是第二行,计算的是第二行的大小-16
	//2.*(a+1) == a[1],a[1]是第二行的数组名,sizeof(*(a+1))就相当于sizeof(a[1]),意思是把第二行的数组名单独放在
	//sizeof内部,计算的是第二行的大小

	printf("%d\n", sizeof(&a[0] + 1));//a[0]是第一行的数组名,&a[0]取出的是数组的地址,就是第一行的地址
	//&a[0]+1 就是第二行的地址,是地址大小就是4/8个字节

	printf("%d\n", sizeof(*(&a[0] + 1)));//*(a[0] + 1)意思是对第二行的地址解引用,访问的就是第二行,大小就是16字节 
	
	printf("%d\n", sizeof(*a));//a作为数组名并没有单独放在sizeof内部,a表示数组首元素的地址,是二维数组首元素的地址,也就是
	//第一行的地址,*a就是第一行,计算的是第一行的大小,16字节
	//*a == *(a+0) ==a[0]

	printf("%d\n", sizeof(a[3]));//a[3]无需真实存在,仅仅通过类型的推断就能算出长度
	//a[3]是第四行的数组名,单独放在sizeof内部,计算的是第四行的大小,16字节

	return 0;
}

2.2:strlen

代码1:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", strlen(arr));//arr是首元素的地址,数组中没有\0,就会导致越界访问结果是随机的
	
	printf("%d\n", strlen(arr + 0));//arr+0是首元素的地址,数组中没有\0,就会导致越界访问是随机的
	
	printf("%d\n", strlen(*arr));//arr是首元素的地址,*arr是首元素,就是‘a’,‘a'的ascii码值是97
	//就相当于打97作为地址传递给了strlen,strlen得到的就是野指针,代码是有问题
	printf("%d\n", strlen(arr[1]));//arr[1]--'b'--98.传给strlen函数也是错误的

	printf("%d\n", strlen(&arr));//&arr是数组的地址,起始位置是数组的第一个元素的位置,随机值 x

	printf("%d\n", strlen(&arr + 1));//随机值x-6

	printf("%d\n", strlen(&arr[1] + 1));//第2个元素开始向后统计的,得到的也是随机值 x-1
	return 0;
}

代码2: 

#include<stdio.h>
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };

	printf("%d\n", sizeof(arr));//数组名单独放在sizeof内部,计算的是数组的大小,单位是字节--6
	printf("%d\n", sizeof(arr + 0));//arr是数组名表示首元素的地址,arr+0还是首元素的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(*arr));//arr是首元素的地址,*arr就是首元素,大小就是1个字节
	//*arr --  arr[0] -- *(arr+0)等价
	printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素,大小也是1个字节
	printf("%d\n", sizeof(&arr));//&arr是数组地址,数组的地址也是地址,大小是4/8
	//&arr -- char(*)[6]
	printf("%d\n", sizeof(&arr + 1));//&arr+1,跳过整个数组,指向了数组后边的空间,4/8个字节
	printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,是地址就是4/8字节

	return 0;
}

代码3:

#include<stdio.h>
#include<string.h>
int main()
{
	char* p = "abcdef";
	printf("%d\n", strlen(p));//6

	printf("%d\n", strlen(p + 1));//5
	
	pritnf("%d\n", strlen(*p));//*p就是‘a'-97,err

	printf("%d\n", strlen(p[0]));//p[0]-->*(p+0)-->*p //err

	printf("%d\n", strlen(&p));//&p是指针变量p的地址,和字符串“abcdef”关系不大
	//从p这个指针变量的起始位置开始向后数的,p变量存放的地址是什么,不知道,所以答案是随机值

	printf("%d\n", strlen(&p + 1));//随机值

	printf("%d\n", strlen(&p[0] + 1));//5
	return 0;
}

代码4(模拟实现strlen的三种方式):

#include<stdio.h>
#include<string.h>
#include<assert.h>

//计算器方式
int my_strlen1(char* str)
{
	int count = 0;
	assert(str);
	while (*str)
	{
		count++;
		str++;
	}
	return count;
}

//不创建临时变量记数器(递归)
int my_strlen2(const char* str)
{
	assert(str);
	if (*str == '\0')
		return 0;
	else
		return 1 + my_strlen2(str + 1);
}

//指针-指针的方式
int my_strlen3(char* str)
{
	assert(str);
	char* p = str;
	while (*p != '\0')
		p++;
	return p - str;
}

int main()
{
	char *a = "abcdef";
	int s = my_strlen1(a);
	printf("%d\n", s);
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/520255.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【蓝桥杯-单链表-网络寻路】

蓝桥杯-单链表-网络寻路 单链表基本操作操作一&#xff1a;向链表头插入一个数操作二:在第 k个插入的数后插入一个数操作三&#xff1a;删除第 k个插入的数后面的一个数&#xff1b; P8605 [蓝桥杯 2013 国 AC] 网络寻路 单链表基本操作 初始化有关操作 // head 表示头结点的…

Debian12 使用 nginx 与 php8.2 使用 Nextcloud

最近将小服务器升级了下系统&#xff0c;使用了 debian12 的版本&#xff0c;正好试试 nginx 和 php-fpm 这种方式运行 Nextcloud 这个私有云的配置。 一、基本系统及应用安装 系统&#xff1a;debian12 x86_64 位版本最小安装&#xff0c;安装后可根据自己需求安装一些工具&…

如何优化TCP?TCP的可靠传输机制是什么?

在网络世界中&#xff0c;传输层协议扮演着至关重要的角色&#xff0c;特别是TCP协议&#xff0c;以其可靠的数据传输特性而广受青睐。然而&#xff0c;随着网络的发展和数据量的激增&#xff0c;传统的TCP协议在效率方面遭遇了挑战。小编将深入分析TCP的可靠性传输机制&#x…

【C++初阶】 vector 在OJ中的使用

前言&#xff1a; &#x1f3af;个人博客&#xff1a;Dream_Chaser &#x1f388;博客专栏&#xff1a;C &#x1f4da;本篇内容&#xff1a;只出现一次的数字 和 杨辉三角 OJ 目录 一、只出现一次的数字 题目描述&#xff1a; 二、杨辉三角OJ 题目描述&#xff1a; 一、只…

vue快速入门(七)内联语句

注释很详细&#xff0c;直接上代码 上一篇 新增内容 button点击事件绑定内联语句写法与要求 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wid…

phpstorm设置头部注释和自定义注释内容

先说设置位置&#xff1a; PhpStorm中文件、类、函数等注释的设置在&#xff1a;setting-》Editor-》FIle and Code Template-》Includes-》PHP Function Doc Comment下设置即可&#xff0c;其中方法的默认是这样的&#xff1a; /** ${PARAM_DOC} #if (${TYPE_HINT} ! "…

【第九篇】使用BurpSuite进行编码与解码

Burp存在一个功能&#xff0c;可以识别包含不透明数据&#xff08;例如会话令牌&#xff09;的消息。 如图&#xff1a;如果 Burp 识别所选内容的编码格式&#xff0c;它会自动解码数据。解码后的文本显示在 Inspector面板中。 在编码工具模块中&#xff0c;可对数据进行重复解…

C. MEX Game 1

本题如果我们去模拟这个算法的话会很麻烦&#xff0c;也会TLE&#xff0c;首先我们想 1&#xff0c;对于alice来说&#xff0c;先取小的&#xff0c;对于bob来说先删除alic想取的下一个小的 2&#xff0c;那如果这个数多于两个&#xff0c;那也就是说&#xff0c;alice肯定能…

电工技术学习笔记——正弦交流电路

一、正弦交流电路 1. 正弦量的向量表示法 向量表示方法&#xff1a;正弦交流电路中&#xff0c;相量表示法是一种常用的方法&#xff0c;用于描述电压、电流及其相位关系。相量表示法将正弦交流信号表示为复数&#xff0c;通过复数的运算来描述电路中各种参数的相互关系 …

C/C++预处理过程

目录 前言&#xff1a; 1. 预定义符号 2. #define定义常量 3. #define定义宏 4. 带有副作用的宏参数 5. 宏替换的规则 6. 宏和函数的对比 7. #和## 8. 命名约定 9. #undef 10. 命令行定义 11. 条件编译 12. 头文件的包含 13. 其他预处理指令 总结&#x…

IP地址:是给主机配置的,还是给网卡配置的?

在探索网络的奥秘时&#xff0c;我们经常会遇到一个看似简单但又复杂的问题&#xff1a;IP地址到底是配置在主机上&#xff0c;还是配置在网卡上&#xff1f;为什么我们通常说的是“主机IP地址”呢&#xff1f;让我们一起深入探讨。 1. 网卡与IP地址 &#x1f5a5;️&#x1f…

有同学和我说,深度学习不用特征工程,只有浅层机器学习方法采用特征工程,我说你误会了,我给你好好解释吧!!

1. 通俗解释 浅层机器学习算法&#xff08;如逻辑回归、决策树、支持向量机等&#xff09;和深度学习算法&#xff08;如神经网络&#xff09;在特征工程上的依赖性确实存在一些差异。 浅层机器学习算法的特征工程依赖性&#xff1a; 浅层算法通常需要手工选择和设计特征&…

lua学习笔记5(分支结构和循环的学习)

print("*****************分支结构和循环的学习******************") print("*****************if else语句******************") --if 条件 then end a660 b670 --单分支 if a<b thenprint(a) end --双分支 if a>b thenprint("满足条件")…

RGB三通道和灰度值的理解

本文都是来自于chatGPT的回答!!! 目录 Q1:像素具有什么属性?Q2:图像的色彩是怎么实现的?Q3:灰度值和颜色值是一个概念吗?Q4:是不是像素具有灰度值&#xff0c;也有三个颜色分量RGB&#xff1f;Q5:灰度图像是没有色彩的吗&#xff1f;Q6: 彩色图像是既具有灰度值也具有RGB三…

11_printf函数移植串口通信

printf函数移植串口通信 printf函数移植串口通信串口显示汉字乱码问题解决代码 printf函数移植串口通信 MicroLIB是Keil为嵌入式平台优化的一个精简库 --no-multibyte-chars 串口显示汉字乱码问题解决 法一 法二 代码 主函数 #include "stm32f10x.h" …

[StartingPoint][Tier1]Sequel

Task 1 During our scan, which port do we find serving MySQL? (在扫描过程中&#xff0c;我们发现哪个端口为 MySQL 提供服务&#xff1f;) 3306 Task 2 What community-developed MySQL version is the target running? (目标正在运行哪个社区开发的 MySQL 版本&…

详解 Redis 在 Centos 系统上的安装

详解 Redis 在 Centos 系统上的安装 1. 使用 yum 安装 Redis 5 如果是Centos8&#xff0c;yum 仓库中默认的 redis 版本就是5&#xff0c;直接 yum install 即可 如果是Centos7, yum 仓库中默认的 redis 版本是3系列&#xff0c;版本就比较老 使用yum list | grep redis命令…

【问题解决】电脑突然 总蓝屏,这份火爆全网的452页Linux运维 Framework内核解析

“你的设备遇到问题&#xff0c;需要重启。我们智手机某些错误信息&#xff0c;然后为你重新启动。” 电脑突然就蓝屏了&#xff0c;终止代码显示&#xff1a;UNEXPECTED_STORE_EXCEPTION。 原因分析&解决方案 可能性原因解决方案1出现蓝屏的情况&#xff0c;大部分原因都…

【C++ STL容器适配器】queue 队列

文章目录 【 1. 基本原理 】【 1. queue 的创建 】2.1 使用默认的 deque 基础容器创建一个空的 queue2.2 指定基础容器创建 queue2.3 通过基础容器来初始化 queue 容器适配器2.4 通过一个 queue 初始化另一个 queue 【 3. queue 支持的成员函数 】 【 1. 基本原理 】 STL queu…

ChatGPT(3.5版本)开放无需注册:算力背后的数据之战悄然打响

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…