| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2393 人关注过本帖
标题:[原创]谭浩强《C程序设计(第二版)》或《C++程序设计》讲解有误导或者疏漏 ...
只看楼主 加入收藏
grub2linux
Rank: 1
等 级:新手上路
帖 子:335
专家分:0
注 册:2004-12-25
收藏
 问题点数:0 回复次数:15 
[原创]谭浩强《C程序设计(第二版)》或《C++程序设计》讲解有误导或者疏漏!
谭浩强《C++程序设计》P182(或 C程序设计(第二版)P229 也差不多)中
关于xxx (*p)[n] (xxx为数据类型,n为数组元素个数) 的讲解有误导或者疏漏!

他的概念是“指向由m个元素组成的一维数组的指针变量”
但是下面的代码中却以二维数组的格式才能引用,换句话说,按以上的概念以一维数组的格式
根本就不能引用!(大家可以试试,比如 cout<<*(p+0)或p[0];)

#include <iostream>

using namespace std;

int main()

{

int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int (*p)[4],i,j;

cin>>i>>j;

p=a;

cout<<*(*p+i)+j)<<endl;  // 此处仅仅是a数组的简单重复,完全可直接用a[i][j] *(*(a+i)+j)来引用

return 0;

}

实际上,xxx (*p)[n] 是指固定以n个元素为一组,一直类推下去。。。这样,实际上内含二维数组的结构。引用时,要指定延伸的次数,
比如:

int a[20]={1,2,3,4,5,6,7,8,9,10,11,12,13......};
// 改成二维数组或多维数组也一样:
// int a[2][10]={1,2,3,4,5,6,7,8,9,10,11,12,13......};
// int a[2][2][5]={1,2,3,4,5,6,7,8,9,10,11,12,13......};

int (*p)[3]=a;  // 以3个元素为一组,一直类推下去。。。
printf("%d",p[2][4] 也可以*(*(p+2)+4)); // 表示要引用,从类推2次后(从0开始)的地址(7的地址)往后数第4个数(从0开始),
就是11。 // 如果改成 printf("%d",p[2](在0到2之内));  编译就会出错,因为仅仅是地址。

(但xxx (*p)[n] 好象在钱能的C++程序设计教程 清华版 里没提到)

[此贴子已经被作者于2005-7-9 17:32:46编辑过]


搜索更多相关主题的帖子: 谭浩强 疏漏 讲解 误导 
2005-07-04 16:01
realoneyjw
Rank: 1
等 级:新手上路
帖 子:99
专家分:0
注 册:2005-5-13
收藏
得分:0 
这本书没有看过

我一直告诫自己:要做一个踏实认真的人 E-mail:realoneyjw@ qq:18238423
2005-07-04 21:23
kai
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:52
帖 子:3450
专家分:59
注 册:2004-4-25
收藏
得分:0 
To grub2linux, 首先想说的是,我没看过谭先生的这本书,仅从你上面的这段描述,我认为,谭先生没有说错. 引用你的帖子:    他的概念是“指向由m个元素组成的一维数组的指针变量” 这个概念正确! 二维数组 是 一维数组的延伸. 比如 int a[3]; // 一维数组,在内存中开辟的3个integer 所需要的空间, 其首地址为 a, int a[3][4]; // 二维数组, 一维数组的延伸, 这里的3表示存在3个地址,              // 如果有地址变量指向该地址, 那么我们可以直接引用该地址变量, // 在该地址下开辟了4个Integer变量所需要的空间.      int (*p)[4]; p = a; // p 指向了二维数组的首地址, 也可以理解为, 地址的一维数组的起始值赋值于 p // 这样我们便可以对p 的引用而对 二维数组的值予以操作.    

