【指针进阶】

news2024/11/15 23:55:28

1 字符指针

#include <stdio.h>
int main()
{
	char str1[] = "hello bit.";
	char str2[] = "hello bit.";
	
	const char* str3 = "hello bit.";
	const char* str4 = "hello bit.";
	
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

这里str3和str4指向的是一个同一个常量字符串。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串的时候,他们实际会指向同一块内存。但是用相同的常量字符串去初始化不同的数组的时候就会开辟出不同的内存块。所以str1和str2不同,str3和str4相同。

#include <stdio.h>

int main()
{
	char arr[] = "abcdef";
	//[a b c d e f \0]

	const char* p = "abcdef";//常量字符串

	printf("%s\n", p);//地址
	printf("%c\n", *p);//取地址的值

	return 0;
}

2 指针数组
指针数组是一个存放指针的数组

指针数组:
整型数组 - 存放的数组
字符数组 - 存放字符的数组

指针数组 - 存放指针的数组
int main()
{
	int* arr[10];//存放整型指针的数组
	return 0;
}
#include<stdio.h>
//使用指针数组模拟实现二维数组

int main()
{
	int arr1[] = { 1,2,3,4,5 };//arr1 - int*
	int arr2[] = { 2,3,4,5,6 };
	int arr3[] = { 3,4,5,6,7 };

	//指针数组
	int* arr[3] = { arr1, arr2, arr3 };

	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

3 数组指针

int (*p)[10];
解释:p先和*结合,说明p是一个指针变量,然后指着指向的是一个大小为10个整型的数组。所以p是一个指针,指
向一个数组,叫数组指针。

这里要注意:[]的优先级要高于*号的,所以必须加上()来保证p先和*结合。

数组名的理解:

数组名是数组首元素的地址

有2个例外:

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

除此之外,所有的地方的数组名都是数组首元素的地址

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);

	return 0;
}
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%d\n", sizeof(arr));//40

	return 0;
}

在这里插入图片描述

#include<stdio.h>

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);//
	//printf("%p\n", arr+1);//

	printf("%p\n", &arr[0]);//
	//printf("%p\n", &arr[0]+1);//

	printf("%p\n", &arr);//取出的是数组的地址(整个数组)
	//printf("%p\n", &arr+1);//

	
	return 0;
}

在这里插入图片描述

#include<stdio.h>

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);//
	printf("%p\n", arr+1);//

	printf("%p\n", &arr[0]);//
	printf("%p\n", &arr[0]+1);//

	printf("%p\n", &arr);//取出的是数组的地址(整个数组)
	printf("%p\n", &arr+1);//

	
	return 0;
}

对于数组名来说:&数组名得到的是数组的地址

#include<stdio.h>
int main()
{
	int arr[10] = {1,2,3,4,5,6,7,8,9,10};
	//数组的地址,存储到数组指针变量
	// 
	//int[10] *p = &arr;//err
	int (* p)[10] = &arr;//int(*)[10]
	//数组指针
	int* p2 = &arr;//err

	return 0;
}

数组指针的使用:

#include<stdio.h>

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	
	int (*p)[10] = &arr;//*&arr --> arr

	int i = 0;
	for (i = 0; i < 10; ++i)
	{
		//printf("%d ", *((*p) + i));
		printf("%d ", (*p)[i]);
	}

	return 0;
}

数组指针怎么使用呢?一般在二维数组上才方便

二维数组传参,形参是二维数组的形式

void Print(int arr[3][5], int r, int c)
{
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
	Print(arr, 3, 5);

	return 0;
}

关键点:

二维数组传参,形参是指针的形式

#include<stdio.h>
void Print(int (*p)[5], int r, int c)
{
	int i = 0;
	for (i = 0; i < r; i++)
	{
		int j = 0;
		for (j = 0; j < c; j++)
		{
			printf("%d ", *(*(p + i) + j));
			p+i是指向某一行
			然后解引用拿到这一行(就是首元素的地址)
			通过加j来遍历每一行的地址
			最后解引用取值
		}
		printf("\n");
	}
}

int main()
{
	int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };

	//arr 是数组名,数组名表示数组首元素的地址

	Print(arr, 3, 5);
		
	return 0;
}

