C语言的指针详解(概念理解)

以下内容为平时工作中的一些学习笔记,没有来得及排版整理,请谅解!

指针就是地址,是可以直接引用的,在c语言当中地址分为:(可直接引用)

  1. 指针

  2. 函数名

  3. 数组名

  4. 结构体名

指针用法1:作为函数参数
函数的参数类型与函数返回值类型:

    1.   基本数据类型

    2.   指针(基本指针类型、函数指针、结构体指针、数组指针等)

用函数指针做参数的好处 举例:

Process ( int xint yint ( *fun )())
{
        int result ;
result = ( *fun )( xy );
}

好处:有了函数指针做参数,只需要修改 Process 的函数指针就可以实现 一个函数指向多个功能函数 ,简单高效!**

基础知识补充: 指针,找到根源!程序的快捷方式!

使用指针的好处:

  1. 有效地表示复杂的数据结构;

    2 有效而方便地使用数组;

  2. 动态地分配存储器,直接处理内存地址;

  3. 在调用函数时还能输入或返回多于 1 个的变量值;

  4. 可以使程序简洁、紧凑、高效。

/*
如果你有一个或两三个保险柜 , 那么你可以将这几个保险柜的钥匙都放在身上 .~ 如果你有几百个保险柜 , ~ 你还愿意都将钥匙放在身上吗 ? 呵呵 , 肯定不愿意的吧 . 那么怎么办 ?~ 哈哈 , ~ 对拉 ! ~ 就是将保险柜钥匙贴上标签放到一个抽屉里面 , 而你身上只带着这把抽屉的钥匙 . ~~ 需要的时候就拿钥匙开抽屉罗 . 指针也就是这样啦 . 指针存放的是地址 ( 也就是保险柜的钥匙 ). 数据 ( 也就是保险柜的物品 ) 是通 ~ 过地址打开的 !
*/

在数据传递时,如果数据块较大(比如说数据缓冲区或比较大的结构),这时就可以使用指针传递地址而不是实际数据,即提高传输速度,又节省大量内存。

  1. 指针(间接访问方式): 地址就是指针!

定义:专门用来存放地址的变量称为指针变量。指针本身(的地址)是不变的,变的是它存放的地址。

与其它变量的区别:存的是地址,使用时与其它变量的使用方法一样。

运算符区分:

” * “的作用:

  1. 用于定义时,表示申请一个”指针变量”( 用于存取地址 )如: int *p; // 定义一个指针变量

  2. 用于运算时,表示它所指向的变量的值( 取出被指向的变量的值 ),可直接代表真正的值。

” & “的作用:取地址运算符。一般用它来取地址给指针变量。

如: int *ap, int a;

    ap = &a;//ap 指向变量 a        

指针使用步骤:

○ 1 定义: int *ap ;

○ 2 指向: ap = &a;//ap 指向变量 a

○ 3 使用 x=*ap ;

指针一般可以指向哪些类型?

○ 1 变量

○ 2 函数

○ 3 结构体

○ 4 数组

*p 指向谁,就代表谁!

结构体:把多个不同类型的变量结合在一起形成一个组合型变量,称为构造变量,简称结构体。

  1. 定义结构体的类型

形式:

struct 结构名

{

结构成员说明;

} 变量名 ;

如:

struct date{

        int monthint dayint year ;

}date1 , date2 ;
  1. 定义结构体类型变量
struct date{

        int monthint dayint year ;

} ;

struct date date1,date2;/* 定义结构的变量名 */

  1. 结构体类型变量的引用:

○ 1. 结构不能作为一个整体参加赋值、存取和运算 ; 也不能整体地作为函数的参数,或函数的返回值。

对结构所执行的操作 ,只能用” & “运算符取结构的地址 ,或对结构变量的成员 分别加以引用 。

如: UartTx_Put_EffectiveFrame(&UartTxBuf[BufIndex]); // 引用结构体数组

引用的方式:结构体变量名 . 成员名;如 date1.year =2003 ;

” . “” -> “符号是成员运算符,优先级最高。

“.” 用于非指针成员

” -> “只能用于指针成员,但” . “也可以用于指针成员。

