`
810364804
  • 浏览: 783020 次
文章分类
社区版块
存档分类
最新评论

指针——C语言的灵魂

 
阅读更多

为什么说C指针是C语言的灵魂?

来自读者对C和指针的解说

  1. 他可以直接访问硬件,这是灵活性和效率的体现,程序离硬件越近自然效率越高,当然运用不当也可导致效率低下

  2. 难掌握及太危险,如果对指针理解含混,访问过程不当易导致程序奔溃或隐藏潜在危险

  3. 指针作用总的说是调高程序运行效率,原因是它对c语言中定义的各种数据结构进行地址传递,而不需要进行不断地进行值传递。理解起来可以联想一下数据共享与建立副本的区别。

注:欢迎各位程序猿们继续补充

挖掘C语言的灵魂,推荐《征服C指针》

enter image description here

读者对本书的评价:

  • 针对性极强,全书以一种精准但又不考究的方式解读C语言指针。看过经典的“C和指针”后再看看日本程序员对指针的理解,也许会获得又一番的感悟。这是最棒的C书 、
  • 日本人都是工匠,从精密机械到各种探测器,从av情色片到美食,小日本干任何事都精益求精。 我看过小日本的几本计算机书,binary hack, debug hack, 以及这本,全都是精品。 他们的书逻辑性不强,特点是人的因素多,注重细节,教给读者诀窍,读来畅快淋漓,爱不释手。 可能我的性格里也有黑客的成份吧,不喜欢那种冷冰冰的知识罗列的书

买前必读:

这是一本关于C 语言的数组和指针的书。

■ 本书的读者群虽然定位于“学习过C 语言,但是在指针的运用上遇到困难”的读者,但还是能随处可见一些高难度的内容。那是因为我也不能免俗,偶尔也喜欢把自己掌握的知识拿出来显摆一下。

■ 对于初学者,你完全没有必要从头开始阅读。遇到还不太明白的地方,也不要过分纠结。阅读中可以跳跃章节。对于第0章和第1章,最好还是按顺序阅读。如果认为第2章有点难度,你可以先去啃第3章。如果第3章也不懂,不妨尝试先去阅读第4章。这种阅读方式是本书最大的卖点。

■ 在本书中,我会经常指出一些“C的问题点”和“C的不足”。可能会有一些读者认为我比较讨厌C语言。恰恰相反,我认为C是一门伟大的开发语言。倒不是因为有“情人眼里出西施”、“能干的坏小子也可爱”这样的理由,毕竟在开发现场那些常年被使用的语言中,C语言还是有相当实力的。就算是长得不太帅,但论才干,那也是“开发现场的老油条”了。

精彩片段:

应该记住:数组和指针是不同的事物

为什么会引起混乱?

首先,请允许我强调一下本章的重要观点。

C 语言的数组和指针是完全不同的。

大家都说C语言的指针比较难,可是真正地让初学者“挠墙”的,并不是指针自身的使用,而是“混淆了数组和指针”。此外,很多“坑爹”的入门书对指针和数组的讲解也是极其混乱。

比如,K&R 中就有下面一段文字(p.119), C 语言的指针和数组之间有很强的关联关系,因此必须将指针和数组放在一起讨论。

很多C程序员认为“数组和指针是几乎相同的事物”,这种认识是引起C的混乱的主要原因。

从图3-17中可以一目了然地看出,数组是一些对象排列后形成的,指针则表示指向某处。它们是完全不同的。

enter image description here

带着“数组和指针是几乎相同的事物”这样的误解,初学者经常写出下面这样的代码:

int *p;

p[3] = ……   ←突然使用没有指向内存区域的指针
——自动变量的指针在初期状态,值是不定的。
char str[10];
    .
    .
    .
str = abc”;    ←突然向数组赋值

——数组既不是标量,也不是结构体,不能临时使用。

int p[]; ←使用空的[]声明本地变量 ——只有在“函数的形参的声明”中,数组的声明才可以被解读成指针。 对于数组和指针,它们在哪些地方是相似的,又在哪些地方是不同的?不好意思,可能在下面会出现和前面重复的内容。

表达式之中 在表达式中,数组可以被解读成指向其初始元素的指针。所以,可以写成下面这样:

int array[10];

p = array;      ←将指向array[0]的指针赋予p

可是,反过来写成下面这样,

array = p;

就是不可以的。确实,在表达式中array 可以被解读成指针,可是,本质上它其实是被解释成了&array[0],此时的指针是一个右值*。(此时的指针是右值这个理由之外,在标准中,数组也不是“可变更的左值”。)

比如,对于int类型的变量a,a = 10;这样的赋值是可以的,但肯定没有人想做a + 1 = 10;这样的赋值吧。尽管a 和a + 1 都是int,但是a + 1没有对应的内存区域,只是一个右值,所以不能被赋值。同样的道理,array也不能被赋值。此外,对于下面这个指针,

int *p;

如果p指向了某个数组,自然可以通过p[i]的方式进行访问,但这并不代表p就是指针。

p[i]只不过是*(p + i)的语法糖,只要p正确地指向一个数组,就可以通过p[i]对数组的内容进行访问,如图3-18所示。

enter image description here

如果是“指针的数组”和“数组的数组”,就会有很大的不同。

char *color_name[] = {      ←指针的数组
    red”,
    green”,
    blue”,
};

对以上的代码进行图解(参照图3-19),

![enter image description here][5]

char color_name[][6] = {
    red”,
    green”,
    blue”,
}

对以上的代码进行图解(参照图3-20),

enter image description here

以上两种情况都可以用color_name[i][j]的方式对数组进行访问,但是内存中数据的布局是完全不同的。

声明 只有在声明函数的形参的时候,数组的声明才能解读成指针的声明(参照3.5.1节)。

以上的语法糖,与其说使C变得更加容易理解,倒不如说它使C语言的语法变得更加混乱。是不是有很多人这么想?我就是其中的一个(虽然使用这个语法糖可以让多维数组作为参数被传递时更容易理解……)。而且K&R的说明更是使这种混乱局面雪上加霜。

在不是声明函数的形参的时候,数组声明和指针的声明是不可能相等的。

使用extern 的时候是最容易出现问题的(参照3.5.2节)。另外,声明局部变量或者结构体的成员时,写成

int hoge[];

会引起语法错误(对于结构体的成员,在ISO C99 中是允许这种写法的)。

存在数组初始化表达式的情况下,可以使用空的[],但这是因为编译器能够计算出数组元素的个数,所以可以省略书写元素个数。仅此而已,这种特征和数组扯不上任何关系。

要 点 【非常重要!!】 •数组和指针是不同的事物。

恶名昭著的指针究竟是什么

关于“指针”一词,在K&R 中有下面这样的说明(第5 章“指针和数组”的开头部分): 指针是一种保存变量地址的变量,在C 中频繁地使用。

其实在表达上,这样的说明是有很大问题的。总会让人感觉,一旦提起指针,就要把它当作变量的意思。实际上并非总是如此。

此外,在C 语言标准中最初出现“指针”一词的部分,有这样一段话:

指针类型(pointer type)可由函数类型、对象类型或不完全的类型派生,派生指针类型的类型称为引用类型。指针类型描述一个对象,该类对象的值提供对该引用类型实体的引用。由引用类型T 派生的指针类型有时称为“(指向)T 的指针”。从引用类型构造指针类型的过程称为“指针类型的派生”。这些构造派生类型的方法可以递归地应用。

这段话的内容也许会让你一头雾水(既然是标准,那总要有点标准的范儿吧)。那就让我们先关注第一句话吧,那里出现了“指针类型”一词。

提到“类型”,立刻会让人想起“int 类型”、“double 类型”等。同样,在C 语言中也存在“指针类型”这样的类型。

“指针类型”其实不是单独存在的,它是由其他类型派生而成的。以上对标准内容的引用中也提到“由引用类型T 派生的指针类型有时称为‘(指向)T 的指针’”。

也就是说,实际上存在的类型是“指向int 的指针类型”、“指向double的指针类型”。 因为“指针类型”是类型,所以它和int类型、double类型一样,也存在“指针类型变量”和“指针类型的值”。糟糕的是,“指针类型”、“指针类型变量”和“指针类型的值”经常被简单地统称为“指针”,所以非常容易造成歧义,这一点需要提高警惕*。

(*至少本书还是尽力将这些说法进行区别的,但有时候,无论怎么写也做不到自然地表述想要表达的意思,最后只好投降……非常抱歉。)

要 点

先有“指针类型”。 有了“指针类型”,才有了“指针类型的变量”和“指针类型的值”。

比如,在C中,使用int 类型表示整数。因为int是“类型”,所以存在用于保存int型的变量,当然也存在int型的值。指针类型同样如此,既存在指针类型的变量,也存在指针类型的值。

因此,几乎所有的处理程序中,所谓的“指针类型的值”,实际是指内存的地址。

变量的内容是保存在内存的某个地方的,“某个地方”的说法总是会让人产生困惑,因此,就像使用“门牌号”确定“住址”一样,在内存中,我们也给变量分配“门牌号”。在C的内存世界里,“门牌号”被称为“地址”。

分享到:
评论

相关推荐

    靳润昭 《C语言教程讲义》——很好的一本教程

    1 C语言概述 2 程序的灵魂—算法 3 数据类型、运算符与表达式 4 最简单的C程序设计—顺序程序设计 5 分支结构程序 6 循环控制 7 数组 8 函 数 9 预处理命令 10 指针 11 结构体与共用体 12 位运算 13 ...

    C语言程序设计(谭浩强)第三版

    第2章:算法——程序的灵魂 2.1什么是算法 2.2简单的算法举例 2.3算法的特性  2.4怎样表示一个算法  2.4.1;用自然语言表示算法 2.4.2用流程图表示算法 2.4.3三种基本结构和改进的流程图  2.4.4用N-S流程图表示...

    c语言配套教材电子教案

    第2章 程序的灵魂——算法 第3章 数据类型、运算符与表达式 第4章 最简单的C程序设计——顺序程序设计 第5章 选择结构程序设计 第6章 循环控制 第7章 数组 第8章 函数 第9章 预处理命令 第10章 指针 第11章...

    C程序设计 第四版 谭浩强 高清扫描版 带完整书签目录 加 学习辅导

    第2章 算法——程序的灵魂 2.1 什么是算法 2.2 简单的算法举例 2.3 算法的特性 2.4 怎样表示一个算法 2.4.1 用自然语言表示算法 2.4.2 用流程图表示算法 2.4.3 三种基本结构和改进的流程图 2.4.4 用N?S流程图表示...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    *5.6 C++处理字符串的方法——字符串类与字符串变量 5.6.1 字符串变量的定义和引用 5.6.2 字符串变量的运算 5.6.3 字符串数组 5.6.4 字符串运算举例 习题 第6章 指针 6.1 指针的概念 6.2 变量与指针 6.2.1 定义...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    *5.6 C++处理字符串的方法——字符串类与字符串变量 5.6.1 字符串变量的定义和引用 5.6.2 字符串变量的运算 5.6.3 字符串数组 5.6.4 字符串运算举例 习题 第6章 指针 6.1 指针的概念 6.2 变量与指针 6.2.1 定义...

    c语音新课件

    第2章 程序的灵魂——算法 第3章 数据类型、运算符与表达式 第4章 顺序结构程序设计 第5章 选择结构程序设计 第6章 循环结构程序设计 第7章 数组 第8章 函数 第9章 编译预处理 第10章 指针 第11章 结构与链表 第12...

    PPT-of-Tanghaoqiang-(C).rar_Windows编程_Visual_C++_

    第1章 C语言概述.ppt 第2章 程序的灵魂——算法.ppt 第3章 数据类型、运算符与表达式.ppt 第4章 最简单的C程序设计——顺序程序设计.ppt 第5章 选择结构程序设计.ppt 第6章 循环控制.ppt 第7章 数组.ppt 第8...

    我的编程感悟(中文PDF)(共37M二分卷)分卷二

    7.2.3 SIMD技术在C语言环境下的使用 196 7.2.4 MMX 编码技巧 197 7.2.5 SIMD 的应用举例 201 7.2.6 SIMD编程注意要点 203 7.2.7 SIMD的性能检测 204 第8章 引擎中的优化 205 8.1 Blit的优化 207 8.2 脏矩形优化 209 ...

    我的编程感悟(中文PDF)(共37M二分卷)分卷一

    7.2.3 SIMD技术在C语言环境下的使用 196 7.2.4 MMX 编码技巧 197 7.2.5 SIMD 的应用举例 201 7.2.6 SIMD编程注意要点 203 7.2.7 SIMD的性能检测 204 第8章 引擎中的优化 205 8.1 Blit的优化 207 8.2 脏矩形优化 209 ...

    c程序设计习题参考(谭浩强三版)习题参考解答

    第2章 程序的灵魂——算法 2 2.1 什么叫结构化的算法?为什么要提倡结构化的算法? 2 2.7 什么叫结构化程序设计?它的主要内容是什么? 2 第3章 数据类型、运算符与表达式 2 3.3请将下面各数用八进制和十六进制数...

Global site tag (gtag.js) - Google Analytics