- 浏览: 445437 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
进退取舍:
谢谢,这个用上了!!
Java 一个线程池的示例 -
pb_water:
感谢楼主,打算买楼主的书,支持一下,楼主功德无量
JavaScript内核系列第0版整理稿下载 -
lancezhcj:
有图会直观的多呢,再摸索摸索
有限自动机与建模 -
hsmsyy:
这里应该是原创了吧,楼主我觉得闭包的作用:实现面向对象。有待商 ...
JavaScript内核系列 第7章 闭包 -
wll52:
在应用退出之前,需要释放连接 con.disconnect() ...
使用smack与GTalk通信
前言
C语言中指针,可以算是最灵活,最强大的地方,同时也是最艰深的地方。用不好的话,什么段错误,内存违例等以前没见过的东西都会跳出来。最近看《UNIX系统编程》,感觉能把C语言用到这个水平,才能算是登堂入室。
一般来说,我们会把指针跟数组联系起来理解,比如*p就是一个一维数组,**p是两维数组等,而一般而言,见到两维的指针也算是难得了,更高维的只怕看一会就会晕掉。《UNIX系统编程》中有个关于参数列表的例子,感觉对指针运用的已经到出神入化的境地,所以贴出来大家参考一下。
指向指针的指针
在C语言的入口main函数中,有一个**argv参数,指明命令行参数,一般写法是这样:
int main(int argc, char **argv){ /* * code here. */ }
这个**argv,是一个指向指针的指针,用来将命令行参数保存下来,比如,输入一条命令:
**argv中的内容即为 prog, -c, -v, 200. 因为prog, -c等的长度不等,就需要一个指针来引用他们,而prog后边接几个参数也是不定的,所以有需要有一个指针来引用,所以就是这里的二维指针了。画一个table可能看起来比较清晰一些:
prog |
-c |
-v |
200 |
再考虑这样一种情况,shell程序,对于你会输多少行命令也是不知道的,那它就需要再多一个指针来引用你会有多少个命令输入。这就是我们今天要看的(***ptr)了。
指向"指针的指针"的指针
书中的例子是这样,先看下函数的原型:
int makeargv(const char *s, const char *delimiters, char ***argvp);
函数接受三个参数,第一个是要分析的串,第二个是界定符序列,第三个是生成的"指针的指针"(即二维数组)的指针。实现比较简单,主要是看其中关于指针的用法:
/* * author : juntao.qiu */ int makeargv(const char *s, const char *delimiters, char ***argvp){ int error; int i; int numtokens; const char *snew; char *t; if((s == NULL) || (delimiters == NULL) || (argvp == NULL)){ error = EINVAL; return -1; } *argvp = NULL; snew = s + strspn(s, delimiters); if((t = malloc(strlen(snew)+1)) == NULL) return -1; strcpy(t, snew); numtokens = 0; if(strtok(t, delimiters) != NULL) for(numtokens = 1; strtok(NULL, delimiters)!= NULL; numtokens++); if((*argvp = malloc((numtokens+1)*sizeof(char *))) == NULL){ error = errno; free(t); errno = error; return -1; } if(numtokens == 0){ free(t); }else{ strcpy(t, snew); **argvp = strtok(t, delimiters);//注意此处的指针操作 for(i = 1;i < numtokens;i++) *((*argvp)+i) = strtok(NULL, delimiters);//注意此处的指针操作 } *((*argvp)+numtokens) = NULL; return numtokens; }
程序的主体比较简单,就是按照传入的s,按照界定符delimiters对其进行分割,分割完成后将其放在一个二维数组中,第一维表示最后数组,第二维表示第一个数组中每一个元素的值。
测试
好了,我们测试一下其运行情况:
int main(int argc, char **argv){ char delim[] = " \t"; int i; char **argvp; int numtokens; char *test = "mine -c 10 2.0"; if((numtokens = makeargv(test, delim, &argvp)) == -1){ fprintf(stderr, "failed to parse the string you given:%s\n", test); return 1; } printf("argument contains :\n"); for(i = 0;i < numtokens;i++) printf("%d:%s\n", i, argvp[i]); return 0; }
运行结果如下:
Makefile a.exe makeargv.c nbproject
C:\development\cpl\usp>a
argument contains :
0:mine
1:-c
2:10
3:2.0
个人感觉,能把指针用到这种熟练程度,才算是对C掌握了。《UNIX系统编程》中的代码非常优雅,从大二一直读到毕业,毕业后得空还在读。我会尽量陆续把体会贴出来,以供参考。
评论
对于c来说,the simple,the best。
当然,指的是产品,做产品和自己研究是不一样的。
你完全可以用N级指针搞个代码,贴在网上。
你不是在说笑吧?二级指针就不敢用了,那是做什么系统的?Hello,world吗?the simple, the best是没错,但是也不能simple到连二级指针都不敢用吧?那就干脆别用C了,用C就是用个指针!
我还真没见过那个项目中没有用到二级(和二级以上)的指针层次。
也许是领域不同,在嵌入式领域,我真没见过用三级指针的,二级指针就很少了。
不知道您是在哪个领域。。。。。
对于c来说,the simple,the best。
当然,指的是产品,做产品和自己研究是不一样的。
你完全可以用N级指针搞个代码,贴在网上。
你不是在说笑吧?二级指针就不敢用了,那是做什么系统的?Hello,world吗?the simple, the best是没错,但是也不能simple到连二级指针都不敢用吧?那就干脆别用C了,用C就是用个指针!
我还真没见过那个项目中没有用到二级(和二级以上)的指针层次。
对于c来说,the simple,the best。
当然,指的是产品,做产品和自己研究是不一样的。
你完全可以用N级指针搞个代码,贴在网上。
知己啊,我也是喜欢把星号紧跟在类型的后面然后再空格。一般这么写让我看着清楚些,除了一口气声明多个变量的时候:
char c, *lpszName, d;
所以我声明变量都是一行行分开来声明……
C认为声明形式应该尽量接近使用形式。但我认为这个牵强。把声名的东西是什么明确指示出来才更重要。这也是Java做的努力吧。。
1:如果numtokens=0,根本没必要分配一次内存。应该将分配放在numtokens==0的检查之后。
2:函数内部分配了内存,如果调用者没有释放,则造成内存泄漏。
个人认为,第一,指针超过二重就不要用了;第二,不要用typedef,试图屏蔽数据类型的行为很恶心(迫不得已平台相关,条件编译的除外)
而且不考虑初级还是高级,希望LZ过一年再来看自己的代码,能写出这种内存使用代码的人也能如此狂妄,怪不得开源社区一直高质量代码百分比不高,原来多亏LZ你啊
大侠,你看完帖子了没有就在这儿喊?如果是看完了,那只能说你不识字了,我早就说明那个是《UNIX系统编程》中的一个例子,写的很好,所以贴出来大家学习下。不是我写的,再说了,说这个代码写的烂的人只不过是在暴露自己不学无术的真面目而已。
已经说了,文章的题目起的有点大了,例子给的比较简单,不好意思。
向你这样半吊子而且狂妄的人不多了
复制一段代码:
void freemakeargv(char **argv) {
if (argv == NULL)
return;
if (*argv != NULL)
free(*argv);
free(argv);
}
请问这个代码在你的测试里有涉及吗?
非得我挑明了说,真是笑话
能写出这样的代码,可见你的功底之差。根本就是为了代码而代码,根本就没理解二重指针的使用范畴。
因此,看见你在里面判断argv==NULL就让我发笑,还不如林博士的在strcpy里面用assert。最起码,林博士的assert对于粗心的程序员还有用,你的argv==NULL只能对入错行的程序员有用。比你高级点。
我认为二维数组 char *a[];的方式比较好
这个作为C里面的一种很基础的东西,是很实用的,处理多条字符串的时候就需要用到。
先声明一些指针,然后按照需求在对应的地址上malloc。
一定程度上满足了我一些洁癖的要求,呵呵。
知己啊,我也是喜欢把星号紧跟在类型的后面然后再空格。一般这么写让我看着清楚些,除了一口气声明多个变量的时候:
char c, *lpszName, d;
所以我声明变量都是一行行分开来声明……
int main(int argc, char* argv[]);
???
都说了,可以把指针理解成数组(当然不是完全等价),所以
char *argv[] == char **argv == char argv[][], 你可以分别试一下。
char argv[][]
你试过吗?数组那一维可以留空,留空是什么意思您讲解一下?
代码不是等价就算过,char* argv[]可读性更好,星号也应该打在类型这一边。
如果从团队出发,最好不超过二级,否则影响维护,而且出错概率大大增加
我好像知道它把[][]看成什么了。。。嗯。。。
好像就是* xxx[],而不是二位数组。。。。那个[][]和[][N]完全是不同的东西。。。。
这个明显是编译期bug么。。。
研究所为的看成什么对C是没有意义的,C有很多的hacks可以做,比如char *a[0]之类的声明很多人经常用,无非是为了方便,增强后续代码的可读性,和文面的意义关联不大。总之C是一门简单清晰的语言,语法上只是忠实翻译一些东西,比如&无非就是取址,具体赋予其什么样的意义取决于传统,设计,以及环境。
至于所谓的***,我觉得单个情况也就罢了,一般来讲最好还是用typedef把具体的意义抽象出来,否则不好读。
嗯。。。
我只是从原理上说一下。。。这么搞应该属于编译器bug
分享C语言或者Linux kernel 可以到chinaunix 那边去。
和这里不是一个级别的。
虽说物以类聚,不过大家都是一步步走过来的,哪里都可以交流。我看这个论坛有些人就很有意思,别人说话刻薄,或者回小白贴也不恼怒,只是就着技术上接着讨论,这样的人多一些自然能成风气,说话刻薄的只会自讨没趣。
分享C语言或者Linux kernel 可以到chinaunix 那边去。
和这里不是一个级别的。
这类的定义挺有意思的,能做出一些面向对象的东西来。
还有Linux里面head_list也挺有意思的。
也有点面向对象的意思在里面。
发表评论
-
JavaScript内核系列 第15章 服务器端的JavaScript
2012-02-12 21:39 2214第15章已经在icodeit上发布,这一章分为上/下两篇,请朋 ... -
使用vim开发python及graphviz绘图
2011-12-23 14:49 6341基本需求 使用vim中的autocmd命令可以很容易的将正在 ... -
Java脚本技术应用实例
2011-01-22 11:24 4094前言 一直以来都很喜欢可以自由扩展的软件,这一点应该已经在很 ... -
可编程计算器(phoc)的设计与实现
2011-01-17 11:34 1865前言 借助JavaScript脚本 ... -
函数式编程(javascirpt)
2009-04-18 22:18 1217前言 Javascript,有人称 ... -
C和指针
2009-05-21 23:15 1061前言 指针是C的灵魂,正是指针使得C存在了这么多年,而且将长 ... -
C和指针(续)
2009-05-25 23:41 1317前言 上一篇《C和指针》可能对关于C和指针的有些内容没有说透 ... -
有限自动机与建模
2009-06-06 10:48 1649前言 在学校学程序设计语言的时候,能接触到的所有例子没有一个 ... -
事件和监听器
2009-06-21 22:06 1370前言 事件监听器是经 ... -
基于总线的消息服务(BBMS)的设计与实现
2009-07-25 22:19 1311前言 异步事件的通知机制在比较有规模的软件设计中必然会有涉及 ... -
JavaScript内核系列 第9章 函数式的Javascript
2010-05-13 19:20 3714第九章 函数式的Javascript 要说Ja ... -
JavaScript内核系列 第8章 面向对象的JavaScript(下)
2010-05-06 09:40 3593接上篇:JavaScript内核系列 第8章 面向对象的Jav ... -
JavaScript内核系列 第8章 面向对象的JavaScript(上)
2010-05-06 09:26 2848第八章 面向对象的 Javascript ... -
JavaScript内核系列 第7章 闭包
2010-05-04 08:48 3776第七章 闭包 闭包向来给包括JavaScript程序 ... -
JavaScript内核系列 第6章 正则表达式
2010-04-27 19:44 3945第六章 正则表达式 正则表达式是对字符串的结构 ... -
JavaScript内核系列 第5章 数组
2010-04-24 15:17 4378第五章 数组 JavaScript的数组也是一个比较 ... -
Swing小应用(Todo-List)之三
2010-04-22 20:47 2066前言 去年9月份开发的那个小工具sTodo,只是做到了能用, ... -
JavaScript内核系列 第4章 函数
2010-04-18 17:31 4964第四章 函数 函数,在C语言之类的过程式语言中 ... -
JavaScript内核系列 第3章 对象与JSON
2010-04-12 09:12 6021第三章 对象与JSON JavaScript对象与传 ... -
JavaScript内核系列 第2章 基本概念
2010-04-03 19:44 5522第二章 基本概念 ...
相关推荐
利用C语言的多级指针创建了三维动态数组,并操纵数组.最后释放三级指针.这个例子展示了C语言指针功能的强大、灵活与“危险”。
这是我自己写的关于多级指针的使用方法,讲解简短使用
多级反馈队列调度C语言设计进程控制块PCB表结构,适用于多级反馈队列调度算法。PCB结构通常包括以下信息:进程名,进程优先数,轮转时间片,进程已占用的CPU时间,进程还需要的CPU时间,进程的状态,当前队列指针等...
C语言多维数组与多级指针[参照].pdf
指针定义与使用、指针与函数、指针与数组、指针与字符串、指针数组与多级指针 、指针与动态内存分配
掌握数组的使用 了解多维数组的使用 掌握指针的概念和使用 了解多级指针的概念
多级指针,数组指针和函数指针的介绍和相关实例
C语言教程_C语言指针教程 包括指针的概念、指针变量、动态内存分配、多级指针等 资源为视频教程资源 希望对你的 C语言 学习有所帮助。
多维数组与多级指针是初学者经常感觉迷糊的一个地方。超过二维的数组和超过二级的指针其实并不多用。但只要掌握一定的方法,理解多级指针和“多维”数组完全可以像理解一级指针和一维数组那样简单。
自己编写的C语言指针培训教材。适用于公司内中级水平的嵌入式软件开发工程师。 内容包括:C语言指针的概念、用法、多级指针、函数指针等高级用法。
解决你C语言指针的各种概念总结(包括空指针、野指针、数组指针、指针数组、函数指针、指针函数、多级指针等等)。代码工程基于VS19平台。 参考说明:https://blog.csdn.net/qq_44078824/article/details/118379594
主要介绍了浅谈使用C++多级指针存储海量qq号和密码,分享了相关实例代码,具有一定借鉴价值,需要的朋友可以参考下
介绍C指针 与 提高 介绍指针的使用,一级指针 二级指针 多级指针的使用 整理
6.1.5 指向指针变量的指针与多级指针 6.1.6 指向void类型的指针 6.2 指针与数组 6.2.1 数组元素的指针引用 6.2.2 多字符串的存储与处理 6.2.3 内存的动态分配与动态数组的建立 6.3 指针与函数 6.3.1...
1. C语言概述 ...7.4 多级指针 93 7.5 指针和函数 93 7.7 指针和字符串 95 返回值:成功转换后整数 106 7.8 指针小结 107 8. 内存管理 107 8.1 作用域 107 8.2 内存布局 110 8.3 内存分区代码分析 116
本书的每一章先介绍概念,再结合问题写程序。书中给出了各种类型的程序实例,使用户进一步...指针是C语言的难点,书中程序从简单到复杂,并给出了示意图,使用户很容易掌握多级指针。书中还给出了一些图形编程的例子。
第一章 关键字 1.1 最宽恒大量的关键字auto 1.2 最快的关键字register ...4.5 多维数组与多级指针 4.6 数组参数与指针参数 4.7 函数指针 第五章 内存管理 5.1 什么是野指针 5.2 栈堆静态区 5.3 常见内存错误与对策
10.7 指针数组和指向指针的指针 161 10.7.1 指针数组的概念 161 10.7.2 指向指针的指针 164 10.7.3 main 函数的参数 166 10.8 有关指针的数据类型和指针运算的小结 167 10.8.1 有关指针的数据类型的小结 167 10.8.2 ...