总结:

一维数组传参,形参的部分可以是数组,也可以是指针

void test1(int arr[5], int sz)
{}
void test2(int* p, int sz)
{}

int main()
{
	int arr[5] = { 0 };
	test1(arr, 5);
	test2(arr, 5);
	return 0;
}
二维数组传参,形参的部分可以是数组,也可以是指针(数组指针)

void test3(char arr[3][5], int r, int c)
{}

void test4(char (*p)[5], int r, int c)
{}
int main()
{
	char arr[3][5] = {0};
	test3(arr, 3, 5);
	test4(arr, 3, 5);

	return 0;
}

二维数组的行可以省略但是列不可以省略

数组指针 与 指针数组:
数组指针 是 指针 是指向数组的指针
指针数组 是 数组 是存放指针的数组


数组参数与指针参数:

一维数组传参

#include <stdio.h>
void test(int arr[])//ok
{}
void test(int arr[10])//ok
{}
void test(int* arr)//ok
{}
void test2(int* arr[20])//ok
{}
void test2(int** arr)//ok
{}
int main()
{
	int arr[10] = { 0 };
	int* arr2[20] = { 0 };
	test(arr);
	test2(arr2);
}

二维数组传参

void test(int arr[3][5])//ok
{}
void test(int arr[][])//no ok
{}
void test(int arr[][5])//ok
{}
//总结:二维数组传参,函数形参的设计只能省略第一个[]的数字。
//因为对一个二维数组,可以不知道有多少行,但是必须知道一行多少元素。
//这样才方便运算。
void test(int *arr)//no ok
{}
void test(int* arr[5])//no ok
{}
void test(int (*arr)[5])//ok
{}
void test(int **arr)//no ok
{}
int main()
{
 int arr[3][5] = {0};
 test(arr);
}

一级指针传参

#include <stdio.h>
void print(int *p, int sz)
{
 int i = 0;
 for(i=0; i<sz; i++)
 {
 printf("%d\n", *(p+i));
 }
}
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9};
 int *p = arr;
 int sz = sizeof(arr)/sizeof(arr[0]);
 //一级指针p,传给函数
 print(p, sz);
 return 0;
 }

当一个函数的参数部分为一级指针的时候,函数能接收什么参数?
二级指针传参

#include <stdio.h>
void test(int** ptr)
{
 printf("num = %d\n", **ptr); 
}
int main()
{
 int n = 10;
 int*p = &n;
 int **pp = &p;
 test(pp);
 test(&p);
 return 0;
}

当函数的参数为二级指针的时候,可以接收什么参数?


函数指针

函数指针 - 指向函数的指针
数组指针 - 指向数组的指针

int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int arr[10] = {0};
	int (*pa)[10] = &arr;
	//printf("%p\n", &Add);
	//printf("%p\n", Add);
	//函数名是函数的地址
	//&函数名也是函数的地址

	int (*pf)(int, int) = &Add;//pf是函数指针变量
	//int (*)(int, int) 是函数指针类型
	return 0;
}
void test(char* pc, int arr[10])
{
}
int main()
{
	void (*pf)(char *, int [10]) = test;
	//void (*pf)(char *, int [10]) = &test;
	return 0;
}
int Add(int x, int y)
{
	return x + y;
}

int main()
{
	//int (*pf)(int, int) = &Add;
	int (*pf)(int, int) = Add;

	int r = Add(3, 5);
	printf("%d\n", r);

	int m = (*pf)(4, 5);

	printf("%d\n", m);

	return 0;
}

//0 - int
//  - int* 
//0x0012ff40 - int
//           - int*

void (*p)() -p是函数指针
void (*)()是函数指针类型
int main()
{
	//调用0地址处的函数
	//1. 将0强制类型转换为void (*)()  类型的函数指针
	//2. 调用0地址处的这个函数
	( *( void (*)() )0 )();

	return 0;
}

//typedef unsigned int uint;
//typedef int* ptr_t;
//
//typedef int(*parr_t)[10];
//typedef int (*pf_t)(int, int) ;


//int main()
//{
//	uint u1;
//	ptr_t p1;
//	int* p2;
//	return 0;
//}

