重新学习C指针(笔记)

发布于:2022-12-21 ⋅ 阅读:(432) ⋅ 点赞:(0)


前言

            在笔试的过程中,楼主发现自身的指针知识不牢固,所以重新复习C语言中的指针


一、指针是什么?

指针是C语言用来存储地址,自身的地址由系统分配,地址偏移与系统有关(64位为8字节,32位为4字节)。

1.指针与const

常指针:指向不能改变

 int * const p; 

常目标指针 指向的内容不能改变

const int *p;

int const *p

指向和指向的内容不能改变

const int const *p;

 2.指针与数组

2.1指针与数组关系

数组名类似常指针   char * const q; 代表数组首元素   &str代表整个数组的首地址

char str[]="123456";

str++;  //达咩,出错!  

指针为动态分配的,数组为系统分配

char a[]="123456";   //存放在栈

char *p=&a;

a[0]='1';  //ok

对指针存储的字符串使用 sizeof 大小与存放的内容无关(数组作为参数传递时为指针)

char *p =“123456789”; //指向常量(静态存储区),自动补齐const(c99)

sizeof(p)结果为指针大小(4或8)

p[0]='0'; //达咩,出错!  常量不能修改

对数组的sizeof 大小与内容有关

char a[]="123456";

sizeof(a)结果为7; //包括字符串后的‘/0’

2.2 数组指针

        int (*p)[];
 

2.3 指针数组

        int *p[];

        int a[3][4]={{1,2,3,4},{2,3,4,5},{3,4,5,6}}; 

        int *p[3]={a[0],a[1],a[2]);   //p[i][j]    *(*(p+i)+j)  *(p[i]+j) 三者等价

 3.指针和函数

       函数名为函数所占用内存的首地址。

   3.1函数指针   

          int (*p)(int)   //函数指针,指向参数为int,返回值为int的函数

使用如下

int add(int x,int y)
{
    return x+y;
}

int main()
{   
    int (*q)(int,int);
    q=add;
    printf("%d",q(1,2));
    return 0;
}

      题外:  f() 意味参数可以为任意个。没有参数为void

               多用作回调函数(信号函数,内核中断服务......)

int select_down(int x,int y)
{
   return x>y?1:0;
}
int select_up(int x,int y)
{
   return x<y?1:0;
}

/*@function交换两数*/
void swap(int *a,int *b)
{
    *a=*a+*b;
    *b=*a-*b;
    *a=*a-*b;
} 
/*@function 冒泡函数
*@param - (*p)(int,int) : select_down :降序排   select_up: 升序排
*@param - a :待排序列
*@param - size :待排序列长度
*/           
void bubble_sort(int *a,int size,int (*p)(int,int))
{
    int i,j,tmp,key=0;
    for(i=0;i<size-1;i++)
{
    key=0;
    for(j=0;j<size-1-i;j++)
    //if(a[j+1]<a[j]){
    if(p(a[j],a[j+1])){
    swap(&a[j+1],&a[j]);
    }
    if(key=0)break;
}
  
}        

3.2指针函数

                函数返回类型为指针。    // tips!!不能返回函数局部变量的地址(栈内存)。

          int * fun();

             tips:函数对局部变量的回收需要一定的时间的,有时候返回结果看似成功,其实是是因为局部变量还没回收完毕,再sleep(1)等待一会,他的值就会被回收而改变。故指针函数的返回地址一定不能是该函数栈内存,可以为动态申请的堆空间或者静态存储区空间。

            

        题外: 如果要修改实参的值,必须传递地址)函数参数为地址传递(即指针时),其参数指针指向真实变量的的地址(非该函数的栈空间),其经过地址变换或者未变换都可以用作返回。传递数组给函数时作为指针传递,一般需要再加数组长度作为形参。

二、指针作用

1.节省空间

         当传入函数的参数的类型大小过大时,可以通过指针传地址的方式节省空间。

        64位传入指针大小为8,32位指针大小为4;

(示例):

static struct T
{
   int value;
   char string;
   char a[10];
};//占16字节,实际在应用中可能更大
void fun(struct *ptr)
{
   printf("%d",sizeof(ptr)); 
   //ptr->value=1; 使用结构体成员      
}
int main()
{
   struct T test;  
   printf("%d",sizeof(T));  
   fun(&test);
   return 0; 
}

2.使得函数修改值不止一个,同时腾出返回值用作运算的状态(出错或者其他情况)

    函数的返回值只有一个或者没有,可以通过指针来使得函数可以修改多个值并回馈给主函数;

(示例):

int fun(int *s,int size,int *max,int *min)
{
    ret=0;
    for(int i=0;i<size-1;i++){
        if(*max<s[i]) *max=s[i];
        if(*min>s[i]) *min=s[i];
    } 
     if(*min>*max) ret=-1;
       return ret;   
}

 3.用作命令行参数

int main (int argc, const char **argv)

./a.out  test  go  on

此时文件本身a.out为argv[0]; argv[1]为test  argv[2]为go argv[3]为on

argc范围为1~4;argc最小为1,即本身

三、指针使用

空指针 指针指向NULL(0地址)

野指针 指针指向未知的,不能被访问的地址 (对指针的不正确使用会造成)

1.指针申请和释放内存

             定义指针最好初始化内存,避免野指针而造成运行段错误(访问了不能用的内存)

(1)用户动态申请

        /*申请内存时要注意4点
        *1.有申请就要有释放,避免内存泄漏
        *2.释放后指针让其指向NULL
        *3.不要重复释放
        *4.malloc申请的地址,释放时就释放对应的地址,即申请的指针地址不能改变
        */

int *p=NULL;  //初始化指针给地址,或者空

p=(int *)malloc(8*sizeof(int));  

free(p);

p=NULL;

(2)指向现有的内存

int a=1;
int *p =&a;

2.指针运算

(1)指针自加减

  意为增加或者减去几个‘’单元‘’

char a[10];

char  *p=a; p++; 偏移1个字节

int  a[10];

int  *p=a; p++; 偏移4个字节

(2)两个指针减法

int a[10]={0,1,2,3,4,5}

int *p=a; int*q=&a[4]

printf("%d", q-p);   //打印结果为4 ,意味能放几个东西       地址实际相差16字节;

(3)指针与解引用*的运算

int x=3;y=0, *p =&x;

y=*p+5;  //y=8

y=++*p;   //y=4

y=*p++;    //y=3,p++;

四、指针分析

                对指针的分析最好通过画内存图来进行分析;

 附录:

用变量a给出下面的定义 

(1)一个整型数: int a。
(2)一个指向整型数的指针(一重指针): int *a。
(3)一个指向指针的的指针,它指向的指针是指向一个整型数的指针(二重指针): int **a。
(4)一个有10个整型数的数组 :int a[10]。
(5)一个有10个指针的数组,这10个指针是指向整型数的(指针数组): int *a[10]。
(6)一个指向有10个整型数数组的指针(数组指针):int (*a)[10]。
(7)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(函数指针):int (*a)(int)。
(8)一个有10个指针的数组,这10个指针均指向函数,该函数有一个整型参数并返回一个整型数(函数指针数组): int (*a[10])(int)。

总结

                C语言的指针是C的精华,好好学习掌握对linux编程应用有很大的作用,同时也可以加强对内存的理解应用。


网站公告

今日签到

点亮在社区的每一天
去签到