前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >指针(一)基础

指针(一)基础

作者头像
木杉乀
发布2021-04-02 06:33:44
3280
发布2021-04-02 06:33:44
举报
文章被收录于专栏:木杉の小屋木杉の小屋

指针(一) 基础

一 指针的概念

  1. 为了方便访问内存中的内容,给每个内存单元一个编号,我们称这个编号为地址,及为指针.
  2. 指针也是一种数据类型 所以指针都有自己的内存 存储的是地址(编号)

指针的四要素

  1. 指针本身的类型 除去指针名,剩下的就是指针本身的类型
  2. 指针指向的类型 除去指针名和一个*,剩下的就是指针指向的类型
  3. 指针本身的内存 用来存储一个编号(4字节)
  4. 指针指向的内存 可以是各种类型
代码语言:javascript
复制
    int num = 0;          // 类型: int
    int arr[10] = {};     // 类型: int [10]
    int* MuShan = {1,2,3};
    //去掉名字,剩下的就是类型

二 指针的定义

1 运算符

*: 定义时,表示定义的是一个指针 其他的时候表示解析引用

&: 取地址符(用于取地址)

2 定义

指针的定义有多种理解方式;

  1. 类型 变量名;
代码语言:javascript
复制
int* p; // 类型: int
        // 变量名: *p
  1. 指针本身类型 指针名;
代码语言:javascript
复制
int* p; // 指针本身的类型: int*
        // 指针名: p
  1. 指针指向的类型* 指针名;
代码语言:javascript
复制
int* p; // 指针指向的类型: int
        // 指针名: p

反推:

  1. 除去指针名,剩下的就是指针本身的类型
  2. 除去指针名和一个*,剩下的就是指针指向的类型
代码语言:javascript
复制
int****** p1; // p1本身的类型: int****** 
              // p1指向的类型: int*****  (6级指针可以指向5级指针)

三 指针的内存

  1. 所有的指针,无论类型,在内存中都占4个字节的内存(存的是地址)(具体和64/32位环境相关)
代码语言:javascript
复制
#include 
int main()
{
	char*       pch;
	short*      psh;
	int*        pn;
	float*      pf;
	double*     pd;
    
	printf("%d\n", sizeof(pch));  // 4
	printf("%d\n", sizeof(psh));  // 4
	printf("%d\n", sizeof(pn));   // 4
	printf("%d\n", sizeof(pf));   // 4
	printf("%d\n", sizeof(pd));   // 4
    
	return 0;
}
  1. 指向起始地址
代码语言:javascript
复制
int num = 10;
int* p = #
在这里插入图片描述
在这里插入图片描述

四 指针的初始化与赋值

1 用对应类型变量的地址

代码语言:javascript
复制
	int num = 10;
	int* pn = #   //初始化

	float f = 3.14f;
	float* pf;
	pf = &f;          //赋值

2 用相同类型的指针

代码语言:javascript
复制
	int num = 10;
	int* pn = #     // 初始值
	int* p1 = pn;       // 初始化
	int* p2;
	p2 = pn;            // 赋值

3 直接用地址

代码语言:javascript
复制
	int* p = (int*)0x36;

4 用数组名

一级指针可以接受一堆一位数组的数组名

代码语言:javascript
复制
	int arr[5] = { 1,2,3,4,5 };
	int* p = arr;

5 字符串

代码语言:javascript
复制
#include 
int main()
{
	// 数组名就是数组的首地址
	char arr[5] = { 'a','b','c' };
	char* p = arr;
	printf("%s\n",p);     //输出:abc
	char str[5] = "abcd";
	p = str;
	printf("%s\n", str);  //输出:abcd
	printf("%s\n", p);    //输出:abcd
	// ==> char*类型的指针可以直接用来打印整个字符串到'\0'停止
	const char* p1;
	p1 = "1234";
	printf("%s\n",p1);    //输出:1234
	const char* p2 = "Mushan";
	printf("%s\n",p2);    //输出:Mushan
	return 0;
}

6 置空

代码语言:javascript
复制
	int* p = NULL;
	int* p1 = (int*)0x0;
代码语言:javascript
复制
/*
   NULL: #define NULL  0
   0地址
   有时候,指针定义好了,但是暂时没有指向
   或者是,指针用完了,没有指向了
   指针不知道指向哪里(会随机指向)
   此时的指针,很危险(野指针)
   所以 这些情况下的指针
   统一安排一个地址给他们指向
   指向0地址
*/

7 多级指针

代码语言:javascript
复制
#include

