C 语言编程教程

C 语言 - 首页

C 语言基础

C 语言 - 概述 C 语言 - 特性 C 语言 - 发展历史 C 语言 - 环境设置 C 语言 - 程序结构 C 语言 - Hello World C - 编译过程 C - 注释 C - 标记 C - 关键字 C - 标识符 C - 用户输入 C - 基本语法 C - 数据类型 C - 变量 C - 整数提升 C - 类型转换 C - 类型转换 C - 布尔值

C 语言中的常量和文字

C - 常量 C - 字面量 C - 转义序列 C - 格式说明符

C 语言中的运算符

C - 运算符 C - 算术运算符 C - 关系运算符 C - 逻辑运算符 C - 位运算符 C - 赋值运算符 C - 一元运算符 C - 递增和递减运算符 C - 三元运算符 C - sizeof 运算符 C - 运算符优先级 C - 其他运算符

C 语言中的决策

C - 决策 C - if 语句 C - if...else 语句 C - 嵌套 if 语句 C - switch 语句 C - 嵌套 switch 语句

C 语言中的循环

C - 循环 C - While 循环 C - For 循环 C - Do...while 循环 C - 嵌套循环 C - 无限循环 C - Break 语句 C - Continue 语句 C - goto 语句

C 语言中的函数

C - 函数 C - Main 函数 C - 按值调用函数 C - 按引用调用函数 C - 嵌套函数 C - 可变参数函数 C - 用户定义函数 C - 回调函数 C - return 语句 C - 递归

C 语言中的作用域规则

C - 作用域规则 C - 静态变量 C - 全局变量

C 语言中的数组

C - 数组 C - 数组的属性 C - 多维数组 C - 将数组传递给函数 C - 从函数返回数组 C - 可变长度数组

C 语言中的指针

C - 指针 C - 指针和数组 C - 指针的应用 C - 指针运算 C - 指针数组 C - 指向指针的指针 C - 将指针传递给函数 C - 从函数返回指针 C - 函数指针 C - 指向数组的指针 C - 指向结构体的指针 C - 指针链 C - 指针 vs 数组 C - 字符指针和函数 C - NULL 指针 C - void 指针 C - 悬垂指针 C - 解引用指针 C - Near、Far 和 Huge 指针 C - 指针数组的初始化 C - 指针与多维数组

C 语言中的字符串

C - 字符串 C - 字符串数组 C - 特殊字符

C 语言的结构体和联合

C - 结构体 C - 结构体和函数 C - 结构体数组 C - 自引用结构 C - 查找表 C - 点 (.) 运算符 C - 枚举(或 enum) C - 结构填充和打包 C - 嵌套结构 C - 匿名结构和联合 C - 联合 C - Bit 位字段 C - Typedef

C 语言中的文件处理

C - 输入和输出 C - 文件 I/O(文件处理)

C 语言中的预处理器

C - 预处理器 C - #pragma 编译指示 C - 预处理器操作符 C - 宏 C - 头文件

C 语言中的内存管理

C - 内存管理 C - 内存地址 C - 存储类

C 其他主题

C - 错误处理 C - 可变参数 C - 命令执行 C - 数学函数 C - static 静态关键字 C - 随机数生成 C - 命令行参数

C 语言编程资源

C语言问题与解答答案 C语言快速指南 C语言速查表 C语言实用资源 C语言讨论


C 语言中的指针

C 语言中的指针是什么?

C 语言指针是一种派生数据类型,用于存储另一个变量的地址,也可用于访问和操作存储在该位置的变量数据。指针被视为派生数据类型。

使用指针,您可以访问和修改内存中的数据,在函数之间高效地传递数据,以及创建动态数据结构,例如链表、树和图。

指针声明

要声明指针,请使用解引用运算符 (*),后跟数据类型。

语法

指针变量声明的一般形式为:-

type *var-name;

