以下内容为平时工作中的一些学习笔记,没有来得及排版整理,请谅解!
指针就是地址,是可以直接引用的,在c语言当中地址分为:(可直接引用)
指针
函数名
数组名
结构体名
指针用法1:作为函数参数
函数的参数类型与函数返回值类型:
1. 基本数据类型
2. 指针(基本指针类型、函数指针、结构体指针、数组指针等)
用函数指针做参数的好处 举例:
Process ( int x , int y , int ( *fun )())
{
int result ;
result = ( *fun )( x , y );
}
好处:有了函数指针做参数,只需要修改 Process 的函数指针就可以实现 一个函数指向多个功能函数 ,简单高效!**
基础知识补充: 指针,找到根源!程序的快捷方式!
使用指针的好处:
有效地表示复杂的数据结构;
2 有效而方便地使用数组;
动态地分配存储器,直接处理内存地址;
在调用函数时还能输入或返回多于 1 个的变量值;
可以使程序简洁、紧凑、高效。
/*
如果你有一个或两三个保险柜 , 那么你可以将这几个保险柜的钥匙都放在身上 .~ 如果你有几百个保险柜 , ~ 你还愿意都将钥匙放在身上吗 ? 呵呵 , 肯定不愿意的吧 . 那么怎么办 ?~ 哈哈 , ~ 对拉 ! ~ 就是将保险柜钥匙贴上标签放到一个抽屉里面 , 而你身上只带着这把抽屉的钥匙 . ~~ 需要的时候就拿钥匙开抽屉罗 . 指针也就是这样啦 . 指针存放的是地址 ( 也就是保险柜的钥匙 ). 数据 ( 也就是保险柜的物品 ) 是通 ~ 过地址打开的 !
*/
在数据传递时,如果数据块较大(比如说数据缓冲区或比较大的结构),这时就可以使用指针传递地址而不是实际数据,即提高传输速度,又节省大量内存。
- 指针(间接访问方式): 地址就是指针!
定义:专门用来存放地址的变量称为指针变量。指针本身(的地址)是不变的,变的是它存放的地址。
与其它变量的区别:存的是地址,使用时与其它变量的使用方法一样。
运算符区分:
” * “的作用:
用于定义时,表示申请一个”指针变量”( 用于存取地址 )如: int *p; // 定义一个指针变量
用于运算时,表示它所指向的变量的值( 取出被指向的变量的值 ),可直接代表真正的值。
” & “的作用:取地址运算符。一般用它来取地址给指针变量。
如: int *ap, int a;
ap = &a;//ap 指向变量 a
指针使用步骤:
○ 1 定义: int *ap ;
○ 2 指向: ap = &a;//ap 指向变量 a
○ 3 使用 x=*ap ;
指针一般可以指向哪些类型?
○ 1 变量
○ 2 函数
○ 3 结构体
○ 4 数组
*p 指向谁,就代表谁!
结构体:把多个不同类型的变量结合在一起形成一个组合型变量,称为构造变量,简称结构体。
- 定义结构体的类型
形式:
struct 结构名
{
结构成员说明;
} 变量名 ;
如:
struct date{
int month ;
int day ;
int year ;
}date1 , date2 ;
- 定义结构体类型变量
struct date{
int month ;
int day ;
int year ;
} ;
struct date date1,date2;/* 定义结构的变量名 */
- 结构体类型变量的引用:
○ 1. 结构不能作为一个整体参加赋值、存取和运算 ; 也不能整体地作为函数的参数,或函数的返回值。
对结构所执行的操作 ,只能用” & “运算符取结构的地址 ,或对结构变量的成员 分别加以引用 。
如: UartTx_Put_EffectiveFrame(&UartTxBuf[BufIndex]); // 引用结构体数组
引用的方式:结构体变量名 . 成员名;如 date1.year =2003 ;
” . “” -> “符号是成员运算符,优先级最高。
“.” 用于非指针成员
” -> “只能用于指针成员,但” . “也可以用于指针成员。
○ 2. 如果结构体变量的成员本身又属于一个结构类型变量,则要用若干个” . “一级一级找到最低一级的成员,只有最低一级的成员才能参加赋值、存取和运算。
- 指向结构体类型数据的指针 (可作为函数参数传递)
○ 1. 指向结构体数据的指针 就是该结构体数据在内存中的 首地址 。
○ 2. 指向一个结构数组的指针 就是本结构体 数组的起始地址 。
指向结构体类型数据的指针定义的一般形式:
struct 结构体类型名 * 指针变量名; 如: struct msg1 *msg ;
或者
struct{
结构体成员说明;
}* 指针变量名;
定义一个结构体指针后需要:
赋值
方法 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};
- 函数指针 ( 专门用来存放函数入口地址 ) 调用函数
一个函数在编译时 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 数组名作函数参数时,应该在调用函数和被调用函数中 分别定义数组。
○ 2 实参数组与形参数组的类型一致
○ 3 实参数组与形参数组的大小可以一致,也可以不一致。( 不看形参,看实参 ) C 编译器对形参数组的大小不作检查,只是将实参数组的地址传给被调函数。
总结: 数组指针做参数,调用被调都定义,不看形参看实参。
- 用指向函数的指针变量作为函数的参数
参数为指针函数,执行指向函数,传递参数与执行函数
即,传指针,指向谁,执行谁!
- 用指向结构的指针变量作为函数的参数
问: 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 ) 数组指针:所谓数组的指针,就是数组的起始地址(数组名)。
例如: a[10]; a 就是数组指针(因为数组名是地址)
2 ) 指向数组的指针变量:用来存放一个数组的起始地址(指针)。
int a[10];
int app;/ 与一般指针变量一样形式 */
app=&a[0];
- 数组
定义:一组 同类型且有序数据 的集合叫做数组。定义一个数组时, C 编译器就会在系统的存储空间中开辟一个区域,用于存放该数组的内容。数组就包含在这个由 连续存储 单元组成的模块的存储体内。
二维数组:存取顺序是:按行存取,先存取第一行元素的第 0 列, 1 列, 2 列 ……. ,直到第一行的最后一列;然后返回到第二行开始,再取第二行的第 0 列, 1 列, ….. 以此类推。
总结:
- 函数指针:指向函数的指针
○ 1 定义: 函数类型 ( * 指针变量名) ( 形参列表 ) ;
例如:
int (*p)(int x);
○ 2 指向: p= factorial;// 只给地址即可
○ 3 调用: p ( j ) ;
返回指针的函数 :返回值是指针(函数的地址)
定义:
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];