Cprogramming 简明教程

Pointers in C

What is a Pointer in C?

C 指针是派生数据类型,用于存储其他变量的地址,还可以用来访问和操控在该位置存储的变量数据。指针被视为派生数据类型。

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

Pointer Declaration

若要声明一个指针,请使用 dereferencing operator ( )*后跟数据类型。

Syntax

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

type *var-name;

在此处, type 是指示器的基本类型;它必须是一个有效的 C data type ,而 var-name 是指示器变量的名称。用于声明指向器的星号 * 与用于乘法的星号相同。然而,在此声明中,星号用于将变量指定为一个指向器。

Example of Valid Pointer Variable Declarations

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

int    *ip;    /* pointer to an integer */
double *dp;    /* pointer to a double */
float  *fp;    /* pointer to a float */
char   *ch     /* pointer to a character */

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

Pointer Initialization

声明一个指针变量后,您需要使用 address of (&) operator 将其初始化为另一个变量的地址。此过程称为 referencing a pointer

Syntax

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

pointer_variable = &variable;

Example

以下是一个指针初始化的示例 −

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

此处,x 是一个整数变量,ptr 是一个整数指针。指针 ptr 正在用 x 初始化。

Referencing and Dereferencing Pointers

指针引用内存中的位置。从该存储位置获取存储值的过程称为 dereferencing the pointer

在 C 中,了解以下两个运算符在指针机制中的目的是很重要的 −

  1. The & Operator − 它还称为“取地址运算符”。用于引用,表示使用 & 获取现有变量的地址以设置指针变量。

  2. The * Operator − 它还被称为“解引用运算符”。使用 * operator 解引用一个指针,以从指向器指向的内存地址获取值。

指针用于按引用传递参数。如果程序员希望某个函数对参数的修改对函数的调用者可见,则该函数非常有用。此功能还可以从函数返回多个值。

Access and Manipulate Values using Pointer

可以访问和操作由指针指向的变量的值,方法是使用指针变量。您需要在指针变量中使用星号 (*) 符号来访问和操作变量的值。

Example

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

#include <stdio.h>

int main() {
  int x = 10;

  // Pointer declaration and initialization
  int * ptr = & x;

  // Printing the current value
  printf("Value of x = %d\n", * ptr);

  // Changing the value
  * ptr = 20;

  // Printing the updated value
  printf("Value of x = %d\n", * ptr);

  return 0;
}
Value of x = 10
Value of x = 20

How to Use Pointers?

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

您可以将指向器用于任何类型的变量,例如整数、浮点数、字符串等。您还可以将指向器用于导出数据类型,例如 arraystructureunion 等。

Example

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

#include <stdio.h>

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

  // Pointer declaration and initialization
  int * ptr_x = & x;
  float * ptr_y = & y;
  char * ptr_z = & z;

  // Printing the values
  printf("Value of x = %d\n", * ptr_x);
  printf("Value of y = %f\n", * ptr_y);
  printf("Value of z = %c\n", * ptr_z);

  return 0;
}
Value of x = 10
Value of y = 1.300000
Value of z = p

Size of a Pointer Variable

指针变量所占据的内存(或大小)并不取决于其所指向变量的类型。指针的大小取决于系统架构。

Example

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

#include <stdio.h>

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

  // Pointer declaration and initialization
  int * ptr_x = & x;
  float * ptr_y = & y;
  char * ptr_z = & z;

  // Printing the size of pointer variables
  printf("Size of integer pointer : %lu\n", sizeof(ptr_x));
  printf("Size of float pointer : %lu\n", sizeof(ptr_y));
  printf("Size of char pointer : %lu\n", sizeof(ptr_z));

  return 0;
}
Size of integer pointer : 8
Size of float pointer : 8
Size of char pointer : 8

Examples of C Pointers

练习以下示例以了解指针的概念 -

Example 1: Using Pointers in C

以下示例演示如何在 C 中使用 &* 操作符执行与指针相关的操作 −

#include <stdio.h>

int main(){

   int  var = 20;   /* actual variable declaration */
   int  *ip;        /* pointer variable declaration */

   ip = &var;   /* store address of var in pointer variable*/

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

   /* address stored in pointer variable */
   printf("Address stored in ip variable: %p\n", ip);

   /* access the value using the pointer */
   printf("Value of *ip variable: %d\n", *ip );

   return 0;
}

执行代码并检查其输出 −

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

Example: Print Value and Address of an Integer

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

#include <stdio.h>

int main(){

   int var = 100;

   printf("Variable: %d \t Address: %p", var, &var);

   return 0;
}

运行代码并检查其输出:

Variable: 100   Address: 0x7ffc62a7b844

Example: Integer Pointer

在此示例中, var 的地址存储在 intptr 变量中,使用 & 操作符

#include <stdio.h>