此处,type 是指针的基类型;它必须是有效的 C 数据类型var-name 是指针变量的名称。用于声明指针的星号 * 与用于乘法的星号相同。然而,在此语句中,星号被用来将变量指定为指针。

有效指针变量声明示例

查看一些有效的指针声明 −

int *ip; 	/* 指向整数的指针 */
double *dp; /* 指向双精度数的指针 */
float *fp; 	/* 指向浮点数的指针 */
char *ch 	/* 指向字符的指针 */

所有指针(无论是整数、浮点数、字符型还是其他类型)的实际数据类型都是相同的,即一个表示内存地址的长十六进制数。不同数据类型的指针之间的唯一区别在于指针指向的变量常量的数据类型。

指针初始化

声明指针变量后,需要使用取地址 (&) 运算符,用另一个变量的地址初始化该指针变量。此过程称为引用指针

语法

以下是初始化指针变量的语法

pointer_variable = &variable;

示例

以下是指针初始化的示例

int x = 10;
int *ptr = &x;

这里,x 是一个整型变量,ptr 是一个整型指针。指针 ptr 正在使用 x 初始化。

引用和解除引用指针

指针引用内存中的某个位置。获取存储在该位置的值称为解除引用指针

在 C 语言中,理解指针机制中以下两个运算符的用途非常重要 -

  • & 运算符 - 也称为"取地址运算符"。它用于引用,即获取现有变量的地址(使用 &)来设置指针变量。
  • * 运算符 − 也称为"取消引用运算符"。取消引用 指针是使用 * 运算符 从指针指向的内存地址获取值来实现的。

指针用于通过引用传递参数。如果程序员希望函数对参数的修改对函数调用者可见,则这非常有用。这对于从函数返回多个值也很有用。

使用指针访问和操作值

可以使用指针变量访问和操作指针指向的变量的值。您需要使用星号 (*) 和指针变量来访问和操作变量的值。

示例

在下面的示例中,我们将一个整数变量及其初始值更改为新值。

#include <stdio.h>

