极速手机网

怎样了解C言语中的指针,怎样运用?

什么是 C言语指针?

图一 怎样了解C言语中的指针,怎样运用

不同的数据类型的主要差异在于占用的存储空间不同。咱们知道,C 程序是运转在计算机的内存中的,因而 C 程序的变量也是存在于内存中的。C 标准规则 char 类型占用一个字节的存储空间,对其他整型却没有做规则,现在为了解说的便利,咱们假定 int 类型的数据占用内存 4 个字节。

假定咱们如下界说了两个变量:

signed char i = 3;int j = 8;

那么,i 占用了 1 字节的内存空间,j 占用了 4 字节的内存空间,方框表示内存空间,内部表示存储的值。咱们把内存逐字节编号,方框外部的数字表示方框的编号(这样的内存“编号”即所谓的“内存地址”)。修正变量 i 的值,实际上便是修正地址为 4000 的内存空间里的值。那反过来呢?假如我修正了地址为 4000 的内存空间里的值,i 的值会相应改变吗?答案是肯定的,请持续往下看,内存地址“4000”是我为了解说便利随意取的。那么,在实际应用中,变量 i 的地址怎样获取呢?C 言语供给了“&”运算符,便是获取变量地址的。请看下面的例子:

#include

int main()

{

signed char i = 3;

int j = 8;

long p1 = (long)&i;

printf(\\\"p1: %ld \\\",p1);

return 0;

}

咱们取出了 i 的地址,把它强制转换为 long 型(关于强制类型转换,可参阅上一节),传递给 p1 了。编译履行,发现变量 i 的地址被打印出来了。这说明,C 程序变量的地址也是一个整数。

依照上面的说法,修正 i 的值除了直接对 i 赋值以外,还能够经过修正 p1 地址处的内存空间里的数值。那,怎样才能“经过修正 p1 地址处的内存空间里的数值”修正 i 的值呢?

上面的代码实例中,咱们运用了 long 型变量 p1 存储了 i 的地址。事实上,C 言语有专门的数据类型存储地址,界说方式也很简单,便是:“类型描述符 * ”,例如,能够界说以下变量存储地址:

signed char *p1 = &i;int *p2 = &j;

p1 和 p2 便是 C 言语中所谓的指针类型,由于 i 是 signed char 类型的,所以界说了 signed char * 类型的指针存储 i 的地址。j 是 int 类型的,所以界说了 int * 类型的指针存储 j 的地址。别的,C 言语供给了“&”运算符取变量地址,与之对应的,还供给了“ * ”运算符从相应地址内存里取出数值。

好了,了解了 C 言语的指针类型和“ * ”运算符,现在来看看怎样“经过修正 p1 地址处的内存空间里的数值”修正 i 的值。请看如下代码:

signed char *p1 = &i;

*p1 = 5;

printf(\\\"i=%d \\\",i);

编译运转,发现程序输出“i=5”,这样咱们就完成了“经过修正 p1 地址处的内存空间里的数值”修正 i 的值。

在界说变量时,” * “放在变量符号前,能够界说指针变量。在界说完指针变量后,“ * ”放在变量前,就表示从地址取值的运算符了。别的,“ * ”还能够表示乘法运算符,读者自己思考什么情况下,“ * ”表示乘法运算符。

以上的操作,实际上便是 C 言语的指针操作,能够看出它一点也不奥秘,接下来几节,咱们将持续讨论 C 言语的指针,比方为什么 int 类型的变量 j 的地址要运用 int* p2; 界说,而不能运用 signed char* p2; 界说,运用指针为何能写出紧凑、高效的 C 程序等等。

为什么要运用指针?

在开始讨论为什么运用 C 言语指针之前,先介绍一下复杂点的指针,这是新知识,也是衬托。不想看衬托能够往后翻一翻。

前面几节介绍了 C 言语中指针,也讨论了数组指针和指针数组的差异,但归根结底,至今咱们说的都是根底数据类型界说的指针,C 言语有复合数据类型,那么它有复合数据类型的指针吗?答案是肯定的,事实上,在 C 言语中复合类型指针的运用相当广泛。

先来看看结构体指针。仍是从实例动身,咱们界说一个结构体类型,它有两个成员,分别是 sleep_time(睡觉时刻) 和 work_time(工作时刻),然后界说这种结构体类型的变量和指针:

struct week{

double sleep_time;

double work_time;

};

struct week w;

struct week *pw = &w;

能够经过结构体指针 pw 拜访 week 结构体的成员:

(*pw).sleep_time = 7.0;

这样写有点费事,因而 C 言语十分贴心的供给了“->”运算符,所以咱们还能够这样经过结构体指针拜访成员:

pw->sleep_time = 7.0;

为什么要运用 C 言语中的指针

好了,现在咱们已经知道 C 言语中的结构体指针怎样运用了,衬托完了。可是,分明运用结构体变量 w 就能很好的读写 week 结构体啊,为什么要用结构体指针呢?这不是费事了吗?

为什么要运用结构体指针,其实能够延伸到“为什么要运用指针”,本节将以结构体指针为例讨论一下这个问题。

是的,仅仅拜访 week 的 sleep_time 成员,只运用结构体变量 w 就足够了,再经过 pw 拜访真的费事了。可是工具会不会带来便利,要看咱们怎样运用,不能由于高射炮打蚊子不便利就说高射炮没用。恰当的运用结构体指针,有利于咱们写出愈加紧凑,功率更高的 C 程序。

图二 怎样了解C言语中的指针,怎样运用

一周有五天工作日,两天周末,一般来说,在工作日(weekday),人们的睡觉时刻较短,工作时刻较长,所以咱们界说 weekday 函数来规划工作日的时刻:

void weekday(struct week wd)

{

wd.sleep_time = 7.0; // 7 小时

wd.work_time = 8.5; // 8.5 小时

}

而在周末(weekend)则反过来,工作间较短,睡觉时刻较长,所以咱们界说 weekend 函数来规划周末的时刻:

void weekend(struct week we)

{

we.sleep_time = 9.0; // 9 小时

we.work_time = 2.5; // 2.5 小时

}

这两个函数很好的规划了一周的睡觉和工作时刻,可是却并不好用。为什么呢?由于它俩只在自己内部规划了,咱们外界看不到啊!想在 main 函数把规划好的时刻打印出来都办 不到,由于它俩在自己内部规划好以后,就把“规划书”销毁了。

这儿把 weekday 和 weekend 函数的局部变量比作“规划书”,函数退出后,局部变量就自动销毁了。能够参阅《c言语入门5,一文彻底弄懂函数的形参和实参》一节。可能你会说,那我能够把“规划书”返回给 main 函数啊,让 weekday 和 weekend 函数有返回值就能够了:

struct week weekday(struct week wd)

{

wd.sleep_time = 7.0; // 7 小时

wd.work_time = 8.5; // 8.5 小时

return wd;

}

struct week weekend(struct week we)

{

we.sleep_time = 9.0; // 9 小时

we.work_time = 2.5; // 2.5 小时

return we;

}

int main()

{

struct week w;

w = weekday(w);

printf(\\\"weekday,sleep time: %0.1f,work time: %0.1f \\\",w.sleep_time,w.work_time);

weekend(w);

printf(\\\"weekend,sleep time: %0.1f,work time: %0.1f \\\",w.sleep_time,w.work_time);

return 0;

}

是的,这的确是一个解决问题的办法,main 能够把 weekday 和 weekend 函数的“规划书”打印出来了。

可是这种解决问题的办法有一点臃肿,许多程序员把这样的代码称为“不优雅”的代码。你看,main 现在有一份空的“规划书”,需求 weekday 和 weekend 函数处理。weekday 和 weekend 函数能处理,可是它们要仿制一份“规划书”回到自己内部做,这种仿制就造成了空间浪费。此外,weekday 和 weekend 函数做完了规划书,还要把“规划书”再从自己内部取出,return 给 main,这就有时刻浪费。

更节省资源,更有功率的做法是:weekday 和 weekend 函数处理这份“规划书”时,直接处理 main 里的“规划书”就能够了。不要仿制后再处理,完事了还要在从自己内部传出。那,weekday 和 weekend 函数应该怎样修正呢?请看:

void weekday(struct week *wd)

{

wd->sleep_time = 7.0; // 7 小时

wd->work_time = 8.5; // 8.5 小时

}

void weekend(struct week *we)

{ we->sleep_time = 9.0; // 9 小时

we->work_time = 2.5; // 2.5 小时

}

int main()

{

struct week w;

weekday(&w);

printf(\\\"weekday,sleep time: %0.1f,work time: %0.1f \\\",w.sleep_time,w.work_time);

weekend(&w);

printf(\\\"weekend,sleep time: %0.1f,work time: %0.1f \\\",w.sleep_time,w.work_time);

return 0;

}

图三 怎样了解C言语中的指针,怎样运用

看到了没,利用指针,整个 C 代码简练多了。weekday 和 weekend 函数接收到的参数都是 main 里结构体变量 w 的地址,所以它俩都是直接操作 w 的。这样就不用在自己的栈帧里仿制一份 w 再处理了,也不用在处理完毕还要 return 给 main 了。

看到这儿,你可能会说,什么嘛,不便是用指针代替了结构体做参数吗?指针说不定比结构体还要耗空间呢!对吗?一起来看下:结构体变量 w,它占用内存至少两个 sizeof(double) 的空间(一个 double 型数据一般占用 8 字节空间)。而一个指针,不管它是什么类型的,在大多数 32 位计算机中,它只占 4 字节空间,在大多数 64 位计算机中,它也仅仅占 8 字节空间。所以运用指针做 weekday 和 weekend 函数的参数,在空间上,肯定是比直接运用 week 结构体节省空间的,况且指针还提高了功率,简练了代码。

假如是一个 char 型变量,它只占用 1 字节空间,这时运用指针的确更浪费空间。可是假如是一个十分复杂的结构体,它占用的内存空间甚至达几千字节,这时运用指针就十分节省空间了。所以说,工具是死的,人是活的。

到这儿,相信你已经了解 C 言语指针在节省空间,提高程序功率方面的作用了。事实上,这儿咱们介绍的仅仅是指针的冰山一角,在以后的文章里,你会益发觉得 C 言语指针的强壮的。

相关文章

大家都在找