指针进阶(3)

文章目录

    • 9. 指针和数组笔试题解析
    • 10. 指针笔试题

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

在做题之前,我们再次明确一下数组名的理解:

数组名是数组首元素的地址,但是有2个例外:

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址

接下来是一些笔试题:

#include <stdio.h>

int main()
{
	int a[] = { 1,2,3,4 };
 
	printf("%d\n", sizeof(a));//4*4=16
	printf("%d\n", sizeof(a + 0));//数组名a是数组首元素的地址,a+0还是首元素的地址,地址的大小4/8
	printf("%d\n", sizeof(*a));//数组名a是数组首元素的地址,*a就是首元素,大小就是4个字节
	printf("%d\n", sizeof(a + 1));//数组名a是数组首元素的地址,a+1是第二个元素的地址,地址的大小4/8
	printf("%d\n", sizeof(a[1]));//第二个元素的大小就是4个字节
	printf("%d\n", sizeof(&a));//&a是数组的地址,数组的地址也是地址,是地址4/8个字节
	printf("%d\n", sizeof(*&a));//16个字节
	//sizeof(*&a) --> sizeof(a) - 16
	//&a --> int (*)[4]
	//对整型指针解引用,拿到的是整型;对数组指针解引用,拿到的就是整个数组
	printf("%d\n", sizeof(&a + 1));//&a+1相对于&a是跳过了整个数组,但是即使跳过了整个数组,&a+1依然是地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&a[0]));//&a[0]是首元素的地址,4/8个字节
	printf("%d\n", sizeof(&a[0] + 1));//&a[0]是首元素的地址,&a[0]+1就是第二个元素的地址,是地址就是4/8个字节

	return 0;
}
#include <stdio.h>
#include <string.h>

int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
 
	printf("%d\n", sizeof(arr));//数组名单独放在sizeof内部,这里的arr表示整个数组,计算的是整个数组的大小,单位是字节,总共6个字节
	printf("%d\n", sizeof(arr + 0));//arr表示数组首元素的地址,arr+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是数组的地址,但是数组的地址也是地址,是地址就是4/8
	printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过整个数组后的地址,是地址就是4/8个字节
	printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,是4/8个字节
	
	printf("%d\n", strlen(arr));//因为字符数组arr中没有\0,所以在求字符串长度的时候,会一直往后找,产生的结果就是随机值
	printf("%d\n", strlen(arr + 0));//arr + 0是首元素的地址,和第一个一样,也是随机值
	//printf("%d\n", strlen(*arr));//err  arr是数组首元素的地址,*arr就是数组首元素,就是'a' - 97
	
	//strlen函数参数的部分需要传一个地址,当我们传递的是'a'时,'a'的ASCII码值是97,那就是将97作为地址传参
	//strlen就会从97这个地址开始统计字符串长度,这就非法访问内存了
	
	//printf("%d\n", strlen(arr[1]));//err
	printf("%d\n", strlen(&arr));//随机值  &arr是数组的地址,数组的地址和数组首元素的地址,值是一样的,那么传递给strlen函数后,依然是从数组的第一个元素的位置开始往后统计
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址,结果也是随机值
	
	return 0;
}
#include <stdio.h>
#include <string.h>

