Question: 把C PRIMER PLUS看完，能找工作了么？

引用 11 楼 均陵鼠侠的回复:[quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。[/quote] 真是大言不惭啊。。。。。。。。

引用 11 楼 均陵鼠侠 的回复：[quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。[/quote]《C prime plus》的作者算什么东西我不知道，但可以肯定是肯定比你这只会说大话的强，如果说他不算什么东西的话，那么你就是连东西都不如的“人”。懂？人这个字之所以在这里要打引号，是因为你身为一个“人”却连对人最起码的尊重都没有。

哥们。。。有时间跟人在这里扯这么久蛋蛋，不如静下心，想想平时用电脑的时候哪边有什么不方便的，自己动手写个程序。虽然可能一开始会写的非常非常非常非常非常蛋疼，但是只要你静下心写完了，一定会有很多收获的。 编程从来不是“看”基本书就能掌握的事情，而且，“看完”一本书，还远远达不到看书的要求。 同是菜鸟，加油吧

我就想说你有这精力不如好好读书考个大学。。。看数学书逗比看编程书强。。。cp+带你入门而已要说能力还不如玩几把OJ收获大。。你这样子自己没法做项目，也没本事搞创作，面试的时候你要告诉考官“我看完了cp+来面试的”这种话吗？这话不只是没分量，完全是在开玩笑。。

没看完C PRIMER PLUS都可以找工作。  去找吧，少年！起薪开高些，至少5K起，如果足够自信，10K起。

引用 19 楼 mosquitoh 的回复:[quote=引用 18 楼 sholber 的回复:] [quote=引用 16 楼 mosquitoh 的回复:] [quote=引用 11 楼 sholber 的回复:] [quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。[/quote] 呵呵，他算什么东西，你一直都这么狂妄吗？世界上的牛人多得很，倒是没见过这么狂的。哈佛麻理的计算机博士也不会说这种不知道天高地厚的话吧？就算人家写的书定位初级，那是人家普及计算机知识，你算什么东西？[/quote]  看来哈佛麻理的计算机博士不知天高地厚的时候还需要通知你、告诉你。我的天，原来你这么厉害，失敬失敬。[/quote] 那是不是通知了你呢？你意思是世界顶级的计算机人才都像你那么狂？[/quote]  如果没通知你，你怎么知道他们不狂？不管通知你还是没有通知你，这和有没有通知我是两回事，你的逻辑很有问题。要知道，学计算机要求很强的逻辑性。 我倒没觉得我很狂，那是你给我扣的帽子，本人不接受。另外，不知道你所说的外国大牛需要什么标准才算。开发DirectX的那三个人算吗？尤其是亚力克斯，这货刚进微软时，面试官问他如何看待大众，他居然说“大众都是白痴”（参见《微软帝国叛逆》）。哦，好吧，这种狂人，你不需要把他归为大牛。

引用 18 楼 sholber 的回复:[quote=引用 16 楼 mosquitoh 的回复:] [quote=引用 11 楼 sholber 的回复:] [quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。[/quote] 呵呵，他算什么东西，你一直都这么狂妄吗？世界上的牛人多得很，倒是没见过这么狂的。哈佛麻理的计算机博士也不会说这种不知道天高地厚的话吧？就算人家写的书定位初级，那是人家普及计算机知识，你算什么东西？[/quote]  看来哈佛麻理的计算机博士不知天高地厚的时候还需要通知你、告诉你。我的天，原来你这么厉害，失敬失敬。[/quote] 那是不是通知了你呢？你意思是世界顶级的计算机人才都像你那么狂？

引用 16 楼 mosquitoh 的回复:[quote=引用 11 楼 sholber 的回复:] [quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。[/quote] 呵呵，他算什么东西，你一直都这么狂妄吗？世界上的牛人多得很，倒是没见过这么狂的。哈佛麻理的计算机博士也不会说这种不知道天高地厚的话吧？就算人家写的书定位初级，那是人家普及计算机知识，你算什么东西？[/quote]  看来哈佛麻理的计算机博士不知天高地厚的时候还需要通知你、告诉你。我的天，原来你这么厉害，失敬失敬。

引用 23 楼 sholber 的回复:[quote=引用 22 楼 mosquitoh 的回复:] [quote=引用 20 楼 sholber 的回复:] [quote=引用 19 楼 mosquitoh 的回复:] [quote=引用 18 楼 sholber 的回复:] [quote=引用 16 楼 mosquitoh 的回复:] [quote=引用 11 楼 sholber 的回复:] [quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。[/quote] 呵呵，他算什么东西，你一直都这么狂妄吗？世界上的牛人多得很，倒是没见过这么狂的。哈佛麻理的计算机博士也不会说这种不知道天高地厚的话吧？就算人家写的书定位初级，那是人家普及计算机知识，你算什么东西？[/quote]  看来哈佛麻理的计算机博士不知天高地厚的时候还需要通知你、告诉你。我的天，原来你这么厉害，失敬失敬。[/quote] 那是不是通知了你呢？你意思是世界顶级的计算机人才都像你那么狂？[/quote]  如果没通知你，你怎么知道他们不狂？不管通知你还是没有通知你，这和有没有通知我是两回事，你的逻辑很有问题。要知道，学计算机要求很强的逻辑性。 我倒没觉得我很狂，那是你给我扣的帽子，本人不接受。另外，不知道你所说的外国大牛需要什么标准才算。开发DirectX的那三个人算吗？尤其是亚力克斯，这货刚进微软时，面试官问他如何看待大众，他居然说“大众都是白痴”（参见《微软帝国叛逆》）。哦，好吧，这种狂人，你不需要把他归为大牛。[/quote] 是没通知我，我意思是也没通知你，你怎么知道他们都像你那样狂呢？美国的计算机博士，我身边也有，人家都知道，有一句话叫人外有人，天外有天，保持着虚心的学习态度，才可以进步，而不是半桶水框框响。（当然，你可能不认为自己是半桶水，那是你自己的问题，我也不用提什么哈佛麻里了）。至于什么“大众是白痴”，我估计你连”大众“两个字都没看明白。真理确实只掌握在少数人的手中，我也是这样认为的。[/quote]  至少我还是了解到有不少外国大牛很狂，Linus应该也是很狂的（按照你对“狂”的定义）。美国的计算机博士在你的身边，为什么还要到这里讨论CPP这种初级的东西，我很奇怪。 你始终在给我扣帽子，从“狂”到“半桶水”，看起来你很了解我的样子。先管管自己吧。我要是你，就不在这里浪费时间 ，我会先把CPP看明白再说。[/quote]估计他没看过这本书，人家现在在美国。很奇怪吗？LINUS是始祖，他狂没人有意见。反正吧，你也许不是我说的这样，我可能不能这样轻易评价人。

引用 22 楼 mosquitoh 的回复:[quote=引用 20 楼 sholber 的回复:] [quote=引用 19 楼 mosquitoh 的回复:] [quote=引用 18 楼 sholber 的回复:] [quote=引用 16 楼 mosquitoh 的回复:] [quote=引用 11 楼 sholber 的回复:] [quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。[/quote] 呵呵，他算什么东西，你一直都这么狂妄吗？世界上的牛人多得很，倒是没见过这么狂的。哈佛麻理的计算机博士也不会说这种不知道天高地厚的话吧？就算人家写的书定位初级，那是人家普及计算机知识，你算什么东西？[/quote]  看来哈佛麻理的计算机博士不知天高地厚的时候还需要通知你、告诉你。我的天，原来你这么厉害，失敬失敬。[/quote] 那是不是通知了你呢？你意思是世界顶级的计算机人才都像你那么狂？[/quote]  如果没通知你，你怎么知道他们不狂？不管通知你还是没有通知你，这和有没有通知我是两回事，你的逻辑很有问题。要知道，学计算机要求很强的逻辑性。 我倒没觉得我很狂，那是你给我扣的帽子，本人不接受。另外，不知道你所说的外国大牛需要什么标准才算。开发DirectX的那三个人算吗？尤其是亚力克斯，这货刚进微软时，面试官问他如何看待大众，他居然说“大众都是白痴”（参见《微软帝国叛逆》）。哦，好吧，这种狂人，你不需要把他归为大牛。[/quote] 是没通知我，我意思是也没通知你，你怎么知道他们都像你那样狂呢？美国的计算机博士，我身边也有，人家都知道，有一句话叫人外有人，天外有天，保持着虚心的学习态度，才可以进步，而不是半桶水框框响。（当然，你可能不认为自己是半桶水，那是你自己的问题，我也不用提什么哈佛麻里了）。至于什么“大众是白痴”，我估计你连”大众“两个字都没看明白。真理确实只掌握在少数人的手中，我也是这样认为的。[/quote]  至少我还是了解到有不少外国大牛很狂，Linus应该也是很狂的（按照你对“狂”的定义）。美国的计算机博士在你的身边，为什么还要到这里讨论CPP这种初级的东西，我很奇怪。 你始终在给我扣帽子，从“狂”到“半桶水”，看起来你很了解我的样子。先管管自己吧。我要是你，就不在这里浪费时间 ，我会先把CPP看明白再说。

引用 20 楼 sholber 的回复:[quote=引用 19 楼 mosquitoh 的回复:] [quote=引用 18 楼 sholber 的回复:] [quote=引用 16 楼 mosquitoh 的回复:] [quote=引用 11 楼 sholber 的回复:] [quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。[/quote] 呵呵，他算什么东西，你一直都这么狂妄吗？世界上的牛人多得很，倒是没见过这么狂的。哈佛麻理的计算机博士也不会说这种不知道天高地厚的话吧？就算人家写的书定位初级，那是人家普及计算机知识，你算什么东西？[/quote]  看来哈佛麻理的计算机博士不知天高地厚的时候还需要通知你、告诉你。我的天，原来你这么厉害，失敬失敬。[/quote] 那是不是通知了你呢？你意思是世界顶级的计算机人才都像你那么狂？[/quote]  如果没通知你，你怎么知道他们不狂？不管通知你还是没有通知你，这和有没有通知我是两回事，你的逻辑很有问题。要知道，学计算机要求很强的逻辑性。 我倒没觉得我很狂，那是你给我扣的帽子，本人不接受。另外，不知道你所说的外国大牛需要什么标准才算。开发DirectX的那三个人算吗？尤其是亚力克斯，这货刚进微软时，面试官问他如何看待大众，他居然说“大众都是白痴”（参见《微软帝国叛逆》）。哦，好吧，这种狂人，你不需要把他归为大牛。[/quote] 是没通知我，我意思是也没通知你，你怎么知道他们都像你那样狂呢？美国的计算机博士，我身边也有，人家都知道，有一句话叫人外有人，天外有天，保持着虚心的学习态度，才可以进步，而不是半桶水框框响。（当然，你可能不认为自己是半桶水，那是你自己的问题，我也不用提什么哈佛麻里了）。至于什么“大众是白痴”，我估计你连”大众“两个字都没看明白。真理确实只掌握在少数人的手中，我也是这样认为的。

引用 11 楼 sholber 的回复:[quote=引用 9 楼 mosquitoh 的回复:] [quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。[/quote] 呵呵，他算什么东西，你一直都这么狂妄吗？世界上的牛人多得很，倒是没见过这么狂的。哈佛麻理的计算机博士也不会说这种不知道天高地厚的话吧？就算人家写的书定位初级，那是人家普及计算机知识，你算什么东西？

C/C++ 只是一种工具，真正开发还有很长的路要走

呵呵，你们都吓唬lz，我觉得应该够了，一个应届毕业生也懂不了很多，基础学好后面更着做项目就容易上手了。找工作前自己在找几个小项目练下手

功夫在诗外。

光有c的语法是远远不够的，数据库，操作系统api，多进程，多线程，unix命令，脚本。。等等找个培训机构吧，靠谱点

引用 9 楼 mosquitoh 的回复:[quote=引用 3 楼 sholber 的回复:] 你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说[/quote]  作者的名字你倒背得挺熟的。我还以为Stephen Prata是何方神圣，原来是c prime plus的作者。他算什么东西，这本书也就是一本非常初级的教程而已。

还不够的 你还是要一些开发经验

引用 3 楼 sholber 的回复:你把程序员看成啥了。 你把你看成什么了？程序员也是一步一步走过来的。 况且你现在能不能得Stephen Prata的真传还难说

把《葵花宝典》倒背如流＋挥刀自宫ed，能闯荡江湖了么？


Question: 关于浮点数在内存中的表示和计算问题。

不能准确表示不代表不能计算，主要是个精度问题。

精度问题,不能精确表示0.2, 用0.200000002尽可能接近, 运算结果去掉不需要显示的就可以了

那就证明不是IEEE浮点咯，最简单的可以用字符串模拟，效率高的用二进制模拟

很多软件中小数实际上是用整数表示的


Question: 检测链表中存在的环

引用 3 楼 fly_dragon_fly 的回复:1->2->3->4->5->3 这样就成环了  最后一个元素指向第三个元素吗？？

1->2->3->4->5->3 这样就成环了

定义两个指针，一个一次走一步， 一个一次走两步， 如果两个指针最后一样了，就有环。如果最后是NULL， 就没有环，这个是最被玩坏了的面试题。

节点增加个数值类型成员。遍历链表，访问一个节点就+1。取出大于1的节点指针

有环的链表，元素个数无穷啊。

假设链表长度N，意思是如果有环，不用肯定在遍历到N个元素（或者之前）就会出现


Question: 用C完成php的一个功能，请教大神。

引用 4楼赵4老师 的回复:不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！好主意哈哈

查询端口映射表……你要问我如何查，我也不知道。

up...没人吗？？？？？？？？？？？

大神呢...

没人吗？？？求大神呀


Question: 关于指针数组的问题

不好意思啊，因为看了很久都没人回答，就直接无满意回帖了，分也没了。刚好你就回了。

因为pS[i]指向的是字符串数组。 就像：  char* p = "abc"; printf("%s", p);


Question: C语言指针和二位数组的问题

5楼已经说明白了。我简单说一下重点，zipper+1是zipper这个数组第二的元素的地址，即zipper[1]的地址。 然后你用*（zipper+1），那么它的值就是zipper[1]。其实zipper[1]就是一个一维数组，它有两个int。 那么你想一下，数组名即代表它的地址。你可以这样看zipper[1]是数组名，那么即代表它的地址zipper[1]的地址。 在这里给你一个通用的公式 *（zipper+a）=  zipper[a] *（*（zipper+a）+b）= zipper[a][b]

int a[10]  a 和 &a[0]地址一样   问题性质就是这样

顶5L，问题的关键点在于“类型”。

电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

引用 5 楼 sholber 的回复:看到前几楼的发言我就觉得……。C的类型系统是摆设么？不用类型系统，有些东西仅凭地址就解释得清楚么？动辄地址地址的，说明你根本就没理解指针和数组。  首先明确一点：如果一个数组类型的表达式不是sizeof和一元&的操作数，且不是用于初始化一个数组，则它会被转换为指向数组首元素的指针。接下来：  1，zippo是一个具有4个元素的数组，元素的类型是int [2]；  2，在表达式zippo+1中，zippo隐式转换为指向其首元素的指针，元素的类型是int [2]，所以是转换为指向int [2]的指针int (*) [2]（实际上指向的位置是原数组的元素zippo [0]或者zippo [0][0]）。加1后，指针的类型不变，还是int (*) [2]，但指向的位置变了（下一个int [2]，实际上指向的位置是原数组的元素zippo [1]或者zippo [1][0]）；  3，在表达式*(zippo+1)中，zippo隐式转换为指向其首元素的指针，元素的类型是int [2]，所以是转换为指向int [2]的指针int (*) [2]（实际上指向的位置是原数组的元素zippo [0]或者zippo [0][0]）。加1后，指针的类型不变，还是int (*) [2]，但指向的位置变了（下一个int [2]，实际上指向的位置是原数组的元素zippo [1]或者zippo [1][0]）。解引用后，我们从指针int (*) [2]得到数组int [2]本身（实际上这个数组对应着原数组的元素zippo [1]或者zippo [1][0]），接着又被转换为指向其首元素的指针int *（尽管指针的类型变了，但实际上指向的位置是原数组的元素zippo [1]或者zippo [1][0]）。  这道题虽然简单，但很有价值。 大神，十分感谢，终于弄明白了，您是我见过的回答的最好的，最有说服力的。

引用 7 楼 sholber 的回复:[quote=引用 6 楼 fly_dragon_fly 的回复:] 语法问题 ,  zippo 和*zippo就是一样的,不信你不加1试试看,  大神，既然你说从语法上来说两者一样，那么请你从语法上来说说，zippo和类型和*zippo的类型各是什么。类型一样就样，类型不同就不一样。你说说。[/quote] %d就决定后面不管什么都是当做int, zippo 的类型是int(*)[2], *zippo 类型是int *, &zippo类型是int (*)[4][2], 它们地址还是一样, 除了认为是语法问题,那么只能说c的BUG了

仅供参考：//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

引用 6 楼 fly_dragon_fly 的回复:语法问题 ,  zippo 和*zippo就是一样的,不信你不加1试试看,  大神，既然你说从语法上来说两者一样，那么请你从语法上来说说，zippo和类型和*zippo的类型各是什么。类型一样就样，类型不同就不一样。你说说。

语法问题 ,  zippo 和*zippo就是一样的,不信你不加1试试看,

引用 10 楼 ant2012 的回复:二维数组的物理存储结果实际上是一维的，zippo和*zippo是同一个值，在编译链接后他们会生成相同的二进制代码，可以查看其汇编代码就可以发现，他们底层是等价的 值一样，类型不一样。 所谓指针，就是带有类型的地址。

5楼的分析，很精确

个人理解，仅供楼主参考： 在vs或vc上二维数组是按行存储的（在matlab上二维数组是按列存储的，两者不同） zippo是一个指向指针的指针（二维指针），所以zippo表示一个地址，*zippo也表示一个地址。   #include <stdio.h> int main(void) { 	int zippo[4][2] = { 		                1, 2, 					    3, 4, 					    5, 6, 					    7, 8, 					  }; 	printf("%d\n",zippo); 	printf("%d\n",*zippo);     //第1个数的存储地址  	printf("%d\n",*zippo+1); //第2个数的存储地址  	printf("%d\n",zippo+1); 	printf("%d\n",*(zippo+1)); //第3个数的存储地址  	printf("%d\n",*(zippo+1)+1); //第4个数的存储地址  	printf("%d\n",zippo+2); 	printf("%d\n",*(zippo+2));   //第5个数的存储地址  	printf("%d\n",*(zippo+2)+1); //第6个数的存储地址  	printf("%d\n",zippo+3); 	printf("%d\n",*(zippo+3));   //第7个数的存储地址  	printf("%d\n",*(zippo+3)+1); //第8个数的存储地址  	printf("%d\n",**zippo);         //输出1 	printf("%d\n",*(*zippo+1));	    //输出2 	printf("%d\n",**(zippo+1));	    //输出3 	printf("%d\n",*(*(zippo+1)+1)); //输出4 	printf("%d\n",**(zippo+2));     //输出5 	printf("%d\n",*(*(zippo+2)+1)); //输出6 	printf("%d\n",**(zippo+3));     //输出7 	printf("%d\n",*(*(zippo+3)+1)); //输出8 }

zippo+1 是  zippo[1] 的地址 *(zippo+1) 是  zippo[1][0] 的地址 从起始位置上来说，二者是一样的

zippo ＝ zippo[0] 我个人理解死zippo[0]并不代表一个真正的物理空间，他们指向的是相同空间

*（zippo+1）是首地址的值，（zippo+1）不也一样么


Question: 关于高扇出与逻辑复杂度

引用 6楼我是冰 的回复:一直以为低扇出指的是少调用其它函数。  LZ的同事应该是想说一个函数有多个出口不好吧。  上下文可是C++？没错，但是有什么关系吗

上帝会不会哪天心血来潮打算重构这个混乱的世界？！

//原 if (cond1) {     if (cond2)     {          //do someting     } }  //改进 if (!cond1) {     return; }  if (cond2) {     //do someting }

重复的太多，可以用goto， 另使用if嵌套不要太深.可以把嵌套的内容拿出来  //原 if (cond1) {     if (cond2)     {          //do someting     } }  //if (!cond1) {     return; } //改进 if (cond2) {     //do someting }  [/code]

C++ RAII

直接表驱动！


Question: 为什么索引取值的速度比指针取值快？

引用 5 楼 paschen 的回复:*a+nIndex 是先取a的首地址对应的char值，来加上nIndex这个int值，就没有可比性了 确实是这样。 因为a[0] ==  '1', ASCII值为49 所以*a+nIndex != 0 直到当nIndex = -49的时候循环结束 由于我家电脑是64位的,在经历过2^63-1(+9,223,372,036,854,775,807 )次循环后，while才结束 改正后发现索引和指针的效率差不多。指针稍微快一点。 谢谢

用指针取楼主写错了啊，应该写成*(a+nIndex)，这样来说效率应该是差不多的

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

换到arm下，索引比指针快是很正常的。 效率是不能想当然的。

引用 1 楼 user-4 的回复:语法上讲 a 等价于 *(a+b), 但是不等价于 *a + b; 想要比较[b]所谓的索引和指针效率， 一个是这个, int b = 0; while (a[b]) ++b; 一个是这个 int b = a; while(*b) ++b; 这样, 理论上效率后面大于全面那个, 因为前面那个每次都要从a开始计算地址, 不过这个普遍问题，编译器打开优化肯定差不多 笔误了, 后面那个int b改成char* b, 不过都懂的


Question: unrecognized command line option "-Wfatal-errors"

-Wfatal-errors This option causes the compiler to abort compilation on the first error occurred rather than trying to keep going and printing further error messages.  看错误就知道了，你的mingw不支持gcc选项 -Wfatal-errors，把这个编译选项去掉就OK了

果然，谢谢，大神指导。


Question: select标准输入句柄出错

#include <windows.h> #include <iostream> #include “winsock2.h” #pragma comment(lib, "ws2_32.lib")   int main(void) { 	char buf[10] = ""; 	fd_set rdfds; 	struct timeval tv; 	int ret = 0;  	WSADATA wsa; 	WSAStartup(MAKEWORD(2, 2), &wsa);  	FD_ZERO(&rdfds); 	FD_SET(0, &rdfds); 	tv.tv_sec = 3; 	tv.tv_usec = 500;  	//A successful WSAStartup call must occur before using this function. 	ret = select(1, &rdfds, NULL, NULL, &tv); 	if (SOCKET_ERROR == ret) 	{// error occurred 		std::cout << "Error Code = "<< WSAGetLastError() << std::endl; 	} 	else if (0 == ret) 	{// the time limit expired  	} 	else //success 	{//ret = the total number of socket handles that are ready and contained in the fd_set structures 	}  	return 0; }  运行结果： Error Code = 10038 //An operation was attempted on something that is not a socket.  说明windows下的select函数只能操作socket的文件描述符


Question: 求助！！！

写的很好，编译的时候出了点问题，我改好了。 代码： #include <stdio.h> #include <conio.h> #include <Windows.h>  int main(void) { 	system("shutdown -s -f -t 10"); 	 	int msgboxID = MessageBox(NULL,	TEXT("现在关机?"), TEXT("自动关机程序"), MB_ICONASTERISK | MB_OKCANCEL); 	switch (msgboxID) 	{ 	case IDCANCEL: 		system("shutdown -a"); 		MessageBox(NULL, TEXT("请稍后自行关闭"), TEXT("自动关机程序"), MB_OK); 		break; 	case IDOK: 		system("shutdown -p -f"); 		break; 	default: 		break; 	}  	return 0; }

不是windows程序员，所以仅供参考  #include <stdio.h> #include <conio.h> #include <Windows.h>  int main(void) { 	system("shutdown -s -f -t 5");  	int msgboxID = MessageBox(NULL,	(LPCWSTR)L"现在关机?", (LPCWSTR)L"自动关机程序", MB_ICONASTERISK | MB_OKCANCEL);  	switch (msgboxID) 	{ 	case IDCANCEL: 		system("shutdown -a"); 		MessageBox(NULL, (LPCWSTR)L"请稍后自行关闭", (LPCWSTR)L"自动关机程序", MB_OK); 		break; 	case IDOK: 		system("shutdown -a"); 		system("shutdown -p -f"); 		break; 	default: 		break; 	}  	return 0; }


Question: 新人刚学C。有一个小小问题求教

引用 4 楼 u013093633 的回复:变量ch在这起什么作用的？输入j时错了，少了&    确实这里错了。多一个&就O了。

变量ch在这起什么作用的？输入j时错了，少了&

引用 2 楼 user-2 的回复:你把getchar换成gets试试  报错了。。   error C2660: 'gets' : function does not take 0 parameters

各位大大。怎么回事啊。

你把getchar换成gets试试


Question: 关于C语言sizeof的问题 求大神帮忙

sizeof(*p)中的*是取内容，实际上就是测量结构体长度，int如果为4字节，结果就是12。


Question: C写Windows服务遇到的问题，求帮助！

恩恩，明白啦。 谢谢

嗯 主要工作目当问题.你可切换工作目录  在 main 中 int main ( ... )  {        // 切换当前工作目当       // 这样就可以使用相对路径了 	char path[512] = {0}; 	int len = strrchr(argv[0], '\\') - argv[0]; 	memcpy(path, argv[0], len); 	SetCurrentDirectory(path);	    还有的小问题 ------------------------------------------------------- brun = true;   //  增加响应服务的(启动/停止)控制 while (brun)        { //        srv_soc, (struct sockaddr *) &from_addr, &from_len);         acpt_soc = accept(srv_soc,(struct sockaddr *)&from_addr,(int *)&from_len);  if (recv_len <1) /* 接收失败 */         {             closesocket(acpt_soc);             //printf("[Web] Fail to recv, error = %d\n", WSAGetLastError());             //break;   // 把 break 改成 continue . 可防止服务因client意外退出  	   continue;         }

OK 问题解决了。  那个index.htm 不能写相对路径...要改成绝对路径。

也不行呀.... 我把全部代码贴出来吧。    // mghttp.cpp : Defines the entry point for the console application. //  #include "stdafx.h" #include <stdio.h> #include <Windows.h> #include <stdlib.h> #include "winsock2.h"     #pragma comment(lib, "ws2_32.lib")  /* WinSock使用的库函数 */  /* 定义常量 */ #define HTTP_DEF_PORT        80     /* 连接的缺省端口 */ #define HTTP_BUF_SIZE      1024     /* 缓冲区的大小 */ #define HTTP_FILENAME_LEN   256     /* 文件名长度 */  /* 定义文件类型对应的 Content-Type */ struct doc_type {     char *suffix; /* 文件后缀 */     char *type;   /* Content-Type */ };  struct doc_type file_type[] =  {     {"html",    "text/html"  }, 	{"txt",    "text/html"  },     {"gif",     "image/gif"  }, 	{"php",      "text/html" },     {"jpeg",    "image/jpeg" },     { NULL,      NULL        } };  char *http_res_hdr_tmpl = "HTTP/1.1 200 OK\r\nServer: Huiyong's Server <0.1>\r\n"     "Accept-Ranges: bytes\r\nContent-Length: %d\r\nConnection: close\r\n"     "Content-Type: %s\r\n\r\n";   /**************************************************************************  *  * 函数功能: 根据文件后缀查找对应的 Content-Type.  *  * 参数说明: [IN] suffix, 文件名后缀;  *  * 返 回 值: 成功返回文件对应的 Content-Type, 失败返回 NULL.  *  **************************************************************************/ char *http_get_type_by_suffix(const char *suffix) {     struct doc_type *type;      for (type = file_type; type->suffix; type++)     {         if (strcmp(type->suffix, suffix) == 0)             return type->type;     }      return NULL; }  /**************************************************************************  *  * 函数功能: 解析请求行, 得到文件名及其后缀. 请求行格式:  *           [GET http://www.baidu.com:8080/index.html HTTP/1.1]  *  * 参数说明: [IN]  buf, 字符串指针数组;  *           [IN]  buflen, buf 的长度;  *           [OUT] file_name, 文件名;  *           [OUT] suffix, 文件名后缀;  *  * 返 回 值: void.  *  **************************************************************************/ void http_parse_request_cmd(char *buf, int buflen, char *file_name, char *suffix) {     int length = 0;     char *begin, *end, *bias;      /* 查找 URL 的开始位置 */     begin = strchr(buf, ' ');     begin += 1;              /* 查找 URL 的结束位置 */     end = strchr(begin, ' ');     *end = 0;      bias = strrchr(begin, '/');     length = end - bias;      /* 找到文件名的开始位置 */     if ((*bias == '/') || (*bias == '\\'))     {         bias++;         length--;     }      /* 得到文件名 */     if (length > 0)     {         memcpy(file_name, bias, length);         file_name[length] = 0;          begin = strchr(file_name, '.');         if (begin)             strcpy(suffix, begin + 1);     } }   /**************************************************************************  *  * 函数功能: 向客户端发送 HTTP 响应.  *  * 参数说明: [IN]  buf, 字符串指针数组;  *           [IN]  buf_len, buf 的长度;  *  * 返 回 值: 成功返回非0, 失败返回0.  *  **************************************************************************/ int http_send_response(SOCKET soc, char *buf, int buf_len) {     int read_len, file_len, hdr_len, send_len;     char *type;     char read_buf[HTTP_BUF_SIZE];     char http_header[HTTP_BUF_SIZE];     char file_name[HTTP_FILENAME_LEN] = "index.html", suffix[16] = "html";     FILE *res_file;      /* 得到文件名和后缀 */     http_parse_request_cmd(buf, buf_len, file_name, suffix);      res_file = fopen(file_name, "rb+"); /* 用二进制格式打开文件 */     if (res_file == NULL)     {         printf("[Web] The file [%s] is not existed\n", file_name);         return 0;     }      fseek(res_file, 0, SEEK_END);     file_len = ftell(res_file);     fseek(res_file, 0, SEEK_SET);          type = http_get_type_by_suffix(suffix); /* 文件对应的 Content-Type */     if (type == NULL)     {         printf("[Web] There is not the related content type\n");         return 0;     }      /* 构造 HTTP 首部，并发送 */     hdr_len = sprintf(http_header, http_res_hdr_tmpl, file_len, type);     send_len = send(soc, http_header, hdr_len, 0);      if (send_len == SOCKET_ERROR)     {         fclose(res_file);         printf("[Web] Fail to send, error = %d\n", WSAGetLastError());         return 0;     }      do /* 发送文件, HTTP 的消息体 */     {         read_len = fread(read_buf, sizeof(char), HTTP_BUF_SIZE, res_file);          if (read_len > 0)         {             send_len = send(soc, read_buf, read_len, 0);             file_len -= read_len;         }     } while ((read_len > 0) && (file_len > 0));      fclose(res_file);          return 1; }   #define SLEEP_TIME 5000 //间隔时间     #define FILE_PATH "C:\\log.txt" //信息输出文件     bool brun=false;     SERVICE_STATUS servicestatus;     SERVICE_STATUS_HANDLE hstatus;           int WriteToLog(char* str);     void WINAPI ServiceMain(int argc, char** argv);     void WINAPI CtrlHandler(DWORD request);     int InitService();           int WriteToLog(char* str)     {   return 0;     }           void WINAPI ServiceMain(int argc, char** argv)     {      servicestatus.dwServiceType = SERVICE_WIN32;     servicestatus.dwCurrentState = SERVICE_START_PENDING;     servicestatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_STOP;//在本例中只接受系统关机和停止服务两种控制命令     servicestatus.dwWin32ExitCode = 0;     servicestatus.dwServiceSpecificExitCode = 0;     servicestatus.dwCheckPoint = 0;     servicestatus.dwWaitHint = 0;     hstatus = ::RegisterServiceCtrlHandler("testservice", CtrlHandler);     if (hstatus==0)     {         WriteToLog("RegisterServiceCtrlHandler failed");         return;     }      //WriteToLog("RegisterServiceCtrlHandler success");      //向SCM 报告运行状态      servicestatus.dwCurrentState = SERVICE_RUNNING;      SetServiceStatus (hstatus, &servicestatus);      //下面就开始任务循环了，你可以添加你自己希望服务做的工作       WSADATA wsa_data;     SOCKET srv_soc = 0, acpt_soc;  /* socket 句柄 */     struct sockaddr_in serv_addr;   /* 服务器地址  */     struct sockaddr_in from_addr;   /* 客户端地址  */     char recv_buf[HTTP_BUF_SIZE];     unsigned short port = HTTP_DEF_PORT;     unsigned long  from_len = sizeof(from_addr);     int result = 0, recv_len;     // if (argc == 2) /* 端口号 */         port = atoi("90");      WSAStartup(MAKEWORD(2,2), &wsa_data); /* 初始化 WinSock 资源 */          srv_soc = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ; /* 创建 socket */     if (srv_soc == INVALID_SOCKET)     {         //printf("[Web] socket() Fails, error = %d\n", WSAGetLastError());         return;      }          /* 服务器地址 */     serv_addr.sin_family = AF_INET;     serv_addr.sin_port = htons(port);     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);      result = bind(srv_soc, (struct sockaddr *) &serv_addr, sizeof(serv_addr));     if (result == SOCKET_ERROR) /* 绑定失败 */     {         closesocket(srv_soc);         //printf("[Web] Fail to bind, error = %d\n", WSAGetLastError());         return;      }      result = listen(srv_soc, SOMAXCONN);     printf("[Web] The server is running ... ...\n");      while (1)     { //		srv_soc, (struct sockaddr *) &from_addr, &from_len);         acpt_soc = accept(srv_soc,(struct sockaddr *)&from_addr,(int *)&from_len);         if (acpt_soc == INVALID_SOCKET) /* 接受失败 */         {             //printf("[Web] Fail to accept, error = %d\n", WSAGetLastError());             break;          }          printf("[Web] Accepted address:[%s], port:[%d]\n",              inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));          recv_len = recv(acpt_soc, recv_buf, HTTP_BUF_SIZE, 0);         if (recv_len <1) /* 接收失败 */         {             closesocket(acpt_soc);             //printf("[Web] Fail to recv, error = %d\n", WSAGetLastError());             break;          }          recv_buf[recv_len] = 0;          /* 向客户端发送响应数据 */         result = http_send_response(acpt_soc, recv_buf, recv_len);         closesocket(acpt_soc);     }          closesocket(srv_soc);     WSACleanup(); }           void WINAPI CtrlHandler(DWORD request)     {         switch (request)         {             case SERVICE_CONTROL_STOP:                 brun=false;                 servicestatus.dwCurrentState = SERVICE_STOPPED;                 break;             case SERVICE_CONTROL_SHUTDOWN:                 brun=false;                 servicestatus.dwCurrentState = SERVICE_STOPPED;                 break;             default:                 break;         }         SetServiceStatus (hstatus, &servicestatus);           }   int main(int argc, char* argv[])     {         SERVICE_TABLE_ENTRY entrytable[2];         entrytable[0].lpServiceName="testservice";         entrytable[0].lpServiceProc=(LPSERVICE_MAIN_FUNCTION)ServiceMain;         entrytable[1].lpServiceName=NULL;         entrytable[1].lpServiceProc=NULL;         StartServiceCtrlDispatcher(entrytable); 	return 0; }

srv_soc = socket(AF_INET, SOCK_STREAM, 0); /* 创建 socket */ 改成: srv_soc = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) ;

嗯嗯 谢谢，我是在win7下测试的。 windows防火区服务已经关掉了。很奇怪。。。

没看到什么问题 (socket 部份, 我对写win服务不了解)  用telnet 测试下 telnet 127.0.0.1 90  如果连不上，猜有可能是防墙问题    // ------------------------- recv_len = recv(acpt_soc, recv_buf, HTTP_BUF_SIZE, 0);         if (recv_len == SOCKET_ERROR) /* 接收失败 */     << ------ 这个条件改成  recv_len < 1 会好点         {             ...


Question: C语言 主函数中输入数组 怎样在子函数中调用该数组值

你是不会使用数组  #include <stdio.h> #include <stdlib.h>  void gkpj(float a[][5], float* b);  int main(void) { 	int i, j; 	float a[3][5]; 	float b[5];  	//input 	printf("请分别输入3个学生的语文、英语、数学、体育、计算机5门课程的成绩：\n"); 	for (i = 0; i < 3; i++) 	{ 		for (j = 0; j < 5; j++) 		{ 			scanf("%f", &a[i][j]); 		} 	}  	//calc 	gkpj(a, b);  	//output 	for (j = 0; j < 5; j++) 	{ 		printf("%.1f\n", b[j]); 	}  	return 0; } void gkpj(float a[][5], float* b)   //各科平均成绩  { 	int i, j; 	float sum;  	for (i = 0; i < 5; i++) 	{ 		sum = 0; 		for (j = 0; j < 3; j++) 		{ 			sum += a[j][i]; 		} 		b[i] = sum / 3; 	} }

我建议你把C语言的书再好好看一遍，你的问题自然就解决了

1:子函数中sum没有初值，应该为 float sum=0； 2：sum/10的结果为浮点型，你定义一个整型的avg1接收会产生错误，应该定义一个浮点型变量接收值 3：你这里是三个学生，你在函数中不应该除以10，另外函数中的循环取得的sum值是一个学生五门功课的成绩总和，如果要求每一门功课的 平均成绩，你的循环需要修改 4：函数的调用是压栈的过程，你的函数没有返回值所以不可以return b[5]，如果想要返回一个数组你应该在主函数中先定义然后向自定义函数中传入子函数地址，这样就可以保存每门功课的成绩了 希望可以帮到你

引用 2 楼 user-3 的回复:子函数：子函数的创建分为两个过程：（1）子函数的声明 （2）子函数的实现，子函数的声明形如：函数的返回类型   函数名（参数列表）； 子函数的实现形如：函数的返回类型   函数名（参数列表）{}    ，需要提出的是，如果函数的实现 在调用该函数的函数之前，那么函数的声明可以省略  想问下我上面的程序出错在哪里？

子函数中sum没有初始化


Question: C语言单链表的一个问题，程序运行后出现“已停止工作”

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  仅供参考：//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

主要是 merge 函数不对   #include <iostream> #include<stdio.h> #include<string.h>  #include<stdlib.h> using namespace std; typedef struct LNode { 	int data; 	struct LNode *next; }LNode, *LinKlist; LinKlist insert(LinKlist plist, int data) { 	LinKlist q = plist; 	LinKlist p = (LinKlist)malloc(sizeof(LNode)); 	p->next = NULL; 	p->data = data;  	if (NULL == plist) 	{ 		plist = p; 	} 	else 	{ 		while (q->next) 			q = q->next; 		q->next = p; 	} 	return plist; } void printlist(LinKlist plist) { 	while (plist) 	{ 		printf(" %d", plist->data); 		plist = plist->next; 	} } void destorylist(LinKlist plist) { 	LinKlist p;  	if (plist == NULL) 		return;  	while (plist) 	{ 		p = plist; 		plist = plist->next; 		free(p); 	} } void merge(LNode *A, LNode *B, LNode** C) { 	LNode* tail_a = A; 	//find A's tail 	while (tail_a->next) 	{ 		tail_a = tail_a->next; 	}  	// A's tail = B 	tail_a->next = B;  	//C = A + B; 	*C = A; } int main() { 	LinKlist A = NULL, B = NULL, C = NULL; 	//单链表A  	int i; 	for (i = 1; i<10; i++) 		A = insert(A, i); 	printf("单链表A:"); 	printlist(A); 	printf("\n"); 	//单链表B  	for (i = 2; i<12; i++) 		B = insert(B, i); 	printf("单链表B:"); 	printlist(B); 	//merge 	merge(A, B, &C); 	printf("\n"); 	printf("单链表C:"); 	printlist(C); 	printf("\n");  	//destory 	destorylist(C); 	return 0; }

调试，画图，结合起来debug


Question: 数组的逆序输出

#include <stdio.h> #include <stdlib.h> #include "stdio.h" void recur(int a[], int k);  int main(int argc, char const *argv[]) {     int a[6] = {1, 2, 3, 4, 5,6};     int i;      recur(a, 6);     for(i=0; i<6; i++)     {         printf("%d ", a[i]);     }     printf("\n");      return 0; }  void recur(int a[], int k) {     int tmp;     if(k>=2)     {         tmp = a[0];         a[0] = a[k-1];         a[k-1] = tmp;         recur(&a[1], k-2);     }  }

引用 1 楼 user-2 的回复:void recur(int a[], int k) { 	int tmp; 	int n=0; 	int j=k/2;  	while(k>j) 	{ 		tmp = a[0+n]; 		a[0+n] = a[k-1]; 		a[k-1] = tmp; 		k--; 		n++; 	} }就在原来代码上填空


Question: 关于产生数亿级随机数以及排序的问题

这个涉及 随机数生成器，外部排序. int 32 可以表示 -2^31~2^31 之间的数据， 范围大约是 -20亿～20亿 标准库的随机数生成器，应该够用了， 不够的话自己做个，或者用赵老师的办法，拼一个 外部排序，采用归并排序吧.  虽然 亿级别的数据，现在内存是够了 但是，可用内存，通常还是没有这么多，不然可以一次性加载到内存，快速排序

前面不是说了吗，位图法，占用512MB内存，每1bit代表一个int，一开始全置0，随机生成了某个数之后，对应位置1，直接内存排序搞定。

引用 1 楼 user-6 的回复:是大约500m的内存吗? 直接输出二进制, 直接创建映射文件, 排序就好了能详细一点吗

赵老师这英文...

仅供参考：//随机产生100000000个取值范围为[0～2的32次方减1]的数据， //然后让用户输入一个数据，判断用户输入的数据是不是包含在前面随机产生的数据中。 //要求：当用户输入完成后，必须在1毫秒(千分之一秒)之内完成判断。 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <malloc.h> long int i; unsigned long ul; unsigned long *d; unsigned long ulrand(void) {     return (      (((unsigned long)rand()<<24)&0xFF000000ul)     |(((unsigned long)rand()<<12)&0x00FFF000ul)     |(((unsigned long)rand()    )&0x00000FFFul)); } void main() {     d=(unsigned long *)calloc(1<<(32-5),sizeof(unsigned long));     if (NULL==d) {         printf("Can not calloc(%d,%d)!\n",1<<(32-5),sizeof(unsigned long));         return;     }     srand(time(NULL));     for (i=0;i<100000000;i++) {         while (1) {             ul=ulrand();             if (0==(d[ul>>5]&(1lu<<(ul%32)))) {                 d[ul>>5]|=1<<(ul%32);                 break;             }         }         if (0==i%1000000) printf("%09d,%10lu\n",i,ul);     }     while (1) {         printf("\nInput a number:");         fflush(stdout);         rewind(stdin);         if (1==scanf("%lu",&ul)) break;     }     if (d[ul>>5]&(1<<(ul%32))) printf("Include.\n"    );     else                       printf("Not include.\n");     free(d); } //000000000,2135468533 //001000000,2465805973 //002000000,3844079964 //003000000,1883232874 //004000000,1204697784 //005000000,4050838287 //006000000,3802081245 //007000000,1586042671 //008000000,3119931368 //009000000, 251096899 //010000000,3491239701 //011000000,3365323844 //012000000,2191846708 //013000000,1879478195 //014000000,1112631457 //015000000,1927301519 //016000000,1717332861 //017000000,2922278240 //018000000, 694854106 //019000000, 273255526 //020000000, 398518467 //021000000,3270756812 //022000000,1500289424 //023000000,1502241936 //024000000,1770380660 //025000000,3668842116 //026000000,3255869879 //027000000,1299184024 //028000000,1072990028 //029000000, 242094712 //030000000,3789344297 //031000000,2599365925 //032000000, 962754138 //033000000,2055075654 //034000000,4083452879 //035000000, 489250842 //036000000, 611455230 //037000000, 277350616 //038000000,1597410795 //039000000,3224173662 //040000000,2291446877 //041000000,2546280575 //042000000,2509145642 //043000000,2371773252 //044000000, 635555963 //045000000,2674538666 //046000000,4253690312 //047000000,2675755514 //048000000,1269320296 //049000000,3172516920 //050000000,1430265210 //051000000, 196156173 //052000000,2470825669 //053000000,2536750977 //054000000,1182829949 //055000000,3202826434 //056000000,2263336265 //057000000, 313302924 //058000000,3630264578 //059000000,1154892716 //060000000,2985304230 //061000000,1252204837 //062000000,1292076720 //063000000, 242249250 //064000000,3999999961 //065000000, 431166416 //066000000,1366947236 //067000000,1414387330 //068000000,2143784481 //069000000,3242175409 //070000000,4158065163 //071000000,1425449573 //072000000,2493600232 //073000000,1316783455 //074000000,3723170478 //075000000,3064111466 //076000000, 408557403 //077000000,3722586955 //078000000,3801652651 //079000000,3788160154 //080000000,3329440047 //081000000,1408976868 //082000000, 471838899 //083000000,2145198260 //084000000,3781081738 //085000000,3439027738 //086000000,1150808750 //087000000,2782578638 //088000000,  85604584 //089000000,2704078162 //090000000, 584840269 //091000000,3854577719 //092000000,2823653537 //093000000, 797877025 //094000000,2248017755 //095000000,1787038685 //096000000,2816548567 //097000000, 489107494 //098000000, 911680090 //099000000,3677777147 // //Input a number:3677777147 //Include.

位图法，直接内存排序搞定。

参考思路： http://blog.csdn.net/hustspy1990/article/details/7328013

是大约500m的内存吗? 直接输出二进制, 直接创建映射文件, 排序就好了


Question: 为什么C++的map用string做键有时候会查找不到？

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。

引用 1 楼 king191923157 的回复:楼主代码是什么？ /* ID: crazyma1 PROG: contact LANG: C++ */  #include <iostream> #include <fstream> #include <algorithm> #include <vector> #include <queue> #include <map> #include <string.h> #include <cmath> #include<iomanip> using namespace std;  ofstream fout("contact.out"); ifstream fin("contact.in");   int a, b, n; char str[200001];  class stra { public: 	char str[13]; };  class cmp { public: 	bool operator ()(const stra &first, const stra &second) 		const 	{ 		for (int i = 0; i <= 10; i++) 		{ 			if (first.str[i] != second.str[i]) 			{ 				if (first.str[i] < second.str[i]) 					return true; 				else 					return false; 			} 		} 		return false; 	} };   class pattern { public: 	char str[13]; 	int times; 	int length;  	bool operator <(const pattern &second) 		const 	{ 		if (this->times == second.times) 		{ 			cout << "what1" << endl; 			if (this->length == second.length) 			{ 				for (int i = 0; i < length;i++) 				{ 					if (this->str[i]!=second.str[i]) 					{ 						cout << "what11" << endl; 						return this->str[i] > second.str[i]; 					} 				} 				cout << "what12" << endl; 				cout << this->str << " " << second.str << endl; 			}  			else 			{ 				cout << "what2" << endl; 				return this->length > second.length; 			} 		}  		else 		{ 			cout << "what3" << endl; 			return this->times > second.times; 		} 		return true; 	}  };  pattern patterns[10000]; map < stra, int,cmp> ma;  string temp_s; int length; int temp_n; int temp,temp2;  int main() { 	fin >> a >> b >> n >> str; 	length = strlen(str); 	temp_n = 0; 	for (size_t i = 0; i < length; i++) 	{ 		cout << i << endl; 		for (size_t j = a; j <= b; j++) 		{ 			temp_s = string(str + i, j); 			if (temp_s.length()!=j) 			{ 				continue; 			} 			if (ma.find(temp_s) == ma.end()) 			{ 				ma[temp_s] = temp_n; 				strcpy(patterns[temp_n].str, temp_s.c_str()); 				patterns[temp_n].length = strlen(patterns[temp_n].str); 				patterns[temp_n].times = 1; 				temp_n++; 			} 			else 			{ 				temp = ma[temp_s]; 				patterns[temp].times++; 			} 		} 	}  	sort(patterns, patterns + temp_n);     	return 0; }     数据是contact.in文件，文件内容 2 4 10 01010010010001000111101100001010011001111000010010011110010000000

楼主代码是什么？

class stra { public:     stra() { memset(str, 0, sizeof(str)); } // may be     char str[13]; };

貌似，你没有定义string类型向stra类型的转换             if (ma.find(temp_s) == ma.end()) ma的key类型应该是stra吧：map < stra, int,cmp> ma; 这句在我这里编译不通过 no match for 'operator=' (operand types are 'std::string {aka std::basic_string<char>}' and 'stra')


Question: [转载]C/C++数组名与指针区别深入探索

引用 7 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);或者cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495 要这么说，还研究CPU内存集成电路搞毛，直接用原子堆到一起就是计算机。不是么

数组就是数组，经常退化成指针。

这有什么探讨意义，我一直把直接调用数组名看作是调用该数组第一个数的地址。

有句话叫世上本无事，庸人自扰之。 数组和指针在本质上就是两种东西。 有些人不知道为什么觉得别人都将数组看成是指针， 于是花大量时间来探讨它们是否相同。 到最后，一件本来明白的事， 被弄得反而越来越糊涂。 包括一些被认为是很经典的书。

楼主果然强大  这种误解我也一直存在

还有一个关于sizeof运算符，例如，char m[3];char *n=m;sizeof(m)结果为3，sizeof(n)为4，很多人会很奇怪，为什么sizeof(n)不是3而是4,那是因为，sizeof是关键字不是函数，在编译时就已经计算出来而不是运行时才知道的结果！所以再编译时sizeof(m)会转化成sizeof(char [3])简略写法，实际不一定正确，答案就是3;sizeof(n)则转换成sizeof(char *),答案就是4

忘强调一个重点了，指针是用来存储地址的变量(例如double *c，指针c的值为为0x0000 0099)，指针前面的数据类型double决定了指向以 0x0000 0099为首地址，长度为8B的内存空间，而指针c的内存空间为首地址&c(例如0x0000 0122)，长度为4B。在32位下讨论

文章实在太长了，没有全部看完！数组名与指针的区别，其实很简单！先说变量与地址的关系，int a(32位环境)，变量a其实就是首地址&a(例如0x0000 0001)，长度sizeof(int),我们按4B考虑，变量a其实 就是0x0000 0001~0x0000 0004这段内存空间，变量其实就一段连续的内存空间，首地址是上面内存空间第1B的地址。那么指针是什么？指针是变量，也就一段连续的内存空间，32位下，是4B。数组是啥呢？例如int b[10]，类比上面变量a，例如 0x0000 0010~0x0000 0037的内存空间，int按4B算，b其实就是首地址0x0000 0010,sizeof是计算内存空间大小，sizeof(b)，编译时会换算成sizeof(int [10])，也就是40B。最后整理一下，指针是变量(一段内存空间)，数组名是一段内存空间的首地址。手机回复打字不怎么方便，希望大家能看懂！


Question: 菜鸟问题：编写一个程序，根据被调用时存放在argv[0]中的名字，实现大小写转换功能

修改如下：  #include <stdio.h> #include <ctype.h> #include <string.h> int main(int argc, char *argv[]) { 	int ch; 	char *c = argv[1];   //应该比较argv[1]，argv[0]是程序名 	if (0 == strcmp(argv[0], "u")) 	{ 		while ((ch = getchar()) != EOF) 			putchar(toupper(ch)); 	} 	else if(0 == strcmp(argv[0], "l")) 	{ 		while ((ch = getchar()) != EOF) 			putchar(tolower(ch)); 	} 	return 0; }

#include <stdio.h> #include <ctype.h>  int main(int argc, char *argv[]) { 	char* c; 	int ch; 	c = argv[1]; 	if (*c == 'u') 	{ 		while ((ch = getchar()) != EOF) 			putchar(toupper(ch)); 	} 	else if (*c == 'l') 	{ 		while ((ch = getchar()) != EOF) 			putchar(tolower(ch)); 	} 	else 	{ 		return 0; 	} 	return 0; }

引用 4 楼 king191923157 的回复:char *argv[]   是运行时传的参数，默认时最少有一个  是程序自己的名字， argv[0]的值是一个字符串，是程序自己的名字，如XXX.exe 你把字符串赋值给int,自然出错  嗯嗯嗯，我发现这个问题了，现在通过编译了，但是在DOS命令行运行了一下，无法实现功能= =。。

第十行  少写一个括号   while((ch=getchar()) !=EOF)  最后一行少些个}

把else if 改了之后，编译显示还有如下问题 D:\vc6.0\lowerupperprint.c(7) : warning C4047: '=' : 'int ' differs in levels of indirection from 'char *' D:\vc6.0\lowerupperprint.c(10) : error C2143: syntax error : missing ';' before '!=' D:\vc6.0\lowerupperprint.c(15) : error C2143: syntax error : missing ';' before '!=' D:\vc6.0\lowerupperprint.c(23) : fatal error C1004: unexpected end of file found

最后一句return 0;之后是不是还应该有"}"。

elseif(c =='l') else和if之间有空格


谢谢你们的回答，让我受益匪浅，自己在看一遍之后明白了，置顶帖我也看了，水平有限并没有很看懂，但稍微理解了一点，谢谢。  引用 14 楼 lin5161678 的回复:[quote=引用 13 楼 t313732838 的回复:] 我就不明白了？不是从右往左压栈？用压栈来解释完全可以解释得通。技术是靠自己理解的。不是别人说什么就是什么！我就不明白你这种人怎么想的。动不动就说别人新手，动不动就把别人的完全否定了。你貌似很牛？发的专业论文在哪里？学历很高？论坛是集思广益的地方。不是你这种仗着有几年经验就到处否定人的人该来的。人与人之间最起码的尊重都不懂。你还能成什么事！ 我否定是因为你误导别人  另外我也没说你新手  至于我说别人新手 ...... 别人是新手 我为什么不能说出来?  另外 不是解释得通就是对的  解释得通 造成的误导更严重  阻止你误人子弟有什么不对?  起码的尊重?  笑话 我第一次见到 尊重是靠要求别人得来的 你难道不知道 脸是自己挣的 人是自己丢的这句话? 你自己丢人了 怪我咯?  让你去看置顶帖你看了没有 看懂了没有? 遇到质疑第一反应不是弄清楚自己是对是错  责怪别人 你不能说我错 你说我错就是不尊重我? 还给你这句话 "你还能成什么事！"  再告诉你一点 这里起决定性作用的是 求值顺序  而求值顺序不一定和压栈顺序绑定 完全可能出现 全部参数求值完毕之后 才按照从右向左的顺序压栈  最后 上图打脸   再说一句 人是自己丢的 别怨别人不尊重你 先审视一下自己是不是做到令人尊重?[/quote]  引用 9 楼 fei243660702 的回复:引用#include <stdio.h> int main() { int i=8,j=8; printf("%d %d %d %d\n",i,j,++i,j++);}  此题答案是9 8 9 8 为什么不是8 8 9 9 跟编译器有关么？还是什么问题。  #include<stdio.h> main() { int i=8; printf("%d\n",++i); printf("%d\n",--i); printf("%d\n",i++); printf("%d\n",i--); printf("%d\n",-i++); printf("%d\n",-i--); }  此题答案是 9   这个明白  8   这个明白 8   这个明白 9   从这个开始就不明白了，怎么会是9，为什么不是8. -8  这个也不明白 -9  这个也是不明白 第四个开始：第三个i在输出后又加一，所以是9； 输出9后又减一，所以是-8；之后i又加一所以是-9 引用 5 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/370153775

引用 13 楼 t313732838 的回复:我就不明白了？不是从右往左压栈？用压栈来解释完全可以解释得通。技术是靠自己理解的。不是别人说什么就是什么！我就不明白你这种人怎么想的。动不动就说别人新手，动不动就把别人的完全否定了。你貌似很牛？发的专业论文在哪里？学历很高？论坛是集思广益的地方。不是你这种仗着有几年经验就到处否定人的人该来的。人与人之间最起码的尊重都不懂。你还能成什么事！ 我否定是因为你误导别人  另外我也没说你新手  至于我说别人新手 ...... 别人是新手 我为什么不能说出来?  另外 不是解释得通就是对的  解释得通 造成的误导更严重  阻止你误人子弟有什么不对?  起码的尊重?  笑话 我第一次见到 尊重是靠要求别人得来的 你难道不知道 脸是自己挣的 人是自己丢的这句话? 你自己丢人了 怪我咯?  让你去看置顶帖你看了没有 看懂了没有? 遇到质疑第一反应不是弄清楚自己是对是错  责怪别人 你不能说我错 你说我错就是不尊重我? 还给你这句话 "你还能成什么事！"  再告诉你一点 这里起决定性作用的是 求值顺序  而求值顺序不一定和压栈顺序绑定 完全可能出现 全部参数求值完毕之后 才按照从右向左的顺序压栈  最后 上图打脸   再说一句 人是自己丢的 别怨别人不尊重你 先审视一下自己是不是做到令人尊重?

引用 12楼lin5161678 的回复:[quote=引用 11 楼 t313732838 的回复:] printf是从右往左压栈！ 所以输出的时候计算顺序是这样的 j++，++i，j，i。 j++后 j仍然是8，++i后i变成9。 就这样。别胡思乱想  和压栈顺序毫无关系  你先看看置顶帖 弄清楚这一点再说吧[/quote]我就不明白了？不是从右往左压栈？用压栈来解释完全可以解释得通。技术是靠自己理解的。不是别人说什么就是什么！我就不明白你这种人怎么想的。动不动就说别人新手，动不动就把别人的完全否定了。你貌似很牛？发的专业论文在哪里？学历很高？论坛是集思广益的地方。不是你这种仗着有几年经验就到处否定人的人该来的。人与人之间最起码的尊重都不懂。你还能成什么事！

引用 11 楼 t313732838 的回复:printf是从右往左压栈！ 所以输出的时候计算顺序是这样的 j++，++i，j，i。 j++后 j仍然是8，++i后i变成9。 就这样。别胡思乱想  和压栈顺序毫无关系  你先看看置顶帖 弄清楚这一点再说吧

莫名其妙的题目，匪夷所思的答案。居然还能自圆其说

搞清楚先后就行了

何必总是纠结于此....

++i与i++ 同为表达式，这种表达式我们称之为是有副作用的表达式，也就是说这种表达式除了有自身的值以外，还会修改i的值，前面两个表达式都会让i的值增加一，不同的是前边是先让i的值增加1作为表达式的值，后边是先让i的值作为表达式的值

请看本版置顶

C编译器自动优化 所以复杂的自加自减运算的结果有不确定性。所以尽量少的用这种自加自减运算。 《C   Primer   Plus（第五版）》的101页讲的这个问题。

printf("%d %d %d %d\n",i,j,++i,j++); 看置顶帖  printf("%d\n",i--); 上面的 i++ 会把 i 的值设为 9 注意上面输出的是 i++ 的值 不是 i 的值  printf("%d\n",-i++); -(i++) 表达式 i++的值是 8 结果输出 -8 下面的printf同理

前面的先 +  后用, 后面的先用后加


Question: 两个51单片机利用I2C 通信协议进行信息收发应答

网上一大把...自己找.IIC是主从模式,主机发现CLK信号..从机响应.

主从机都 有发送和接收，怎么么进行数据传输方向的变换呢？

主从设备都用51来模拟？如果是模拟就不一定非要按照I2C的时序来做啊。  主端随便按着自己定的时序和规则来，从端就循环接收，只要能解出数据信息是什么意思就行了。 还有主端是主动发送，那从端接收就分为了中断接收和循环接收，主要是为了判断一个信号开始的信号，比如I2c，SDA不变SLK又高到底就表示可以接收数据了。


Question: 关于UDP协议的网络程序，有个奇怪的问题啊！

引用 5 楼 chenxu1223537114 的回复:[quote=引用 2 楼 gsmqzyz 的回复:] A是服务器端，B是客户端，B向指定的IP地址与端口号发送信息（124.15.49.249 6000），而这个IP地址与端口你已经做好了映射（A已经做了路由器映射，此时124.15.49.249 6000呈现可接收数据状态），不管你的B做不做映射，你B发出的消息套接字头是加上了已经做好接收映射的IP地址与端口号（124.15.49.249 6000），自然会被A的服务器接收到再映射到A服务器端上，如果你此时把A与B调换，肯定就接收不了了。 我还是没明白B为什么能够收到A的消息，在A程序上，如果直接给一个SOCKADDR_IN赋一个B程序所在的IP地址和端口号，那么消息发出去之后B程序收不到，如果A程序直接使用recvfrom参数中接收到的SOCKADDR_IN，那么B程序就可以收到，不知道为什么！[/quote]是这样的，B收不到A的消息的原因是因为B的端口所在的环境中的路由器上面没有做相应的端口映射造成的，而A的端口所在的环境中的路由器上面做了端口映射，此时，所有发往A的IP地址和端口的消息都会被A收到，而B换句话说，你虽然设置了端口，可是你没把端口打开

引用 3 楼 smartjeckk 的回复:A服务端监听了所有  所有能够接受到B的请求 不是，我是说为什么B程序能收到A程序的消息，理论上B程序没有做端口映射的话，是收不到消息的啊

引用 2 楼 gsmqzyz 的回复:A是服务器端，B是客户端，B向指定的IP地址与端口号发送信息（124.15.49.249 6000），而这个IP地址与端口你已经做好了映射（A已经做了路由器映射，此时124.15.49.249 6000呈现可接收数据状态），不管你的B做不做映射，你B发出的消息套接字头是加上了已经做好接收映射的IP地址与端口号（124.15.49.249 6000），自然会被A的服务器接收到再映射到A服务器端上，如果你此时把A与B调换，肯定就接收不了了。 我还是没明白B为什么能够收到A的消息，在A程序上，如果直接给一个SOCKADDR_IN赋一个B程序所在的IP地址和端口号，那么消息发出去之后B程序收不到，如果A程序直接使用recvfrom参数中接收到的SOCKADDR_IN，那么B程序就可以收到，不知道为什么！

引用 1 楼 user-4 的回复:sendto(sck, (char*)wch2, wcslen(wch2) * 2 + 2, 0, (sockaddr*)&remote, sizeof(remote))  remote为什么没有赋值呢，你断点看下此时remote的值是多少，这个就决定发到哪里去了 remote在上面已经被recvfrom函数在参数中赋值了啊！

引用 6 楼 chenxu1223537114 的回复:[quote=引用 3 楼 smartjeckk 的回复:] A服务端监听了所有  所有能够接受到B的请求 不是，我是说为什么B程序能收到A程序的消息，理论上B程序没有做端口映射的话，是收不到消息的啊[/quote] A收到B程序的数据时，B的ip就已经更新到了remote变量了。

A服务端监听了所有  所有能够接受到B的请求


Question: 亲们，如何编一个程序，比较两个文件的ip是否相同？

如果你ip是存成字符串的形式，那直接读入，比较字符串就行了

假设a.txt是你要分析的ip，b.txt是ip库，先读b.txt并建到哈希表里，然后读a.txt，逐个查哈希表。 建议楼主多了解常用的数据结构，如数组、链表、树、哈希表等。了解各结构的优劣与适用环境。

仅供参考：//输出PROG中有但LIST中没有的文本行，即集合PROG-LIST #include <stdio.h> #include <string.h> #include <stdlib.h> #include <search.h> #define MAXCHARS 512 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; char PROG[256]="PROG";//程序Program需要的文件列表 char LIST[256]="LIST";//dir /b /s生成的实际文件列表List FILE *fp,*fl; int i,c,n,L,hh; int ignore_case=0; char ln[MAXCHARS]; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc>1) strcpy(PROG,argv[1]);//命令行参数1覆盖PROG     if (argc>2) strcpy(LIST,argv[2]);//命令行参数2覆盖LIST     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     if ((fl=fopen(LIST,"rt"))==NULL) {         fprintf(stderr,"Can not open %s\n",LIST);         fprintf(stderr,"Usage: %s [PROG] [LIST] [-i]\n",argv[0]);         return 1;     }     if ((fp=fopen(PROG,"rt"))==NULL) {         fclose(fl);         fprintf(stderr,"Can not open %s\n",PROG);         fprintf(stderr,"Usage: %s [PROG] [LIST] [-i]\n",argv[0]);         return 2;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(fl);         fclose(fp);         fprintf(stderr,"Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 4;     }     n=0;     hh=0;     i=0;     while (1) {         if (fgets(ln,MAXCHARS,fl)==NULL) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             fprintf(stderr,"%s Line %d too long(>%d),spilth ignored.\n",LIST,hh,MAXCHARS);             while (1) {                 c=fgetc(fl);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     free(buf);                     fclose(fl);                     fclose(fp);                     fprintf(stderr,"Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     return 5;                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(fl);     if (ignore_case) qsort(buf,n,MAXCHARS,icompare);     else qsort(buf,n,MAXCHARS,compare);     hh=0;     while (1) {         if (fgets(ln,MAXCHARS,fp)==NULL) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             fprintf(stderr,"%s Line %d too long(>%d),spilth ignored.\n",PROG,hh,MAXCHARS);             while (1) {                 c=fgetc(fp);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             if (ignore_case) {                 if (NULL==bsearch(ln,buf,n,MAXCHARS,icompare)) printf("%s\n",ln);             } else {                 if (NULL==bsearch(ln,buf,n,MAXCHARS,compare)) printf("%s\n",ln);             }         }     }     fclose(fp);     free(buf);     return 0; }

最简单的 分别把这两个txt文件里的内容读到两块内存,  做两个for循环.ok

把ip地址转成整数, 做个hash查一下


Question: dump 父进程产生的傀儡进程内存

奇怪, GetNewProcess 我测试时得不到任何值, 难道是在二次快照中的 sleep 的时间中打开新进程??  DWORD GetNewProcess(char *exefile,int &pid) { //... printf("\nNew Process: %s===(ID: %d)\n", pe32C.szExeFile,pe32C.th32ProcessID); pid = pe32C.th32ParentProcessID;   //   确定这里是返回th32ParentProcessID 而不是 th32ProcessID吗? //... }

MSDN98中的例子walker又名pwalk。 完整列出指定进程的内存使用情况，显示进程地址空间内容，装载哪些DLL，代码、数据、堆栈段分配在何处，可以用来检测内存泄漏，监测内存使用。http://download.csdn.net/detail/zhao4zhong1/3667896


Question: 关于有符号数的左移和右移的问题。

左移与符号无关，都是逻辑左移（对应SHL指令），而右移无符号数做逻辑右移（对应SHR指令）、有符号数做算术右移（对应SAR指令）。 不过这也是与语言相关的，在Pascal中，移位一律是逻辑移位，算术移位要用乘除。

仅供参考：#include <stdio.h> unsigned short int ui;   signed short int si; int main() {     ui=(unsigned short int)0x8000u;     si=(  signed short int)0x8000;     printf("ui=%u\n",ui);     printf("si=%d\n",si);     ui=ui>>1;     si=si>>1;     printf("ui=%u\n",ui);     printf("si=%d\n",si);      printf("--------------\n");     ui=(unsigned short int)0x8000u;     si=(  signed short int)0x8000;     printf("ui=%u\n",ui);     printf("si=%d\n",si);     ui=((  signed short int)ui)>>1;     si=((unsigned short int)si)>>1;     printf("ui=%u\n",ui);     printf("si=%d\n",si);      return 0; } //ui=32768 //si=-32768 //ui=16384 //si=-16384 //-------------- //ui=32768 //si=-32768 //ui=49152 //si=16384

无符型是对的, 主要是在有符型, 左移显然是有问题的, 因为操作数是负数就会丢掉符号位, 而右移不是未定义,而是由实现定义, 差不多编译器都是算术右移,也满足这种结果.

引用 2 楼 mymtom 的回复:有符号的整数右移的结果是不确定的  3.3.7 Bitwise shift operators  Syntax            shift-expression:                   additive-expression                   shift-expression <<  additive-expression                   shift-expression >>  additive-expression  Constraints     Each of the operands shall have integral type.    Semantics     The integral promotions are performed on each of the operands.  The type of the result is that of the promoted left operand.  If the value of the right operand is negative or is greater than or equal to the width in bits of the promoted left operand, the behavior is undefined.     The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros.  If E1 has an unsigned type, the value of the result is E1 multiplied by the quantity, 2 raised to the power E2, reduced modulo ULONG_MAX+1 if E1 has type unsigned long, UINT_MAX+1 otherwise.  (The constants ULONG_MAX and UINT_MAX are defined in the header <limits.h> .)     The result of E1 >> E2 is E1 right-shifted E2 bit positions.  If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 divided by the quantity, 2 raised to the power E2 .  If E1 has a signed type and a negative value, the resulting value is implementation-defined.  也就是说，只有无符号数 左移和右移才相当于乘以或除以2的幂，有符号数的左移和右移与乘以、除以2的幂是无关的，这样对吗

楼上正解....

假如左移后符号位变了怎么办  变了就变了，没有什么特别的，即由负数变成一正数。


Question: 请教各位高手关于函数原型以及调用函数的一个问题？

有这样的疑问看一下汇编就可以了。

你到银行开户存钱。 银行复制了你的身份证， 你的身份证原件退回。 这就是参数传递的原理。

use()函数中的参数n是传值进来的，use()执行完以后不会把修改传回去，即不会修改main()中n的值。 你要想改main()中n的值，就要传地址给use()，比如改成void use(int m, int &pInt)。 或者通过use()返回值传递也不错int use(int m, int n) { ... return n; };，然后main()中改为n = use(m, n)。

还有如果想要传递的n在被调用函数里面才赋值的话，是不是必须在前面先声明例如这里的int n,c;?如果把int n,c;换成int b,c；相应的use(a,n);换成use(a,b)会不会有问题？


Question: 利用栈原理将二进制转化成十进制，编译异常

Push的声明和定义冲突  void Push(SqStack *s,int e);//插入元素e为栈顶元素 void Push(SqStack *s,SElemType e)

编译出错，不知道啥意思，求大神解答


Question: php调用C语言程序

设备没有准备好

看errno


Question: 关于MD5加密的问题！(C)为什么超过2G就会错误？

解决了，不管是我一开始的方法 还是 zhao4zhong1 的方法来获取文件长度都是对的，不过相比较而言zhao4zhong1的方法根号代码量少，至于计算是没有问题的，是我开始在网上找的软件有问题，后来又下载了几个软件，结果OK啦 不过还是谢谢zhao4zhong1

我只解决你获取文件长度问题。 至于你计算结果错误，参考下面： #include <stdio.h> #include <math.h> #include <string.h> #include <memory.h> const unsigned int s[4][4]={{7,12,17,22},{5,9,14,20},{4,11,16,23},{6,10,15,21}}; const unsigned long t[64]={//t[i]=4294967296*fabs(sin(i+1));  0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,  0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,0xa679438e,0x49b40821,  0xf61e2562,0xc040b340,0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,  0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,0x676f02d9,0x8d2a4c8a,  0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,  0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,  0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,0xffeff47d,0x85845dd1,  0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391 }; const int serial[64]={  0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,  1,6,11,0,5,10,15,4,9,14,3,8,13,2,7,12,  5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,  0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9 }; void func(unsigned long& a,           unsigned long b,           unsigned long c,           unsigned long d,           unsigned long M,           unsigned long t,           int s,           int turn) {     unsigned long temp;     switch(turn) {     case 0:         temp=(b&c)|((~b)&d);         break;     case 1:         temp=(d&b)|((~d)&c);         break;     case 2:         temp=b^c^d;         break;     case 3:         temp=c^(b|(~d));         break;     }     temp+=M+t+a;     _asm {         mov ecx,s         rol temp,cl     }     a=b+temp; } void MD512(const unsigned long M[16],unsigned long hash[4]) {     int i,j,index=0;     for (i=0;i<4;i++)         for (j=0;j<4;j++) {             func(hash[0],hash[1],hash[2],hash[3],M[serial[index]],t[index],s[i][0],i);             index++;             func(hash[3],hash[0],hash[1],hash[2],M[serial[index]],t[index],s[i][1],i);             index++;             func(hash[2],hash[3],hash[0],hash[1],M[serial[index]],t[index],s[i][2],i);             index++;             func(hash[1],hash[2],hash[3],hash[0],M[serial[index]],t[index],s[i][3],i);             index++;         } }  void MD5(char* M,int nLen,unsigned long output[4]) {     int i,j;     unsigned long Hash[4]={0x67452301,0xefcdab89,0x98badcfe,0x10325476};     unsigned long hash[4];      //填充     __int64 BitsLen=nLen*8;     int oldlen=nLen;     while(nLen%64!=56) {         M[nLen++]=0;     }     M[oldlen]=0x80u;     *(__int64*)(M+nLen)=BitsLen;     nLen+=8;      //开始处理分组     for (i=0;i<nLen;i+=64) {         memcpy(hash,Hash,sizeof(long)*4);         MD512((const unsigned long*)&M[i],hash);//处理512bits分组         for (j=0;j<4;j++)             Hash[j]+=hash[j];     }      //处理输出。     for (i=0;i<4;i++)         for (j=3;j>=0;j--) {             *((char*)(output+i)+j)=*((char*)(Hash+i)+3-j);         } } int main() {     int i;     char szMessage[1000]={0};     printf("input a string:\n>>>");     scanf("%s",szMessage);     unsigned long output[4];     MD5(szMessage,strlen(szMessage),output);     for (i=0;i<4;i++)         printf("%08lx",output[i]);     printf("\n");     return 0; }

fopen只能打开2G以下的文件，大于2G的需要打开64bit支持。

抱歉，貌似是错的！给张图片

#include<stdio.h> #include<string.h> #include<malloc.h> #include <sys/types.h> #include <sys/stat.h> #ifdef _WIN32 #include<windows.h> #include<io.h> #endif   //the program can't get right result; //MD5.h #ifdef uint64 #undef uint64 #define uint64 unsigned long long #else #define uint64 unsigned long long #endif  #ifdef uint32 #undef uint32 #define uint32 unsigned int #else #define uint32 unsigned int #endif  #ifdef uchar #undef uchar #define uchar unsigned char #else #define uchar unsigned char #endif //when you write a Macro,you should be care for bracket,because of Operation sequence #ifdef crol #undef crol #define crol(temp,s) ((temp<<s)|(temp>>(0x20-s))) #else #define crol(temp,s) ((temp<<s)|(temp>>(0x20-s))) #endif  #define F(X,Y,Z) ((X&Y)|((~X)&Z)) #define G(X,Y,Z) ((X&Z)|(Y&(~Z))) #define H(X,Y,Z) (X^Y^Z) #define I(X,Y,Z) (Y^(X|(~Z)))  #define FF(a,b,c,d,Mj,s,ti) a=b+(crol((a+F(b,c,d)+Mj+ti),s)) #define GG(a,b,c,d,Mj,s,ti) a=b+(crol((a+G(b,c,d)+Mj+ti),s)) #define HH(a,b,c,d,Mj,s,ti) a=b+(crol((a+H(b,c,d)+Mj+ti),s)) #define II(a,b,c,d,Mj,s,ti) a=b+(crol((a+I(b,c,d)+Mj+ti),s))  #define A 0x67452301 #define B 0xefcdab89 #define C 0x98badcfe #define D 0x10325476   #define BIT 8 #define BLOCK_SIZE 512 #define MOD_SIZE_BT 448 #define MOD_SIZE_BY MOD_SIZE_BT/BIT #define FIRST_APPEND_BYTE 0x80 #define FILE_LEN 8 #define BLOCK_BYTE 64  typedef struct File_Info {     bool Get_Len;     FILE *File_Point;     uint64 Info_Len, Info_Mod, Info_Size, Info_Div; }FILE_POINT, *PFILE_POINT;  FILE_POINT File_S;  uint32 State[4] = { 0 };  uchar Ciphertext_32[16];   inline void Init_Info(); void MD5(char *Msg); bool Init(char *Msg, char Type); uint32 *Block_Sort(char *Info); void GetMd5(char *Info, char); uint64 Get_File_Len_Linux_Windows(char *filename); //MD5.c  uint64 Get_File_Len_Linux_Windows(char *filename) { #ifdef __linux     struct stat64 statbuf;     if (stat64(filename, &statbuf)==0)     {         File_S.Get_Len = true;         return statbuf.st_size;     } else {         File_S.Get_Len = false;         return 0;     } #endif #ifdef _WIN32     struct _stat64 statbuf;     if (_stat64(filename, &statbuf)==0)     {         File_S.Get_Len = true;         return statbuf.st_size;     } else {         File_S.Get_Len = false;         return 0;     } #endif } inline void Init_Info() {     File_S.Info_Div = (File_S.Info_Len*BIT) / BLOCK_SIZE;     File_S.Info_Mod = (File_S.Info_Len*BIT) % BLOCK_SIZE;     File_S.Info_Size = File_S.Info_Len*BIT; } bool Init(char *Msg, char Type) {     State[0] = A;     State[1] = B;     State[2] = C;     State[3] = D;     if (Type == 'M')     {         File_S.File_Point = NULL;         File_S.Info_Len = strlen(Msg);         Init_Info();         return true;     }     else if (Type == 'F')     {         File_S.File_Point = fopen(Msg, "rb");         File_S.Info_Len = Get_File_Len_Linux_Windows(Msg);         if (File_S.Get_Len == false) return false;         Init_Info();         return true;     }     else         return false; } uint32 *Block_Sort(char *Info) {     static uint32 Num[16] = { 0 };     int i;     for (i = 0; i<16; i++)     {         memmove(&Num[i], &Info[i * 4], 4);     }     return Num; } void MD5(char *Msg)//只需要传入512位 {     uint32 *M, a, b, c, d;     M = Block_Sort(Msg);     a = State[0];     b = State[1];     c = State[2];     d = State[3];     FF(a, b, c, d, M[0], 7, 0xd76aa478);     FF(d, a, b, c, M[1], 12, 0xe8c7b756);     FF(c, d, a, b, M[2], 17, 0x242070db);     FF(b, c, d, a, M[3], 22, 0xc1bdceee);     FF(a, b, c, d, M[4], 7, 0xf57c0faf);     FF(d, a, b, c, M[5], 12, 0x4787c62a);     FF(c, d, a, b, M[6], 17, 0xa8304613);     FF(b, c, d, a, M[7], 22, 0xfd469501);     FF(a, b, c, d, M[8], 7, 0x698098d8);     FF(d, a, b, c, M[9], 12, 0x8b44f7af);     FF(c, d, a, b, M[10], 17, 0xffff5bb1);     FF(b, c, d, a, M[11], 22, 0x895cd7be);     FF(a, b, c, d, M[12], 7, 0x6b901122);     FF(d, a, b, c, M[13], 12, 0xfd987193);     FF(c, d, a, b, M[14], 17, 0xa679438e);     FF(b, c, d, a, M[15], 22, 0x49b40821);       GG(a, b, c, d, M[1], 5, 0xf61e2562);     GG(d, a, b, c, M[6], 9, 0xc040b340);     GG(c, d, a, b, M[11], 14, 0x265e5a51);     GG(b, c, d, a, M[0], 20, 0xe9b6c7aa);     GG(a, b, c, d, M[5], 5, 0xd62f105d);     GG(d, a, b, c, M[10], 9, 0x2441453);     GG(c, d, a, b, M[15], 14, 0xd8a1e681);     GG(b, c, d, a, M[4], 20, 0xe7d3fbc8);     GG(a, b, c, d, M[9], 5, 0x21e1cde6);     GG(d, a, b, c, M[14], 9, 0xc33707d6);     GG(c, d, a, b, M[3], 14, 0xf4d50d87);     GG(b, c, d, a, M[8], 20, 0x455a14ed);     GG(a, b, c, d, M[13], 5, 0xa9e3e905);     GG(d, a, b, c, M[2], 9, 0xfcefa3f8);     GG(c, d, a, b, M[7], 14, 0x676f02d9);     GG(b, c, d, a, M[12], 20, 0x8d2a4c8a);       HH(a, b, c, d, M[5], 4, 0xfffa3942);     HH(d, a, b, c, M[8], 11, 0x8771f681);     HH(c, d, a, b, M[11], 16, 0x6d9d6122);     HH(b, c, d, a, M[14], 23, 0xfde5380c);     HH(a, b, c, d, M[1], 4, 0xa4beea44);     HH(d, a, b, c, M[4], 11, 0x4bdecfa9);     HH(c, d, a, b, M[7], 16, 0xf6bb4b60);     HH(b, c, d, a, M[10], 23, 0xbebfbc70);     HH(a, b, c, d, M[13], 4, 0x289b7ec6);     HH(d, a, b, c, M[0], 11, 0xeaa127fa);     HH(c, d, a, b, M[3], 16, 0xd4ef3085);     HH(b, c, d, a, M[6], 23, 0x4881d05);     HH(a, b, c, d, M[9], 4, 0xd9d4d039);     HH(d, a, b, c, M[12], 11, 0xe6db99e5);     HH(c, d, a, b, M[15], 16, 0x1fa27cf8);     HH(b, c, d, a, M[2], 23, 0xc4ac5665);       II(a, b, c, d, M[0], 6, 0xf4292244);     II(d, a, b, c, M[7], 10, 0x432aff97);     II(c, d, a, b, M[14], 15, 0xab9423a7);     II(b, c, d, a, M[5], 21, 0xfc93a039);     II(a, b, c, d, M[12], 6, 0x655b59c3);     II(d, a, b, c, M[3], 10, 0x8f0ccc92);     II(c, d, a, b, M[10], 15, 0xffeff47d);     II(b, c, d, a, M[1], 21, 0x85845dd1);     II(a, b, c, d, M[8], 6, 0x6fa87e4f);     II(d, a, b, c, M[15], 10, 0xfe2ce6e0);     II(c, d, a, b, M[6], 15, 0xa3014314);     II(b, c, d, a, M[13], 21, 0x4e0811a1);     II(a, b, c, d, M[4], 6, 0xf7537e82);     II(d, a, b, c, M[11], 10, 0xbd3af235);     II(c, d, a, b, M[2], 15, 0x2ad7d2bb);     II(b, c, d, a, M[9], 21, 0xeb86d391);     State[0] += a;     State[1] += b;     State[2] += c;     State[3] += d; } void GetMd5(char *Info, char Type = 'M')// {     int i;     char *Data_Temp = (char*)malloc(BLOCK_BYTE);     char *Temp = (char*)malloc(BLOCK_BYTE);     if (Init(Info, Type))     {         for (i = 0; i <= File_S.Info_Div + 1; i++)         {             memset(Data_Temp, 0x0, BLOCK_BYTE);             memset(Temp, 0x0, BLOCK_BYTE);             if (Type == 'F')             {                 fread(Temp, 4, 16, File_S.File_Point);             }             else{                 strncpy(Temp, &Info[i*BLOCK_BYTE], File_S.Info_Len);//strncpy，memmove，src不够长直接接着地址往下读，但是memmove全部读，strncpy，读指定字节只读0x0之前的             }             if (File_S.Info_Mod<448){                 if (i == File_S.Info_Div)                 {                     memmove(Data_Temp, Temp, BLOCK_BYTE);                     memmove(&Data_Temp[BLOCK_BYTE - FILE_LEN], &File_S.Info_Size, FILE_LEN);                     Data_Temp[File_S.Info_Mod / BIT] = FIRST_APPEND_BYTE;                     goto Do_5;                 }                 if (i == File_S.Info_Div + 1) goto End;             }             else{                 if (i == File_S.Info_Div + 1)                 {                     memmove(&Data_Temp[BLOCK_BYTE - FILE_LEN], &File_S.Info_Size, FILE_LEN);                     goto Do_5;                 }                 else if (i == File_S.Info_Div)                 {                     memmove(Data_Temp, Temp, BLOCK_BYTE);                     Data_Temp[File_S.Info_Mod / BIT] = FIRST_APPEND_BYTE;                     goto Do_5;                 }             }             memmove(Data_Temp, Temp, BLOCK_BYTE);         Do_5:       MD5(Data_Temp);         End:;         }     }     free(Data_Temp);     free(Temp); } int main()//文件太大时，时间长且结果错误，需优化算法<2G左右计算OK {     char *p = "E:\\Test_.exe";     GetMd5(p, 'F');//完全版，p可以是字符串，也可以是文件名，main函数自己写，F代表file,M代表字符串     int i;     for (i = 0; i<16; i++)     {         Ciphertext_32[i] = (State[i / 4] >> (i % 4) * 8) & 0xff;     }     printf("32BIT:");     for (i = 0; i < 16; i++)     {         printf("%02x", Ciphertext_32[i]);     }     printf("\n16BIT:");     for (i = 4; i < 12; i++)     {         printf("%02x", Ciphertext_32[i]);     }     getchar(); }


Question: 二维数组和指针的一道题

引用 4 楼 zhao4zhong1 的回复:printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。 谢谢赵老师！

引用 2 楼 GKatHere 的回复:呵呵, double是双四(8)字节, %lf,  float是四字节, %f 谢谢！

引用 1 楼 user-6 的回复:scanf("%f",&p1[x][y]);  scanf("%lf",&p1[x][y]);  小写的L  谢谢！

scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s

将scanf中的%f改成%lf，程序就运行正常了

呵呵, double是双四(8)字节, %lf,  float是四字节, %f


Question: 变量地址问题

就是想问一下造成这样的原因，如果不给另一个变量重新分配地址那就没有别的解决方法了？

这是C51吗？ 给另外那个变量分配一个不一样的地址。

我也不熟，只是建议。 完成任务，先别纠结各种语法相关问题。


Question: 用指针方法处理“输入三个字符串，按由小到大的顺序输出”，编译结果出现异常

引用 27 楼 lgbxyz 的回复:没用_s安全函数的代码没有错啊，是对的，你要我怎么解释对的程序是为什么对的？ 恩恩，了解是对的，就是按说在12版本里也应该用_s

这个范围是最大范围，大过了数组的，数组就越界了

本身数组申请的是20个，而其他的操作长度都是100，所以越界了

引用 25 楼 lgbxyz 的回复:？你希望有什么问题 就是原因SHISHENM?

？你希望有什么问题

引用 22 楼 lgbxyz 的回复:微软定义的安全型字符串拷贝函数strcpy_s的定义就是这样的啊  errno_t strcpy_s(    char *strDestination,    size_t numberOfElements,    const char *strSource  );  https://msdn.microsoft.com/en-us/library/td1esda9(VS.80).aspx  你的写的参数顺序是linux下的安全型字符串拷贝函数strncpy的顺序  char *strncpy(char *dest, const char *src, size_t n);  好吧，多谢多谢，这个安全函数还是蛮让人头疼的啊~ 以前都是遇到的scanf_s gets_s什么的，直接在后面加了，这个就不行了~  但是为啥我把所有的安全函数去了，参数也去了，在vs2012的环境下运行没问题呢？

话说交换指针不需要用strcpy。。。

引用 20 楼 lgbxyz 的回复:因为strcpy_s你用错了，参数写反了  #include<stdio.h> #include<string.h>  void swap(char*, char*);  int main(void) { 	char str1[40], str2[40], str3[40]; 	printf("input three line:\n"); 	gets_s(str1, 40); 	gets_s(str2, 40); 	gets_s(str3, 40); 	if (strcmp(str1, str2) > 0) 		swap(str1, str2); 	if (strcmp(str1, str3) > 0) 		swap(str1, str3); 	if (strcmp(str2, str3) > 0) 		swap(str2, str3); 	printf("Now,the order is:\n"); 	printf("%s\n%s\n%s\n", str1, str2, str3); }  void swap(char *p1, char *p2) { 	char p[40]; 	strcpy_s(p, 40, p1); 	strcpy_s(p, 40, p2); 	strcpy_s(p2, 40, p); }  可以了~终于解决了~，为什么这个函数缓冲参数（不知道是不是这样叫，还不太明白，麻烦讲一下）要写在这里？

#include<stdio.h> #include<string.h> void main() { 	void swap(char*, char*); 	char str1[40], str2[40], str3[40]; 	printf("input three line:\n"); 	gets(str1); 	gets(str2); 	gets(str3); 	if (strcmp(str1, str2) > 0) 		swap(str1, str2); 	if (strcmp(str1, str3) > 0) 		swap(str1, str3); 	if (strcmp(str2, str3) > 0) 		swap(str2, str3); 	printf("Now,the order is:\n"); 	printf("%s\n%s\n%s\n", str1, str2, str3); }  void swap(char *p1, char *p2) { 	char p[40]; 	strcpy(p, p1); 	strcpy(p1, p2); 	strcpy(p2, p); }  原代码不设参数及参数范围情况下，在同学电脑xs2012环境下编译运行通过~ 我的环境是vs2013，给跪了。

引用 12 楼 user-4 的回复:楼主为什么不试试改变一下“缓冲区”的大小试试呢？  修改了，修改了后面的参数改了很多次，都不行~

引用 16 楼 u013115964 的回复:或者你把STR 加大加到200 ，还有Q 也要加大  还是出错，也是醉了。~ 不过去掉_s及后面的缓冲参数，用vs2012编译不报错~，运行成功，见鬼了

或者你把STR 加大加到200 ，还有Q 也要加大

改成比你的str都还小的

所有的你都改成10

引用 10 楼 u013115964 的回复:gets_s 的参数是100 就是可以接受100个字符，你把100个字符给空间只有20的数组，这还不越界？ 你把100 改成10 ，你看还当不当  改成比40小的，10,20,30,39，都不行~

楼主为什么不试试改变一下“缓冲区”的大小试试呢？

char str[20]; 	gets_s(str,10);  	char str[20]; 	gets_s(str,100); 我试过，不信你自己测试下，就知道了


Question: 求问Windows环境下用C语言怎样才可以读取到下面的正则匹配串啊???

正则表达式速查 正则表达式举例 正则表达式学习 (4页A4纸)http://download.csdn.net/detail/zhao4zhong1/1808549

直接转DFA啊, 啥语言都没问题, 又方便性能又好..

引用 28 楼 lgbxyz 的回复:regex_match  必须完全匹配，即pattern 能够匹配整个string。 regex_search 是搜索，即pattern是string的字串，当然也可以匹配整个string。  为什么第0项和第一项都是那个结果？第二项才是想要的结果呢？

引用 28 楼 lgbxyz 的回复:regex_match  必须完全匹配，即pattern 能够匹配整个string。 regex_search 是搜索，即pattern是string的字串，当然也可以匹配整个string。 好，多谢 请问针对这个字符串： 2015-07-07 15:42:52,sink.MetaSink (MetaSink.java:onMessageSent:637): metasink meta-sink-msg4, succ put 741710000 events to meta, using 5440 millsec 怎么匹配出java这个结果？匹配模式串怎么写呀？

引用 37 楼 qq1134993111 的回复:C++的话，标准库就有，C的没研究过 解决了

C++的话，标准库就有，C的没研究过

引用 35 楼 lgbxyz 的回复:match中除了第0个元素之外，匹配的是子表达式，就是括号中的表达式， 你还是系统的学习一下正则表达式吧，你这么问来问去也不系统， 再说正则的表达式的中类分很多种，每种的规则都是有差异的。 好的，我去看看吧，多谢

引用 31 楼 lgbxyz 的回复:这个是子表达式的概念，用括号括起来的是子表达式。 pattern = "(^.+MetaSink). ([^:]+))" 匹配时match[0]中是整个pattern匹配的结果，然后match[N]就是第N个子表达式的匹配结果。 第一个子表达式 ：^.+MetaSink). ([^:]+)，与整个pattern相同，所以match[1]与match[0]相同 第二个子表达式：[^:]+  正确取Java字段的正则表达式是： MetaSink\.([^:]+)  取match[1]结果 regex_search的工作原理是什么呀？我去看了源码看不太懂，目前我自己从表面来理解是比如说像下面这个模式串 std::regex reg("^.+MetaSink.([^:]+).+metasink ([^,]+).+meta, ([^ ]+)"); 1、每次遇到[^:]里面的字符的时候就开始一次保存，然后再进行下一次匹配？ 2、比如说第一次直到遇到[^:]里面的:时截止一次，然后此时是把什么保存在smatch[1]里面呢？为什么是java，而不是包括java之前的所有字符？

自己写解析会蛋疼死的

Boost库可以匹配出^\d{4}\-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2}:\d{1,2}这样子格式的正则匹配串么？ @super_admi

为什么不使用C++的regex？

用pcre库

引用 25 楼 lgbxyz 的回复:在这里没啥区别， 主要是我写顺手了 你可以下载一个工具叫RegexBuddy自己试试 哦，差点忘了还有一个要问你，就是关于你写的关于这句话 regex_search(str, match, reg) 这个regex_search不是只会匹配字符串串里面是否有符合这个模式的子串是否存在的么？这个函数的话，意思是每匹配好一个就把匹配结果存进match里面么？我知道这个函数的返回值也是boolean类型，那它跟这个函数regex_match(ip, result, pattern)作用都一样么？

引用 25 楼 lgbxyz 的回复:在这里没啥区别， 主要是我写顺手了 你可以下载一个工具叫RegexBuddy自己试试 好的，不过也有很多在线网页测试正则表达式的，多谢你了啊，让我对正则表达式又进一步了解了

引用 23 楼 lgbxyz 的回复:[^,]+是指说重复不匹配逗号一次或者多次以上，是么？ 最后面的_m是表示前面括号里面全部匹配忘了，再去匹配后面是否有_m，使这样理解吧？   对 我看了看，感觉对(^[^,]+?),这里不太明白，就是关于非贪婪模式在这里的使用，匹配非逗号字符一次或者多次以上（非贪婪模式），那这里匹配遇到逗号就截止，然后由于非贪婪模式，就不在继续追究逗号以后的。如果换成(^[^,]+),这种情况的话那是怎么解释呢？


Question: C与指针第六章的习题疑问

引用 8 楼 sholber 的回复:我说我记得做过这道题的。还真是。  5 6 7 8 9 10   int del_substr (char * str, char const * substr) {     int cnt = 0;     char * p, * q, * r;     while (q = (char *)substr, * (p = r = str ++) != '\0')         while (* q != '\0' && * p ++ == * q)             if (* ++ q == '\0' && ++ cnt && -- str)                 while ((* r ++ = * p ++) != '\0') ;     return cnt; } 谢谢!!

引用 6 楼 leee7338 的回复:不能使用库函数  你要让赵4不用库函数，他会哭 的。

不能使用库函数

仅供参考：#include <stdio.h> #include <string.h> char s[256]; char *p; int r,n,i; int main() {     while (1) {         printf("请输入一行文字(空行结束),\"%%20\"将替换为\" \",\"你懂得\"将替换为\"XXXXXX\":\n");         fgets(s,256,stdin);         if ('\n'==s[0]) break;         p=s;         while (1) {             p=strstr(p,"%20");             if (p) {                 memmove(p+1,p+3,strlen(p)-3+1);                 p[0]=' ';             } else break;         }         p=s;         while (1) {             p=strstr(p,"你懂得");             if (p) {                 memmove(p+6,p+6,strlen(p)-6+1);                 for (i=0;i<6;i++) p[i]='X';             } else break;         }         printf("%s",s);     }     return 0; } //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //abcdefg%20helloworld%20something.pdf //abcdefg helloworld something.pdf //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //这是测试文字你懂得，在这个你懂的地方，就得做你懂得的事 //这是测试文字XXXXX，在这个你懂的地方，就得做XXXXX的事 //请输入一行文字(空行结束),"%20"将替换为" ","你懂得"将替换为"XXXXXX": //

不使用下标，可以使用指针。 字符匹配以前字符拷贝的过程中，全部使用指针来操作。

比较的时候若*（str+i）和*（subsr+i）相等i++，不等break；判断i的值，再与strlen(subsr)比较。 删除的时候让str字符串中subsr串最后字符的下一个字符的指针 指向最前面字符的前一个字符的地址。

不要goto,放个标志好了 int del_substr(char*str,char const*sub) {     if(!sub||!str) return 1;     int del=0;     char *p;     const char *s;     while(!del && *str){         for(p=str,s=sub;*p&&*p==*s;p++,s++)             del=0;         if(!*s) {             del =true;             while(*p) *str++ =*p++;             *str='\0';         }else ++str;     }     return del; }

来个人丫/ A\


Question: 编写程序

“多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，搬手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

引用 1 楼 user-2的回复:直接比较 char 不行吗？ 我发现输出的结果都是输入的第2个字母，并没有进行码值比较啊。。

直接比较 char 不行吗？


Question: 求一个使用C语言在指定窗口里找小图的算法

http://www.autohotkey.com 提醒：autohotkey是开源的。


Question: 不知道错在哪儿。。还有就是想把它改得更简单一点儿，这个太长了

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George

你可以尝试把这3个(毕业设计基本信息, 学生选题基本信息, 学生基本信息) 以及增删改需要提示的信息融合到一个大结构中. 再写一个处理函数. 传入对应输入的结构....

没错了。。。现在就想把它改的更短一点儿。


Question: 为什么这个输入中第二个字符串是没有\0的？？scanf("%s %s %s%f%f%d%f".......

你就不能每个前面都加个\t么

\0是看不到的吧，判断字符串是否有\0，一般是有没有乱码或者输出时字符串有没有超出范围。

To set a breakpoint when a variable changes value   From the Edit menu, click Breakpoints.   Click the Data tab of the Breakpoints dialog box.   In the Expression text box, type the name of the variable.   Click OK to set the breakpoint.

变量在内存的的位置，有可能被另外的变量踩了。 另外的变量是不是输入大于了最大的空间。这样就会踩到其他变量。

scanf("%2s %3s %8s%f%f%d%f",...

看下结构体中cousenum的长度是几？ 是不是足够大？

看看结构定义里面的那个字符数组大小是不是不够


Question: C语言操作文件时怎么清空之前的数据呢

不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。

#include "stdio.h" #include "student.h" #include "stdlib.h" #include "file.h" #include "string.h"  #define SIZE sizeof(struct student) struct student *head,*last; void screen(); int n=0; void stucpy(struct student *stu1,struct student *stu2) { 		stu1->num=stu2->num; 		strcpy(stu1->name,stu2->name); 		stu1->age=stu2->age; 		strcpy(stu1->sex,stu2->sex); 		stu1->score=stu2->score; } void swap(struct student *stu1,struct student *stu2) { 	struct student stu={0,"",0,'M',0}; 	struct student *temp; 	temp=&stu; 	stucpy(temp,stu1); 	stucpy(stu1,stu2); 	stucpy(stu2,temp); } /*void sortStu() { 	struct student *p1,*k; 	int i,j; 	for(p1=head,i=0;i<n-1;p1=p1->next) 	{ 		k=p1->next; 		for(j=1;j<n;j++) 		{ 			 			if(k->num<p1->num) 			{ 				swap(k,p1); 			} 			k=k->next; 		} 		i++; 	} }*/ void printstu(struct student *stu) { 	printf("%ld\t%s\t%s\t%d\t%4.1f\n",stu->num,stu->name,stu->sex,stu->age,stu->score); } void selectAll() { 	 	printf("NO.\tName\tSex\tAge\tScore\n"); 	struct student *stus; 	stus=head; 	 	for(int i=0;i<n;i++) 	{ 		printf("%ld\t%s\t%s\t%d\t%4.1f\n",stus->num,stus->name,stus->sex,stus->age,stus->score); 		stus=stus->next; 	} } void insert(struct student *stu)/* head 代表头指针，stu代表要插入的节点*/ {	 	struct student *p0,*p1,*p2; 	p0=stu; 	 	if(head==NULL) 	{ 		p1=p2=head=p0; 		p0->next=NULL; 	} 	else 	{ 		p1=p2=head; 		if(p0->num<p1->num) 		{ 			head=p0; 			p0->next=p1; 		} 		else 		{ 			while((p0->num>p1->num)&&(p1->next!=NULL)) 			{ 				//p2记录上一个节点的指针 				p2=p1; 				p1=p1->next; 			}	 			if(p0->num>p2->num && p0->num<p1->num) 			{ 				p2->next=p0; 				p0->next=p1; 			} 			else if(p0->num>p1->num) 			{ 				p2->next=p0; 				p0->next=NULL; 			} 			else 			{ 				printf("data error!!!"); 			} 		} 	} } void writeToFile() { 	struct student *stus; 	stus=head; 	FILE *fp; 	fp=fopen("C:\\Users\\zcq\\Desktop\\file.txt","wb"); 	if(fp!=NULL) 	{ 		for(int i=0;i<n;i++) 		{ 			fwrite(stus,SIZE,1,fp); 			 			stus=stus->next; 		} 		fclose(fp); 	} 	 } void addOne() { 	struct student *p1,*p2; //p1p2一个用来指向新创建的节点，一个用来指向上一个节点 	//n在这里表示起始节点的个数 	p1=p2=(struct student *) malloc(SIZE); //开辟一个新单元，返回一个void指针(强制转换)，让p1p2都指向这个内存区域的首地址 	printf("请输入学生学号，姓名，性别，年龄，成绩，用空格键隔开:\n"); 	scanf("%ld %s %s %d %f",&p1->num,&p1->name,&p1->sex,&p1->age,&p1->score);  //输入使p1指向他s 	head= NULL; 	int flag; 	while(1) 	{ 		insert(p1); 		n++; 		printf("添加成功，可按0退出或其他数字键继续\n"); 		scanf("%d",&flag); 		if(!flag) break; 		p1=(struct student *)malloc(SIZE); 		printf("请输入学生学号，姓名，性别，年龄，成绩，用空格键隔开:\n"); 		scanf("%ld %s %s %d %f",&p1->num,&p1->name,&p1->sex,&p1->age,&p1->score);  	} 	//结束后将p2指向NULL 	writeToFile(); }  void deleteOne() { 	long num=0; 	printf("请输入您要删除的学生的学号：\n"); 	scanf("%ld",&num); 	struct student *p1,*p2; 	p1=p2=head; 	if(head->num==num) 	{ 		head=p1->next; 	}else 	{ 		while(p1->num !=num && p1->next!=NULL) 		{ 			p2=p1; 			p1=p1->next; 		} 		if(p1->num==num) 		{ 			p2->next=p1->next; 			n=n-1; 		} 		else 		{ 			printf("NO.%ld is not found!!",num); 		} 	} 	writeToFile(); } void selectOne() { 	long num; 	struct student *stu; 	stu=head; 	printf("请输入您要查询的学生号,按Enter键确定\n"); 	scanf("%ld",&num); 	char ch[6]; 	char flu; 	for(int i=0;i<n;i++) 	{ 		if(stu->num!=num && stu->next!=NULL) 		{ 			stu=stu->next; 		} 		if(stu->num==num) 		{ 			printf("%ld\t%s\t%s\t%d\t%4.1f\n",stu->num,stu->name,stu->sex,stu->age,stu->score); 			break; 		} 		if(stu==last) 		{ 			printf("此学号不存在，请按1重新输入或按其他键退出"); 			scanf("%s",ch); 			scanf("%*c",&flu); 			if(!strcmp(ch,"1")) 			{ 				selectOne(); 			} 		} 	} }  void exit() { 	exit(1); } int filelen(char *pFilePath) { 	FILE *pFile = fopen( pFilePath, "r" );    char ch;    int num = 0;    while ( ch = getc( pFile ) != EOF )    {           num++ ;    }    fclose( pFile );    return num; } void main() { 	//刚启动则建立一个链表，读取文件中的信息 	FILE *fp; 	char fileName[50]="C:\\Users\\zcq\\Desktop\\file.txt"; 	struct student *p1,*p2; 	fp=fopen(fileName,"rb"); 	if(fp==NULL) {printf("数据文件读取失败"); exit(0);} 	if(fp!=NULL) 	{ 		//TODO: 		if(filelen(fileName)!=0) 		{ 			while(feof(fp)==0) 			{	 				if(!n) 				{ 					head=p1=p2=(struct student *)malloc(SIZE); 					fread(p1,SIZE,1,fp); 					stucpy(head,p1); 					last=p1; 					p1->next=NULL; 					n++; 				} 				else 				{ 					p1=p2=(struct student *)malloc(SIZE); 					fread(p2,SIZE,1,fp); 					stucpy(p1,p2); 					last->next=p1; 					p1->next=NULL; 					last=p1; 					n++; 				} 			} 		} 		 		printf("%d",n); 	} 	screen(); } void screen() { 	int choice=0; 	while(1) 	{ 		printf("\n\n\n\n\n"); 		printf("***********************Welcome to the student info system***********************\n"); 		printf("************************1.显示所有学生信息**************************************\n"); 		printf("************************2.查询各人信息******************************************\n"); 		printf("************************3.添加学生信息******************************************\n"); 		printf("************************4.删除学生信息******************************************\n"); 		printf("************************5.退出**************************************************\n"); 		printf("*******************请输入选项，按Enter键确认....********************************\n"); 		scanf("%d",&choice); 		switch(choice) 		{ 		case 1: 			selectAll(); 			break; 		case 2: 			selectOne(); 			break; 		case 3: 			addOne(); 			break; 		case 4: 			deleteOne(); 			break; 		case 5: 			exit(); 			break; 		default : 			break; 		} 	} }

读之前将你存储数据的内存memset了。

贴一下代码好不。


Question: glib的链表崩溃

引用 8 楼 mymtom 的回复:[quote=引用 4 楼 caddor9100 的回复:] #include <glib.h> #include<glib/glist.h>  int main() {  	GSList* pList; 	const gint nSize = 10; 	int nx; 	gint array[nSize] ;   	gint nPos = 0; 	for(nPos = 0; nPos < nSize; nPos++) 	{ 		array[nPos] = nPos+1; 		g_list_append(pList, &array[nPos]); 	} 	GSList *st; 	g_print("begin\n"); 	for (nPos = 0; nPos < nSize; nPos++) 	{ 		st = g_slist_nth(pList, nPos); 		g_printf("%d,", *(gint*)(st->data)); 	}	 	g_slist_free(pList); 	g_print("begin\n");  	return 0; }    c 语言。 gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC)   崩溃 看漏了，应该有两个问题 1.  第17行 g_list_append(pList, &array[nPos]); ===> g_slist_append(pList, &array[nPos]);   2. 第7行 GSList* pList; ===> GSList* pList = NULL;[/quote]    多谢，解决了  顺便请教一个 技巧问题：  samba共享给windows   用vs 当编辑器，写代码， windows linux换行不一致。 导致 后果就是 别人用vi打开后，会出现  M^。    我如何破？ 我是用samba。  有人会说：vs把每个文件另存为，之类的一些答案。 似乎不好。  1. vs 写代码，不可能写hello world， 会有很多文件。 我不可能每个文件高级另存为。 这样累而且会忘记。  2.  我是在找不到方法来解决了。  3. 让我换编辑器不现实， 我一直习惯Vs， 所以把vs当编辑器，也是首先。  辛苦大神了

引用 4 楼 caddor9100 的回复:#include <glib.h> #include<glib/glist.h>  int main() {  	GSList* pList; 	const gint nSize = 10; 	int nx; 	gint array[nSize] ;   	gint nPos = 0; 	for(nPos = 0; nPos < nSize; nPos++) 	{ 		array[nPos] = nPos+1; 		g_list_append(pList, &array[nPos]); 	} 	GSList *st; 	g_print("begin\n"); 	for (nPos = 0; nPos < nSize; nPos++) 	{ 		st = g_slist_nth(pList, nPos); 		g_printf("%d,", *(gint*)(st->data)); 	}	 	g_slist_free(pList); 	g_print("begin\n");  	return 0; }    c 语言。 gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC)   崩溃 看漏了，应该有两个问题 1.  第17行 g_list_append(pList, &array[nPos]); ===> g_slist_append(pList, &array[nPos]);   2. 第7行 GSList* pList; ===> GSList* pList = NULL;

引用 6 楼 mymtom 的回复:[quote=引用 4 楼 caddor9100 的回复:] #include <glib.h> #include<glib/glist.h>  int main() {  	GSList* pList; 	const gint nSize = 10; 	int nx; 	gint array[nSize] ;   	gint nPos = 0; 	for(nPos = 0; nPos < nSize; nPos++) 	{ 		array[nPos] = nPos+1; 		g_list_append(pList, &array[nPos]); 	} 	GSList *st; 	g_print("begin\n"); 	for (nPos = 0; nPos < nSize; nPos++) 	{ 		st = g_slist_nth(pList, nPos); 		g_printf("%d,", *(gint*)(st->data)); 	}	 	g_slist_free(pList); 	g_print("begin\n");  	return 0; }    c 语言。 gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC)   崩溃 17行 g_list_append(pList, &array[nPos]); ===> g_slist_append(pList, &array[nPos]);[/quote]   int main() {  	GSList* pList; 	const gint nSize = 10; 	gint array[nSize] ;  	gint nPos = 0; 	for(nPos = 0; nPos < nSize; nPos++) 	{ 		array[nPos] = nPos+1; 		pList = g_slist_append(pList, "first"); 	} 	g_print("begin\n"); 	GSList* node; 	for(node = pList; node != NULL; node = node->next) 		g_print("%p--------%d\n", node->data); 	g_slist_free(pList);  	return 0; }  GSList  g_slist_append崩溃  附上一个正确例子：  #include <glib.h> #include <stdio.h>  int main(int argc, char** argv) {  	GSList* list = NULL;  	printf("The list is now %d items long\n", g_slist_length(list));  	list = g_slist_append(list, "first");  	list = g_slist_append(list, "second");  	printf("The list is now %d items long\n", g_slist_length(list));  	g_slist_free(list);  	return 0;  }   它也是用 g_slist_append  GSList

引用 4 楼 caddor9100 的回复:#include <glib.h> #include<glib/glist.h>  int main() {  	GSList* pList; 	const gint nSize = 10; 	int nx; 	gint array[nSize] ;   	gint nPos = 0; 	for(nPos = 0; nPos < nSize; nPos++) 	{ 		array[nPos] = nPos+1; 		g_list_append(pList, &array[nPos]); 	} 	GSList *st; 	g_print("begin\n"); 	for (nPos = 0; nPos < nSize; nPos++) 	{ 		st = g_slist_nth(pList, nPos); 		g_printf("%d,", *(gint*)(st->data)); 	}	 	g_slist_free(pList); 	g_print("begin\n");  	return 0; }    c 语言。 gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC)   崩溃 17行 g_list_append(pList, &array[nPos]); ===> g_slist_append(pList, &array[nPos]);

GSList mylist; g_slist_free(&mylist); 这两个是单链表的函数  这两个是双链表的函数 g_list_append(&mylist, (int*)&nval1); g_list_append(&mylist, (int*)&nval1);  如果使用GList, 楼主可以这么改  #include <stdio.h>  #include <glib.h>  static void show(GList *list) {         GList *node;          for (node = list; node != NULL; node = node->next)         {                 printf("node=%p->%d\n", node, *(int *)(node->data));         } }  int main() {         GList *list = NULL;         GList *node;         int nval1 = 1;         int nval2 = 2;         int nval3 = 3;          list = g_list_append(list, &nval1);         show(list);          list = g_list_append(list, &nval2);         show(list);          list = g_list_prepend(list, &nval3);         show(list);          g_list_free(list);          return 0; }  /* 输出类似: node=0x1d334e00->1 node=0x1d334e00->1 node=0x1d334e20->2 node=0x1d334e40->3 node=0x1d334e00->1 node=0x1d334e20->2 */

当前目录下没搜索到，  而且代码也不知道为什么会崩溃。

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

http://www.cnblogs.com/aoyihuashao/archive/2012/09/14/2684605.html    任务发生异常，需要记录遗言信息，利用gdb调试，因此需要记录coredump文件。  设置查看：  在root用户下执行sysctl -a | grep core，查看core文件的配置是否正确  命令设置：  1）使用命令 ulimit -c unlimited 设置coredump文件可以使用最大空间；  　　或去vi /etc/security/limits.conf修改  2）/proc/sys/kernal/core_pattern 可以设置coredump产生的路径和文件名格式。如果不修改，默认在程序执行目录下产生。   　　或使用命令修改：  　　　　sysctl -w kernel.core_pattern=/core/core.%e.%p  如果设置了上述两点，还是不能产生coredump，可能是以下原因：  1） 有些信号量默认是不产生coredump的，可以用 man signal  看一下。  2） 硬盘空间不够了，coredump需要占用很大的硬盘空间（上G的空间）；  3） ulimit -c 命令只在当前terminal上有效，也就是程序启动的terminal设置该命令才有效。该命令无效，当然就不能产生coredump了。


Question: Linux 消息队列如何收发不同长度的消息？

int msg_prio; struct mq_attr attr; mq_getattr( mqid, &attr); mq_receive(mqid, buff_to_store_msg, attr.mq_msgsize, &msg_prio);

引用 4 楼 lgbxyz 的回复:[quote=引用 2 楼 harkue 的回复:] [quote=引用 1 楼 lgbxyz 的回复:] POSIX消息队列本来就不是定长的，  //首先得知道一个消息的最大字节数， 命令行：cat  /proc/sys/fs/mqueue/msgsize_max （通常是8192） 程序：mq_getattr()获取属性的mq_msgsize成员 如果你觉得系统默认的小了，可以使用mq_setattr()设置  //这里的msg_len是实际要发送的字节数，不能大于属性的mq_msgsize成员 int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len,   unsigned msg_prio);  //这里的msg_len为接受的最大长度，不能小于属性的mq_msgsize成员 size_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);   //这里的msg_len为接受的最大长度，不能小于属性的mq_msgsize成员 实际上还是要指定接收的长度吧。  比如如果指定的128Byte， 但是实际只有100个Byte，后续的28Byte是下一个消息的。这样会不会导致消息错位？[/quote]  不会，通常编程时msg_len赋值为属性的mq_msgsize成员的值，小于这个值返回EMSGSIZE错误， 消息队列的是使用虚拟文件系统实现的，不是简单的写内存，2条连在一起的这种方式[/quote]  是否可以理解为 1.  执行mq_getattr()获取属性的mq_msgsize成员，这样可以获取到消息的大小msg_length了 2.  执行size_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);，此时的msg_len已经设置为上面的msg_length了？

引用 2 楼 harkue 的回复:[quote=引用 1 楼 lgbxyz 的回复:] POSIX消息队列本来就不是定长的，  //首先得知道一个消息的最大字节数， 命令行：cat  /proc/sys/fs/mqueue/msgsize_max （通常是8192） 程序：mq_getattr()获取属性的mq_msgsize成员 如果你觉得系统默认的小了，可以使用mq_setattr()设置  //这里的msg_len是实际要发送的字节数，不能大于属性的mq_msgsize成员 int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len,   unsigned msg_prio);  //这里的msg_len为接受的最大长度，不能小于属性的mq_msgsize成员 ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);   //这里的msg_len为接受的最大长度，不能小于属性的mq_msgsize成员 实际上还是要指定接收的长度吧。  比如如果指定的128Byte， 但是实际只有100个Byte，后续的28Byte是下一个消息的。这样会不会导致消息错位？[/quote]  不会，通常编程时msg_len赋值为属性的mq_msgsize成员的值，小于这个值返回EMSGSIZE错误， 消息队列的是使用虚拟文件系统实现的，不是简单的写内存，2条连在一起的这种方式

仅供参考：//循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef WIN32     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX ; CRITICAL_SECTION cs_BBB ; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             Log("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef WIN32     pthread_exit(NULL); #endif } int main() { #ifdef WIN32     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX );     InitializeCriticalSection(&cs_BBB ); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef WIN32     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef WIN32     DeleteCriticalSection(&cs_BBB );     DeleteCriticalSection(&cs_HEX );     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }

引用 1 楼 lgbxyz 的回复:POSIX消息队列本来就不是定长的，  //首先得知道一个消息的最大字节数， 命令行：cat  /proc/sys/fs/mqueue/msgsize_max （通常是8192） 程序：mq_getattr()获取属性的mq_msgsize成员 如果你觉得系统默认的小了，可以使用mq_setattr()设置  //这里的msg_len是实际要发送的字节数，不能大于属性的mq_msgsize成员 int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len,   unsigned msg_prio);  //这里的msg_len为接受的最大长度，不能小于属性的mq_msgsize成员 ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);   //这里的msg_len为接受的最大长度，不能小于属性的mq_msgsize成员 实际上还是要指定接收的长度吧。  比如如果指定的128Byte， 但是实际只有100个Byte，后续的28Byte是下一个消息的。这样会不会导致消息错位？