首页 > 编程笔记 > C语言笔记 阅读:145

C语言指针的定义和使用(附带大量实例)

指针是 C语言中的重要概念,也是 C语言的精华所在。指针的概念比较复杂,其使用非常灵活。学会使用指针,可以让程序更加高效、简洁。

在C语言中,指针即内存地址,每个变量在内存中都会有对应的地址或位置。

【实例】直接输出定义变量的地址。代码如下:
#include <stdio.h>
 
int main()
{
    int i_a = 1;
    printf("i_a变量的地址为: %p\n",&i_a); //将i_a的地址以%p格式符输出
    return 0;
}
编译运行,结果如下:

i_a变量的地址为: 0060FE9C

这个地址不是固定的,每次编译运行后输出 i_a 变量的地址可能不同。计算机可以通过地址找到相应的变量,如同根据身份证号码找到对应的人。

指针变量的定义

指针变量是保存地址的变量,指针变量存放的值是内存中的地址。

定义指针变量的一般形式为:
类型名 *指针变量名;
例如:
//定义int型指针变量,该变量是指向整型变量的指针变量,简称int指针
int *p_i;
//定义float型指针变量,该变量是指向单精度浮点变量的指针变量,简称float指针
float *p_f;
//定义double型指针变量,该变量是指向双精度浮点变量的指针变量,简称double指针
double *p_d;
//定义char型指针变量,该变量是指向字符型变量的指针变量,简称char指针
char *p_c;
由以上内容可知,定义指针变量与定义普通变量非常相似,在变量名的前面加“*”就可定义相应类型的指针变量。

注意,int 型指针变量只能存放 int 型变量的地址,float 型和 double 型指针变量同理。


在定义指针变量的同时,可对它进行初始化,如:
int i_a = 100;
int *p_i_a = &i_a; //取整型变量i_a的地址赋给指针变量p_i_a

C语言NULL指针

一般情况下,在声明指针变量的时候,如果没有确切的地址可以赋值,就为指针变量赋 NULL 值,赋 NULL 值的指针变量被称为空指针。

【实例】输出被赋 NULL 值的指针变量中的地址。
#include <stdio.h>
 
int main()
{
    int *p_i = NULL;
    printf("p_i的值:%p\n", p_i);
    return 0;
}
编译运行,结果如下:

p_i的值:00000000


如果需要检查 p_i 指针变量是否为空指针,则可以使用 if 语句,具体如下:
//如果p_i不是空指针
if(p_i!=NULL)
{
}
//如果p_i是空指针,则进行以下步骤
else
{
}
在声明一个指针变量 p_i 后,尽管没有赋值,程序编译器也可能会给指针变量 p_i 赋一个值,因此,即使没有赋值,指针变量 p_i 也不一定为空。

指针变量的使用

下面通过几个实例学习使用指针变量。

【实例】通过指针变量输出地址。
#include <stdio.h>
 
int main()
{
    int i_a;
    int *p_i; //定义指针变量,用来存放地址的变量
 
    p_i = &i_a; //通过取地址符号&,将i_a的地址赋给指针变量p_i
    printf("i_a变量的地址为:%p\n",p_i); //将变量i_a的地址以%p格式符输出
   
    return 0;
}
编译运行,结果如下:

i_a变量的地址为: 0060FE98

在定义指针变量时需要加上“*”,给指针变量赋地址值时不能带“*”。就像在定义整型变量时,需要在变量名前加“int”,而之后使用整型变量进行赋值或者运算操作时,无须在变量名前添加“int”。

【实例】指针运算符“*”的初步理解与使用。
#include <stdio.h>
 
int main()
{
    int i_a = 10;
    int *p_i; //定义int型指针变量
    p_i = &i_a; //将变量i_a的地址赋给指针变量p_i
 
    printf("输出&i_a的值: %p\n",&i_a); //输出i_a变量的地址
    printf("输出p_i的值: %p\n",p_i); //输出指针变量p_i中存放的地址
    printf("输出i_a的值: %d\n",i_a); //输出变量i_a的值
    printf("输出*p_i的值: %d\n",*p_i); //输出指针变量p_i中存放地址指向的变量值
 
    return 0;
}
编译运行,结果如下:

输出&i_a的值: 0060FE98
输出p_i的值: 0060FE98
输出i_a的值: 10
输出*p_i的值: 10

可以看到,输出结果的第一行和第二行的值相同,因为在程序中,将变量 i_a 的地址赋给了指针变量 p_i。输出结果的第三行和第四行的值相同,因为指针变量 p_i 存放了变量 i_a 的地址,*p_i 则根据 p_i 中存放的地址,找到变量 i_a 并获取变量 i_a 的值。可以称 p_i 是指向变量 i_a 的指针变量。

“*”为指针运算符,*p_i 代表指针变量 p_i 所指内存位置对应的值,下面通过实例继续说明。

【实例】通过指针变量修改所指变量的值。
#include <stdio.h>
 
int main ()
{
   int i_a = 33;
 
   int *p_i = &i_a; //将变量i_a的地址赋给指针变量p_i
   printf("输出i_a的值:%d\n",i_a); //输出变量i_a的值
   *p_i = 55;
   printf("输出i_a的值:%d\n",i_a);
 
   return 0;
}
编译运行,结果如下:

输出i_a的值:33
输出i_a的值:55

当指针变量 p_i 中存放的是变量 i_a 的地址时,对 *p_i 进行的所有操作等同于对变量 i_a 的操作,因此可将指针变量 *p_i 替换成变量 i_a 去理解。

【实例】通过指针交换主程序中两个变量的值。
#include <stdio.h>
 
void swap(int *i_a,int *i_b) /*函数定义*/
{
   int  temp;
   temp = *i_a ; /*将指针变量i_a地址所指的值赋给变量temp*/
   *i_a  = *i_b; /*将指针变量i_b地址对应的值赋给指针变量i_a地址所指的变量*/
   *i_b = temp; /*把变量temp的值赋值给指针变量i_b所指的变量*/
 
   return; //该函数无返回值
}
 
int main ()
{
    int i_a = 100;
    int i_b = 200;
 
    printf("交换前i_a, i_b 的值: %d,%d\n",i_a,i_b);
    swap(&i_a,&i_b); /*调用函数交换值,将i_a和i_b地址传过去*/
    printf("交换后i_a,i_b 的值: %d,%d\n",i_a,i_b);
 
    return 0;
}
编译运行,结果如下:

交换前i_a, i_b的值: 100,200
交换后i_a, i_b的值: 200,100

关于传值和传地址,可以通过举例说明。将孙悟空定义为一个变量,杨戬定义为一个函数,变量孙悟空可通过分身术产生一个形参传递给函数杨戬,这时候为值传递。函数杨戬怎样收拾变量孙悟空的分身(形参,只传递值的副本)都不会对变量孙悟空本身产生任何影响。

如果变量孙悟空把他真身的地址告诉了函数杨戬(地址传递,变量孙悟空在内存中的地址),函数杨戬就可以根据地址找到变量孙悟空,这时候函数杨戬对变量孙悟空的操作就会改变变量孙悟空的值。

相关文章