int main()
{
	char arr[] = "abcdef";//[a b c d e f \0]
 
	printf("%d\n", sizeof(arr));//7
	printf("%d\n", sizeof(arr + 0));//arr + 0 是首元素的地址 4/8
	printf("%d\n", sizeof(*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个字节
	printf("%d\n", sizeof(&arr + 1));//&arr + 1是跳过一个数组的地址,4/8
	printf("%d\n", sizeof(&arr[0] + 1));//&arr[0] + 1是第二个元素的地址 4/8

	printf("%d\n", strlen(arr));//6
	printf("%d\n", strlen(arr + 0));//6
	//printf("%d\n", strlen(*arr));//err
	//printf("%d\n", strlen(arr[1]));//err
	printf("%d\n", strlen(&arr));//6
	printf("%d\n", strlen(&arr + 1));//随机值
	printf("%d\n", strlen(&arr[0] + 1));//5

	return 0;
}
#include <stdio.h>
#include <string.h>

int main()
{
	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就是'a',就是1个字节
	printf("%d\n", sizeof(p[0]));//p[0] --> *(p+0) --> *p  1个字节
	printf("%d\n", sizeof(&p));//4/8
	//&p -- char**
	printf("%d\n", sizeof(&p + 1));//4/8
	printf("%d\n", sizeof(&p[0] + 1));//4/8,&p[0] + 1得到的是'b'的地址

	printf("%d\n", strlen(p));//6
	printf("%d\n", strlen(p + 1));//5
	//printf("%d\n", strlen(*p));//err
	//printf("%d\n", strlen(p[0]));//err
	printf("%d\n", strlen(&p));//随机值
	printf("%d\n", strlen(&p + 1));//随机值
	printf("%d\n", strlen(&p[0] + 1));//5

	return 0;
}

&p+1的指向


#include <stdio.h>

int main()
{
	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内部了,计算的是整个数组的大小,大小是16个字节
	printf("%d\n", sizeof(a[0] + 1));//4/8
	//a[0]作为第一行的数组名,没有单独放在sizeof内部,没有&
	//a[0]表示数组首元素的地址,也就是a[0][0]的地址
	//所以a[0]+1是第一行第二个元素的地址,是地址就是4/8个字节
	
	printf("%d\n", sizeof(*(a[0] + 1)));//4 计算的就是第一行第2个元素的大小
	printf("%d\n", sizeof(a + 1));//4/8 a是数组首元素的地址,是第一行的地址(int(*)[4]),a+1就是第二行的地址
	printf("%d\n", sizeof(*(a + 1)));//16
	//1. *(a+1) --> a[1]  sizeof(*(a+1)) --> sizeof(a[1])计算的是第二行的大小
	//2. a+1是第二行的地址(int(*)[4])  *(a+1)访问的是第二行的数组
	
	printf("%d\n", sizeof(&a[0] + 1));//4/8 &a[0]是第一行的地址(int(*)[4]),&a[0]+1是第二行的地址(int(*)[4])
	printf("%d\n", sizeof(*(&a[0] + 1)));//16 计算的是第二行的大小
	printf("%d\n", sizeof(*a));//计算的是第一行的大小 - 16
	//1. a是数组首元素的地址,就是第一行的地址
	//*a就是第一行
	//2. *a --> *(a+0) --> a[0]

	printf("%d\n", sizeof(a[3]));//16  a[3] --> int[4]

	return 0;
}

二维数组的相关理解
对于以上代码中最后一行代码,我们再稍作解释:

//编译    +    链接 --> 可执行程序 -->  运行  --> 结果
//sizeof                              s = a + 2
//因为sizeof在编译期间就已经处理了,所以在运行时就不会再执行s = a + 2这个代码了

//表达式都有2个属性:
//1. 值属性
//2. 类型属性
//s = a + 2 --> short
//值属性:9

#include <stdio.h>

int main()
{
	int a = 7;
	short s = 4;
	printf("%d\n", sizeof(s = a + 2));//short 2
	//sizeof内部的表达式是不会真的计算的,它只关注表达式最后的类型
	printf("%d\n", s);//4

	return 0;
}

10. 指针笔试题

#include <stdio.h>

int main()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int* ptr = (int*)(&a + 1);
	printf("%d,%d", *(a + 1), *(ptr - 1));//2,5
	
	return 0;
}
#include <stdio.h>

//由于还没学习结构体,这里告知结构体的大小是20个字节
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p = (struct Test*)0x100000;

//假设p的值为0x100000。 如下表表达式的值分别为多少?
//已知结构体Test类型的变量大小是20个字节
int main()
{
	printf("%p\n", p + 0x1);//00100014  +1要跳过一个结构体(20个字节)
	printf("%p\n", (unsigned long)p + 0x1);//00100001  整数+1就是+1
	printf("%p\n", (unsigned int*)p + 0x1);//00100004 +1要跳过一个整型(4个字节)
	
	return 0;
}
//假设是小端存储
//%x是以十六进制形式输出
#include <stdio.h>

int main()
{
	int a[4] = { 1, 2, 3, 4 };
	int* ptr1 = (int*)(&a + 1);
	int* ptr2 = (int*)((int)a + 1);
	printf("%x,%x", ptr1[-1], *ptr2);//4,2000000
	//ptr[-1] --> *(ptr-1)

	return 0;
}

指针笔试题3


#include <stdio.h>

int main()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };//这个二维数组里是逗号表达式,如果想把0,1放在第一行,要用{ },所以二维数组中存的是1,3,5,0,0,0
	int* p;
	p = a[0];//数组名是数组首元素地址 --> &a[0][0]
	printf("%d", p[0]);//1   p[0] --> *(p+0) --> *p
	
	return 0;
}
#include <stdio.h>

int main()
{
	int a[5][5];
	int(*p)[4];
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//FFFFFFFC,-4
	//-4
	//10000000000000000000000000000100
	//11111111111111111111111111111011
	//11111111111111111111111111111100
	
	return 0;
}