//int main()
//{
//	//signal 是一个函数声明
//	//signal 函数有2个参数,第一个参数的类型是int,第二个参数的类型是 void(*)(int) 函数指针类型
//	//该函数指针指向的函数有一个int类型的参数,返回类型是void
//	//signal 函数的返回类型也是void(*)(int) 函数指针类型,该函数指针指向的函数有一个int类型的参数,返回类型是void
//	//
//	typedef void(*pf_t)(int);
//	pf_t signal(int, pf_t);
//
//	void (* signal(int, void(*)(int) ) )(int);
//
//	return 0;
//}
//

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DataEase安装与教程,人人都会的大数据可视化与BI工具!!!

文章目录 一 DataEase介绍1.1 可视化工具介绍1.2 什么是 DataEase1.3 DataEase 的优势1.4 DataEase 支持的数据源1.5 DataEase 模板市场1.6 快速开始 二 Dataease安装部署2.1 登陆DataEase2.2 DataEase界面2.3 数据源连接2.4 数据集2.5 看板案例 一 DataEase介绍 1.1 可视化工…

第三节 给SpringBootAdmin的client端加入spring security安全控制

前言 本来想用一节就写完SpringBootAdmin的&#xff0c;但随着研究的深入发现一节应该是不够的&#xff0c;网上的资料也不会非常系统&#xff0c;官网的例子有些已经好几年没更新了&#xff0c;所以接下来还是系统性的来写下吧 第一节 完成基础配置&#xff0c;暴露所有端点…

B2B2C商城模式适合哪些的企业?

随着互联网的发展&#xff0c;电商也变得的越来越火热&#xff0c;很多个人和企业进驻其中&#xff0c;所以竞争激烈&#xff0c;如天猫和京东&#xff0c;他们内部的店家多不胜数&#xff0c; 在这种大环境下&#xff0c;企业开始做出不一样的举动&#xff0c;纷纷都搭建一个b…

samba参数配置教程(samba配置参数讲解)(/etc/samba/smb.conf )

文章目录 samba smb.conf配置文档smb.conf重要配置参数讲解1. workgroup&#xff1a;指定Samba服务器所在的工作组名称。2. server string&#xff1a;指定Samba服务器的描述信息。3. security&#xff1a;指定Samba服务器的安全模式&#xff0c;可以是user、share或domain。4.…

ssh配置多账号(Mac)

一. 应用场景 当存在同时需要git在GitHub、gitee、gitlab等多个不同git托管平台进行ssh代码操作的时候。 二. 具体操作 默认 ssh-keygen -t rsa -C "你的邮箱"之后一直回车就可以&#xff0c;会默认在~/.ssh目录下生成id_rsa、id_rsa.pub 指定文件 ssh-keygen …

实验九 单周期MIPS CPU设计实验(基于Logisim)

一、实验目的 学生掌握控制器设计的基本原理&#xff0c;能利用硬布线控制器的设计原理在Logisim平台中设计实现MIPS单周期CPU。 二、实验内容 利用运算器实验&#xff0c;存储系统实验中构建的运算器、寄存器文件、存储系统等部件以及Logisim中其它功能部件构建一个32位MIPS …

基本数据类型转换

自动类型转换 当Java程序在进行赋值或运算时&#xff0c;精度小的类型自动转换为精度大的数据类型&#xff0c;这个就是自动类型转换。 int a 3; double d a; // 类型转换 int --> double自动类型转换使用和细节&#xff1a; 有多种类型的数据混合运算时&#xff0c;系统…

基于Java养老院老人健康监护平台设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

element-ui组件中的Tooltip 文字提示:el-tooltip中content是变量怎么写

<el-tooltip content"Top center" placement"top"><el-button>Dark</el-button> </el-tooltip> 这样的效果是&#xff1a; 可以看出&#xff0c;content是提示内容。如果是文字提示可以直接写在content里面。 content是变量应该…

飒智智能机器人核心技术与应用论坛暨一体化控制器发布会成功举办

