指针不过如此,看完后我差点飘了(二)

简介: 指针不过如此,看完后我差点飘了

函数的指针


一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址。我们可以把函数的这个首地址赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是函数指针。


函数指针的定义形式为:


returnType (*pointerName)(param list);


returnType 为函数返回值类型,pointerNmae 为指针名称,param list 为函数参数列表。参数列表中可以同时给出参数的类型和名称,也可以只给出参数的类型,省略参数的名称,这一点和函数原型非常类似。


用指针来实现对函数的调用:

#include <stdio.h>
//返回两个数中较大的一个
int max(int a, int b)
{
    return a>b ? a : b;
}
int main()
{
    int x, y, maxval;
    //定义函数指针
    int (*pmax)(int, int) = max;  //也可以写作int (*pmax)(int a, int b)
    printf("Input two numbers:");
    scanf("%d %d", &x, &y);
    maxval = (*pmax)(x, y);
    printf("Max value: %d\n", maxval);
    return 0;
}

结构体和指针


结构体指针有特殊的语法: -> 符号


如果p是一个结构体指针,则可以使用 p ->【成员】 的方法访问结构体的成员


typedef struct
{
    char name[31];
    int age;
    float score;
}Student;
int main(void)
{
    Student stu = {"Bob" , 19, 98.0};
    Student*ps = &stu;
    ps->age = 20;
    ps->score = 99.0;
    printf("name:%s age:%d
",ps->name,ps->age);
    return 0;
}

const 和 指针


指向常量的指针,值不能改变,指向可改变


常指针值能改变,指向不可改变


指向常量的常指针,都不能改变


#include <stdio.h>
int main()
{
  // 1 可改变指针
  const int a = 10;
  int *p = &a;
  *p = 1000;
  printf("*p = %d\n", *p);
  // 2 可改变指针
  const b = 10;
  int *pb = &b;
  pb = p;
  printf("*pb = %d\n", *pb);
  // 3
  const c = 10;
  int * const pc = &c;
  *pc = 1000;
  //pc = pb;不能改变
  //4
  const d = 10;
  const * int const pd = &d;
  //*pd = 1000; 不能改变
  printf("\n");
  return 0;
}

深拷贝和浅拷贝


如果2个程序单元(例如2个函数)是通过拷贝 他们所共享的数据的 指针来工作的,这就是浅拷贝,因为真正要访问的数据并没有被拷贝。如果被访问的数据被拷贝了,在每个单元中都有自己的一份,对目标数据的操作相互 不受影响,则叫做深拷贝。

#include <iostream>
using namespace std;
class CopyDemo
{
public:
  CopyDemo(int pa,char *cstr)  //构造函数,两个参数
  {
     this->a = pa;
     this->str = new char[1024]; //指针数组,动态的用new在堆上分配存储空间
     strcpy(this->str,cstr);    //拷贝过来
  }
//没写,C++会自动帮忙写一个复制构造函数,浅拷贝只复制指针,如下注释部分
  //CopyDemo(CopyDemo& obj)  
  //{
  //   this->a = obj.a;
  //  this->str = obj.str; //这里是浅复制会出问题,要深复制
  //}
  CopyDemo(CopyDemo& obj)  //一般数据成员有指针要自己写复制构造函数,如下
  {
     this->a = obj.a;
    // this->str = obj.str; //这里是浅复制会出问题,要深复制
     this->str = new char[1024];//应该这样写
     if(str != 0)
        strcpy(this->str,obj.str); //如果成功,把内容复制过来
  }
  ~CopyDemo()  //析构函数
  {
     delete str;
  }
public:
     int a;  //定义一个整型的数据成员
     char *str; //字符串指针
};
int main()
{
  CopyDemo A(100,"hello!!!");
  CopyDemo B = A;  //复制构造函数,把A的10和hello!!!复制给B
  cout <<"A:"<< A.a << "," <<A.str << endl;
  //输出A:100,hello!!!
  cout <<"B:"<< B.a << "," <<B.str << endl;
  //输出B:100,hello!!!
  //修改后,发现A,B都被改变,原因就是浅复制,A,B指针指向同一地方,修改后都改变
  B.a = 80;
  B.str[0] = 'k';
  cout <<"A:"<< A.a << "," <<A.str << endl;
  //输出A:100,kello!!!
  cout <<"B:"<< B.a << "," <<B.str << endl;
  //输出B:80,kello!!!
  return 0;
}

根据上面实例可以看到,浅复制仅复制对象本身(其中包括是指针的成员),这样不同被复制对象的成员中的对应非空指针会指向同一对象,被成员指针引用的对象成为共享的,无法直接通过指针成员安全地删除(因为若直接删除,另外对象中的指针就会无效,形成所谓的野指针,而访问无效指针是危险的;


除非这些指针有引用计数或者其它手段确保被指对象的所有权);而深复制在浅复制的基础上,连同指针指向的对象也一起复制,代价比较高,但是相对容易管理。


相关文章
|
存储 程序员 C语言
指针不过如此,看完后我差点飘了(一)
指针不过如此,看完后我差点飘了
159 0
指针不过如此,看完后我差点飘了(一)
|
1月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
105 13
|
6月前
|
C语言
指针进阶(C语言终)
指针进阶(C语言终)
|
2月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
36 0
|
3月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
136 4
|
4月前
|
C语言
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
【C初阶——指针5】鹏哥C语言系列文章,基本语法知识全面讲解——指针(5)
|
4月前
|
C语言
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
【C初阶——指针4】鹏哥C语言系列文章,基本语法知识全面讲解——指针(4)
|
4月前
|
存储 编译器 C语言
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
【C初阶——指针3】鹏哥C语言系列文章,基本语法知识全面讲解——指针(3)
|
5月前
|
编译器 C语言
【C语言初阶】指针篇—下
【C语言初阶】指针篇—下
|
5月前
|
存储 C语言
【C语言初阶】指针篇—上
【C语言初阶】指针篇—上