欢迎光临散文网 会员登陆 & 注册

C语言指针

2023-07-06 10:19 作者:自闭选手的Z23  | 我要投稿

指针

*的两种含义:

1. 在定义时表示 后面的变量是指针

2. 使用时表示取值(取指针地址的值)

不论指向的类型是什么,指针大小为4字节(64位为8字节 )

 

下列交换a b值的程序为什么错误?

原因是只交换了形参xy的值,在执行swap()函数后释放xy。

没有交换实参

如果要交换实参的值,必须要传地址



修改如下:

*x就是a , *y就是b。



野指针

int *p;    //不能随意定义指针

如何合法使用内存?

1 系统分配

    Int a ;

    Int  *p=&a;

2 用户申请内存(堆内存)

    malloc(32);//动态内存分配,运行时才能找到一个内存使用

    malloc()不清楚什么类型的返回值,所以干脆返回void类型


在申请内存时需要强制转换类型,如下:

    char  *str=(char *)malloc(32);  //str指针指向了申请的32位内存

     free(str);//用完内存后需要释放内存

     str=NULL;//防止野指针



指针和数组

指针数组是数组,

数组指针是指针,如 int (*p)[5];  一个指针占4个字节。

数组名为首元素的地址

int *p = a;     int *p = &a[0];     相同

a[i]    *(p+i)     相同


一维数组a[10],a表示首元素地址;

二维数组a[3][4],a表示首行地址(16字节),a[0]表示首行首元素地址(4字节)。

&a表示数组地址(48字节,12*4).

 


/*

问:如何不用3,4,直接用函数表示几行几列?

*/


/*

问:char str = "hello world"; char *p = "hello world"; 区别

 

(64位操作系统)

//str++   报错   数组名是常指针(地址常量),不能修改

//p++           指向下一个元素e

//str[0] = ‘x’;           把str首元素改为x

//p[0] = ‘x’; 不能运行   字符串常量,不能被修改

//sizeof(str) = 5*4(字节长度)  32位操作系统

//sizeof(p) =  4

*/



/*

问:P1[0],p2[0],p3[0]的值分别是多少?

int  a[5] = {1,2,3,4,5}; //设a的首地址为0x100

1.int *p1 = (int*)(&a + 1);

2.int *p2 = (int*)((int)a+1);

3.int *p3 = (int*)(a + 1);  


1.&a表示数组的地址     a表示数组首元素地址

&a+1  表示跳过20字节,直接跳到下个数组;将数组指针转为(int*)型,指向下一个数组的首地址,由于下个数组没有定义,所以

P1[0]为野指针

 

2.P[2]先执行(int*)((int)a+1);,

将a的首地址0x100转为int型100,加一得101,再转为(int*)型0x101 进入a[0]的首地址的第二个字节。

P2[0]不合法

 

3.P3[0]为2, 就算不转 (a+1)也为(int*)类型

*/



指针和字符串 

char *string[] = {"hello","world"};

printf("%s\n",string);

 

string是数组还是指针?(64位)

    先括号,再char*,是数组,存放的内容为指针,指针型数组。

 

printf("%s\n",string); 能不能输出hello world?

    string表示数组首元素地址,不能输出(野指针)

    printf("%s\n",string[0]); 输出hello

    printf("%s\n",string[1]); 输出world 




函数指针

指向函数的指针

    函数名为该函数所占内存区的首地址   函数名 = 函数内存首地址(函数入口地址)

    把函数的首地址(函数入口地址)赋予一个指针变量,使指针指向函数。

    通过指针变量就可以找到调用这个函数,这种指向函数的指针叫“函数指针变量”

格式为:类型说明符(*指针变量名)();

如:   void (*p)();     *p表示它是一个指针,右边的括号表示它指向一个函数 ,括号里空的表明它没有参数 ,void表示它没有返回值        

 

申明很麻烦,可以加一个定义 typedef  int(*T)(int,int);  这样T就是定义函数指针了

T  q = add; 等价于 int(*q)(int,int);




指针函数

返回值是指针的函数

/*

int (*p)()           int *p()    的区别?

    int (*p)() 是一个函数指针,是一个变量,返回值是整形。

    int *p() 是一个函数声明,说明p是一个指针型函数,返回值是一个指向整形量的指针。


    找到变量名,先右后左

*/




                                        回调函数

回调函数:把函数名作为另一个函数的参数

作用:修改函数的功能

冒泡排序


    程序实现了从小到大排序,在函数都封装好之后,要实现从大到小排序,如何实现?

能不能让paixu()既实现从小到大排序又实现从大到小排序?                                                                                                              

                                                                                                                 

复杂函数声明

1.int*(*(*fp)(int))[10];

2.int*(*(*array[5])())();

怎么解释?

右左法则


1. int*(*(*fp)(int))[10];

先找变量fp, 看括号          int*(*(*fp)(int))[10];   ,fp是一个指针

向右看,也是一个括号 (int),   int*(*(*fp)(int))[10];

括号表明指针指向一个函数,有整型的参数。

向左看,函数的返回值        int*(*(*fp)(int))[10];  返回值是一个指针

得出fp是一个指针指向函数,函数有一个int类型的参数,函数的返回值也是指针。

 

再向右看,返回的指针指向[10],int*(*(*fp)(int))[10];  ,指向一个10个元素的数组。

再向左看,10个元素的类型,int*(*(*fp)(int))[10]; , 每个元素都是整形指针。

 

总结:fp是指针,指向一个函数,函数有整型参数,函数的返回值是指针,指向有10个元素的数组,元素是整型指针。

 


2. int*(*(*array[5])())();

array是一个有5个元素的数组,元素是指针,指向一个函数,函数没有参数,函数的返回值是指针,指针指向另一个

函数,这个函数没有参数,返回值是一个整型指针。


问:const和volatile能同时使用吗?

可以,volatile表示编译器不要优化变量;

const修饰指针时,表示不能使用指针来修改地址上的值,但是可以用其他指针或变量修改。

const修饰变量时,表示不能使用变量直接修改值,但是可以使用其他指针来修改。




C语言指针的评论 (共 条)

分享到微博请遵守国家法律