7月6日&#xff0c;智能机器人核心技术与应用论坛暨移动操作复合机器人一体化智能控制器发布会在上海举行。本次活动由上海飒智智能科技有限公司主办&#xff0c;得到上海市经信委、闵行区科委、闵行区经委、“大零号湾”属地单位南滨江公司、江川路街道办事处的支持&#xff0…

给大模型持久记忆!GitHub 2万星向量数据库云服务升级,国内云产品下周上线

一个在GitHub上标星超2万的数据库&#xff0c;究竟是什么来头&#xff1f; 原来&#xff0c;这正是最近大火的向量数据库之一、首个在这一赛道开源产品Milvus。 自大模型爆火以来&#xff0c;它的关注度也一路飙升&#xff0c;官方显示&#xff0c;目前Milvus已经拥有超过1000企…

数据结构中队列的操作方式,一目了然

队列的概念 首先我们联想一下链表&#xff0c;在单链表中&#xff0c;我们只能对他的链表表尾进行插入&#xff0c;对链表的表头进行结点的删除&#xff0c;这样强限制性的链表&#xff0c;就是我们所说的队列。 也就是说&#xff0c;队列&#xff08;queue&#xff09;是限定…

云盘选择攻略:寻找易用且高效的同步云盘服务

同步云盘是集备份、同步、共享于一体的软件&#xff0c;备受用户青睐。在这个信息化的时代&#xff0c;我们经常需要在不同的设备之间共享文件&#xff0c;而同步云盘正可以帮助我们在多台设备之间同步文件。不过目前市面上同步云盘众多&#xff0c;我们该如何选择同步云盘呢&a…

数据结构【考研笔记】

数据结构【考研笔记】 第一章 绪论一、数据结构的基本概念1、基本概念1&#xff09;数据2&#xff09;数据元素、数据项3&#xff09;数据对象、数据结构4&#xff09;数据类型、抽象数据类型&#xff08;ADT&#xff09; 2、三要素1&#xff09;逻辑结构2&#xff09;存储结构…

C++学习 指针

目录 指针 指针的定义和使用 指针所占用的内存空间 空指针与野指针 const修饰指针 指针和数组 指针和函数 指针 指针是一个变量&#xff0c;其值为另一个变量的地址&#xff0c;即内存位置的直接地址。就像其他变量或常量一样&#xff0c;您必须在使用指针存储其他变量地…

动态规划:背包问题

01背包&#xff1a;物品只能选一个 完全背包&#xff1a;物品可以选无数个 注&#xff1a;01背包与完全背包&#xff0c;不论是求背包装的最多物品的价值&#xff0c;还是求装满容量为bag的背包最多有几种方法&#xff0c;区别都在里层遍历背包时&#xff0c;01背包使用倒序…

three.jsgsap滚动交互网页实现 1-模糊背景线条

实现 模型只有其中的一根线条 加载完模型后 将其圆形排列一周 要实现圆形排列一周可以自己计算sin和cos实现&#xff0c;更简单的可以使用vector3的setFromCylindricalCoords方法实现 该方法计算返回圆柱上的点&#xff0c;圆柱上的点由参数决定 使用方法&#xff1a; for (let…

监听DOM尺寸变化 - ResizeObserver

一、与 MutationObserver Api的区别 MutationObserver 主要用来监听 DOM 元素的属性和节点变化的&#xff0c;非 DOM 样式尺寸&#xff0c;可查看之前一篇 blog - DOM规范 - MutationObserver接口观察DOM元素的属性和节点变化ResizeObserver 主要用来监听 DOM 元素的 内容区域…

Stable Diffusion WebUI 不同采样方法的效果、耗时对比记录

测试方法 所有测试除了采样方法调整&#xff0c;其他均保持一致。主要参数信息如下 1girl, 3d, architecture, blurry, blurry background, blurry foreground, breasts, brown hair, building, cherry blossoms, city, cityscape, cosplay photo, cowboy shot, day, depth o…

hive2.3.7安装部署-问题:show databases;没反应

目录 一、安装包准备 二、安装mysql 三、hive安装 四、hive启动 五、问题 环境&#xff1a;CentOS7.2.xx、hadoop2.6.4、jdk1.8.0xx、mysql-5.7.38 hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射成一张表&#xff0c;并提供类SQL查询功能。…