C 指针

本文介绍了 C 语言中的指针,以及如何使用指针和使用指针过程中常见的错误,并提供了有效的示例。

指针是 C 和 C++ 中的强大功能。在我们学习指针之前,让我们先了解一下 C 语言中的内存地址的概念。

C 中的地址

在 C 语言中,假设在你的程序中有一个变量 var, 那么 &var 会指向变量 var 对应的内存地址。

我们在使用 scanf() 函数时多次使用过地址。

scanf("%d", &var);

这里,用户输入的值存储在 var 变量中。让我们举一个示例:

#include <stdio.h>
int main()
{
  int var = 5;
  printf("var: %d\n", var);

  // Notice the use of & before var
  printf("address of var: %p", &var);
  return 0;
}

输出

var: 5
address of var: 2686778

! **注意:**当您运行上述代码时,您可能会得到一个不同的地址。

C 指针

指针(指针变量)是一种特殊的变量,用于存储地址而不是值。

指针语法

声明指针的方式如下:

int* p;

在这里,我们声明了一个 int 类型的指针 p

我们还可以通过这些方式声明指针:

int *p1;
int * p2;

让我们再举一个声明指针的例子:

int* p1, p2;

在这里,我们声明了一个指针 p1 和一个正常的变量 p2

为指针分配地址

让我们举个例子。

int* pc, c;
c = 5;
pc = &c;

这里,5 被分配给 c 变量。而且,c 变量的地址被分配给 pc 指针。

获取指针指向地址中的值

为了获取指针指向地址中的值,我们需要使用了 * 操作符。例如:

int* pc, c;
c = 5;
pc = &c;
printf("%d", *pc);   // Output: 5

在这里,变量 c 的地址被分配给 pc 指针。为了获取存储在该地址中的值,我们需要使用 *pc

**注意:**在上面的例子中, pc 是一个指针, *pc 不是指针。你不应该也不能这样做: *pc = &c

顺便说一下, * 称为解引用运算符(使用指针时)。它解析指针引用,并返回存储在指针指向内存地址中的值。

改变指针指向的值

让我们举个例子。

int* pc, c;
c = 5;
pc = &c;
c = 1;
printf("%d", c);    // Output: 1
printf("%d", *pc);  // Ouptut: 1

我们将 pc 指针赋值为变量 c 的地址。

然后,我们将变量 c 的值改为 1, 由于 pc 指向的就是变量 c 的地址,因此 *pc 的值为 1

让我们再举一个例子。

int* pc, c;
c = 5;
pc = &c;
*pc = 1;
printf("%d", *pc);  // Ouptut: 1
printf("%d", c);    // Output: 1

我们将 pc 指针赋值为变量 c 的地址。

然后,我们使用 *pc = 1; 将对应的地址的值改为 1。 由于 pc 指向的就是变量 c 的地址,因此 c 的值为 1

让我们再举一个例子。

int* pc, c, d;
c = 5;
d = -15;

pc = &c;
printf("%d", *pc); // Output: 5
pc = &d;
printf("%d", *pc); // Ouptut: -15

开始我们将 pc 指针赋值为变量 c 的地址,因此 *pc 的值为 5

然后我们将 pc 指针赋值为变量 d 的地址,因此 *pc 的值为 -15

示例:指针的原理

我们通过下面的示例了解指针的工作原理。

#include <stdio.h>
int main()
{
   int* pc, c;

   c = 22;
   printf("Address of c: %p\n", &c);
   printf("Value of c: %d\n\n", c);  // 22

   pc = &c;
   printf("Address of pointer pc: %p\n", pc);
   printf("Content of pointer pc: %d\n\n", *pc); // 22

   c = 11;
   printf("Address of pointer pc: %p\n", pc);
   printf("Content of pointer pc: %d\n\n", *pc); // 11

   *pc = 2;
   printf("Address of c: %p\n", &c);
   printf("Value of c: %d\n\n", c); // 2
   return 0;
}

输出

Address of c: 2686784
Value of c: 22

Address of pointer pc: 2686784
Content of pointer pc: 22

Address of pointer pc: 2686784
Content of pointer pc: 11

Address of c: 2686784
Value of c: 2

程序说明

  1. int* pc, c;

    创建一个指针变量和一个普通变量。

    在这里,创建了一个 int 类型的指针变量 pc 和一个 int 类型的正常变量 c。但,这两个变量都没有赋值。

  2. c = 22;

    22 赋值给变量 c

    将变量 c 赋值为 22, 即 22 存放在变量 c 的内存位置。

  3. pc = &c;

    变量 c 的地址被赋值给指针 pc

    现在,将指针 pc 指向了变量 c 的内存地址。

  4. c = 11;

    11 赋值给给变量 c

    将变量 c 赋值为 11

  5. *pc = 2;

    指针变量的地址中的值改为 2

    现在指针 pc 指向的内存地址的值变成了 2。即,变量 c 的地址变成了 2

使用指针时的常见错误

假设,你想要指针 pc 指向变量 c 的地址,然后,

int c, *pc;

// pc 是地址, c 不是
pc = c; // 错误

// &c 是地址, *pc  不是
*pc = &c; // 错误

//  &c and pc 都是地址
pc = &c;

//  c and *pc 都是值
*pc = c;

下面是一个指针语法初学者经常感到困惑的例子。

#include <stdio.h>
int main() {
   int c = 5;
   int *p = &c;

   printf("%d", *p);  // 5
   return 0;
}

为什么我们在使用时没有收到错误 int *p = &c;

这是因为

int *p = &c;

相当于

int *p:
p = &c;

在这两种情况下,我们创建了一个指针 p 并赋值为 &c

为了避免这种混淆,我们可以使用这样的语句:

int* p = &c;

现在我们已经了解了什么是指针,下一个教程中我们将要学习指针与数组的关系