○ 2. 如果结构体变量的成员本身又属于一个结构类型变量,则要用若干个” . “一级一级找到最低一级的成员,只有最低一级的成员才能参加赋值、存取和运算。

  1. 指向结构体类型数据的指针 (可作为函数参数传递)

○ 1. 指向结构体数据的指针 就是该结构体数据在内存中的 首地址 。

○ 2. 指向一个结构数组的指针 就是本结构体 数组的起始地址 。

指向结构体类型数据的指针定义的一般形式:

struct 结构体类型名 * 指针变量名; 如: struct msg1 *msg ;

或者

struct{

结构体成员说明;

}* 指针变量名;

定义一个结构体指针后需要:

  1. 赋值

    方法 1: 可以给 p 分配一段内存空间,并使其指向此空间:
    
    p=(struct abc *)malloc(sizeof(struct abc));
    
    p->a = 1;
    
    方法 2 :可以让 p 指向一个已存在的内存空间:
    
    struct abc temp;
    
    p=&temp;
    
    p->a = 1; 
    

结构体数组:

赋初值:

例如一个struct student {char na[5];float grrade} , 它可以这样初始化 struct student stu[2]={“hjk”,4},{“jkl”,45};

方式一:

   struct student stu[100] = {0};

方式二:

   struct student stu[100];

   memset( stu, 0, sizeof(stu) );

方式三:

   struct student stu[2]={"hjk",4},{"jkl",45};
  1. 函数指针 ( 专门用来存放函数入口地址 ) 调用函数

一个函数在编译时 C 编译器会给它分配一个入口地址。这个 入口地址就称为函数的指针 。可以用一个指针变量指向函数,然后通过该指针变量调用此函数。

函数指针的定义: int (p)(int); / 函数指针变量定义 */

1 .函数指针定义

函数类型 ( * 指针变量名) ( 形参列表 ) ;

” 函数类型 ” 说明函数的返回类型,由于 “()” 的优先级高于 “*”, 所以指针变量名外的括号必不可少,后面的 ” 形参列表 ” 表示指针变量指向的函数所带的参数列表。

例如:

int (*f)(int x);

double (*ptr)(double x);

指向 :指针 = 函数名 如: p=factorial ; /* 函数指针变量 p 指向 factorial() 函数 */

调用 :( * 指针)(参数)如: c= ( p)(5 ) ;/ 用指针变量 p 调用 factorial 函数 */

函数指针归纳如下:

○ 1 指向函数的指针变量的一般形式定义为:

函数返回值类型( * 指针变量名)(函数形参表 …… ) ;

定义的函数指针变量:把哪个函数地址赋给它,则它就指向哪个函数。在一个程序中,通过不同的赋值,一个函数指针变量 可以先后指向不同的函数 。

○ 2 在给函数指针变量赋值时, 只需给出函数名而不必给出参数 ,如 p= factorial;// 只给地址即可

○ 3 调用:只需将( *p ) 代替函数名即可 ,在( *p )之后的括号中可根据需要 写实际参数。

如 c= ( p )( 5 ) ; / 调用 p 指向的函数 factorial ,实参为 5 ,返回值赋给 c */

○ 4 对指向函数的指针变量进行诸如 p+n , p++ 和 p- - 的运算是没有意义的。

总结: 函数指针,指针名替函数名,且运算无意义!

  1. 数组、指针作为函数的参数

1 )用数组作为函数的参数

○ 1 数组名作函数参数时,应该在调用函数和被调用函数中 分别定义数组。

○ 2 实参数组与形参数组的类型一致

○ 3 实参数组与形参数组的大小可以一致,也可以不一致。( 不看形参,看实参 ) C 编译器对形参数组的大小不作检查,只是将实参数组的地址传给被调函数。

总结: 数组指针做参数,调用被调都定义,不看形参看实参。

  1. 用指向函数的指针变量作为函数的参数

参数为指针函数,执行指向函数,传递参数与执行函数

即,传指针,指向谁,执行谁!

  1. 用指向结构的指针变量作为函数的参数

问: C 语言不允许整体引用结构体变量名,那么如何将一个结构变量的值从一个函数传递给另一个函数呢?有两种方法:

1 . 直接引用成员。 像用变量作为函数的参数一样,直接引用结构体变量的成员作为参数。

2 .传送结构体地址。 用指向结构变量的指针变量作实际参数,将结构变量的地址传递给被调用函数的形式参数。

即,传指针,指向谁,执行谁!

9.1 返回指针的函数

函数可以返回: int 、 char 、 float 等,同样也可返回指针型数据,即 返回一个数据的地址。

形式:

返回值类型 * 函数名(参数表)

例如: int A ( x , y ) {…..}/ 函数体前带” * “返回指针 */

A 为函数名,调用它后可以得到一个指向 int 型数据的指针(地址)。

与指针函数对比

函数指针的定义: int p() ; / 函数指针变量定义, 函数定义时带” * “为指针函数 */

9.2 定义返回函数指针的函数: return_type(function(func_parameter_list))(parameter_list) 定义了一个函数 function ,该函数的参数列表是 (function_patameter_list) ,返回类型是一个函数指针,这个函数指针的原型是 return_type()(parameter_list) 。

例: int (*add1(int a,int b))(int,int) 此处:此函数的函数主体为 add1,add2 函数作为 add1 的形参,返回值为一个函数指针。 注:返回的函数的形式必须为 int funcname(int,int)

可以用 typedef 来简化定义: // 此函数等效于上面函数 typedef int (*funcp)(int)(int); // 定义整型函数指针 funcp add1(int a,int b);

总结:

传指针,指向谁,代表谁,执行谁!

返指针,指向谁,代表谁,执行谁!

  1. 数组指针和指向数组的指针变量

1 ) 数组指针:所谓数组的指针,就是数组的起始地址(数组名)。

例如: a[10]; a 就是数组指针(因为数组名是地址)

2 ) 指向数组的指针变量:用来存放一个数组的起始地址(指针)。

int a[10];

int app;/ 与一般指针变量一样形式 */

app=&a[0];

  1. 数组

定义:一组 同类型且有序数据 的集合叫做数组。定义一个数组时, C 编译器就会在系统的存储空间中开辟一个区域,用于存放该数组的内容。数组就包含在这个由 连续存储 单元组成的模块的存储体内。

二维数组:存取顺序是:按行存取,先存取第一行元素的第 0 列, 1 列, 2 列 ……. ,直到第一行的最后一列;然后返回到第二行开始,再取第二行的第 0 列, 1 列, ….. 以此类推。

总结:

  1. 函数指针:指向函数的指针

○ 1 定义: 函数类型 ( * 指针变量名) ( 形参列表 ) ;

例如:

int (*p)(int x);

○ 2 指向: p= factorial;// 只给地址即可

○ 3 调用: p ( j ) ;

  1. 返回指针的函数 :返回值是指针(函数的地址)

  2. 定义:

    int A()/ 返回指针的函数,称为指针函数,是函数 */

    {

int (*p)(int);// 定义一函数指针

p =max;// 指向 max ( int x )函数

return p;// 返回函数的地址

}

int (point)(int);/ 可以指向函数的指针,称为函数指针,是指针 */

point=A();// 返回函数指针(地址)给 point 。

包含头文件 #include “stdlib.h”

*malloc(unsigned int size); // 动态分配内存

free(demo1);// 释放指针内存

举例:

demo1=(struct DEMO *)malloc(sizeof(struct DEMO));// 分配内存

free ( demo1 ); // 释放内存

使用函数指针的好处:

1 、 回调函数。

2 、实现面向对象中多态的功能。

结构体函数指针 举例:

struct DEMO

{

    int x;

    int y;

    int (*func)(int,int); 

};




int add2(int x,int y)

{
    return x+y;
}

struct DEMO demo;/* 构造一个结构体 */

demo.func=add2;/* func 指向 add2 函数 */

p->fun();/* 执行结构体中函数 */

指向数组的数组的指针(指向地址的地址)双指针

1.被指的数组指针本身应该是个双维数组

code BYTE **code Vmcd_Str[] = 

{
    Txt_loading_s,        //STR_VMCD_LOADING=0, //加载中
    Txt_reading_s,
};

BYTE  *ptxt; 
ptxt = Vmcd_Str[0][1];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

车载软件开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值