int main() {
    int x = 10;
    
    // 指针声明和初始化
    int * ptr = & x;
    
    // 打印当前值
    printf("Value of x = %d
", * ptr);

    // 更改值
    * ptr = 20;
    
    // 打印更新后的值
    printf("Value of x = %d
", * ptr);

  return 0;
}

输出

Value of x = 10
Value of x = 20

如何使用指针?

要在 C 语言中使用指针,您需要声明一个指针变量,然后用另一个变量的地址对其进行初始化,然后可以通过解引用来获取和更改指针指向的变量的值。

您可以将指针用于任何类型的变量,例如整数、浮点数、字符串等。您还可以将指针用于派生数据类型,例如数组结构联合等。

示例

在下面的示例中,我们使用指针获取不同类型变量的值。

#include <stdio.h>

int main() {
  int x = 10;
  float y = 1.3f;
  char z = 'p';

  // 指针声明和初始化
  int * ptr_x = & x;
  float * ptr_y = & y;
  char * ptr_z = & z;

  // 打印值
  printf("Value of x = %d
", * ptr_x);
  printf("Value of y = %f
", * ptr_y);
  printf("Value of z = %c
", * ptr_z);
  
  return 0;
}

输出

Value of x = 10
Value of y = 1.300000
Value of z = p

指针变量的大小

指针变量占用的内存(或大小)与其指向的变量类型无关。指针的大小取决于系统架构。

示例

在下面的示例中,我们将打印不同类型指针的大小:

#include <stdio.h>

int main() {
  int x = 10;
  float y = 1.3f;
  char z = 'p';

  // 指针声明和初始化
  int * ptr_x = & x;
  float * ptr_y = & y;
  char * ptr_z = & z;

  // 打印指针变量的大小
  printf("Size of integer pointer : %lu
", sizeof(ptr_x));
  printf("Size of float pointer : %lu
", sizeof(ptr_y));
  printf("Size of char pointer : %lu
", sizeof(ptr_z));
  
  return 0;
}

输出

Size of integer pointer : 8
Size of float pointer : 8
Size of char pointer : 8

C 语言指针示例

练习以下示例以学习指针的概念

示例 1:在 C 语言中使用指针

以下示例展示了如何在 C 语言中使用 &* 运算符执行与指针相关的操作 -

#include <stdio.h>

int main(){

    int var = 20; 	/* 实际变量声明 */
    int *ip; 		/* 指针变量声明 */
    
    ip = &var; 		/* 将 var 的地址存储在指针变量中*/

   printf("Address of var variable: %p
", &var);

   /* 指针变量中存储的地址 */
   printf("Address stored in ip variable: %p
", ip);

   /* 使用指针访问值 */
   printf("Value of *ip variable: %d
", *ip );

   return 0;
}

输出

执行代码并检查其输出 −

Address of var variable: 0x7ffea76fc63c
Address stored in ip variable: 0x7ffea76fc63c
Value of *ip variable: 20

示例:打印整数的值和地址

我们将声明一个 int 变量并显示其值和地址 -

#include <stdio.h>

int main(){

   int var = 100;
   
   printf("Variable: %d 	 Address: %p", var, &var);
   
   return 0;   
}

输出

运行代码并检查其输出 −

Variable: 100   Address: 0x7ffc62a7b844

示例:整数指针

在本例中,var 的地址通过 & 运算符存储在 intptr 变量中

#include <stdio.h>

int main(){

   int var = 100;
   int *intptr = &var;
   
   printf("Variable: %d 
Address of Variable: %p 
", var, &var);
   printf("intptr: %p 
Address of intptr: %p 
", intptr, &intptr);
   
   return 0;
}

输出

运行代码并检查其输出 −

Variable: 100 
Address of Variable: 0x7ffdcc25860c 

intptr: 0x7ffdcc25860c 
Address of intptr: 0x7ffdcc258610 

示例 5

现在我们以浮点变量为例,查找其地址 -

#include <stdio.h>

int main(){

   float var1 = 10.55;
   
   printf("var1: %f 
", var1);
   printf("Address of var1: %d", &var1);
}

输出

运行代码并检查其输出 −

var1: 10.550000 
Address of var1: 1512452612

我们可以看到,这个变量(任何类型的变量)的地址都是整数。因此,如果我们尝试将其存储在"浮点"类型的指针变量中,看看会发生什么 -

float var1 = 10.55;
int *intptr = &var1;

编译器不接受这种情况,并报告以下错误 -

从不兼容的指针类型"float *"初始化"int *" [-Wincompatible-pointer-types]

注意:变量的类型和其指针的类型必须相同。

在 C 语言中,变量具有特定的数据类型,用于定义其大小以及存储值的方式。使用匹配类型(例如 float *)声明指针会强制指针与其指向的数据之间保持"类型兼容性"。

在 C 语言中,不同的数据类型占用不同的内存空间。例如,"int"通常占用 4 个字节,而"float"则可能占用 4 个或 8 个字节,具体取决于系统。对指针进行整数加减操作会根据其指向的数据的大小在内存中移动指针。

示例:浮点指针

在此示例中,我们声明一个"float *"类型的变量"floatptr"。

#include <stdio.h>

int main(){

   float var1 = 10.55;
   float *floatptr = &var1;
   
   printf("var1: %f 
Address of var1: %p 
",var1, &var1);
   printf("floatptr: %p 
Address of floatptr: %p 
", floatptr, &floatptr);
   printf("var1: %f 
Value at floatptr: %f", var1, *floatptr);
   
   return 0;
}

输出

var1: 10.550000 
Address of var1: 0x7ffc6daeb46c 

floatptr: 0x7ffc6daeb46c 
Address of floatptr: 0x7ffc6daeb470 

指向指​​针的指针

我们可能有一个指针变量,它存储另一个指针本身的地址。

指针变量

在上图中,"a"是一个普通的"int"变量,其指针指向"x"。反过来,该变量存储"x"的地址。

请注意,"y"被声明为"int **",以指示它是指向另一个指针变量的指针。显然,"y"将返回"x"的地址,"*y"是"x"中的值(即"a"的地址)。

要从"y"获取"a"的值,我们需要使用表达式"**y"。通常,"y"将被称为指向指针的指针

示例

请看以下示例 -

#include <stdio.h>

int main(){

   int var = 10;
   int *intptr = &var;
   int **ptrptr = &intptr;
   
   printf("var: %d 
Address of var: %d 
",var, &var);
   printf("inttptr: %d 
Address of inttptr: %d 
", intptr, &intptr);
   printf("var: %d 
Value at intptr: %d 
", var, *intptr);
   printf("ptrptr: %d 
Address of ptrtptr: %d 
", ptrptr, &ptrptr);
   printf("intptr: %d 
Value at ptrptr: %d 
", intptr, *ptrptr);
   printf("var: %d 
*intptr: %d 
**ptrptr: %d", var, *intptr, **ptrptr);
   
   return 0;
}

输出

运行代码并检查其输出 −

var: 10 
Address of var: 951734452 

inttptr: 951734452 
Address of inttptr: 951734456 

var: 10 
Value at intptr: 10 

ptrptr: 951734456 
Address of ptrtptr: 951734464 
intptr: 951734452 
Value at ptrptr: 951734452 

var: 10 
*intptr: 10 
**ptrptr: 10

您可以使用指向数组的指针,也可以使用struct定义的派生类型。指针具有重要的应用。它们在通过传递引用来调用函数时使用。指针还有助于克服函数只能返回单个值的限制。使用指针,您可以实现返回多个值或数组的效果。

NULL 指针

如果没有要分配的确切地址,最好将 NULL 值赋给指针变量。这在变量声明时完成。被赋值为 NULL 的指针称为指针。

NULL 指针是一个常量,其值为"0",在多个标准库中都有定义。

示例

考虑以下程序 -

#include <stdio.h>

int main(){

   int *ptr = NULL;

   printf("The value of ptr is : %x
", ptr);
 
   return 0;
}

输出

当编译并执行上述代码时,它会产生以下结果 -

The value of ptr is 0

在大多数操作系统中,程序不允许访问地址"0"处的内存,因为该内存由操作系统保留。

内存地址"0"具有特殊含义;它表示指针不打算指向可访问的内存位置。但按照惯例,如果指针包含空值(零),则假定它指向空。

要检查是否为空指针,可以使用 if 语句,如下所示 -

if(ptr) 	/* 如果 p 不为空,则执行成功 */
if(!ptr) 	/* 如果 p 为空,则执行成功 */

变量的地址

众所周知,每个变量都是一个内存位置,每个内存位置都有其定义的地址,可以使用 & 运算符访问,该运算符表示内存中的地址。

示例

考虑以下示例,该示例打印已定义变量的地址 -

#include <stdio.h>

int main(){

   int  var1;
   char var2[10];

   printf("Address of var1 variable: %x
", &var1);
   printf("Address of var2 variable: %x
", &var2);

   return 0;
}

输出

当上述代码被编译并执行时,它将打印变量的地址 -

Address of var1 variable: 61e11508
Address of var2 variable: 61e1150e

指针详解

指针的概念很多,但都很简单,它们对 C 语言编程至关重要。以下重要的指针概念对于任何 C 程序员来说都应该清楚 -

序号 概念 &说明
1 指针运算

指针可以使用四种运算运算符:++、--、+、-

2 指针数组

您可以定义数组来保存多个指针。

3 指向指针的指针

C 语言允许将指针指向指针,因此开启。

4 在 C 语言中向函数传递指针

通过引用或地址传递参数,被调用函数可以在调用函数中更改传递的参数。

5 在 C 语言中从函数返回指针

C 语言允许函数返回指向局部变量、静态变量以及动态分配内存的指针。