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\n", 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\n", a, b, sum);

    // 打印差
    printf("%d-%d=%d\n", a, b, minus);
    return 0;
    }

 ```

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

// 定义一个指针p
char *p;

// 定义一个数组s存放字符串
char s[] = "mj";

// 指针p指向字符串的首字符'm'
p = s; // 或者 p = &s[0];

for (; *p != '\0'; p++) {
    printf("%c \n", *p);
}

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

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

 ```c

// 将字符串str中的小写字母变成大写字母,并返回改变后的字符串
// 注意的是:这里的参数要传字符串变量,不能传字符串常量
char * upper(char *str) {
// 先保留最初的地址。因为等会str指向的位置会变来变去的。
char *dest = str;

// 如果还不是空字符
while (*str != '\0') {
    // 如果是小写字母
    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\n", 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 \n", stu.name, stu.age);
    
    // 方式2:(*指针变量名).成员名
    printf("name=%s, age = %d \n", (*p).name, (*p).age);
    
    // 方式3:指针变量名->成员名
    printf("name=%s, age = %d \n", p->name, p->age);
    
    return 0;
}

posted @ 2016-11-24 23:41  家号  阅读(360)  评论(3编辑  收藏  举报