指针笔试题5


#include <stdio.h>

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

int main()
{
	char* a[] = { "work", "at", "alibaba" };
	char** pa = a;
	pa++;
	printf("%s\n", *pa);///at
	
	return 0;
}

指针笔试题7


#include <stdio.h>

int main()
{
	char* c[] = { "ENTER", "NEW", "POINT", "FIRST" };
	char** cp[] = { c + 3, c + 2, c + 1, c };
	char*** cpp = cp;
	
	printf("%s\n", **++cpp);//POINT
	printf("%s\n", *-- * ++cpp + 3);//ER
	printf("%s\n", *cpp[-2] + 3);//ST   *cpp[-2]+3 --> **(cpp-2)+3
	printf("%s\n", cpp[-1][-1] + 1);//EW  *(*(cpp-1)-1)+1
	
	return 0;
}

一开始的指向关系:
指针笔试题8(1)
第一个printf:
指针笔试题8(2)
第二个printf:
指针笔试题8(3)
第三个printf:
指针笔试题8(4)
第四个printf:
指针笔试题8(5)

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

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

相关文章

[黑马程序员Pandas教程]——Pandas数据结构

目录&#xff1a; 学习目标认识Pandas中的数据结构和数据类型Series对象通过numpy.ndarray数组来创建通过list列表来创建使用字典或元组创建s对象在notebook中不写printSeries对象常用API布尔值列表获取Series对象中部分数据Series对象的运算DataFrame对象创建df对象DataFrame…

pytorch之relu激活函数

目录 1、relu 2、relu6 3、leaky_relu 4、ELU 5、SELU 6、PReLU 1、relu ReLU&#xff08;Rectified Linear Unit&#xff09;是一种常用的神经网络激活函数&#xff0c;它在PyTorch中被广泛使用。ReLU函数接受一个输入值&#xff0c;如果该值大于零&#xff0c;则返回该…

python的format函数的用法及实例

目录 1.format函数的语法及用法 &#xff08;1&#xff09;语法&#xff1a;{}.format() &#xff08;2&#xff09;用法&#xff1a;用于格式化字符串。可以接受无限个参数&#xff0c;可以指定顺序。返回结果为字符串。 2.实例 &#xff08;1&#xff09;不设置位置&…

浮点数存储

//浮点数存储 int main() {int n 9;//00000000 00000000 00000000 00001001//0 00000000 00000000000000000001001//S E(8bit) M(23bit)//E-126//M0.000000000000000000001001// 0.000000000000000000001001 *2^-126float* pFloat (float*)&n;printf("n的值…

挖掘非结构化数据潜能——向量数据库的探索之路

“ 摸着石头过河&#xff0c;一直向前&#xff0c;不断尝试 ” 整理 | 小白 出品&#xff5c;极新 IDC 预测&#xff0c;到 2025 年&#xff0c;中国的数据量将增长到 48.6ZB&#xff0c;80% 是非结构化数据&#xff0c;并且将成为全球最大的数据圈。在我们的日常生活中&…

python使用pysqlcipher3对sqlite数据库进行加密

python对很多项目都需要对sqlite数据库的数据进行加密&#xff0c;最流行的加密方式是使用pysqlcipher3&#xff0c;当前使用的python版本为3.7&#xff0c;本博文是直接使用pysqlcipher3在项目上的应用&#xff0c;使用的是已编译好的pysqlcipher3包&#xff0c;如果你需要pys…

Jmeter_逻辑控制器

逻辑控制器 控制取样器执行顺序的组件实现(分支 循环) 分类 1、如果(if) 控制器 分支实现 2、forEach控制器 循环往复实现 3、循环控制器 循环往复实现 如果(if) 控制器 需求1:测试计划中定义一个 http 请求访问百度&#xff0c;但是该请求不是无条件执行的&#xff0c;…

【uniapp小程序下载】调用uni.uploadfile方法在调试工具里是没有问题的,但是线上版本和体验版就调用不成功,真机调试也没问题

