C语言的灵魂 — 指针

目录

一、指针是个啥?

二、指针变量

三、通过指针引用数组

四、通过指针引用字符串

五、指向函数的指针

六、返回指针值的函数

七、指针数组

八、指向指针数据的指针

九、指针变量的类型及含义


一、指针是个啥?

1、数据在内存中的存储和读取方式

如果在程序中定义了一个变量,在对程序进行编译时,系统就会给这个变量分配内存单元。编译系统根据程序中定义的变量类型,分配一定长度的空间。内存区的每一个字节有一个编号,这就是"地址",它相当于旅馆中的房间编号。在地址所标志的内存单元中存放的数据相当于旅馆中居住的旅客。

2、指针的含义

一个变量的地址称为该变量的"指针"。例如:地址0x2000是变量 i 的指针。如果有一个变量专门用来存放另一个变量的地址(即指针),则称它为"指针变量"。指针变量就是地址变量,用来存放地址,指针变量的值是地址(即指针)。

二、指针变量

1、指针变量的声明格式

定义指针变量的一般形式为:类型名 *指针变量名     如:int  *pointer;

其中 int 是表示指针 pointer 可以指向的变量的类型只能是整型,不能是 float 等别的数据类型。* 表示该变量的类型为指针型变量。pointer 是指针变量名。上面这个例子表示:pointer 是指向整型数据的指针变量

注意:指针变量中只能存放地址(指针),不要将一个整数复制给一个指针变量,如:int  *pointer = 100;是不合法的。

2、怎样引用指针变量

(1)给指针变量赋值:

如:int  a;int  *p  = &a;        //把变量 a 的地址赋值给变量 p

或:int  a[10]; int  *p  = a;           //int *p=后面必须是地址变量!

(2)引用指针变量指向的变量:

如果已执行:int  *p  =  &a;即指针变量 p 指向整型变量 a,则:

printf("%d",*p);其作用是以整数形式输出指针变量 p 所指向的变量的值,即变量 a 的值。

如果有赋值语句:*p = 1;表示将整数 1 赋给 p 指针当前指向的变量,如果 p 指向变量 a,则相当于把1赋给 a,即"a = 1;"

(3)引用指针变量的值:

如:printf("%d",p);作用是以十六进制数形式输出指针变量 p 的值,如果 p 指向了 a,就是输出了 a 的地址,即:&a。

综上

(1)&          取地址运算符。          &a 是变量 a 的地址。

(2)*           直接访问运算符。      *p代表指针变量 p 指向的对象。

三、通过指针引用数组

1、数组元素的指针(数组指针)

一个变量有地址,一个数组包含多个元素,每个数组元素都在内存中占有存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素。所谓数组元素的指针就是数组元素的地址

int a[10] = {0,1,2,3,4,5,6,7,8,9};    //定义 a 为包含 10 个整型数据的数组,并初始化
int *p;                               //定义 p 为指向整型变量的指针变量
p = &a[0];                            //把 a[0] 元素的地址赋值给指针变量 p

p = a;            //C语言中数组名代表数组中首元素的地址,所以这条语句和上面的等价

2、在引用数组元素时指针的运算

当指针指向数组元素的时候,允许对指针进行加和减的运算。比如,指针变量 p 指向数组元素 a[0] ,那么可以直接用 p + 1 表示指向下一个元素 a[1]。注意:指向 p + 1 不是简单的将 p 的值(地址)加 1,而是加上一个数组元素所占的字节数。

3、通过指针引用数组元素

引用一个数组元素,有两种方法:(1)下标法:如 a[i] 的形式。(2)指针法:如 *(a+i) 或 *(p+i)。其中 a 是数组名(数组首个元素的地址),p 是指向数组的指针变量,其初值 p = a;。

注意:利用指针引用数组元素有不少技巧,但是容易混淆。分析一下下面这几种情况:(p 指向数组 a 的首元素,即 p=a)

