广告位联系
返回顶部
分享到

C/C++指针介绍与使用介绍

C语言 来源:互联网 作者:佚名 发布时间:2022-08-27 09:07:09 人浏览
摘要

什么是指针 C/C++语言拥有在程序运行时获得变量的地址和操作地址的能力,这种用来操作地址的特殊类型变量被称作指针。 翻译翻译什么tmd叫tmd指针! 变量或常量的指针存储的数据是

什么是指针

C/C++语言拥有在程序运行时获得变量的地址和操作地址的能力,这种用来操作地址的特殊类型变量被称作指针。

翻译翻译什么tmd叫tmd指针!

变量或常量的指针存储的数据是 :对应的变量或常量在内存中的地址。

图解:

此时 我们定义三个指针 p1, p2, p3 分别指向a, b, c ,那么p1中存储的数据是变量a所占用内存的首地址:0x00;

b和c中存储的数据是什么呢? 没错,就是0x02和0x04。

显然。若要知道变量a的值,首先读取指针p1中的数据0x00,然后读取内存0x00和0x01中的数据就可以了。这个时候,会出现一个问题:怎么才能确定究竟要读取几个单位内存中的数据呢?毕竟p1中只存储了0x00呀。这个时候 ,指针的类型就发挥了作用。举个例子:如果定义的指针是int类型的,那么读取的时候自动从指针中存储的初值向后读取4个字节;float类型的指针就是读取8个字节。这样就可以既完整又不多余的取出所需要的数据了。

总结一下一个指针的两个要素:指针类型和指针所指变量的初地址。

定义指针变量

指针在定义的时候最好直接初始化,否则可能出现意想不到的结果。

@定义一个指向变量的指针。

1

2

3

4

5

6

7

8

/*定义一个指向int类型变量a的指针p*/

int a = 3;

int * p;   

p = &a; //把a的地址赋值给p;

/*下面的语句最好不要用!!!!*/

p = &28;    //这也是可以的,p指向的地址中存储的数据是28.

/*可以用下面的语句代替上面的语句*/

*p = 28;

间接引用指针

间接引用操作符也是 *

*p 取出p指向的内存空间中的值。

所以区分定义或是引用指针可能有些麻烦。

只有同类型的指针和变量才能通过 * 和 & 互相建立关系。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

int a = 0;

int temp;

int * p = &a;

/*指针的间接引用*/

cout<< *p;    //输出结果是0

/*以下两种表达等价*/

*p = 3; //把3赋值给a

a = 3;

/*以下两种表达效果相同。都是把变量a赋值给temp*/

temp = a;

temp = *p;  //temp被赋值为0

/* 以下表达是错误的*/

float f = 3.1;

int * p = &f;   //error,指针类型与变量类型不匹配

常or常常

这个部分本来应该在定义指针变量里,但是因为需要指针的间接引用作为铺垫,所以把它单独拿出来了

我们先区分一组概念:常量、指向常量的指针、常指针以及指向常量的常指针。

1.常量:顾名思义不发生改变的量,想必大家是熟悉的。

2.指向常量的指针:只限制间接访问操作,不限制指针指向的值本身的操作规范。

3.常指针:指针中存储的地址一经初始化就不能改变了,也就是说常指针只能指向一个固定的地址,但是地址中存储的数据是可以改变的哦~

4.指向常量的常指针:根据上面三个概念大家应该可以理解了,就是指针中存储的地址和该地址中的数据皆不可更改。

例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

int b = 4;

const int a = 5;    //定义一个常量a。

/*注意观察以下三个定义中const的位置*/

const int *p = &a;  //定义一个指向常量的指针p,指向常量a。

p = &b; //这个也是没问题的哦

*p = 6; //error,这个间接访问操作是不可以。

int * const p2 = &b;//定义一个常指针p2

*p2 = 6;    //这个是可以的,注意区分和上面的区别

const int * const p3 = &a;  //指向常量的常指针p3

/* emm我也不知道该注释点什么,自行体会吧~*/

*p = 11;    //error,因为p指向的是常量,常量的值不可更改