int main(){

   int var = 100;
   int *intptr = &var;

   printf("Variable: %d \nAddress of Variable: %p \n\n", var, &var);
   printf("intptr: %p \nAddress of intptr: %p \n\n", intptr, &intptr);

   return 0;
}

运行代码并检查其输出:

Variable: 100
Address of Variable: 0x7ffdcc25860c

intptr: 0x7ffdcc25860c
Address of intptr: 0x7ffdcc258610

Example 5

现在让我们举一个 float 变量的示例并查找其地址 −

#include <stdio.h>

int main(){

   float var1 = 10.55;

   printf("var1: %f \n", var1);
   printf("Address of var1: %d", &var1);
}

运行代码并检查其输出:

var1: 10.550000
Address of var1: 1512452612

我们可以看到该变量的地址(就该问题而言,任何类型的变量)都是一个整数。因此,如果我们尝试将其存储在 "float" 类型的指针变量中,看看会发生什么 −

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

编译器不接受它,并报告以下 error

initialization of 'int *' from incompatible pointer type
'float *' [-Wincompatible-pointer-types]

Note: 变量的类型及其指针的类型必须相同。

在 C 中,变量具有定义其大小和存储值方式的特定数据类型。使用匹配类型(例如 float *)声明指针会在指针和它所指向的数据之间强加 “类型兼容性”。

在 C 中,不同的数据类型占据不同的内存空间。例如,“int” 通常占用 4 个字节,而 “float” 可能占用 4 或 8 个字节,具体取决于系统。对指针进行整数加法或减法会将它们基于它们所指向数据的尺寸在内存中移动。

Example: Float Pointer

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

#include <stdio.h>

int main(){

   float var1 = 10.55;
   float *floatptr = &var1;

   printf("var1: %f \nAddress of var1: %p \n\n",var1, &var1);
   printf("floatptr: %p \nAddress of floatptr: %p \n\n", floatptr, &floatptr);
   printf("var1: %f \nValue at floatptr: %f", var1, *floatptr);

   return 0;
}
var1: 10.550000
Address of var1: 0x7ffc6daeb46c

floatptr: 0x7ffc6daeb46c
Address of floatptr: 0x7ffc6daeb470

Pointer to Pointer

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

pointer variable

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

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

要从 “y” 获得 “a” 的值,我们需要使用表达式 “ *y". Usually, "y" will be called as the *pointer to a pointer ”。

Example

请看以下示例:

#include <stdio.h>

int main(){

   int var = 10;
   int *intptr = &var;
   int **ptrptr = &intptr;

   printf("var: %d \nAddress of var: %d \n\n",var, &var);
   printf("inttptr: %d \nAddress of inttptr: %d \n\n", intptr, &intptr);
   printf("var: %d \nValue at intptr: %d \n\n", var, *intptr);
   printf("ptrptr: %d \nAddress of ptrtptr: %d \n\n", ptrptr, &ptrptr);
   printf("intptr: %d \nValue at ptrptr: %d \n\n", intptr, *ptrptr);
   printf("var: %d \n*intptr: %d \n**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

您既可以拥有 pointer to an array ,也可以拥有使用 struct 定义的派生类型。指针具有重要的应用。它们在通过传递引用调用函数时使用。指针还有助于克服函数仅返回单个值的局限性。使用指针,您还可以获得返回多个值或数组的效果。

NULL Pointers

如果您没有确切的地址要分配,那么将 NULL 值分配给指针变量始终是一种好习惯。这在变量声明时完成。分配了 NULL 的指针称为 null 指针。

NULL 指针是一个常量,在多个标准库中定义的值为“0”。

Example

请考虑以下程序 −

#include <stdio.h>

int main(){

   int *ptr = NULL;

   printf("The value of ptr is : %x\n", ptr);

   return 0;
}

编译并执行上述代码后,将产生以下结果 −

The value of ptr is 0

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

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

要检查空指针,您可以使用以下 if 语句:

if(ptr)     /* succeeds if p is not null */
if(!ptr)    /* succeeds if p is null */

Address of the Variables

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

Example

考虑以下示例,它将打印所定义变量的地址:

#include <stdio.h>

int main(){

   int  var1;
   char var2[10];

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

   return 0;
}

Output

当以上代码经过编译和执行时,它将打印变量的地址:

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

Pointers in Detail

指针有很多简单的概念,它们对 C 编程非常重要。任何 C 程序员都应清楚以下重要的指针概念:

Sr.No

Concept & Description

1

Pointer arithmetic 可以用在指针中的有四个算术运算符:+、--、、-

2

Array of pointers 您可以定义数组来容纳多个指针。

3

Pointer to pointer C 允许您拥有指针的指针,依此类推。

4

Passing pointers to functions in C 通过引用或通过地址传递参数使传递的参数能够在调用函数中被被调用函数更改。

5

Return pointer from functions in C C 允许函数返回对局部变量、静态变量以及动态分配的内存的指针。