C语言程序设计——指针

图片发自简书App

我应该比大多数读者年龄都要大一些,所以我就自称”谱哥“,做事靠谱,为人靠谱的意思;针对 C 语言三大核心:数组、指针、函数,今天继续写技术文章。

上次 C 语言写到了数组,有些书是先讲指针,有些书是先讲函数,按照我以前学习 C 语言的顺序,以及对 C 语言的理解,学习的顺序是这样的:数组--->指针--->函数,所以本篇文章讲解 C 之指针。

C 语言是值得好好学习的一门语言,是一门基础语言,更是我编程入门的语言,其中很多编程思想,至今影响着我,在工作中对我的帮助很大。


基本概念


学习 C 语言之指针,必须强烈推荐一本书:《C 和指针》,好好看,把这本书吃透,C 指针就差不多了。

1、

指针有两个要素

(1)、首地址:内存中多个连续字节的第一个字节的编号;在 32 位系统下,每个字节的编号都是 32 位二进制,也就是 4B,任何类型的指针都只占 4B 的存储空间。

1char *a;        char*        a;

2short *b;        short*      b;

3int *c;          int*        c;

4double *d;      double*      d;

5

6printf("%d %d %d %d\n", sizeof(a), sizeof(b), sizeof(c), sizeof(d));

7//32位系统下,结果为:4 4 4 4,证明了只要是指针,都是 4B,其实指针的值就是内存中一个字节的地址,仅仅是代表了一个编号而已

(2)、指针所指向空间的数据类型:以指针的值为首地址,其所指向的空间的数据类型。

2、
指针类与值类

我们之前学习过的各种数据类型:int、float 等等都统称为值类。

指针类和值类不能简单的适用以前所讲述的语法,例如:自动类型转换和强制类型转换是不适用指针类的。

3、

指针的基本运算

& 和 *

A、

&:取地址运算符,单目运算符,优先级在单目运算符中比较低,低于 ++、--。

&左值(左值只能是空间、变量),取的是内存的地址。

&常量和&表达式是语法错误的。

1 &3、&(&n)、&&n,都是错误的形式

B、

1short i, j, *p, *q, **r;

2//两个值类变量:i 和 j;三个指针类变量:p、q、r

3//p、q 是指针变量,其指向的数据类型为:short;

4//r 是指针变量,但是 r 所指的空间的数据类型是 short *

5//对于指针所指向的数据类型:去掉最后一个"*",剩余部分与类型所组成的内容就是了

6

7//p = &i; 是正确的,把变量/空间 i 的地址赋值给 p

8//r = &i; 是错误的,必须保证左边和右边的数据类型是一样的,指针才可以进行赋值操作,r 的数据类型是:short **,&i 的数据类型是:short *,所以赋值失败

9//r = &p; 是正确的,r 指向 p,必须首先的明确这些指针的数据类型的对应关系,以及指向,指向空间的数据类型

C、

* 运算符

单目运算符,与 & 优先级相同,且和 & 互为逆运算(连续的两个 & 和 * 运算符在一起,相互抵消),例如:*&n <=> n、&*p <=> p。

语法:*指针(常量、变量、表达式)

1short i, j, *p, *q, **r;

2p = &i;

3q = &j;

4*p = 30; //把 30 赋值给”p 所指向的空间“,也就是 i,等价 i = 30

5*q = *p + 15; //将 p 所指向空间的值,和 15 求和,把和值赋值给 q 所指向的空间,等价 j = i + 15

*某的理解:

(1)、其在左边,理解为:某所指向的空间;

(2)、其在表达式中,理解为:某所指向的空间的值。

1short i, j, *p, *q, **r;

2p = &i;

3q = &j;

4r = &p;

5*p = **r + *q; //将 r 所指向空间的值所指向空间的值和 q 所指向空间的值求和,赋值给 p 所指向的空间,等价 i = i + j;

4、

指针定义的理解

A、

1char i, j, *p = &i, *q = &j, **r = &p;

2//定义语句中的 *,不是指向运算符,它只是指针身份的声明

B、

double *p;

*p = 3.14;

对于上述语句的理解,是至关重要的。

上述语句会引起:运行时致命错误!!!

变量 p 定义为指针变量,占用 4B,但是没有初始化(没有赋初值),其值为垃圾数据;

*p = 3.14; 的意思是:将 3.14 赋值给 p 所指向的空间,也就是将 3.14 赋值给“以 p 的值作为首地址”,该首地址所指向的空间;

综上所述:将 3.14 赋值给以垃圾值为首地址,所指向的空间,这个空间在哪里,只有鬼知道!这个垃圾值的取值范围在 0 到 40 亿之间,若落在当前软件申请的空间范围内,则相安无事;否则,这个操作(*p = 3.14;),将对不属于本软件所申请的空间进行操作,被操作系统认为是“非法访问”,操作系统将强行终止这个软件的执行!

5