*p2 = 2;    //true,p2是常指针,指向的地址不变,但地址中的值可以更改

*p3 = 4;    //error

p3 = &b;    //error

指向指针的指针

指针本质上也是一个变量或常量,那么指针也是有地址的,而指向这些地址的指针被称为指向指针的指针。

1

2

3

int a = 25;

int * p  = &a;

int pp = &p;    //true,pp指向的地址中存储的是指针p的地址。

指针与数组

一个数组的数组名就是一个常指针。

1

int arr[] = {5,4,6,9,8,3};

arr就是一个指针,而且指向数组的第一个元素arr[0]。

指针数组:

1

char * arr[] ={"this is", "a", "C++ !"};

在此提及一下字符串常量:

1

2

3

4

5

6

char * a

/*

双引号的作用:

    在字符串结尾加一个\0,并分配内存空间,返回首地址。

*/

a = "dshfw";   

指针的运算

指针只能支持 + 和 - 的运算,但这已经足够满足大多数指针操作的需求了。

1

2

3

4

5

6

7

8

9

10

/*接下来以数组为例,只介绍加法 ,减法同理*/

int arr[] = {5,4,6,9,8,3};

cout<< *p;    //输出结果为5

cout<< *(p+1);    //输出结果为4

/*打印整个数组*/

for(int *p = arr; p < arr+5; ++p)

{

    cout<< *p<<' ';

}

cout<<endl;

堆内存分配

C语言

1

2

3

4

5

6

7

8

9

10

11

/*函数原型*/

void * malloc(size_t size);

/*使用:开辟5个int类型变量的存储空间,返回首地址*/

/**/

int *arr;

if(arr = (int *) malloc(5 *sizeof(int)) == NULL)

{

    exit(1);

}

/*释放堆内存*/

free(arr);

C++语言

注意释放数组内存空间时,delete后有[] !!!

1

2

3

4

5

6

/*申请一个5个元素的数组空间*/

int * arr = new int[5];

delete[] arr;

/*申请一个变量的空间*/

int * arr = new int;

delete arr;

指针与函数

函数名和数组名一样都是一个指针,有时我们需要把函数名作为参数传入其他函数中。

数组名作为函数的入口参数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

arr[] = {4,6,9,8,5,3,2,7,5};

/*两种不同的写法均可以*/

void Sort_Shell(int arr[], int n)

{

/*code*/

}

void Sort_Shell(int * arr, int n)

{

/*code*/

}

/*下面这种是不可以的!!!*/

void Sort_Shell(int * arr[], int n)

{

/*code*/

}

举个小小的例子

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

/*来个小小的希尔排序算法*/

void Sort_Shell(int arr[], int n)

{

    int gap = n / 2;

    for(; gap > 0; gap /= 2)

    {

        for(int i = gap; i <n; ++i)

        {

            int temp = a[i];

            int j = i;

            while(j >= gap&& temp < arr[j -  gap])

            {

                a[j] = a[j - gap];

                j -=gap;

            }

            a[j] = temp;

        }

    }

}

开了个小差,接下来回归正题,我们的指针。

函数名作为参数传入其他函数

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

static bool cmp(int a, int b)

{

    return a < b;

}

void show(bool * b)

{

    if( &b)

    {

        cout<< true;

    }

    else

    {

        cout<<false;

    }

}

使用指针修改函数参数

首先来看个例子:

1

2

3

4

5

6

7

8

9

10

11

12

void swip(int a, int b)

{

    int c = a;

    a = b;

    b = c; 

}

int main()

{

    int a = 5, b = 6;

    swip(a, b);

    cout<<a<<' '<<b;

}

输出结果:5 6

并未达到交换的效果,因为函数内部对形参的修改并不能反映到上层的main函数中。

此时我们可以通过指针作为函数的入口参数来实现预期的功能。

1

2

3

4

5

6

7

8

9

10

11

12

void swip(int * a, int* b)

{

    int c = *a;

    *a = *b;

    *b = c;

}

int main()

{

    int a = 5, b = 6;

    swip(&a, &b);

    cout<<a<<' '<<b;

}