把你的下载地址前缀添加到合法域名就解决了 在调试工具里成功了是因为勾选了下面这项 下面是我的下载并打开函数 methods: {// 下载downloadFileFn(data) {if (this.detailsObj.currentUserBuy) {uni.downloadFile({// data是路径url: https:// data,success(res) {//保存到本…

linux地址空间

地址空间 内存空间示意图虚拟地址空间虚拟地址进程地址空间生命周期图解为什么要有地址空间呢&#xff1f; 小结 内存空间示意图 进程是在内存中运行的&#xff0c;为了便于管理&#xff0c;不同的数据会存储在不同的区域&#xff0c;因此内存就被分为几部分&#xff0c;如下图…

新的iLeakage攻击从Apple Safari窃取电子邮件和密码

图片 导语&#xff1a;学术研究人员开发出一种新的推测性侧信道攻击&#xff0c;名为iLeakage&#xff0c;可在所有最新的Apple设备上运行&#xff0c;并从Safari浏览器中提取敏感信息。 攻击概述 iLeakage是一种新型的推测性执行攻击&#xff0c;针对的是Apple Silicon CPU和…

独立键盘接口设计(Keil+Proteus)

前言 软件的操作参考这篇博客。 LED数码管的静态显示与动态显示&#xff08;KeilProteus&#xff09;-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/134101256?spm1001.2014.3001.5501实验&#xff1a;用4个独立按键控制8个LED指示灯。 按下k1键&#x…

Elasticsearch:RAG vs Fine-tunning (大语言模型微调)

如果你对 RAG 还不是很熟悉的话&#xff0c;请阅读之前的文章 “Elasticsearch&#xff1a;什么是检索增强生成 - RAG&#xff1f;”。你可以阅读文章 “Elasticsearch&#xff1a;在你的数据上训练大型语言模型 (LLM)” 来了解更多关于如何训练你的模型。在今天的文章中&#…

Git 内容学习

一、Git 的理解 Git是一个分布式版本控制系统&#xff08;Distributed Version Control System&#xff0c;简称 DVCS&#xff09;&#xff0c;用于对项目源代码进行管理和跟踪变更。分为两种类型的仓库&#xff1a;本地仓库和远程仓库。 二、Git 的工作流程 详解如下&#x…

CATIA环境编辑器用不了时创建项目快捷方式

CATIA环境编辑器用不了时创建项目快捷方式 一、参考适用情况示例二、 解决步骤(一) 先正确放置winb_64部署包(二) 添加环境文件(三) 修改加入的环境文件(四) 复制本机CATIA快捷方式后重命名(五) 修改快捷方式目标的值 一、参考适用情况示例 二、 解决步骤 (一) 先正确放置winb…

社区分享|杭银消费金融基于MeterSphere开展接口自动化测试

杭银消费金融有限公司&#xff08;以下简称“杭银消费金融”&#xff09;成立于2015年12月&#xff0c;是经中国银保监会批准&#xff0c;由杭州银行作为主发起人&#xff0c;联合滴滴出行、中国银泰等企业组建的持牌消费金融机构&#xff0c;注册资本为25.61亿元。杭银消费金融…

关于Alibaba Cloud Toolkit 下载配置以及后端自动部署

idea中File-Settings-Plugins 搜索Alibaba Cloud Toolkit点击下载&#xff0c;下载完成重启 1、点击 Tools-Alibaba Cloud-Deploy to Host 部署到主机 2、配置服务器ip、jar包启动命令、服务器jar存放位置 3、设置服务器ip用户名密码&#xff0c;点击测试连接情况 4、配置脚本…

计算机的运算方法

无符号数 定义&#xff1a;没有符号的数&#xff0c;在寄存器中的每一位均可用来存放数值 表示范围&#xff1a;n 位无符号数 0~2n -1 有符号数 定义&#xff1a;符号位数值位 “0”代表正&#xff0c;“1”代表负 表示范围&#xff1a;n 位有符号整数 原码、反码&#x…

Rust编程基础之引用与借用

1.引用与借用 在上一章节最后的代码中, 我们必须将 String 返回给调用函数&#xff0c;以便在调用 calculate_length 后仍能使用 String&#xff0c;因为 String 被移动到了 calculate_length 内。相反我们可以提供一个 String 值的引用&#xff08;reference&#xff09;。引…

理解交叉熵(Cross Entropy)

交叉熵&#xff08;Cross-Entropy&#xff09;是一种用于衡量两个概率分布之间的距离或相似性的度量方法。在机器学习中&#xff0c;交叉熵通常用于损失函数&#xff0c;用于评估模型的预测结果与实际标签之间的差异。 在分类问题中&#xff0c;交叉熵损失函数通常用于多分类问…

uniapp小程序才到第五层就报错navigateto:fail webview count limit exceed

错误截图 原因 小程序官方描述是说可以跳转10层&#xff0c;但是使用uniapp开发的程序在小程序中才运行到第五层就报错了&#xff0c;原因是因为没有设置appId。如果设置了就正常了。
最新文章