自由,民主,平等,博爱,进步.
中华民国,我的祖国,中华民国万岁!中华民国加油!
本人自愿加入中国国民党,为人的自由性,独立性和平等性而奋斗!
2005-07-04 22:22
grub2linux
Rank: 1
等 级:新手上路
帖 子:335
专家分:0
注 册:2004-12-25
收藏
得分:0 
当然 二维数组 是 一维数组的延伸. 但是,我们在概念上不能混同它们. 他的概念是“指向由m个元素组成的一维数组的指针变量” 在最接近此概念的地方,你自己都说 "p = a; // p 指向了二维数组的首地址, 也可以理解为....等等" 注意, 你这里强调的是"二维数组". 还有,从另一方面说, 对这句话来说, 本身就是多种"歧义"的: 1, 指向一维数组的指针变量,这个一维数组由m个元素组成的 2, 指向一维数组的指针变量,指针变量由m个元素组成的 3, 是指针变量,它(或它们)指向由m个元素组成的一维数组 .... 科研是严谨的,这样表述严谨吗? 再看他的例子: int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; //除此之外,没有说明一维和多维数组都可以..也容易造成误解 int (*p)[4],i,j; //这里的[4]与上面的[4]雷同,(实际上这个数是可以任意指定的!) 这使人误解. 再看看,在此段的讲解中,不难发现: 几乎找不到"二维数组"的概念,绝大多数笔墨是"一维数组"... 补充一下:

int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int (*p)[4],i,j;

//注意:此处的[4]与上面的[4]一模一样.实际上可以为任意的数!

他这样讲解,没有讲出xxx (*p)[n]这种构造的真正关键之处!

相反会误导..

你当时就理解成可以为任意的数吗?

p=a; //此处赋值也是这样,正好把a数组的第一元素的地址赋给p,实际上可以任意指定位置

(当然必须有效),比如 p=a+1, or p=&a[1][2]等等..这样才能理解真正的含义...

cout<<*(*p+i)+j); //此处是以二维数组的格式引用的,

而概念却是"指向由m个元素组成的一维数组的指针变量." 你没有疑问吗?

而且,经过上面的的任意指定地址后,仍然可以用相当于二维数组的结构的方式来引用!

妙就妙在这里!

这些他都没有讲...

大家没有同感吗?..

[此贴子已经被作者于2005-7-5 14:57:40编辑过]


有缘相识!我中文系的 3月拿下C/C++/VC 5天写游戏 2月写游戏系统 有空去http://mykool.go2.
2005-07-05 00:55
kai
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:52
帖 子:3450
专家分:59
注 册:2004-4-25
收藏
得分:0 
To grub2linux, 看了你上面的话,知道你还停留在字面理解,没有明白其实质。 也许你对我上面的这段话会很不服气。 如果你清楚了指针的本质,那么对谭先生的解释,一看便会明白其意。 指针就其本质而言,是地址。如果我们知道了数据的地址,那么我们便可以通过对地址的操作(引用),而实现对数据的操作。 一维数组也好,二维数组也好,或者多维数组。就其本质而言,只是一种数据的存储方式。 一维数组在数据结构中,可以说是最基本的存储方式。二维数组也通常很有用。 但是,如果你清楚OOP的话,通常程序员倾向于使用class 来表达对数据的描述。这是对象化数据描述方式。 其次,像 LinkedList, DoubleLinkedList, Stack, Heap, HashMap, Vector, 等等,这些都被抽象出来,作为某种基本的结构在数据的存储中予以应用。 不过,有一点程序员必须清楚,数据不是漂浮在空气中的。数据的客观存在意味着其地址的客观存在。作为例外,Register没有地址。 如果清楚了这一层,那么你上面讨论的只是技术的支模细节了。 一个合格的程序员应该从宏观着手,把握程序的大局。知道如何将一个问题以模块化方式分析。并将任务分配给小组的每个成员,当然如果你是小组的唯一成员,那么所有的块程序都得你自己写了。这是我想告诉你的无剑胜有剑的道理。 再来说一些技术的枝模细节,二维数组的指针引用是一种丑陋的代码。程序员通常取而代之使用class