(1)p++; *p;表示指针 p 指向数组下一个元素 a[1]。然后执行 *p ,得到元素 a[1] 的值。

(2)*p++;由于++和*同优先级,结合方向为自右向左,因此等价于 *(p++) 。先取 *p 值 a[0],然后使 p 加 1。

(3) *(++p);区别于上一种情况,是先是 p 加1,然后取 *p,得到元素 a[1] 的值。。

(4)++(*p);先取 *p 的值 a[0],然后将 a[0] 中存储的内容值加 1。

四、通过指针引用字符串

在C程序中,字符串是存放在字符数组中的。想要引用一个字符串,可以用以下两种方式:

(1)用字符数组存放一个字符串,可以通过数组名和下标引用字符串中的一个字符,也可以通过数组名和格式声明 "%s" 输出该字符串。比如:定义一个字符数组,其中存放字符串"Hello World!",输出该字符串和第七个字符。

#include<stdio.h>
int main(){
    char string[] = "Hello World!";    //定义字符数组 string ,数组长度为13,'\0'
    printf("%s\n",string);            //用 %s 格式声明输出 string,可以输出整个字符串
    printf("%c\n",string[7]);        //用 %c 格式输出一个字符数组元素    o
    return 0;
}

(2)用字符指针变量指向一个字符串变量,通过字符指针变量引用字符串常量。比如:通过字符指针变量输出一个字符串。下面这个例子实际上是把字符串的第一个元素的地址赋给指针变量string,使string指向字符串的第一个字符。

#include<stdio.h>
int main(){
    char *string = "Hello Wrold!";    //定义字符指针变量string,并将其初始化
    printf("%s\n",string);            //输出字符串
    return 0;
}

五、指向函数的指针

1、函数指针的定义

如果在程序中定义了一个函数,在编译时,编译系统为函数代码分配一段存储空间,这段存储空间的起始地址(又称入口地址)称为这个函数的指针。可以定义一个指向函数的指针变量,用来存放某一函数的起始地址,这就意味着此指针变量指向该函数。例如:

int (*p)(int,int);
//定义p是一个指向函数的指针变量,它可以指向函数的类型为整型且有两个整型参数的函数。p的类型用int(*)(int,int)表示。

2、用函数指针变量调用函数

如果想调用一个函数,除了可以通过函数名调用以外,还可以通过指向函数的指针变量来调用该函数。比如:

#include<stdio.h>            //用函数求整数a,b中的大者
int main(){
    int max(int,int);          //函数声明
    int (*p)(int,int);        //定义指向函数的指针变量 p
    int a,b,c;
    p = max;        //使 p指向 max函数
    printf("请输入两个整数:a,b");
    scanf("%d,%d",&a,&b);
    c = (*p)(a,b);        //通过指针调用 max函数,如果通过函数名调用函数可以写成 c=max(a,b)
    c = max(a,b);       //这是通过函数名调用函数的方式
    printf("a=%d\nb=%d\nc=%d\n",a,b,c);
    return 0;
}
int max(int x,int y){        //定义 max函数
    int z;
    if(x>y)
        z = x;
    else
        z= y;
    return z;
}

3、指向函数的指针变量的定义和使用

定义指向函数的指针变量的一般形式为:

类型名  (*指针变量名)(函数参数列表);          如:"int  (*p)(int,int);",这里的"类型名"是指函数返回值的类型。

(1)定义指向函数的指针变量,并不意味着这个指针变量可以指向任何函数,它只能指向在定义时指定的类型函数。如"int  (*p)(int,int);",表示指针变量 p 只能指向函数返回值为整型且有两个整型参数的函数。

(2)如果用指针调用函数,必须先使指针变量指向该函数。如:p=max;这里把 max函数的入口地址赋给了指针变量 p。

(3)在给函数指针变量赋值时,只须给出函数名而不必给出参数。如:p=max;

