• C指针那点事儿


    • 指针: 用来存放变量地址的变量,就成为"指针变量".

    • 定义: 一般形式:类名标识符 *指针变量名;

      int *p;
      float *q;
      
    • "*"是说明符,用来说明这个变量是个指针变量,是不能省略的,但不属于变量名的一部分

    • 前面的类型标志符表示指针变量所只想的变量的类型,而且只能指向这种类型的变量

    示例1:值交换

     ```c
     void swap(char *v1, char *v2) {
    // 中间变量
    char temp;
    
    // 取出v1指向的变量的值
    temp = *v1;
    
    // 取出v2指向的变量的值,然后赋值给v1指向的变量
    *v1 = *v2;
    
    // 赋值给v2指向的变量
    *v2 = temp;
    }
    int main()
    {
    char a = 10, b = 9;
    printf("更换前:a=%d, b=%d
    ", a, b);
    
    swap(&a, &b);
    
    printf("更换后:a=%d, b=%d", a, b);
    return 0;
    }
    
    ``` 
    

    示例2:函数多个返回值

    ```c
    
       // 计算2个整型的和与差
        int sumAndMinus(int v1, int v2, int *minus) {
        // 计算差,并赋值给指针指向的变量
        *minus = v1 - v2;
    
    // 计算和,并返回和
        return v1 + v2;
        }
        int main()
        {
        // 定义2个int型变量
        int a = 6, b = 2;
    
        // 定义2个变量来分别接收和与差
        int sum, minus;
    
        // 调用函数
        sum = sumAndMinus(a, b, &minus);
    
        // 打印和
        printf("%d+%d=%d
    ", a, b, sum);
    
        // 打印差
        printf("%d-%d=%d
    ", a, b, minus);
        return 0;
        }
    
     ```
    

    示例3:用指针遍历字符串

    // 定义一个指针p
    char *p;
    
    // 定义一个数组s存放字符串
    char s[] = "mj";
    
    // 指针p指向字符串的首字符'm'
    p = s; // 或者 p = &s[0];
    
    for (; *p != ''; p++) {
        printf("%c 
    ", *p);
    }
    
    

    指针也是C语言中的一种数据类型,因此一个函数的返回值肯定可以是指针类型的。
    返回指针的函数的一般形式为:类型名 * 函数名(参数列表)

    示例4:比如下面这个函数,返回一个指向char类型变量的指针

     ```c
    
    // 将字符串str中的小写字母变成大写字母,并返回改变后的字符串
    // 注意的是:这里的参数要传字符串变量,不能传字符串常量
    char * upper(char *str) {
    // 先保留最初的地址。因为等会str指向的位置会变来变去的。
    char *dest = str;
    
    // 如果还不是空字符
    while (*str != '') {
        // 如果是小写字母
        if (*str >= 'a' && *str <= 'z') {
            // 变为大写字母。小写和大写字母的ASCII值有个固定的差值
            *str -= 'a' - 'A';
        }
        
        // 遍历下一个字符
        str++;
    }
    
    // 返回字符串
    return dest;
    }
    
    
    
    > **_指向函数的指针_**函数作为一段程序,在内存中也要占据部分存储空间,它也有一个起始地址,即函数的入口地址。函数有自己的地址,那就好办了,我们的指针变量就是用来存储地址的。因此,可以利用一个指针指向一个函数。其中,函数名就代表着函数的地址。
    定义的一般形式:函数的返回值类型 (*指针变量名)(形式参数1, 形式参数2, ...);
    
    ```c
    #include <stdio.h>
    
    int sum(int a, int b) {
       return a + b;
    }
    
    int main()
    {
       // 定义一个指针变量p,指向sum函数
       int (*p)(int a, int b) = sum;
       // 或者 int (*p)(int, int) = sum;
       // 或者 int (*p)() = sum;
       
       // 利用指针变量p调用函数
       int result = (*p)(1, 3);
       // 或者 int result = p(1, 3);
       
       printf("%d", result);
       return 0;
    }
    

    指向指针的函数注意

    1> 由于这类指针变量存储的是一个函数的入口地址,所以对它们作加减运算(比如p++)是无意义的。难道p++就会指向下一个函数了?可笑至极!!没这回事。

    2> 返回指针的函数的定义char *upper(char *str) 和 指向函数的指针的定义int ( *p)(int a, int b)非常相似,使用时特别注意区分

    3> 指向函数的指针变量主要有两个用途:

    调用函数

    将函数作为参数在函数间传递。我这么一说,可能还不是很明白,举个例子。

    #include <stdio.h>
    
    // 减法运算
    int minus(int a, int b) {
        return a - b;
    }
    
    // 加法运算
    int sum(int a, int b) {
        return a + b;
    }
    
    // 这个counting函数是用来做a和b之间的计算,至于做加法还是减法运算,由函数的第1个参数决定
    void counting( int (*p)(int, int) , int a, int b) {
        int result = p(a, b);
        printf("计算结果为:%d
    ", result);
    }
    
    int main()
    {
        // 进行加法运算
        counting(sum, 6, 4);
        
        // 进行减法运算
        counting(minus, 6, 4);
        
        return 0;
    }
    
    • 每个结构体变量都有自己的存储空间和地址,因此指针也可以指向结构体变量

    • 结构体指针变量的定义形式:struct 结构体名称 *指针变量名

    • 有了指向结构体的指针,那么就有3种访问结构体成员的方式

    结构体变量名.成员名
    (*指针变量名).成员名
    指针变量名->成员名

    #include <stdio.h>
    
    int main(int argc, const char * argv[]) {
        // 定义一个结构体类型
        struct Student {
            char *name;
            int age;
        };
        
        // 定义一个结构体变量
        struct Student stu = {"MJ", 27};
        
        // 定义一个指向结构体的指针变量
        struct Student *p;
        
        // 指向结构体变量stu
        p = &stu;
    
        /*
         这时候可以用3种方式访问结构体的成员
         */
        // 方式1:结构体变量名.成员名
        printf("name=%s, age = %d 
    ", stu.name, stu.age);
        
        // 方式2:(*指针变量名).成员名
        printf("name=%s, age = %d 
    ", (*p).name, (*p).age);
        
        // 方式3:指针变量名->成员名
        printf("name=%s, age = %d 
    ", p->name, p->age);
        
        return 0;
    }
    
    
  • 相关阅读:
    go笔记 (异或交换两个数字变量需要注意的问题)
    java子线程中获取父线程的threadLocal中的值
    关于java线程池的线程废弃与存活条件分析
    .net实现上传图片到共享目录(远程服务器)
    .net 获取两个时间段中间的日期
    ASP .NET数据写入oracle数据库
    MySql定时插入数据
    Sitecore8.2 .net Solr搜索实现
    .net 盘古分词
    json_3层格式_数据源DataSet
  • 原文地址:https://www.cnblogs.com/jiahao89/p/6100035.html
Copyright © 2020-2023  润新知