int main() {
	int num = 10;
	printf(" num = %d\n", num);        //   num = 10;
	printf("&num = %X\n", &num);       //  &num = 10FFA78
    
	int* p = #
	printf("*p = %d\n", *p);           //  *p = 10 (num值)
	printf(" p = %X\n", p);            //   p = 10FFA78 (num的地址)
	printf("&p = %X\n", &p);           //  &p = 10FFA6C

	int** pp = &p; // 一个二级指针
	printf("**pp = %d\n", **pp);       // **pp = 10 (num值)
	printf(" *pp = %X\n", *pp);        //  *pp = 10FFA78 (num的地址)
	printf(" pp = %X\n", pp);          //   pp = 10FFA6C (p的地址)
	printf(" &pp = %X\n", &pp);        //  &pp = 10FFA60 

	int*** ppp = &pp; // 一个三级指针
	printf("***ppp = %d\n", ***ppp);   // ***ppp = 10 (num值)
	printf(" **ppp = %X\n", **ppp);    //  **ppp = 10FFA78 (num地址)
	printf(" *ppp = %X\n", *ppp);      //   *ppp = 10FFA6C (p的地址)
	printf("  ppp = %X\n", ppp);       //    ppp = 10FFA60 (pp的地址)
	printf(" &ppp = %X\n", &ppp);      //   &ppp = 10FFA54

	return 0;
}

五 指针的加减法

核心:指针本身的值(指向)没有变化

指针偏移
  1. 指针可以加上或减去一个整数
  2. 指针加上或减去一个整数后,实际上是进行了偏移
  3. 偏移的范围是加上或减去的整数个单位 单位: 指针指向的类型在内存中所占字节数 偏移:指针指向不变,但是可以根据偏移量取内容
代码语言:javascript
复制
#include 
int main()
{
	int num = 10;
    
	int* p = #
	printf("%X\n", p);          // EFFB5C
	printf("%X\n", p + 1);      // EFFB60
    
	return 0;
}

六 指针的自增自减

自增自减,会改变指针指向

++:表示指针向后移动一个单位

– :表示指针向前移动一个单位

单位:指针指向的类型在内存所占内存中所占的字节数

代码语言:javascript
复制
#include 
int main()
{
	int num = 10;
	int* p = #
	printf("%X\n", p);          // EFFB5C
	printf("%X\n", p + 1);      // EFFB60

	printf("%d\n",*p);          // 10
	printf("%X\n", p += 1);     // EFFB60
	printf("%d\n",*p);          // -858993460(无意义)
	return 0;
}

七 通过指针遍历数组

遍历一维数组

代码语言:javascript
复制
#include 
int main()
{
	int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	for (size_t i = 0; i < 10; i++)
	{
		printf("%2d", arr[i]);
	}
	printf("\n");
	int* p = arr;
	// p和arr,除了arr是一个常量之外,其他几乎是一样的
	for (size_t i = 0; i < 10; i++)
	{
		printf("%2d", p[i]);
	}

	printf("\n");
	printf("%d\n", p[0]);        // 0
	printf("%d\n", *(p + 0));    // 0
	printf("%d\n", p[1]);        // 1(先偏移 后取值)
	printf("%d\n", *(p + 1));    // 1
	// p[n] <==> *(p+n)
	return 0;
}
// p[n]:叫做下标形式
// *(p+n):叫做指针偏移的形式

遍历二维数组

  1. 二维数组也是数组
  2. 二维数组可以看成元素是一维数组的一维数组
  3. 数组的内存是连续的
代码语言:javascript
复制
#include

int main()
{
	int arr[3][4] = {
        {1,2,3,4},
		{5,6,7,8},
		{9,10,11,12}
	};

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

	int* p0 = arr[0];
	int* p1 = arr[1];
	int* p2 = arr[2];
	printf("\n");
	// 1:
	for (size_t i = 0; i < 4; i++)
	{
		printf("%3d", p0[i]);           // 1  2  3  4
	}
	printf("\n");
	for (int i = -4; i <= 7; i++)
	{
		printf("%3d", p1[i]);           // 1  2  3  4  5  6  7  8  9 10 11 12
	}
	printf("\n");
	for (int i = 0; i < 12; i++)
	{
		printf("%3d", arr[0][i]);       // 1  2  3  4  5  6  7  8  9 10 11 12
	}
	printf("\n");
	// 下标: 保证数组不越界即可
    
	// 2:
	int* p = &arr[0][0];
	for (int i = 0; i < 12; i++)
	{
		printf("%3d", arr[0][i]);       // 1  2  3  4  5  6  7  8  9 10 11 12       
	}
	printf("\n");
	for (int i = 0; i < 12; i++)
	{
		printf("%3d", *p);              // 1  2  3  4  5  6  7  8  9 10 11 12
		p++;
	}
	printf("\n");
	return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-02-17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 指针(一) 基础
    • 一 指针的概念
      • 指针的四要素
    • 二 指针的定义
      • 1 运算符
      • 2 定义
    • 三 指针的内存
      • 四 指针的初始化与赋值
        • 1 用对应类型变量的地址
        • 2 用相同类型的指针
        • 3 直接用地址
        • 4 用数组名
        • 5 字符串
        • 6 置空
        • 7 多级指针
      • 五 指针的加减法
        • 六 指针的自增自减
          • 七 通过指针遍历数组
            • 遍历一维数组
            • 遍历二维数组
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档