自由,民主,平等,博爱,进步.
中华民国,我的祖国,中华民国万岁!中华民国加油!
本人自愿加入中国国民党,为人的自由性,独立性和平等性而奋斗!
2005-07-05 20:16
grub2linux
Rank: 1
等 级:新手上路
帖 子:335
专家分:0
注 册:2004-12-25
收藏
得分:0 
对于已经学成者来说,已经早早走过了这个阶段,
但是他的这个教材是最基本的教材种类,要知道,此书的读者是初学者,
必须要把最基本的枝节弄清楚的
没有局部怎么有宏观?

我的帖子已经很清楚的表书了我的意思, 我觉得他没有讲解到要害处,会使学习者一知半解..


[此贴子已经被作者于2005-7-5 21:20:46编辑过]



有缘相识!我中文系的 3月拿下C/C++/VC 5天写游戏 2月写游戏系统 有空去http://mykool.go2.
2005-07-05 21:19
yameng
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2005-7-6
收藏
得分:0 
grub2linux是不是学-钱能C++?

to kai:
同感,grub2linux好象看帖时总是不怎么仔细体会,有时还要针尖对麦芒的争一下。

http://www.
新手,请多关照
2005-07-06 01:45
grub2linux
Rank: 1
等 级:新手上路
帖 子:335
专家分:0
注 册:2004-12-25
收藏
得分:0 
以下是引用yameng在2005-7-6 1:45:20的发言: grub2linux好象看帖时总是不怎么仔细体会,有时还要针尖对麦芒的争一下。
嘿嘿,yameng也在这儿..? 没错, 我是程序员论坛的学-钱能C++ 呵呵.. 说实话,你这话我有点不同意的,对学习问题我是追根究底,为了弄清楚疑惑,对解答者的回帖,当然是认真看的 人家好心化时间写帖帮助嘛.当然是珍惜的,不过觉得kai朋友倒是可能没有细看我的对谭老师在这一知识点上的意见... 要说"针尖对麦芒",我觉得研究问题倒是应该提倡的,这样才能精细的互相发现理解不到的地方, 只要对问题不对人,有什么不好呢?

[此贴子已经被作者于2005-7-6 8:33:31编辑过]


有缘相识!我中文系的 3月拿下C/C++/VC 5天写游戏 2月写游戏系统 有空去http://mykool.go2.
2005-07-06 08:28
apodemas
Rank: 1
等 级:新手上路
帖 子:153
专家分:0
注 册:2005-4-22
收藏
得分:0 
我同意楼主的观点,面向大众的教材中的错误是不能以所谓"没有理解本质"来搪塞的
可是...
我还是不明白
我按照楼主的说法去小改了一下
#include &lt;iostream.h&gt;
void main()
{
 int a[2][3]={1,3,5,4,56,7};
 int (*p)[2]=a;
 int i,j;
 cin&gt;&gt;i&gt;&gt;j;
 cout&lt;&lt;*(*(p+i)+j)&lt;&lt;endl;  // 此处仅仅是a数组的简单重复,完全可直接用a[i][j] *(*(a+i)+j)来引用
}
编译就会出错,而把a[2][3]中的2和3颠倒就OK了,是不是哪里理解错了呢?拜托谁告诉我........

[此贴子已经被作者于2005-7-21 22:54:51编辑过]



2005-07-21 22:43
Antigloss
Rank: 1
等 级:新手上路
帖 子:109
专家分:0
注 册:2004-12-30
收藏
得分:0 
楼上的 void main 也是一个错误,请看 http://bbs.bc-cn.net/bbs/dispbbs.asp?boardID=5&ID=24305&page=1 还有,.h早就过时了。请用 #include <iostream> using std::cout; using std::endl; ... ... 或者干脆用 using namespace std; 不过不推荐哦~ 国产的书不是过时,就是错漏百出~要看还是看国外的好~ 就连国内的教师,真正懂 C/C++ 的人我想也没几个。 都是学了几天就来教别人,真是贻笑大方。 当年教我 C++ 的那个老师,竟然连 复制构造函数 和 赋值运算符重载都分不清,竟然说两者取其一即可。真乃大汗!
2005-08-04 11:44
快速回复:[原创]谭浩强《C程序设计(第二版)》或《C++程序设计》讲解有误导或者 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.045645 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved