ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【C/C++】指针

2021-03-04 19:32:12  阅读:111  来源: 互联网

标签:return 函数 指向 int C++ 地址 指针


(资料来源:https://www.bilibili.com/video/BV1QE41147RT?p=101)

指针:内存地址,用于间接访问内存单元

指针变量:用于存放地址的变量

static int i ;
static int* ptr = &i ;

指针变量的赋值运算

语法形式:指针名 = 地址

(在该地址中存放的数据类型与指针类型必须相符)

地址可以是:

  • 通过取地址符&取得已定义的变量的起始地址

  • 动态内存分配成功时返回的地址

  • 整数零,0可以赋给指针,表示空指针,NULL就是被定义为0(C++11中可以使用nullptr代替NULL)

指向常量的指针

const指针

int a = 1 ;
const int* p1 = &a ;

不能通过指向常量的指针改变所指对象的值,但指针本身可以改变,可以指向别的对象

int a = 1 ;
const int* p1 = &a ;
int b = 2 ;
p1 = &b; // 正确,p1可以指向别的对象
*p1 = a ; // 错误,不能通过p1改变所指向的对象

指针类型的常量

声明指针常量,指针本身的值不能被改变,也就是说指针指向的地址不能被修改。

int a = 1, b = 2 ;
int* const p2 = & a;
p2 = & b ;// 错误,p2是指针常量,不能改变指针指向的地址

指针的运算

指针的算术运算

指针p加上获减去n(p + n、p - n)

  • 其意义是指针当前指向位置的前方或后方第n个数据的起始位置

指针的++、--运算 (p++、p--)

  • 其意义是指向下一个或前一个完整数据的起始

运算的结果取决于指针指向的数据类型,总是指向一个完整数据的起始位置

指针的关系运算

  • 指向相同类型数据的指针之间可以进行各种关系运算
  • 指向不同数据类型的指针,和指针与一般整数类型之间的关系运算无意义
  • 指针可以和零进行比较(相等或不相等),也就是判断该指针是否为空指针。(C++11中,也可以和nullptr进行比较)

指针数组

指针数组:数组的元素是指针类型

int* p[2] ;
// p[0], p[1]分别是两个指针

例子:使用指针数组存放矩阵

#include <iostream>
using namespace std ;
int main() {
    int arr1[] = {1,2,3} ;
    int arr2[] = {4,5,6} ;
    int     [] = {1,2,2} ;

    int* allArr[3] = {arr1, arr2,     } ;

    for (int i = 0;i < 3;i++) {
        for (int j = 0;j < 3;j++) {
            cout << allArr[i][j] << " " ;
        }
        cout << endl ;
    }
    
    return 0;
}
/*
    1 2 3
    4 5 6
    1 2 2
*/

指针数组和二维数组对比

以指针作为函数参数

  • 需要数据双向传递时(比如,交换函数)
  • 需要传递一组数据,只传递首地址运行效率比较高

例子

#include <iostream>
using namespace std ;
void splitFloat(float x, int* intPart, float* fracPart) {
    *intPart = static_cast<int>(x) ; //获取x的整数部分
    *fracPart = x - *intPart ; // 获取x的小数部分
}
int main() {
    cout << "Enter 3 float point numbers:" << endl ;
    for (int i = 0; i < 3; i++) {
        float x, f ;
        int n ;
        cin >> x ;
        splitFloat(x, &n, &f) ;
        cout << "Integer Part = " << n << " Fraction Part = " << f << endl ;
    }
    
    return 0;
}
/*
Enter 3 float point numbers:
2.333
Integer Part = 2 Fraction Part = 0.333
4.999
Integer Part = 4 Fraction Part = 0.999
2.111101
Integer Part = 2 Fraction Part = 0.111101
*/

指针类型的函数

若函数的返回值是指针,该函数就是指针类型的函数

注意,不能将非静态局部变量的地址当作函数的返回值,因为非静态局部变量在函数运行结束后就被释放,此时返回的地址是一个非法地址

返回的指针要确保在主调函数中是有效、合法的地址

  • 主函数中定义的数组,在子函数中对该数组元素进行各种操作后,返回其中一个元素的地址 √

    #include <iostream>
    using namespace std ;
    // 找到数组中第一个为0的元素地址
    int* search(int* a, int n) {
        for (int i = 0;i < n;i++) {
            if (a[i] == 0) {
                return &a[i] ; // 返回的地址指向的元素是在主函数中定义的
            }
        }
        return nullptr ;
    }
    int main() {
        int arr[5] ; // 主函数中定义的数组
        for (int i = 0;i < 5;i++) {
            cin >> arr[i] ;
        }
        int* zeroptr = search(arr, 5) ; // 将主函数中数组的首地址传给子函数
        if (zeroptr == nullptr) {
            cout << "No element with value 0 was found" << endl ;
        } else {
            cout << "The address of the element with a value of 0 is " << zeroptr << endl ;
        }
        return 0;
    }
    /*
    2 3 4 1 0
    The address of the element with a value of 0 is 0x6ffe00
    */
    
  • 在子函数中通过动态内存分配new操作取得的内存地址返回给主函数是合法有效的,但是要记得delete释放内存,避免内存泄漏

指向函数的指针

定义形式

存储类型 数据类型 (*函数指针名) () ;

含义

函数指针指向的是程序代码存储区

函数指针的用途——实现函数回调

  • 通过函数指针调用的函数

    • 例如将函数的指针作为参数传递给一个函数,使得在处理相似事件的时候可以灵活的使用不同的方法

      sort(a, a + n, cmp) // cmp就是通过函数指针调用的函数
      
  • 调用者不关心谁是被调用者

    • 需知道存在一个具有特定原型和限制条件的被调用函数
#include <iostream>
using namespace std ;

int compute(int a, int b, int(*func)(int, int)) {
    return func(a, b) ;
}
int max(int a, int b) {
    return ((a > b) ? a : b) ;
}
int min(int a, int b) {
    return ((a < b) ? a : b) ;
}
int sum(int a, int b) {
    return a + b ;
}
int main() {
    int a,b,res ;
    cin >> a ;
    cin >> b ;
    res = compute(a, b, &max) ;
    cout << "Max of " << a << " and " << b << " is " << res << endl ;
    res = compute(a, b, &min) ;
    cout << "Min of " << a << " and " << b << " is " << res << endl ;
    res = compute(a, b, &sum) ;
    cout << "Sum of " << a << " and " << b << " is " << res << endl ;
    return 0 ;
}
/*
2 3
Max of 2 and 3 is 3
Min of 2 and 3 is 2
Sum of 2 and 3 is 5
*/

对象指针

对象指针定义形式

类名* 对象指针名 ;

#include <iostream>
using namespace std ;

class Point {
public :
    Point(int x = 0, int y = 0) : x(x), y(y) {}
    int getX() const {
        return x ;
    }
    int getY() const {
        return y ;
    }
private:
    int x, y;
} ;
int main() {
    Point a(4,5) ;
    Point* p1 = &a ; // 定义对象指针,用a的地址初始化
    cout << p1->getX() << endl ; // 用指针访问对象成员
    cout << a.getX() << endl ; // 用对象名访问对象成员
    return 0;
}
/*
4
4
*/

this指针

隐含于类的每一个非静态成员函数中

指出成员参数所操作的对象

  • 当通过一个对象调用成员函数中,系统先将该对象的地址赋给this指针,然后调用成员函数,成员函数对对象的数据成员进行操作时,就隐含使用了this指针
// 上面的例子,getX()函数中
return x;
// 相当于
return this->x ;

标签:return,函数,指向,int,C++,地址,指针
来源: https://www.cnblogs.com/Suans/p/14482516.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有