zoukankan      html  css  js  c++  java
  • C语言指针收藏

    指针是什么

    》》每一个内存单元只能同时存储一个数据,如何保证内存单元同时只能存储一个数据,可以使用编号的方式实现内存单元标记,此编号就是指针。

    》》指针是一个变量,指针是存放着一个数据的内存地址而不是数据本身的值,其是查找数据的另一种方式

    相关运算符

    【&】在变量中取地址

    【*】在地址中取变量

    测试小程序:

    #include<stdio.h>
    void main() {
        int i = 10;//定义一个变量,并赋初始值为10
        int *p = &i;//定义一个指针变量,并赋初始值为i的地址
        *p = 199;
        printf("%d=%d", *p,i);//输出199=199
        printf("---%d---", p);//得到变量i的地址
    }

    指针变量的类型

    》》指针类型:int *、float*、long*、double*、char*等等

    》》指针变量的类型需要与存储的数据类型相同

    》》确定类型可以方便指针变量确定存储数据的大小,为数据寻找到结束符,如int类型占四个字节、char占一个字节。也方便指针使用加1或减1操作,如int加减1会跳动4个字节,char加减1会跳动两个字节。

    指针的赋值

    int i=10;  int *p=&i;

    int *pp;

    pp=p;

    指针运算符:

    *p++

    等同于*(p++),运算优先级为从右到左,应该是先*p取值,然后地址移动一位,要区别与*(++p)。

     char *ch="0123";
     //printf("%c
    ",*ch++);//输出0 
     //printf("%c
    ",*(ch++));//输出0 
     printf("%c
    ",*(++ch));//输出1 

    指针变量作为函数参数

    #include<stdio.h>
    //int *a1=&b1;
    void fun(int *a1, int* a2) {
        
        *a1 = 100;
        int ii = 99;
        a2 = &ii;//让指针重新指向另外一个地址
        printf("得到的数据:%d,%d", *a1, *a2);//输出100,99
    }
    void main() {
        int b1 = 1, b2 = 2;
        fun(&b1, &b2);
        printf("调用函数后:%d,%d", b1, b2);//输出100,2
    }

    输出b2的结果并不是相同的值,是因为执行调用函数改变了实参指针变量的值,并不是改变了实参指针变量所指变量的值

    数组作为函数参数

    #include<stdio.h>
    void fun1(int *arr){
       arr[0]=10;
       arr[1]=11;
    }
    void fun2(int arr[]){
       arr[2]=100;
       arr[3]=110;
    }
    void main(){      
       //变量初始化 
       int i;
       int a[]={0,1,2,3,4,5,6};  
       //函数调用 
       fun1(a);
       fun2(a);   
       //打印
       for(i=0;i<sizeof(a)/sizeof(int);i++){
            printf("%d ",a[i]); //10 11 100 110 4 5 6
       }
    } 

    数组作为函数参数会自动退化为指针

    函数形参如果是数组,不管下标是多少都会自动转换为数组的首地址指针

     1 #include<stdio.h>
     2 
     3 void fun1(int *p){
     4     printf("%d",p[0]);//10
     5 }
     6 void fun2(int p[]){
     7     printf("%d",p[0]);//10
     8 } 
     9 
    10 void fun3(int p[100]){
    11     printf("%d",p[0]);//10
    12 }
    13 
    14 void fun4(char *p[]){
    15     printf("%s",p[0]);//dong
    16 } 
    17 
    18 void fun5(char **p){
    19     printf("%s",p[0]);//dong
    20 } 
    21  
    22 void main(){
    23    int ii[]={10,11,12};
    24    fun1(ii);
    25    fun2(ii);
    26    fun3(ii);
    27    char *ch[]={"dong","xiao"};
    28    fun4(ch);
    29    fun5(ch);
    30 } 

    一维数组指针变量

    数组名(如arr)代表元素的首地址,数组第一个元素的地址也是这个数组的首地址(如&arr[0])。

    数组指针中使用加减1将跳到下一个或者上一个数组元素地址,与使用 &arr[n+1] 基本相同。

    如果整数数组名为arr,运行int *p=arr,则*(p+3)、p[3]、*(arr+3)、arr[3]效果均是取出数组arr的第三个元素,在编译时arr[3]实际上是*(arr+3)处理的。

    #include<stdio.h>
    void main() {
        int arr[] = { 5,4,3,2,0 };
        int *p = arr;
        int *pp = &arr[0];
        printf("%d", *(p+3));//输出2
    }

    函数数组参数

    #include<stdio.h>
    //等价于void fun(char a1[]) {
    void fun(char *a1) {
        *(a1 + 2) = 'c';//改变第二个值的内容
    }
    void main() {
        char b1[] = { "123456789" };
        fun(b1);
        printf("调用函数后:%s", b1);//输出: 12c456789
    }

    二维数组指针变量

    #include<stdio.h>
    void main() {
        int a1[][3] = { {10,11,12},{100,110,120} };
        int a[][3] = { 10,11,12,100,110,120 };
        printf("地址:%d==%d==%d==%d", a[0], &a[0][0],*(a+0),a+0);//输出地址
        printf("%d===%d==%d", a[0][1], *(*(a + 0)+1),*(a[0]+1));//得到值
    }

    指针引用字符串

    字符串常量【char *ch = "dong xiao dong";】表示其指向地址的内容不可变,但指向的地址是可变的;

    字符串变量【char ch[] = "dong xiao dong";】其指向地址的内容可变。

    #include<stdio.h>
    void main() {
        //char *ch = "dong xiao dong"; //字符串常量,不可变 
        char ch[] = "dong xiao dong";  //字符数组,可变
        ch[2] = '2';//字符串常量运行这条将报错
        printf("%s
    ", ch);
    }

    可变格式的输出函数:

    #include<stdio.h>
    void main() {
        char *ch = "dong xiao %d
    ";
        printf(ch, 10);
        ch = "xiaoxiao%d
    ";
        printf(ch, 10);
        char chh[] = "dongdong %d
    ";
        printf(ch, 100);
    }

    指向函数的指针

    【int(*p)(int, int);//定义一个函数指针变量p】,第一个int表示返回值类型,第二个int和第三个int表示函数的参数类型。注意*p两侧的括号不能省略,表示p先与*结合,是指针变量,然后再于后面的()结合,()表示是函数,即该指针变量不是指向一般的变量,而是指向函数。如果写成“int * p(int,int);”,由于()优先级高于*,它相当于“int *(p(int,int))”,就成了声明一个p函数,并且这个函数的返回值是指向整型变量的指针。

    返回值为int

    #include<stdio.h>
    void main() {
        int minto(int a, int b);//函数声明
        int(*p)(int, int);//定义一个函数指针变量p
        p = minto;//函数指针指向函数minto首地址
        int cc = (*p)(11, 55);//调用函数
        printf("Min===%d", cc);
    }
    
    int minto(int a, int b) {
        if(a > b) return b;
        else return a;
    }

    无返回值:

    #include<stdio.h>
    void main() {
        void fun(int a);//函数声明
        void (*p)(int);//定义一个函数指针变量p
        p = fun;//函数指针指向函数fun首地址
        (*p)(11);//调用函数
    }
    void fun(int a) {
        printf("%d
    ", a);  
    }

    指向函数指针作为函数的参数

    #include<stdio.h>
    void main() {
        int fun(int(*addpp)(int, int), int x, int y);//函数声明
        int add(int i, int j);
    
        int ii=fun(add, 11, 12);//传递函数名和参数即可
        printf("输出相加的值为:%d", ii);
      }
    
    //int (*addpp)(int,int);addpp=add;
    int fun(int (*addpp)(int,int),int x,int y){
        int cc = (*addpp)(x, y);
        return cc;
    }
    
    int add(int i, int j) {
        return i + j;
    }

    返回指针的函数

    #include<stdio.h>
    void main() {
        int* add(int i, int j);
        int *p = add(10, 4);
        printf("输出相加的值为:%d", *p);
      }
    
    int* add(int i, int j) {
        int aa = i + j;
        return &aa;//返回地址
    }

    指针数组

    一个数组其全部元素都存放着指针,就是指针数组【int * p[5];】

    #include<stdio.h>
    void main() {
        //指针数组
        char * p[] = { "dong1","xiao2","dong3","dong4" };
        printf("%s
    ", p[2]);
      }

    进阶版

    #include<stdio.h>
    void main() {
        //指针数组(字符串)
        char * p[] = { "dong1","xiao2","dong3","dong4" };
        char **pp;
        pp = p;
        printf("%s
    ", *(pp+1));//转换一次就可以拿到对应字符串的首地址通过%s打印
    
        //指针数组(整数)
        int a[5]= {10,11,12,13 };
        int * ip[] = { &a[0],&a[1],&a[2],&a[3],&a[4]};
        int **ppp = ip;
        printf("%d
    ", *(*ppp+1));//转换第一次得到存储的指针,再次转换得到值
      }

    void类型指针

    void a;//定义一个无类型变量,错误,不能确定分配的内存大小
    void *a;//定义一个无类型指针,可行,指针类型都是4个字节(32位,64位为8个字节)

    void *p;表示指针变量p不指向一个确定的类型数据,它的作用仅仅是用来存放一个地址。

    可以将任意类型的指针直接给void指针赋值,但是如果需要将void指针的赋值给其他类型的指针,则需要进行强制类型转换

    #include<stdio.h>
    
    void fun1(void *i){
      int *p=(int *)i;//强制类型转换 
      *p=100;
    }
    
    void main(){
      int ii=10;
      fun1(&ii);
      printf("%d",ii);//输出100 
    } 

    错误示范

    1、

    int *p=10; //等同于:int *p; p=10;

    分析:非法操作,内存地址不能用户自定义。10相当于一个内存地址,该内存地址的值不确定且也不明确该地址是否可以直接访问,正确的应该是使用【&变量名】得到内存地址。

    2、

    int f = 12.3;
    int *p;
    *p = &f;  //错误1
    int ff = &f; //错误2

    分析:指针(地址)必须赋值给指针变量

  • 相关阅读:
    大数加法、乘法实现的简单版本
    hdu 4027 Can you answer these queries?
    zoj 1610 Count the Colors
    2018 徐州赛区网赛 G. Trace
    1495 中国好区间 尺取法
    LA 3938 动态最大连续区间 线段树
    51nod 1275 连续子段的差异
    caioj 1172 poj 2823 单调队列过渡题
    数据结构和算法题
    一个通用分页类
  • 原文地址:https://www.cnblogs.com/dongxiaodong/p/10743246.html
Copyright © 2011-2022 走看看