回到首页 / 上级目录

指针

指针是 C 语言的一个亮点。

指针用于记录某个存储单元的地址。

定义

指针的定义、使用如下:

int a = 100;      // 定义变量 a
int *p = &a;      // 定义指针 p 并指向 a
printf("%X", p);  // 以十六进制格式输出 p 的内容,即 a 的地址
printf("%d", *p); // 输出 a 的内容,即 p 所执行的变量的内容 

// 将指针作为函数参数
void swap(int *p1, int *p2) {
    int temp;
    temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}

数组遍历

指针可以用在数组中,如:

int a[4] = {1, 2, 3, 4}; // 定义数组 a
int *p = a;              // 此时 p 指向 a[0]
p ++;                    // 此时 p 指向 a[1]

// 通过指针遍历数组
for (p = a; p < (a + 4); p ++)
    scanf("%d", *p); 

用数组名做参数,等价于用指针做参数,如下两段代码作用是等价的:

// 用数组名做参数
void func(int a[], int n);

// 用指针做参数
int *p = a;
void func(int *p, int n);

指针也可以遍历二维数组,如:

int a[3][3] = {    // 二维数组
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};
int (*p)[3] = a;   // 指向一维数组的指针变量,注意不是指针数组
for (int i = 0; i < 3; i ++) {
    printf("%d\n", *p[i]);
}

引用字符串

指针可以用来引用字符串,如:

char *s = "Hello!";

函数指针

函数名记录着函数的起始地址,可通过函数名调用函数。

由于指针用来记录地址,因此函数也可以用函数指针进行调用,如:

// 定义一个函数 max
int max(int x, int y) {
    return (x > y) ? x : y;
}
int (*p)(int, int) = max; // 定义函数指针指向 max 函数
c = (*p)(a, b);           // 通过函数指针调用函数

指针可以作为函数参数,因此函数指针可以作为函数的参数和返回值。

例如 malloc 库函数:

void *malloc(unsigned int size);

指针数组

指针数组是元素都是指针类型的数组。定义和使用如下:

char *name[] = {"Hello", "World"}; // 定义有 2 个元素的指针数组
printf("%s", name[0]);             // 输出第 1 个元素

二维指针

二维指针是指向一个指针变量的指针。如:

char *name[] = {"Hello", "World"};
char **p = name[0];

指针应用场景

指针在主函数中常作为形参出现,如:

int main(int argc, char *argv[])

其中 argc 是参数的个数,argv 是参数数组,每个元素都是字符串。

main 函数由操作系统调用,参数在命令行中给出。

内存的动态分配也涉及指针,相应的系统库函数包括:

void *malloc(unsigned int size);           // 开辟 size 字节的连续空间
void *calloc(unsigned n, unsigned size);   // 开辟 n 个长度为 size 的连续空间
void *realloc(void *p, unsigned int size); // 重新分配以 p 开头的连续空间
void free(void *p);                        // 释放以 p 开头的连续空间