指针的其他运算(主要是指针的加减运算)

指针加/减整型值,其结果是一个指针,且指向空间的类型不变。

A、

指针加/减整型

P + 1:所得到的还是指针,将会指向 P 所指向空间的下一个地址(到下一个地址移动的长度是指向空间数据类型的长度)。

指针 +1 所得到的“字节编号”的值。与指针原值(原字节编号)相差sizeof(所指向空间的数据类型)。

指针 +n 的值与指针原值相差 n 倍的 sizeof(所指向空间的数据类型)

B、

指针减指针  => int 类型

指针减指针,其结果的绝对值是:两指针所指向的空间之间 sizeof(数据类型) 元素的个数。

参加指针相减运算的两个指针,其指向空间的数据类型必须一致!

实质上,指针相减的内部运算过程是:两指针值(字节编号)相减,再除以 sizeof(所指向空间的数据类型)

指针不能加指针,会出现语法错误!

总结:指针 + 1 或者 -1,指针移动的步长:是指向空间数据类型的长度(这个长度是通过 sizeof() 可以计算的)。


指针与数组

1、

指针与一维数组

int a[10];

数组名称的本质:是该数组的首地址常量。

A、数组名称是常量

1int a[10], *p = &a[0];

2++a; //错误!++运算的本质是赋值;不能对常量赋值;a 是数组名称,是常量

3++p; //指针变量

B、

数组名称是首地址(指针),可以参加指针能够参与的所有运算。

1*a = 3; //a 的值本质上是 a[0] 的首地址,因此可以说:a 指向 a[0]

2*(a+0) = 3; <=> a[0] = 3;

3*(a+1) = 3; <=> a[1] = 3;

4*(a+2) = 3; <=> a[2] = 3;

int i; //且其取值在有效下标范围内:

*(a+i) = 3; <=> a[i] = 3;

得到了指针与数组的本质:

a[i] <=> *(a+i)

表象          本质

2、

指针与二维数组

指针与二维数组在理解上是比较难的,只有理解了指针与二维数组,那么指针与多维数组,三阶指针、四阶指针、五阶指针、直至多阶指针,一维数组,二维数组,三维数组,直至多维数组,在理解上就都不是问题了,挖掘本质,才能更清楚的认识。

指针与二维数组属于指针的高级进阶,后面有时间在分享这块的知识点。

指针与字符串

1、

"ABCDE" //字符串常量

字符串常量的本质:是该字符串的首地址常量,即指针常量。

1char *p = "I love you";

2

3p = "Hello";

4printf("%s\n", p);

5p[2] = 'm';  //错误,字符串常量是不能进行赋值操作的

2、

字符串常量的本质是指针常量,可以参加指针所能够参加的所有运算。

因此:

字符串常量可以进行 * 和 [] 的运算;

字符串常量不能相加;(指针是不能相加的);

字符串常量的关系运算符(大小比较),实质上比较的是它们的内存首地址的大小比较,而非字符串内容(ASCII码)的大小比较。

字符串常量不能更改其内容。

字符串的本质是字符数组,数组名称的本质依然是指针常量;

所以,以上结论依然适用于字符串!

3、

字符串类处理函数

A、

string.h

对于 scanf("%s"...) 和 gets() 的理解

strlen() 函数的工作原理:

C 语言将其唯一的参数当成首地址,从这个首地址所指向的空间开始,统计所有字符的个数,直到遇到0(结束标志)。

B、

字符串输入、输出函数

输入:scanf("%s", ...)、gets(...)

输出:printf("%s", ...)、puts(...)

C、

strcpy()

声明:char *strcpy(char *target, char *source);

功能:将后者字符串,赋值给前者:将以第二个参数的值为首地址所指向的字节开始的“遇零则止”的字符,复制一份,赋值给第一个参数的值为首地址所指向的字节开始向后的连续存储空间中;该函数的返回值,就是第一个参数的值。

D、

strcat()

声明:char *strcat(char *, char *);

功能:字符串连接,将第二个参数所指向的字符串,连接到第一个参数所指字符串的末尾。

E、

strstr()/strchr()

声明:char *strstr(char *string, char *subString); 

//subString意思为:子串

功能:查找 subString 第一次出现的地址值,若 subString 不是 string 的子串,则返回 NULL。

F、

strcmp()

声明:int strcmp(char *s1, char *s2);

功能:比较 s1 和 s2 所指向的字符串的内容;

若 s1 字符串内容小于 s2 字符串内容,则返回值为负整数;

若 s1 字符串内容大于 s2 字符串内容,则返回值为正整数;

若二者内容相等,则返回为0。

G、

strrev()

声明:char *strrev(char *);

功能:将字符串逆序。

这篇文章仅仅是 C 语言指针的入门篇,看完之后,不知道大家能理解多少,学到多少;根据这篇文章的线路,去学习 C 指针,会清晰很多,只有多思考,才能消化吸收,才能理解。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容