(4)用函数指针变量调用函数时,只需将(*p)代替函数函数名即可,在(*p)之后的括号中根据需要写上实参。如:c = (*p)(a,b);

(5)指向函数的指针变量不能进行算术运算,如:p++、p--、p+n  等是无意义的。

六、返回指针值的函数

1、定义返回指针值的函数的一般形式

类型名  * 函数名(参数列表);

2、返回指针值的函数的概念说明

一个函数可以返回一个整型值、字符值等,也可以返回指针型的数据,即地址。其概念与以前类似,只是返回值类型是指针类型而已。例如:"int  *max(int x,int y);",其中 max是函数名,调用它以后会返回一个 int* 型(指向整型数据)的指针,即整型数据的地址。x,y是函数 max 的形参,为整型。

注意在 *max 两侧没有括号,在 max 的两侧分别为 * 运算符和()运算符。而()优先级高于 * ,因此 max 先与()结合成函数形式。这个函数前面有一个 * ,表示这个函数是指针型函数,函数值是指针,前面的 int 表示返回的指针指向整型变量。

七、指针数组

1、指针数组的概念说明(区别于数组指针)

一个数组,若其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。比如定义一个指针数组:"int  *p[4];"。

由于 [ ] 比 * 优先级高,因此 p 先与 [4] 结合,形成 p[4] 的数组形式,表示 p 数组有 4 个元素。然后再与 p 前面的 * 结合,表示此数组是指针类型的,每个数组元素都可以指向一个整型变量。

2、定义一维指针数组的一般形式

类型名  * 数组名 [数组长度];          比如:int  *name[4] = {"aaa","bbb","ccc","ddd"};//分别指向4个字符串

八、指向指针数据的指针

1、指向指针数据的指针变量,简称指向指针的指针。(双重指针 || 二维指针)

例如下图中,name是一个指针数组,它的每一个元素都是一个指针型的变量,其值为地址。name 既然是一个数组,那么它的每一个元素都由相应的地址。数组名 name 代表该指针数组首元素的位置。name + i 是 name[i] 的地址,name + i 就是指向指针型数据的指针。还可以设置一个指针变量 p,它指向指针数组的元素。

2、定义一个指向指针数据的指针变量

char  ** p;

p 前面有两个 * 号,* 运算符的结合性是从右到左,因此 ** p 相当于 *(*p) ,显然(*p)是指针变量的定义类型。如果没有前面的 * ,那就是定义了一个指向字符数据的指针变量。现在它前面又加了一个 * 号,即 char  ** p,可以把它分成两部分看,即:char  * 和 (*p),后面的(*p)表示 p 是指针变量,前面的 char * 表示 p 指向的是 char * 型的数据。也就是说,p 指向一个字符指针变量,如果引用  *p ,就得到 p 所指向的字符指针变量的值。

二维指针的初始化:

int  **p = 100;

1)首先为二维指针 p 申请了一个地址空间: 0x2000,p的内容为一个地址, *p 为0x3000

2)*p 是一个一级指针,*p 的内容为一个地址,**p 为 0x4000

3)*p 指针指向的地址存放整型数据:100

九、指针变量的类型及含义

变量定义

类型表示

含义

int  i;

int

定义整型标量 i

int  *p;

int  *

定义 p 为指向整型数据的指针变量

int  a[5];

int  [5]

定义整型数组 a,他有 5 个元素

int  *p[4];

int  * [4]

定义指针数组 p,他由 4 个指向整型数据的指针组成

int  (*p)[4];

int  (*)[4]

p 为指向包含 4 个元素的一维数组的指针变量

int  f();

int  ()

f 为返回整型函数值的函数

int  *p();

int  *()

p 为返回一个指针的函数,该指针指向整型数据

int  (*p)();

int  (*)()

p 为指向函数的指针,该函数返回一个整型值

int  **p;

int  **

p 是一个指针变量,它指向一个指向整型数据的指针变量

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值