C Programming: A Modern Approach

第11章 指针基础

2020-03-01  本文已影响0人  橡树人

英文原版:P241

因为指针非常重要,所以本书打算用3个章节来讲述指针相关内容:第11章讲述C语言的基础,第12章和第17章会介绍指针的高级应用

本章的主要内容

11.1节 指针变量

如何理解指针?
第一步:理解为什么需要指针?
第二步:指针是什么?
...
第n步:待补充

为什么需要指针?

指针是什么?

指针就是地址,指针变量就是存储地址的变量

基础知识补充:

概念1 变量的地址

变量的地址就是存储该变量值的首个字节的地址

例1 变量的地址:首字节的地址
假设在地址2000和2001存储着变量i的值,则i的地址就是2000。
使用指针变量p来存储变量i的地址,称作p指向i。

11.1.1节 声明指针变量

格式:

// p是一个指向int类型对象的指针变量
int *p;

C语言对指针的要求:

注意:

例1 声明指针变量1

int *p;
int i, j, a[10], b[10], *p, *q;

例2 声明指针变量2

int *p;
double *q;
char *r;

11.2节 取地址运算符和间接寻址运算符

11.2.1节 取地址运算符&

格式:

&x //该表达式的值是变量x在内存中的地址

例1 使用取地址运算符将指针变量初始化

int i, *p;
...
p = &i;

例2 在声明时将指针变量初始化

int i;
int *p = &i;

例3 将指针变量的声明和初始化放在一起

int i, *p = &i;

11.2.2节 间接寻址运算符

格式:

*p //如果p是一个指针,则*p表示p当前指向的对象,该表达式的值就是该对象的值

注意:

例1 输出变量i的值

int i, *p = &i;
...
printf("%d\n", *p);

例2 理解*p和变量i的等价关系

int i;
int *p = &i;

i = 1;
printf("%d\n", i);// 输出1
printf("%d\n", *p);// 输出1

*p = 2;
printf("%d\n", i);// 输出2
printf("%d\n", *p);// 输出2

例3 对未初始化的指针变量使用间接寻址运算符*

int *p;

printf("%d\n", *p);//可能会打印垃圾信息,导致程序崩溃或者有其他副作用

解释:
如果指针变量p还没初始化,则尝试使用p的值将导致未定义的行为。

int *p;
*p = 1;

解释:
指针变量p还没初始化,尝试给*p赋值是非常危险的。

11.3节 使用指针来赋值

C语言允许:只要左边的指针变量和右边的指针变量具有相同的类型,就可使用赋值运算符来来拷贝指针

例1 使用赋值运算符来拷贝指针

int i, j, *p, *q;

...

p = &i; //指针变量初始化

q = p; //使用指针来给指针赋值

*p = 1;

*q = 2;

例2 间接寻址运算符赋值

int i, j, *p, *q;

p = &i;
q = &j;
i = 1;

*q = *p;

11.4节 使用指针作为函数参数

例1 计算一个double数的整数部分和分数部分
函数调用

decompose(3.141519, &i, &d);

函数原型

void decompose(double x, long *int_part, double *frac_part); 

函数定义

void decompose(double x, long *int_part, double *frac_part)
{
    *int_part = (long)x;
    *frac_part = x - *int_part;
}

例2 使用指针读取整数

int i;
...
scanf("%d", &i);

或者

int i, *p;
...
p = &i;
scanf("%d", p);

注意:

如果一个函数的参数是指针类型,但调用该函数传递的却不是指针类型,则会有可怕的后果。

例3 传递非指针参数值给指针参数

decompose(3.141519, i, d);//这条语句会导致程序修改存储在未知内存地址里的数据。

程序示例:求一个数组中的最大值和最小值

源文件:maxmin.c

#include <stdio.h>

#define N 10

void max_min(int a[], int n, int *max, int *min);

int main(void)
{
    int b[N], i, big, small;

    printf("Enter %d numbers: ", N);
    for (i=0; i<N;i++) {
        scanf("%d", &b[i]);
    }

    max_min(b, N, &big, &small);

    printf("Largest: %d\n", big);
    printf("Smallest: %d\n", small);

    return 0;
}

void max_min(int a[], int n, int *max, int *min)
{
    int i;

    *max = *min = a[0];
    for(i=1; i<N; i++){
        if(a[i]>*max) {
            *max = a[i];
        }else {
            *min = a[i];
        }
    }
}

11.5节 指针作为函数返回值

注意:永远不要返回指向局部变量的指针作为返回值

例1 错误示例:返回指向局部变量的指针作为返回值

int * f(void)
{
  int i;
  ...
  return &i;
}

编译器会发出警告:函数返回了局部变量的地址

例2 返回值是指向int类型的指针
函数调用

int i, j, *p;
...
p = max(&i, &j);

函数定义

int *max(int *a, int *b)
{
  if (*a > *b) {
    return a;
  }else {
    return b;
  }
}

例3 返回指向数组元素的指针作为返回值

int *find_middle(int a[], int n)
{
  return &a[n/2];
}
上一篇 下一篇

猜你喜欢

热点阅读