输出结果:6 5

传递函数的指针虽然能达到预期效果,但是确实以破坏函数的黑盒为代价,可读性差,调试困难。

有没有什么更好的办法呢?接下来 引用登场了。

变量的引用作为函数的参数

1

2

3

4

5

6

7

8

9

10

11

12

void swip(int &a, int &b)

{

    int c = a;

    a = b;

    b = c; 

}

int main()

{

    int a = 5, b = 6;

    swip(a, b);

    cout<<a<<' '<<b;

}

输出结果:6 5

克服了指针作为参数的弊端。话又有点多了,哈哈,这和指针有什么关系呢······

两个常用的字符串函数

  • strcmp() :用于比较字符串的大小。
  • strcpy() :复制字符串。

1

2

3

4

5

6

//函数原型

int strcmp(const char * arr1, const char * arr2);

//使用举例:

char arr1[] = "dfetf";

char arr2[] = "cfefef";

int b = strcmp(arr1, arr2);

输出b的值是大于0 的。

总结

指针强大而又危险,却也是C和C++的灵魂,由于其可以直接操作内存地址的特殊性,使得理解指针是如何工作的在C和C++中必不可少,若想成为一名优秀的C++工作者,必须要掌握指针。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/m0_63011787/article/details/126445392
相关文章
  • C++中类的六大默认成员函数的介绍

    C++中类的六大默认成员函数的介绍
    一、类的默认成员函数 二、构造函数Date(形参列表) 构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。 默认构造函数:无参的构
  • C/C++实现遍历文件夹最全方法总结介绍

    C/C++实现遍历文件夹最全方法总结介绍
    一、filesystem(推荐) 在c++17中,引入了文件系统,使用起来非常方便 在VS中,可以直接在项目属性中调整: 只要是C++17即以上都可 然后头文件
  • C语言实现手写Map(数组+链表+红黑树)的代码

    C语言实现手写Map(数组+链表+红黑树)的代码
    要求 需要准备数组集合(List) 数据结构 需要准备单向链表(Linked) 数据结构 需要准备红黑树(Rbtree)数据结构 需要准备红黑树和链表适配策略
  • MySQL系列教程之使用C语言来连接数据库

    MySQL系列教程之使用C语言来连接数据库
    写在前面 知道了 Java中使用 JDBC编程 来连接数据库了,但是使用 C语言 来连接数据库却总是连接不上去~ 立即安排一波使用 C语言连接 MySQL数
  • 基于C语言实现简单学生成绩管理系统

    基于C语言实现简单学生成绩管理系统
    一、系统主要功能 1、密码登录 2、输入数据 3、查询成绩 4、修改成绩 5、输出所有学生成绩 6、退出系统 二、代码实现 1 2 3 4 5 6 7 8 9 10 11
  • C语言实现共享单车管理系统

    C语言实现共享单车管理系统
    1.功能模块图; 2.各个模块详细的功能描述。 1.登陆:登陆分为用户登陆,管理员登陆以及维修员登录,登陆后不同的用户所执行的操作
  • C++继承与菱形继承的介绍

    C++继承与菱形继承的介绍
    继承的概念和定义 继承机制是面向对象程序设计的一种实现代码复用的重要手段,它允许程序员在保持原有类特性的基础上进行拓展,增加
  • C/C++指针介绍与使用介绍

    C/C++指针介绍与使用介绍
    什么是指针 C/C++语言拥有在程序运行时获得变量的地址和操作地址的能力,这种用来操作地址的特殊类型变量被称作指针。 翻译翻译什么
  • C++进程的创建和进程ID标识介绍
    进程的ID 进程的ID,可称为PID。它是进程的唯一标识,类似于我们的身份证号是唯一标识,因为名字可能会和其他人相同,生日可能会与其他
  • C++分析如何用虚析构与纯虚析构处理内存泄漏

    C++分析如何用虚析构与纯虚析构处理内存泄漏
    一、问题引入 使用多态时,如果有一些子类的成员开辟在堆区,那么在父类执行完毕释放后,没有办法去释放子类的内存,这样会导致内存
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计