💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### 14. 指针 学习 C 语言的指针既简单又有趣。通过指针,可以简化一些 C 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。所以,想要成为一名优秀的 C 程序员,学习指针是很有必要的。 正如您所知道的,每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。请看下面的实例,它将输出定义的变量地址: ~~~ void main(){ int var1; char var2[10]; //%p : 输出指针地址 //%#x:以十六进制形式输出无符号整数(输出前缀0x) printf("var1 变量的地址:%p \n", &var1); printf("var2 变量的地址:%p \n", &var2); } ~~~ 输出: ~~~ var1 变量的地址:0x7ffee7e976b8 var2 变量的地址:0x7ffee7e976be ~~~ 例子: ``` #include <stdio.h> int main () { int var_runoob = 10; int *p; // 定义指针变量 p = &var_runoob; printf("var_runoob 变量的地址: %#x\n", p); printf("指针变量p的地址: %#x\n", &p); return 0; } ``` 输出结果 ~~~ var_runoob 变量的地址: 0x7fff1a9ef2fc 指针变量p的地址: 0x1a9ef2f0 ~~~ ![](https://www.runoob.com/wp-content/uploads/2014/09/c-pointer.png) 通过上面的实例,我们了解了什么是内存地址以及如何访问它。接下来让我们看看什么是指针。 #### 什么是指针? **指针**是一个变量,其**值为另一个变量的地址,即内存位置的直接地址**。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为: ~~~ type *var-name ~~~ 在这里,**type** 是指针的基类型,它必须是一个有效的 C 数据类型,**var-name** 是指针变量的名称。**用来声明指针的星号 \* 与乘法中使用的星号是相同的。但是,在这个语句中,星号是用来指定一个变量是指针**。以下是有效的指针声明: ~~~ int *i; //一个整型的指针 double *d;//double 型指针 float *f;//浮点型指针 char *ch//字符型指针 ~~~ **所有实际数据类型**,不管是整型、浮点型、字符型,还是其他的数据类型,**对应指针的值的类型都是一样的,都是一个代表内存地址的长的十六进制数**。 **不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同**。 #### 如何使用指针? 使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。这些是通过使用一元运算符 \*来返回位于操作数所指定地址的变量的值。下面的实例涉及到了这些操作: 例子: ~~~ //如何使用指针 int var = 66;//实际变量的声明 int *ip;//指针变量的声明 ip = &var; //指针变量中存储 var 的地址 printf("var 变量的地址 : %p \n", &var); //在指针变量中存储的地址 printf("ip 的值:%p \n", ip); //使用指针访问地址 printf("ip 指针对应的地址:%p \n", &ip); //使用指针访问地址对应的值 printf("ip 指针中存储的地址对应的值:%d \n", *ip); ~~~ 输出: ~~~ var 变量的地址 : 0x7ffe7469379c ip 的值:0x7ffe7469379c ip 指针对应的地址:0x7ffe74693790 ip 指针中存储的地址对应的值:66 ~~~ #### C 中的 NULL 指针 在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为**空**指针。 NULL 指针是一个定义在标准库中的值为零的常量。请看下面的程序: ``` void main() { int *ptr; ptr = NULL; printf("指针变量ptr的值是:%d\n",ptr);//0 printf("指针变量ptr的地址是:%#x\n", &ptr);//%#x:以十六进制形式输出无符号整数(输出前缀0x) //printf("指针变量ptr的值是:%d", *p);//p不指向任何东西,那么*p也就没有任何意义了,这里如果运行会报错,读取访问权限冲突 //检查一个空指针 if (ptr) printf(" ptr 不是空指针,则执行"); else printf(" ptr 是空指针,则执行............\n"); system("pause"); } ``` 输出结果是 ~~~ 指针变量ptr的值是:0 指针变量ptr的地址是:0x1d8984d8 ptr 是空指针,则执行............ ~~~ #### C 指针详解 在 C 中,有很多指针相关的概念,这些概念都很简单,但是都很重要。下面列出了 C 程序员必须清楚的一些与指针相关的重要概念: | 概念 | 描述 | | --- | --- | | [指针的算术运算](https://www.runoob.com/cprogramming/c-pointer-arithmetic.html) | 可以对指针进行四种算术运算:++、--、+、- | | [指针数组](https://www.runoob.com/cprogramming/c-array-of-pointers.html) | 可以定义用来存储指针的数组。 | | [指向指针的指针](https://www.runoob.com/cprogramming/c-pointer-to-pointer.html) | C 允许指向指针的指针。 | | [传递指针给函数](https://www.runoob.com/cprogramming/c-passing-pointers-to-functions.html) | 通过引用或地址传递参数,使传递的参数在调用函数中被改变。 | | [从函数返回指针](https://www.runoob.com/cprogramming/c-return-pointer-from-functions.html) | C 允许函数返回指针到局部变量、静态变量和动态内存分配。 |