Question: 什么是字符串指针，什么是数组指针，指针数组他们之间的关系

你老师也有出错的时候,所以适当的怀疑是正确的. 然后,推荐<C prime plus>中文版,很全!

换个老师，不行的话就换本书。

自个百度然后实际写代码测试一下不就得了

理解和讨论之前请先学会如何观察！  计算机组成原理→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

引用 楼主 qq_28334193 的回复:char  s1[]={'i','p','o','n','e''}; char  s2[]="ipone"; char *s3="ipone";    第一个叫字符数组？第二个叫字符串数组？第三个字符串指针？对吗？ 那么s1，s2，s3叫数组指针吗？他们都指向首地址。    我老师这样教我们的：数组的名字是数组指针。 字符串指针一定是数组指针。数组指针不一定是字符串指针。 我想问这样说对吗?求大神回答！ 声明时： s1 s2都叫数组，s3叫指针。 s1叫字符数组没错 s2叫c风格字符串(数组)（因为已经有了C++了） s3是字符指针，指向了一个常量字符串，这个指针还可以指向一个字符。 使用时： s1,s2，代表了数组的首地址，和指针的用法一样，但本质是不同的。这个可读可写。 s3也可以使用下标的用法s3[X]。因为目前指向的是常量，所以可读，但写就属于非法操作了。

还有，地址不能更改，指针可以更改其值，如 int a[] = {0}; int b; a = &b;  //非法 int *p = a; p = &b;  //合法

引用 楼主 qq_28334193 的回复:char  s1[]={'i','p','o','n','e''}; char  s2[]="ipone"; char *s3="ipone";    第一个叫字符数组？第二个叫字符串数组？第三个字符串指针？对吗？ 那么s1，s2，s3叫数组指针吗？他们都指向首地址。    我老师这样教我们的：数组的名字是数组指针。 字符串指针一定是数组指针。数组指针不一定是字符串指针。 我想问这样说对吗?求大神回答！  楼主，你们老师也太坑爹了，这不误人子弟么  首先指针和地址是有区别的，前者是变量，后者是值 数组的名字不是数组指针，它只不过在编译时被翻译成数组的首地址，所以可以通过数组名来得到数组的首地址 char *s3 是字符指针，存放的是字符的地址；char *s3="ipone"; 将字符串常量的首地址，即第一个字符的地址赋给s3。 char (*p)[4]  这样才是数组指针，char*p[4]指针数组，这两句话没错

我在书上看的：  char (*p)[4]  这样才是数组指针    一定要这样的格式吗才算是数组指针吗？我上面问的是不是？            char*p[4]指针数组。


Question: 关于arm与pc之间进行socket通信

你用的socket类库是否依赖于系统？socket通信是不用修改的，关键是看你用的socket类库是否支持跨平台。

楼上正解 。。。。。。

arm中如果是linux系统，直接在pc的linux中交叉编译，然后下载到arm中运行即可

引用 1 楼 zjq9931 的回复:做过很基本的一些，理解不是很深，但是这个既然是socket的，通信协议都是TCP/IP，就没有问题吧？不用做什么修改啊。。。 需要在arm中移植协议吗？还是说直接烧进程序就ok


Question: 《深入理解计算机系统》里的链接器部分问题

引用 12 楼 fetag 的回复:变量在使用之前，会有 “定义” 和 “初始化” 两个操作。其中“定义”的部分是告诉编译器 后面遇到这个标识符要怎样对待，在这个  步骤的时候，编译器是不会实际分配内存空间的；而初始化部分，就是要确实分配内存了，因为要首次给这个变量赋值了。  理解了上面的过程，就很容易解释 extern 关键字了。它的一个含义是：该变量已经在别处初始化过了，此处只是引用，相当于一  个定义，不用为其重新分配内存空间。  从编译器的角度看，foo3.c 和 bar3.c 中的两个x是完全不同的，因为一个初始化了，一个未初始化。未初始化的全局变量 是放在  可执行程序中.bss段的，它不会增加可执行程序的大小；而初始化了的全局变量 是放在.data段中的，这个会增加可执行程序的大  小。举个例子，假如那个x是个长度为100的数组，则初始化了和未初始化的，会导致编译完成的可执行程序size相差大概99左右。 谢谢！！

引用 13 楼 u012033027 的回复:各位洋洋洒洒很多文字，跟楼主的问题几乎不沾边。 楼主的问题，书中已经解释了。初始化的变量是强符号，未初始化的变量是弱符号。所以bar3.c中定义了一个x，但是与foo3.c中的另一个x定义冲突，所以使用了foo3.c中的定义（因为这里是强定义）。 至于为什么没有extern，应该是因为bar2.c中关于x的定义就说明了它要有一个x，但是被foo3.c中的替换了，所以就不用extern定义了。 谢谢！！

引用 9 楼 sunranlb 的回复:那这么说来extend关键字又有什么用呢？这样重名的变量岂不是都可以不用extend关键字了？ int x;编译器会给全局变量分配空间。extend int x; extend其实就是说我编译器不会为这个x分配空间，链接成可执行文件的时候 你链接器要在其他o文件里找。

引用 9 楼 sunranlb 的回复:[quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote]  那这么说来extend关键字又有什么用呢？这样重名的变量岂不是都可以不用extend关键字了？  PS：谢谢老师的回答，你的回答比1楼强多了！[/quote]  读书时一个层次； 读源码是一个层次； 写源码是一个层析

引用 2 楼 ypzhong 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote]  那这么说来extend关键字又有什么用呢？这样重名的变量岂不是都可以不用extend关键字了？  PS：谢谢老师的回答，你的回答比1楼强多了！

吓我一跳， 还好VS中.obj符号名重复会报警

引用 2 楼 ypzhong 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。

引用 1 楼 zhao4zhong1 的回复:有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。

引用 7 楼 ypzhong 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] [quote=引用 5 楼 ypzhong 的回复:] [quote=引用 3 楼 zhao4zhong1 的回复:] [quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。[/quote] 不要很多情况，就在这个情况下你来说说你看到源码体会和直接给你原理的体会有什么不一样。[/quote] 源码实现时遇到的N多特殊情况以及在该情况下如何做，在原理、书籍、博客、讲演稿、……中没提的多了。  说是一物即不中。  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？ [/quote] 你不去创办个宗教就可惜了，绝对这方面的人才，因为你们有一个共同点，就是一个答案解释所有问题。[/quote] 实践是检验真理的唯一标准。

引用 6 楼 zhao4zhong1 的回复:[quote=引用 5 楼 ypzhong 的回复:] [quote=引用 3 楼 zhao4zhong1 的回复:] [quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。[/quote] 不要很多情况，就在这个情况下你来说说你看到源码体会和直接给你原理的体会有什么不一样。[/quote] 源码实现时遇到的N多特殊情况以及在该情况下如何做，在原理、书籍、博客、讲演稿、……中没提的多了。  说是一物即不中。  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？ [/quote] 你不去创办个宗教就可惜了，绝对这方面的人才，因为你们有一个共同点，就是一个答案解释所有问题。

引用 5 楼 ypzhong 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] [quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。[/quote] 不要很多情况，就在这个情况下你来说说你看到源码体会和直接给你原理的体会有什么不一样。[/quote] 源码实现时遇到的N多特殊情况以及在该情况下如何做，在原理、书籍、博客、讲演稿、……中没提的多了。  说是一物即不中。  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？

引用 3 楼 zhao4zhong1 的回复:[quote=引用 2 楼 ypzhong 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 有工夫阅读一下Linux下链接器的源代码。 别出馊主意了，这种问题读源码比直接看理论难多少倍。 楼主多看几遍原文，你看第一行的意思，如果一个模块里x未被初始化，那么链接器会选择另外一个被初始化的x。明显foo3.c这个模块x被初始化了，那么链接器会把 bar3.c f()函数里的x链接到foo3.c里的x。链接不仅仅是很多个o文件的函数链接到同一个可执行文件里，还包括全局变量。[/quote] 很多情况下，使用最笨最累最痛苦的办法学习一门技术，比使用最聪明最轻松最舒服的办法学习这门技术学得更到位且体会更刻骨铭心。[/quote] 不要很多情况，就在这个情况下你来说说你看到源码体会和直接给你原理的体会有什么不一样。

有工夫阅读一下Linux下链接器的源代码。


Question: 关于指针变量，求大神解惑

注意*和&在声明时和调用时的意思不一样。

能不能先把断句、标点标清楚了再发帖？

int *a 你可以看做是 typedef int* INT_PTR; 然后  INT_PTR a; 单独的 *a 不是取地址，而是解引用，取指针指向的内容, 和 & 是相反的操作 a  ===  *(&a)

你啥意思，拿出实际代码来问吧； 另外： int* a; *a 代表a这个指针指向的那块内存； &a 代表a这个指针本身的地址；

难道楼主说的是函数指针？  这个指针是指向函数首地址的

引用 1 楼 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 赵4 老师

看得不知所云, 不明白就直接写代码出来问吧

刚开始学 C，先不要去理解 C++ 中的引用，要不一个 & 符号初学者会疯掉的：int func(int *&); int a   = 1; int b   = 2; int c   = a & b; int t   = func(&c); int *p  = &c; int &r  = a; int *&f = p; int q   = func(f); int n   = r + *f;

// C 中的指针： // 指针运行时初始化赋值 int i1  = 0; int *p1 = NULL; p1 = &i1; // 指针亦可初始化时赋值 int i2  = 0; int *p2 = &i2; // 参数的传递： // 声明： int func1(int);     // 参数为 int 类型 int func2(int *);   // 参数是一个 int 类型的地址 // 调用： // 1. 值传递，函数中无法改变原参数的值 func1(i1); func1(*p1);         // p1 就是 i1 的地址，因此 *p1 就是 i1 的值 func1(i2); func1(*p2);         // p2 就是 i2 的地址，因此 *p2 就是 i2 的值 // 2. 指针值传递，函数中无法改变原指针(参数)的值 // 但可通过指针(参数)改变指针(参数)指向的值 func2(&i1);         // 这里的 & 就是取 i1 (int 类型) 的地址 func2(p1);          // p1 就是 i1 (int 类型) 的地址值 func2(&i2);         // 这里的 & 就是取 i2 (int 类型) 的地址 func2(p2);          // p2 就是 i1 (int 类型) 的地址值传入的值是没法改变的，只有传入值的类型为非常量指针时，才可以间接改变其指向变量的值而已。// C++ 中的引用： // 指针用法同上 int i    = 0; int *p   = &i; // 引用，在类型后面添加 & 符号 int &ri  = i;       // 引用 ri 为 i 的别名，改变 ri 的值等于改变 i int *&rp = p;       // 引用 rp 为 p 的别名，改变 rp 的值等于改变 p                     // 改变 *rp 等于改变 *p，也等于改变了 i 和 ri // 参数的传递： // 声明： int func1_1(int);   // 参数为 int 类型 int func1_2(int &); // 参数为 int 类型的引用 int func2_1(int *); // 参数为 int 类型的指针 int func2_2(int *&);// 参数为 int 类型的指针的引用 调用： // 值传递，函数中无法改变原参数的值 func1_1(i); func1_1(ri); // 引用 ri 相当于 i 的别名，函数中都可以直接地改变原 ri/i 的值 func1_2(i); func1_2(ri); // 指针值传递，引用 rp 相当于 ip 的别名，函数中两者可以间接地改变 ri/i 的值 func2_1(p); func2_1(rp); // 同上。由于指针也是引用传递，函数中两者可以直接地改变 rp/p 的值，也可以间接地通过指针改变 ri/i 的值 func2_2(p); func2_2(rp);引用参数传入的值是可以改变的，如果传入值的类型为非常量指针时，还可以间接改变其指向变量的值。

如函数声明为引用如：  void LiRu1(int &a) {     printf("%d",a); }  调用： int a = 0; LiRu(a);  自己试着看看这两个函数输出的是啥！（上面的函数返回值是void）

语文没学好！  若有函数声明：如int LiRu(int &a); 这里是引用c++里的，和指针没关系。 若有函数调用：如int LiRu(&a); 这里的函数再声明时参数是指针类型的. 如：  int LiRu(int *li) {       printf("%d",li); }  void main(){      int a = 0;      int *c;      c = &a;      LiRu(&a);      LiRu(c); }


Question: 条件运算符求3个数中间数

int mid( int a, int b, int c ) { 	if ( a > b ) 	{ 		if ( a < c ) 		{ 			return a; 		} 		else 		{ 			if ( b > c ) 			{ 				return b; 			}  			else 			{ 				return c; 			} 		} 	} 	else 	{ 		if ( b < c ) 		{ 			return b; 		} 		else 		{ 			if ( a > c ) 			{ 				return a; 			}  			else 			{ 				return c; 			} 		} 	} } 我真是太无聊了。

int d = a > b ? a : b;          if (d == a && d < c) {         printf("%d\n", a);     } else if (d == b && d < c) {         printf("%d\n", b);     } else {         printf("%d\n", c);     } 有点感觉

a > b ? (a < c ? a : (b > c ? b : c)) : (b < c ? b : (a > c ? a : c)); a==b,上面为false,所以直接跑到 (b < c ? b : (a > c ? a : c)); b==c,上面为false，所以直接跑到 (a > c ? a : c)); a==c,上面为false，所以直接跑到c


Question: pthread如何从子线程向主线程发消息?

引用 8 楼 madpc 的回复:多谢楼上各位的热心回复, 受教了, 还有点问题想问一下: 1 楼上有加互斥锁和队列两种方式, 这两者的最大区别是不是前者更强调实时,后者更像是异步? 2 关于队列, 如果我用一个数组充当队列, 子线程向其追加信息, 主线程定时去取消息, 其实也可以? 1、互斥锁和队列没什么必然联系，只是如果在多线程情况下为了防止资源竞争出现问题，用互斥锁保护一下队列的元素添加删除等操作。当然， 使用队列本身就是一种异步的方式。 2、只要把队列的读写加上同步保护操作，哪个线程操作都没有问题

引用 2 楼 madpc 的回复:[quote=引用 1 楼 mujiok2003 的回复:] 如果经常通信的话,  1.queue 2. tcp/ip 一次性通信的话: 1. future,promise, packaged_task等 2. 条件变量 + 共享变量  这方面刚接触,求详解,另外,请注意我说的是pthread[/quote] pthread 和其他thread api/library没本质区别。  http://stackoverflow.com/questions/4577961/pthread-synchronized-blocking-queue

建一个消息队列，子线程向队列压入消息数据，主线程从队列取出消息数据

仅供参考：//循环向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 楼 mujiok2003 的回复:如果经常通信的话,  1.queue 2. tcp/ip 一次性通信的话: 1. future,promise, packaged_task等 2. 条件变量 + 共享变量  这方面刚接触,求详解,另外,请注意我说的是pthread

//msg queue -lrt #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <mqueue.h>  #define MSQ_NAME "/msg_que_com"  mqd_t qid;   void* thread_entry(void* arg) {     static int i = 0;     char msg_buf[32] = {0};      while (1)     {         i++;         sleep(1);         sprintf(msg_buf, "message %d", i);         mq_send(qid, msg_buf, 32, 0);     }      mq_close(qid);     return NULL; }   int main(void) {     char* msg_ptr;     struct mq_attr attr;     pthread_t tid;      qid = mq_open(MSQ_NAME, O_CREAT | O_RDWR, 644, NULL);     if (qid < 0)     {         perror("mq_open");         exit(EXIT_FAILURE);     }      pthread_create(&tid, NULL, thread_entry, NULL);      mq_getattr(qid, &attr);     msg_ptr = calloc(1, attr.mq_msgsize);      while (1)     {         if (mq_receive(qid, msg_ptr, attr.mq_msgsize, NULL) > 0)         {             printf("msg : %s\n", msg_ptr);         }     }      pthread_join(tid, NULL);      mq_close(qid);     mq_unlink(MSQ_NAME);      return 0; }

#include <stdio.h> #include <stdlib.h> #include <pthread.h>  pthread_mutex_t mutex; pthread_cond_t cond; static char g_msg_buf[256];   void* thread_entry(void* arg) {     static int i = 0;     while (1)     {         i++;         sleep(1);         pthread_mutex_lock(&mutex);         sprintf(g_msg_buf, "message %d", i);         pthread_cond_signal(&cond);         pthread_mutex_unlock(&mutex);     }      return NULL; }   int main(void) {     pthread_t tid;      pthread_mutex_init(&mutex, NULL);     pthread_cond_init(&cond, NULL);      pthread_create(&tid, NULL, thread_entry, NULL);      while (1)     {         pthread_mutex_lock(&mutex);         pthread_cond_wait(&cond, &mutex);         printf("msg : %s\n", g_msg_buf);         pthread_mutex_unlock(&mutex);     }      pthread_join(tid, NULL);      pthread_mutex_destroy(&mutex);     pthread_cond_destroy(&cond);      return 0; }


Question: 求无序数组中的最小K个数，用划分的方法，时间复杂度为什么是O(n)

因为每次递归只进入一边，所以复杂度是 O(n).

引用 3 楼 ri_aje 的回复:因为每次递归只进入一边，所以复杂度是 O(n). 恩，是这个道理。在回复别人的时候突然想通了，快排是必须要向下递归的，而上面这个并不需要递归，而是类似折半。 1+1/2+1/4+1/8+...<2    ，o(2n)=o(n)，所以时间复杂度是o(n)。  欧了。谢谢大神！

引用 5 楼 fly_dragon_fly 的回复:象是select 算法, 记忆中应该是期望时间是O(n), 有兴趣翻一下 CLRS顺序统计量那章,上面有证明 这是快排中的划分方法。快排必须递归到logn层，而求最小k个数可能只需要划分几次就找到index了。

引用 1 楼 user-4 的回复:这个是使用计数排序的吧？不过，用堆来做个人感觉更常见上些 不是计数排序，是用了快排中的划分方法。堆方法适合处理海量数据，性能确实比较好，时间复杂度为o(nlogk)。我现在想知道为什么划分这种方法时间复杂度是o(n) ？

引用 2 楼 GKatHere 的回复:假设  Partition(input, n, start, end); 为 index++; 那么 for(int index = 0; index < k; index++) ;的时间复杂度为多少? 每次 Partition都要扫描一次数组，按照你这种说法时间复杂度就是o(nk)了

引用 7 楼 gk405128494 的回复:[quote=引用 5 楼 fly_dragon_fly 的回复:] 象是select 算法, 记忆中应该是期望时间是O(n), 有兴趣翻一下 CLRS顺序统计量那章,上面有证明 这是快排中的划分方法。快排必须递归到logn层，而求最小k个数可能只需要划分几次就找到index了。[/quote]part具有随机性,不可能完成折半,也就只有期望时间,

这个是使用计数排序的吧？不过，用堆来做个人感觉更常见上些


Question: 现在你们都用什么编译环境啊？

devc++ ，vs2010，vs2013，vs2015,codeblock, c_free，

C-Free只是IDE，还需要编译器、连接器、调试器、库、头文件... 这些，VC6太老了，C++03都不支持（事实上C++98支持多少都很可疑），用免费的Visual Studio Community 2015是不错的选择，追求优化性能要用intel C++，如果要快速开发应用软件，用C++Builder XE5~XE8这一系列最合适。

我已经找到了vc++6.0完整版，还下了c free5,我家旁边大学软件学院用的就这个

引用 14 楼 DelphiGuy 的回复:[quote=引用 11 楼 zjq9931 的回复:] [quote=引用 10 楼 akirya 的回复:] [quote=引用 9 楼 zjq9931 的回复:] 编译环境，这个问题，我曾经也纠结了很久。 后来发现，抛开自己的目标来挑选编译环境，那就是没头的苍蝇。 不清除提问题人的目标，随意推荐编译环境那就是耍流氓啊。 不论平台，就说编译环境的人，不是狂人就是渣。。。 lz是问 “你们用什么的？哪有？还是要花钱买正版？” 没有问自己该用哪个啊。[/quote] 看楼主的内容楼主的意思明显是在问，该用哪个。（当然我也是猜的，可能猜错了。。） 否则的话也不会问出来这种问题了。。。 你的回答还是很切实际的。因为楼主还在下VC6，所以平台什么的都没什么问题。 但是我看到竟然有人回答用GCC。所以呢，心头一万只草泥马狂奔而过。。。[/quote]  这帖里就您一个答非所问、颠三倒四、忘乎所以、出言不逊...  [/quote] 好吧我补上，我用的是VS2010免费版。

引用 11 楼 zjq9931 的回复:[quote=引用 10 楼 akirya 的回复:] [quote=引用 9 楼 zjq9931 的回复:] 编译环境，这个问题，我曾经也纠结了很久。 后来发现，抛开自己的目标来挑选编译环境，那就是没头的苍蝇。 不清除提问题人的目标，随意推荐编译环境那就是耍流氓啊。 不论平台，就说编译环境的人，不是狂人就是渣。。。 lz是问 “你们用什么的？哪有？还是要花钱买正版？” 没有问自己该用哪个啊。[/quote] 看楼主的内容楼主的意思明显是在问，该用哪个。（当然我也是猜的，可能猜错了。。） 否则的话也不会问出来这种问题了。。。 你的回答还是很切实际的。因为楼主还在下VC6，所以平台什么的都没什么问题。 但是我看到竟然有人回答用GCC。所以呢，心头一万只草泥马狂奔而过。。。[/quote]  这帖里就您一个答非所问、颠三倒四、忘乎所以、出言不逊...

vs2013 MyEclipse2015

FileTool.exe 替换打开和添加到项目中 Visual C++ 的新功能 http://support.microsoft.com/kb/241396/zh-cn

主要还是看要做什么。

引用 10 楼 akirya 的回复:[quote=引用 9 楼 zjq9931 的回复:] 编译环境，这个问题，我曾经也纠结了很久。 后来发现，抛开自己的目标来挑选编译环境，那就是没头的苍蝇。 不清除提问题人的目标，随意推荐编译环境那就是耍流氓啊。 不论平台，就说编译环境的人，不是狂人就是渣。。。 lz是问 “你们用什么的？哪有？还是要花钱买正版？” 没有问自己该用哪个啊。[/quote] 看楼主的内容楼主的意思明显是在问，该用哪个。（当然我也是猜的，可能猜错了。。） 否则的话也不会问出来这种问题了。。。 你的回答还是很切实际的。因为楼主还在下VC6，所以平台什么的都没什么问题。 但是我看到竟然有人回答用GCC。所以呢，心头一万只草泥马狂奔而过。。。

引用 9 楼 zjq9931 的回复:编译环境，这个问题，我曾经也纠结了很久。 后来发现，抛开自己的目标来挑选编译环境，那就是没头的苍蝇。 不清除提问题人的目标，随意推荐编译环境那就是耍流氓啊。 不论平台，就说编译环境的人，不是狂人就是渣。。。 lz是问 “你们用什么的？哪有？还是要花钱买正版？” 没有问自己该用哪个啊。

大神告诉你 vi + gcc

Visual Studio Community 2015 免费

VC++ 2013、VC++ 2010、gcc 4.8.1、intel C++ XE 2013、CB XE5...

Microsoft Visual C++ 2010 Express C++Builder 6


Question: 为什么memcpy会让程序崩溃呢

原因楼上已经说了，常量区不可写  楼主可以这样写：  	char a[]="abcde";   	char *b="12345";   	memcpy(a,b,2);       printf("*a=%c,*b=%c",*a,*b);  上面的a中字符串是在栈上分配的，所以可以

#pragma comment(linker,"/SECTION:.rdata,RW") //加这句可以让常量区可写，后果自负！

楼主去看看程序内存组成，有些是const不可写，只能读

楼上正解，但是这其实与编译器有关，你的程序也就能在Turbo C下正常运行。

char *a="abcde"这种写法数据在常量静态区写入非法


Question: sqlite C语言开发  如何在一个字段中存储数组

跟sqlite怎么存没什么关系, 把 sqlstr  打出来看看

https://sqlite.org/cintro.html 看过没？

data_data[2] 存储的都是可见字符吗？还是可能有非可见字符？

为什么不用blob呢？ 此外，sqlite是弱类型，哪怕你数据库中定义为int类型，依然可以正确的插入、读取text类型。

引用 1 楼 jiqiang01234 的回复:用  data varchar(5) 没有问题。但你的数据定义是char data_data[2]，只有两个字符。如果要用%s来格式化字符串，那必须保证字符串的最后一个字符是'\0'  但如果不想加 “\0”   只是单纯地 存储 data_data[2]     那样的话，可以用 varchar(5)  吗


Question: c89和c99都函数的使用，是不是有区别？

prinf即可

“管道”这个概念虽然是通用的，但具体实现和操作系统有关，所以一般需要调用操作系统的API来创建、使用和管理管道。 这属于“进程间通信”的一种方式。  quote=引用 5 楼 caddor9100 的回复:] 引用 4 楼 lgbxyz 的回复:对于你的程序来说 echo的字符串就是标准输入  #include <stdio.h>  int main(void) {     char buf[512] ={0};      gets(buf);      printf("%s\n", buf);      return 0; }   验证过代码，是可以的。  那么一个程序向管道别给别人，改如何呢、  比如，我想实现一个类似echo 的功能的程序，我该如何做？  ./myprogram "segsg" | wc -l   [/quote]

多谢。   引用 2 楼 lgbxyz 的回复:怎么无法验证了，gcc默认的是-std=gun89而已，    //test.c #include <stdio.h>  int main(void) {     int x = 1;      printf("x = %d\n", x);      int y = 2;      printf("y = %d\n", y);      return 0; }  /* result [linux]$ gcc test.c -std=c89 test.c:1: error: expected identifier or ‘(’ before ‘/’ token  */    请教一个问题，如何实现一个程序，能够接受标准输入。  比如我从网上找一条命令，  echo "hewsggds" | ./myprogram  echo 把字符串写到标准输出里，  而我的程序可以读取  "hewsggds"。  我该如何做？

怎么无法验证了，gcc默认的是-std=gun89而已，    //test.c #include <stdio.h>  int main(void) {     int x = 1;      printf("x = %d\n", x);      int y = 2;      printf("y = %d\n", y);      return 0; }  /* result [linux]$ gcc test.c -std=c89 test.c:1: error: expected identifier or ‘(’ before ‘/’ token In file included from /usr/include/stdio.h:75,                  from test.c:2: /usr/include/libio.h:332: error: expected specifier-qualifier-list before ‘size_t’ /usr/include/libio.h:364: error: expected declaration specifiers or ‘...’ before ‘size_t’ /usr/include/libio.h:373: error: expected declaration specifiers or ‘...’ before ‘size_t’ /usr/include/libio.h:495: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘_IO_sgetn’ In file included from test.c:2: /usr/include/stdio.h:336: error: expected declaration specifiers or ‘...’ before ‘size_t’ /usr/include/stdio.h:704: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘fread’ /usr/include/stdio.h:710: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘fwrite’ [linux]$ gcc test.c -std=c99 [linux]$  */

代码在哪里？


Question: 请问注册表里的ip和网卡的ip为什么不一致?

引用 5 楼 moonworld1 的回复:针对楼上提到的禁用问题 我试过 但是在ip地址 子网掩码 默认 网关里只有默认网关修改成功..  当然注册表依然显示全部修改成功重启试试

搜devcon

改了之后把网卡禁用再启用试试

网卡 down ，然后up 一下

不知道你用什么API修改的。 其实用CMD命令就可以修改成功： netsh interface ip set address 本地连接 static 192.168.1.47 255.255.255.0 192.168.1.1 netsh interface ip set dns 本地连接 static 192.168.1.1


Question: c/c++文本输入问题

用记事本打开，查找替换

引用 8 楼 kedaxiaojiang 的回复:[quote=引用 6 楼 cjqpker 的回复:] [quote=引用 5 楼 kedaxiaojiang 的回复:] [quote=引用 3 楼 cjqpker 的回复:] [quote=引用 2 楼 kedaxiaojiang 的回复:] 能不能简单写段代码呢，我没搞懂你的意思是怎么用  假设你有三个字符串 string a = "a,b,c"; string b = "cd,e,cc,"; string c = "aa,ss,d";  FILE* p = fopen("path/to/your/file", "a+"); fprintf(p, "%s\n", a.c_str()); fprintf(p, "%s\n", b.c_str()); fprintf(p, "%s\n", c.c_str());   也可以写成  fprintf(p, "%s\n%s\n%s\n", a.c_str(), b.c_str(), c.c_str()); 格式可以自己定义[/quote]  哦哦，我其实是想一次输一段字符，不是像你这样的方式，你这个相当于还是要一行一行的定义，我期待的是类似于这样的效果， fputs("a,ba,c             aa,dd,cc             yi,c m",fp) 类似于这样的一次就输进去了，因为我要输的文本实在是有点多，如果一行一行的定义往里面输的话，工作量太大了，还是非常感谢你帮我解答哈 [/quote]  那就写成如下形式      fputs("this "         "is "         "a "         "demo "         "string", p); [/quote] 我刚刚试过你的那个方法，得到的结果是this,is,a,demo,string 字符没有自动分行，而且字符与字符之间多了个逗号[/quote] 当然不会换行啊，要是换行就错了。这是C里面常用的一种写法

引用 8 楼 kedaxiaojiang 的回复:  void main() {     char* s1 = "this "         "is "         "a "         "demo "         "string\n";      char* s2 = "this "         "is "         "another "         "string\n";      FILE* p = fopen("D:/a.txt", "a+");     if (p)     {         fputs(s1, p);         fputs(s2, p);         fclose(p);     } }

引用 6 楼 cjqpker 的回复:[quote=引用 5 楼 kedaxiaojiang 的回复:] [quote=引用 3 楼 cjqpker 的回复:] [quote=引用 2 楼 kedaxiaojiang 的回复:] 能不能简单写段代码呢，我没搞懂你的意思是怎么用  假设你有三个字符串 string a = "a,b,c"; string b = "cd,e,cc,"; string c = "aa,ss,d";  FILE* p = fopen("path/to/your/file", "a+"); fprintf(p, "%s\n", a.c_str()); fprintf(p, "%s\n", b.c_str()); fprintf(p, "%s\n", c.c_str());   也可以写成  fprintf(p, "%s\n%s\n%s\n", a.c_str(), b.c_str(), c.c_str()); 格式可以自己定义[/quote]  哦哦，我其实是想一次输一段字符，不是像你这样的方式，你这个相当于还是要一行一行的定义，我期待的是类似于这样的效果， fputs("a,ba,c             aa,dd,cc             yi,c m",fp) 类似于这样的一次就输进去了，因为我要输的文本实在是有点多，如果一行一行的定义往里面输的话，工作量太大了，还是非常感谢你帮我解答哈 [/quote]  那就写成如下形式      fputs("this "         "is "         "a "         "demo "         "string", p); [/quote] 我刚刚试过你的那个方法，得到的结果是this,is,a,demo,string 字符没有自动分行，而且字符与字符之间多了个逗号

fprintf  就可以啊，可以指定格式 不知道你指的不要用fputs是因为没法指定格式？

#include <iostream> #include <fstream> #include <string>  using namespace std;  int main() {//循环，每次读入一行string，当eof时终止，读入string中输出到文件中 	string str; 	ofstream out("myflie.txt"); 	while (cin>>str) 	{ 		out << str << endl; 	} 	out.close(); 	 	return 0; } 用c++写的不知道这样行不行

引用 5 楼 kedaxiaojiang 的回复:[quote=引用 3 楼 cjqpker 的回复:] [quote=引用 2 楼 kedaxiaojiang 的回复:] 能不能简单写段代码呢，我没搞懂你的意思是怎么用  假设你有三个字符串 string a = "a,b,c"; string b = "cd,e,cc,"; string c = "aa,ss,d";  FILE* p = fopen("path/to/your/file", "a+"); fprintf(p, "%s\n", a.c_str()); fprintf(p, "%s\n", b.c_str()); fprintf(p, "%s\n", c.c_str());   也可以写成  fprintf(p, "%s\n%s\n%s\n", a.c_str(), b.c_str(), c.c_str()); 格式可以自己定义[/quote]  哦哦，我其实是想一次输一段字符，不是像你这样的方式，你这个相当于还是要一行一行的定义，我期待的是类似于这样的效果， fputs("a,ba,c             aa,dd,cc             yi,c m",fp) 类似于这样的一次就输进去了，因为我要输的文本实在是有点多，如果一行一行的定义往里面输的话，工作量太大了，还是非常感谢你帮我解答哈 [/quote]  那就写成如下形式      fputs("this "         "is "         "a "         "demo "         "string", p);

引用 3 楼 cjqpker 的回复:[quote=引用 2 楼 kedaxiaojiang 的回复:] 能不能简单写段代码呢，我没搞懂你的意思是怎么用  假设你有三个字符串 string a = "a,b,c"; string b = "cd,e,cc,"; string c = "aa,ss,d";  FILE* p = fopen("path/to/your/file", "a+"); fprintf(p, "%s\n", a.c_str()); fprintf(p, "%s\n", b.c_str()); fprintf(p, "%s\n", c.c_str());   也可以写成  fprintf(p, "%s\n%s\n%s\n", a.c_str(), b.c_str(), c.c_str()); 格式可以自己定义[/quote]  哦哦，我其实是想一次输一段字符，不是像你这样的方式，你这个相当于还是要一行一行的定义，我期待的是类似于这样的效果， fputs("a,ba,c             aa,dd,cc             yi,c m",fp) 类似于这样的一次就输进去了，因为我要输的文本实在是有点多，如果一行一行的定义往里面输的话，工作量太大了，还是非常感谢你帮我解答哈

引用 2 楼 kedaxiaojiang 的回复:能不能简单写段代码呢，我没搞懂你的意思是怎么用  假设你有三个字符串 string a = "a,b,c"; string b = "cd,e,cc,"; string c = "aa,ss,d";  FILE* p = fopen("path/to/your/file", "a+"); fprintf(p, "%s\n", a.c_str()); fprintf(p, "%s\n", b.c_str()); fprintf(p, "%s\n", c.c_str());   也可以写成  fprintf(p, "%s\n%s\n%s\n", a.c_str(), b.c_str(), c.c_str()); 格式可以自己定义

能不能简单写段代码呢，我没搞懂你的意思是怎么用


Question: 关于结构体指针问题。什么时候在指针前面加*号，什么时候不加

struct _S {  int F; } S,*pS=&S;  pS->F //等价于 (*pS).F

对于简单的提取成员情况： 如果对指针变量做解引用了（即其前面出现了*），则引用结构体成员时用点（.）运算符 如果对指针变量没有解引用，则引用结构体成员时用指针（->）运算符  如果楼主要用结构体指针的值，就是加*号的 如果是对同类型的指针变量进行相互赋值传递，则是不加*号的，相当于把指针变量内部的值（指向结构体对象的首地址）当作一个无符号整形进行对比和计算（但是指针值的计算一般是比较是否相同，或者相隔多少）；  这个讨论很有趣，大家继续～

不加*是指针，加了*是取指针所指向的值  另外(p + j) -> name也可以写成(*(p + j) ).name  ->这个符号用于指针

引用 楼主 o0Joker0o 的回复:在函数if比较的冒泡排序中，为什么strcmp函数中俩个相比较的指针(p + j) -> name和(p + j + 1) -> name前面为什么不能加*。     但是为什么下面进行冒泡排序赋值的时候就必须要加*   问： (p + j) -> name和(p + j + 1) -> name前面为什么不能加*？  答： p 是Stu * 类型的一个指针变量 p + j 也是Stu * 类型的一个指针变量 p + j  + 1也是Stu * 类型的一个指针变量 用结构体（或者是类）的指针去获取该结构体（或者是类）的成员变量的值有两种方法 1是用->运算符：  p->name， 2是用*运算符：(*p).name 所以你可以写成(p + j) -> name，(p + j + 1) -> name 也可以写成 (*(p + j)).name，(*(p + j + 1)).name  问： 但是为什么下面进行冒泡排序赋值的时候就必须要加*？ 答：*运算符的运算结果是将指针类型运算成结构（或者是类类型） p 是Stu * 类型的一个指针变量 *p则是Stu 类型的一个变量 所以可以Stu temp = *(p + j); 当然，你也可以直接用->运算符，对Stu 的每个成员挨个赋值：如下 Stu temp; temp.name = (p + j)->name; temp.XXX= (p + j)->XXX;

类型要一致 , strcmp第一个参数是const char *, 而name的类型刚好是, 如果*name, 类型就是const char, 就不匹配了,同样, p的类型是Stu*, 你的temp类型是Stu, 不能匹配,

我是小弱，我也不太懂，我来抛砖，说错了大神来拍砖。。 (p + j) -> name：p本身是指针了，你要加*，写成*(p + j). name应该也可以啊。 下边加*，是对指针所指的地址进行操作，这样才能把实参对应的数据修改，否则只是交换形参指针，实参内容没有任何变化，可以参考交换函数void swap(int a, int b) 和 void swap(int* a, int* b)

(p + j) -> name 可以匹配指针 (p+j) 指向结构数组第j个元素的指针 name  结构的成员。是个数组 (p + j) ->   <==>(* (p + j)).name 这是个数组 其中 name 是结构的数组成员的名字 . 表示取结构的成员 .name 也就是数组 name 这部分 数组（名） 可以匹配指针参数


Question: trim 字符串

while ((*pTmp == ' ') && (pTmp >= pStr)) ——这样？

多了没细想，反正你的代码当输入参数是空串时会出问题；当输入参数为只包含一个空格的字符串时，似乎也不能正确处理。 其他情况应该还有，先把这两个解决了，或许就对了。

多了没细想，反正你的代码当输入参数是空串时会出问题；当输入参数为只包含一个空格字符的字符串时，也不能正确处理。 其他情况应该还有，先把这两个解决了，或许就对了。


Question: 正在c进阶，想提高下自己的代码能力，跪求优秀的代码

C语言怪异代码大赛历届作品大全 1984～1996，1998，2000，2001，2004～2006，2011，2012http://download.csdn.net/detail/zhao4zhong1/5538847

引用 9 楼 均陵鼠侠的回复:主流的观点是正确的编码。但是，如果没有尝试非法和怪异的编码，人生是不完整的，而且也无法体验到正确编码的优势所在。这就像人生，如果从小就是乖孩子，通常是没脸出息的。 赞

ftp minidlna filezilla tinyhttpd

nginx apache portable runtime

mid = a > b ? (a < c ? a : (b > c ? b : c)) : (b < c ? b : (a > c ? a : c)); printf("中间数%d\n", mid);

CSDN下载频道挺多有原代码的资源的，楼主可以去看下，另外还要多看书，最好自己有想法，自己来写程序，而不只是看别人写的

《深入理解C指针》这本书不错，当当或者亚马逊都有。  C语言程序开发范例宝典 C语言经典编程282例 《C语言点滴》 《C语言课程设计案例精编》

引用 5 楼 u012830734 的回复:1楼的连接打不开啊 使用chrome浏览器再试试。

1楼的连接打不开啊

glib，一个很棒的C库。http://ftp.gnome.org/pub/GNOME/sources/glib/2.40/glib-2.40.0.tar.xz

nginx不错

下载chromium，看看它的base库，我虽然不佩服他代码的设计（比如类层次太多），但是，对于他的设计思路却佩服的五体投地。


Question: C语言应该怎么学下去？

引用 15 楼 sharonaaz 的回复:[quote=引用 14 楼 T1014216852 的回复:] [quote=引用 11 楼 T1014216852 的回复:] [quote=引用 9 楼 sharonaaz 的回复:] 纯粹的看书,看过即忘 再说,只学C语言,如果不是在嵌入式方面,可能什么也做不了 一本C语言,你花半年时间在上面,是不是太浪费了? 谭浩强的 C程序设计,快速过一遍,然后 C++primer  ,然后VC ,MFC,不要把大把的时间浪费在语法上,以后用到的时候,再翻回来看看 !  你觉得你说的挺有道理 那么您觉得一个刚接触编程的小白来说 学C是不是一个好的选择？一本C primer plus 应该花多少时间？[/quote]我就刚接触C的 现在也是学着C primer plus 您觉得我是像你说的那样 快速过一遍然后直接VC 再****** 还是认认真真把书学一次 花个一年半载？我是九月份准备上大一的 软件技术专业[/quote]  还没上大一, 那你的时间太充足了,我是大学毕业工作了后才学的软件编程,大学时学的是自动化 你跟我们不同,你有充足的时间 即然你有这么多时间, 那你可以花个一年半载把C 和C++夯实了,这样以后都不怕了 VC留到大三再开始也不晚.. 是来武汉上大学吗?[/quote]不好意思 这么久才回复你 最近在学C 学到了分支跳转了。我是广东考生 ，准备去珠海读书。也是打算花几个月把这本书看透训练透了。我是读专科的，只有两年时间 ，所以还是得拼命学啊

先把指针学了，不会指针没法玩。

引用 9 楼 sharonaaz 的回复:纯粹的看书,看过即忘 再说,只学C语言,如果不是在嵌入式方面,可能什么也做不了 一本C语言,你花半年时间在上面,是不是太浪费了? 谭浩强的 C程序设计,快速过一遍,然后 C++primer  ,然后VC ,MFC,不要把大把的时间浪费在语法上,以后用到的时候,再翻回来看看 ! 你好，这是我写的一个控制台小程序，还没学习指针，请问我现在这种程度可以直接去学习C++和C#、MFC等其他语言了吗？我算是入门了吗？  代码在这里 http://bbs.csdn.net/topics/391053058

谭浩强的书很经典，多研究例子，c是编程的基础，

代码不是看出来的，是敲出来的多动手敲一些自己不懂得例子，对比下为什么要这样。。。

自学很难，没有方向，没有指导。 最好有老师带，或参加专门的培训，这样子会很快

引用 14 楼 T1014216852 的回复:[quote=引用 11 楼 T1014216852 的回复:] [quote=引用 9 楼 sharonaaz 的回复:] 纯粹的看书,看过即忘 再说,只学C语言,如果不是在嵌入式方面,可能什么也做不了 一本C语言,你花半年时间在上面,是不是太浪费了? 谭浩强的 C程序设计,快速过一遍,然后 C++primer  ,然后VC ,MFC,不要把大把的时间浪费在语法上,以后用到的时候,再翻回来看看 !  你觉得你说的挺有道理 那么您觉得一个刚接触编程的小白来说 学C是不是一个好的选择？一本C primer plus 应该花多少时间？[/quote]我就刚接触C的 现在也是学着C primer plus 您觉得我是像你说的那样 快速过一遍然后直接VC 再****** 还是认认真真把书学一次 花个一年半载？我是九月份准备上大一的 软件技术专业[/quote]  还没上大一, 那你的时间太充足了,我是大学毕业工作了后才学的软件编程,大学时学的是自动化 你跟我们不同,你有充足的时间 即然你有这么多时间, 那你可以花个一年半载把C 和C++夯实了,这样以后都不怕了 VC留到大三再开始也不晚.. 是来武汉上大学吗?

引用 8 楼 bear234 的回复:真心话，我建议你放弃......  学编程需要有吃苦精神和与困难搏斗的精神  更重要的是，你需要整块时间，不是你坐办公室的空档看看书就能学会的，那样学的编程永远只是半吊子～～～   这位仁兄说的对，学编程需要大块的时间，是大块，不是零散时间的累加，所以你一定要想好了。

具体点讲，有本书叫《C和指针》，还有一本叫《C语言程序设计--现代方法》，这是我看过这么多C语言书以后推荐你的，至于其他的，都需要慢慢来，另外，我公司里的一个同事，也在看前一本书。

引用 9 楼 sharonaaz 的回复:纯粹的看书,看过即忘 再说,只学C语言,如果不是在嵌入式方面,可能什么也做不了 一本C语言,你花半年时间在上面,是不是太浪费了? 谭浩强的 C程序设计,快速过一遍,然后 C++primer  ,然后VC ,MFC,不要把大把的时间浪费在语法上,以后用到的时候,再翻回来看看 !  你觉得你说的挺有道理 那么您觉得一个刚接触编程的小白来说 学C是不是一个好的选择？一本C primer plus 应该花多少时间？

引用 11 楼 T1014216852 的回复:[quote=引用 9 楼 sharonaaz 的回复:] 纯粹的看书,看过即忘 再说,只学C语言,如果不是在嵌入式方面,可能什么也做不了 一本C语言,你花半年时间在上面,是不是太浪费了? 谭浩强的 C程序设计,快速过一遍,然后 C++primer  ,然后VC ,MFC,不要把大把的时间浪费在语法上,以后用到的时候,再翻回来看看 !  你觉得你说的挺有道理 那么您觉得一个刚接触编程的小白来说 学C是不是一个好的选择？一本C primer plus 应该花多少时间？[/quote]我就刚接触C的 现在也是学着C primer plus 您觉得我是像你说的那样 快速过一遍然后直接VC 再****** 还是认认真真把书学一次 花个一年半载？我是九月份准备上大一的 软件技术专业

就我觉得，兴趣是最好的老师。只要你对他有激情，有热爱，我相信你是可以学会的。但学会，跟学精是两回事的。看书，忘得也快。有空，多实践实践。学习学习算法，数据结构。这样你进步会更快的。加油

引用 11 楼 T1014216852 的回复:[quote=引用 9 楼 sharonaaz 的回复:] 纯粹的看书,看过即忘 再说,只学C语言,如果不是在嵌入式方面,可能什么也做不了 一本C语言,你花半年时间在上面,是不是太浪费了? 谭浩强的 C程序设计,快速过一遍,然后 C++primer  ,然后VC ,MFC,不要把大把的时间浪费在语法上,以后用到的时候,再翻回来看看 !  你觉得你说的挺有道理 那么您觉得一个刚接触编程的小白来说 学C是不是一个好的选择？一本C primer plus 应该花多少时间？[/quote]  无论你以后是否从事VC编程方向,或者JAVA, C#,等等,C都是基础,学会了C和C++ ,再学其它的就会很轻松

本人菜鸟，接触c语言有一年左右的时间，目前仍然处于未入门阶段。 建议先入手纸质书籍，从最经典的开始，不建议现在学习c primier，虽然很准确很详尽，但是目测楼主现在还不太适合。 至于教程，不建议以此为主，看书上的代码可能会更好一些。

引用 5 楼 a339299936 的回复:[quote=引用 3 楼 fly_dragon_fly 的回复:] 先学会单步调试吧 单步调试是什么？不完整的代码，也就是没有主函数main的代码也可以调试吗？[/quote]调试的前提肯定是编译能过了, 怎么感觉没在电脑上试过代码, 应该多试试, 熟悉一下编译器对你的抱怨

首先，有些人适合编程，有些人不适合编程，就像有些人适合做销售，有些人做销售就很吃力，一样。  其次，指针和数组，确实就是C语言的一道坎。所以如果lz对指针和数组有什么不理解的地方，可以把你自己的问题提出来，论坛上还是有不少愿意替别人解答问题的人存在的。

没有目标就没有动力


Question: 判断浮点数相等的问题

楼主的这种情况在赋值后是区分不了不相等  楼上给的方法都是怎么判断两个浮点数相等  楼主赋值时浮点float本身就没那么多精度，也就是说你数据在赋值时已经不精确了， 所以你的a,b变量在赋值后内存存的都一样  可以使用double，再不行long double，通常是够用了

float.h 中有#define FLT_EPSILON                1.19209290E-07F   #include <float.h>;  double a, b;   if( abs(a-b) < FLT_EPSILON) {}  比较误差小于允许的范围就可以了吧

if( abs(a-b)>0.000000000000000001)

电脑存储的精度问题，只能用误差来比较

仅供参考：#include <stdio.h> #include <stdlib.h> #include <string.h> float f; double d; void showf() {     char bs[65];     char b[65];     unsigned char *p;     char e[12];     char *t;     int ex;      printf("\nf=%.6f\n",f);     p=(unsigned char *)&f;     printf("hex=%02X %02X %02X %02X\n",p[3],p[2],p[1],p[0]);     ltoa(*(long *)&f,b,2);     sprintf(bs,"%032s",b);     printf("bin=%s\n",bs);     printf("bin=%.1s %.8s   %s\n",bs,bs+1,bs+9);     strncpy(e,bs+1,8);e[8]=0;     ex=strtol(e,&t,2);     printf("    %c %-4d-127 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);     ex-=127;     printf("    %c %-8d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9); } void showd() {     char bs[65];     char b[65];     unsigned char *p;     char e[12];     char *t;     int ex;      printf("\nd=%.15lf\n",d);     p=(unsigned char *)&d;     printf("hex=%02X %02X %02X %02X %02X %02X %02X %02X\n",p[7],p[6],p[5],p[4],p[3],p[2],p[1],p[0]);     _i64toa(*(__int64 *)&d,b,2);     sprintf(bs,"%064s",b);     printf("bin=%s\n",bs);     printf("bin=%.1s %.11s   %s\n",bs,bs+1,bs+12);     strncpy(e,bs+1,11);e[11]=0;     ex=strtol(e,&t,2);     printf("    %c %-6d-1023 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);     ex-=1023;     printf("    %c %-11d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12); } int main() {      for (f=0.0f;f<=2.2f;f+=0.2f) showf();     printf("------------\n");     f=2.0f;showf();     printf("-----------------------------------\n");     for (d=0.0 ;d<=2.2 ;d+=0.2 ) showd();     printf("------------\n");     d=2.0 ;showd();      return 0; } // //f=0.000000 //hex=00 00 00 00 //bin=00000000000000000000000000000000 //bin=0 00000000   00000000000000000000000 //  + 0   -127 1.00000000000000000000000 //  + -127     1.00000000000000000000000 // //f=0.200000 //hex=3E 4C CC CD //bin=00111110010011001100110011001101 //bin=0 01111100   10011001100110011001101 //  + 124 -127 1.10011001100110011001101 //  + -3       1.10011001100110011001101 // //f=0.400000 //hex=3E CC CC CD //bin=00111110110011001100110011001101 //bin=0 01111101   10011001100110011001101 //  + 125 -127 1.10011001100110011001101 //  + -2       1.10011001100110011001101 // //f=0.600000 //hex=3F 19 99 9A //bin=00111111000110011001100110011010 //bin=0 01111110   00110011001100110011010 //  + 126 -127 1.00110011001100110011010 //  + -1       1.00110011001100110011010 // //f=0.800000 //hex=3F 4C CC CD //bin=00111111010011001100110011001101 //bin=0 01111110   10011001100110011001101 //  + 126 -127 1.10011001100110011001101 //  + -1       1.10011001100110011001101 // //f=1.000000 //hex=3F 80 00 00 //bin=00111111100000000000000000000000 //bin=0 01111111   00000000000000000000000 //  + 127 -127 1.00000000000000000000000 //  + 0        1.00000000000000000000000 // //f=1.200000 //hex=3F 99 99 9A //bin=00111111100110011001100110011010 //bin=0 01111111   00110011001100110011010 //  + 127 -127 1.00110011001100110011010 //  + 0        1.00110011001100110011010 // //f=1.400000 //hex=3F B3 33 34 //bin=00111111101100110011001100110100 //bin=0 01111111   01100110011001100110100 //  + 127 -127 1.01100110011001100110100 //  + 0        1.01100110011001100110100 // //f=1.600000 //hex=3F CC CC CE //bin=00111111110011001100110011001110 //bin=0 01111111   10011001100110011001110 //  + 127 -127 1.10011001100110011001110 //  + 0        1.10011001100110011001110 // //f=1.800000 //hex=3F E6 66 68 //bin=00111111111001100110011001101000 //bin=0 01111111   11001100110011001101000 //  + 127 -127 1.11001100110011001101000 //  + 0        1.11001100110011001101000 // //f=2.000000 //hex=40 00 00 01 //bin=01000000000000000000000000000001 //bin=0 10000000   00000000000000000000001 //  + 128 -127 1.00000000000000000000001 //  + 1        1.00000000000000000000001 //------------ // //f=2.000000 //hex=40 00 00 00 //bin=01000000000000000000000000000000 //bin=0 10000000   00000000000000000000000 //  + 128 -127 1.00000000000000000000000 //  + 1        1.00000000000000000000000 //----------------------------------- // //d=0.000000000000000 //hex=00 00 00 00 00 00 00 00 //bin=0000000000000000000000000000000000000000000000000000000000000000 //bin=0 00000000000   0000000000000000000000000000000000000000000000000000 //  + 0     -1023 1.0000000000000000000000000000000000000000000000000000 //  + -1023       1.0000000000000000000000000000000000000000000000000000 // //d=0.200000000000000 //hex=3F C9 99 99 99 99 99 9A //bin=0011111111001001100110011001100110011001100110011001100110011010 //bin=0 01111111100   1001100110011001100110011001100110011001100110011010 //  + 1020  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -3          1.1001100110011001100110011001100110011001100110011010 // //d=0.400000000000000 //hex=3F D9 99 99 99 99 99 9A //bin=0011111111011001100110011001100110011001100110011001100110011010 //bin=0 01111111101   1001100110011001100110011001100110011001100110011010 //  + 1021  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -2          1.1001100110011001100110011001100110011001100110011010 // //d=0.600000000000000 //hex=3F E3 33 33 33 33 33 34 //bin=0011111111100011001100110011001100110011001100110011001100110100 //bin=0 01111111110   0011001100110011001100110011001100110011001100110100 //  + 1022  -1023 1.0011001100110011001100110011001100110011001100110100 //  + -1          1.0011001100110011001100110011001100110011001100110100 // //d=0.800000000000000 //hex=3F E9 99 99 99 99 99 9A //bin=0011111111101001100110011001100110011001100110011001100110011010 //bin=0 01111111110   1001100110011001100110011001100110011001100110011010 //  + 1022  -1023 1.1001100110011001100110011001100110011001100110011010 //  + -1          1.1001100110011001100110011001100110011001100110011010 // //d=1.000000000000000 //hex=3F F0 00 00 00 00 00 00 //bin=0011111111110000000000000000000000000000000000000000000000000000 //bin=0 01111111111   0000000000000000000000000000000000000000000000000000 //  + 1023  -1023 1.0000000000000000000000000000000000000000000000000000 //  + 0           1.0000000000000000000000000000000000000000000000000000 // //d=1.200000000000000 //hex=3F F3 33 33 33 33 33 33 //bin=0011111111110011001100110011001100110011001100110011001100110011 //bin=0 01111111111   0011001100110011001100110011001100110011001100110011 //  + 1023  -1023 1.0011001100110011001100110011001100110011001100110011 //  + 0           1.0011001100110011001100110011001100110011001100110011 // //d=1.400000000000000 //hex=3F F6 66 66 66 66 66 66 //bin=0011111111110110011001100110011001100110011001100110011001100110 //bin=0 01111111111   0110011001100110011001100110011001100110011001100110 //  + 1023  -1023 1.0110011001100110011001100110011001100110011001100110 //  + 0           1.0110011001100110011001100110011001100110011001100110 // //d=1.600000000000000 //hex=3F F9 99 99 99 99 99 99 //bin=0011111111111001100110011001100110011001100110011001100110011001 //bin=0 01111111111   1001100110011001100110011001100110011001100110011001 //  + 1023  -1023 1.1001100110011001100110011001100110011001100110011001 //  + 0           1.1001100110011001100110011001100110011001100110011001 // //d=1.800000000000000 //hex=3F FC CC CC CC CC CC CC //bin=0011111111111100110011001100110011001100110011001100110011001100 //bin=0 01111111111   1100110011001100110011001100110011001100110011001100 //  + 1023  -1023 1.1100110011001100110011001100110011001100110011001100 //  + 0           1.1100110011001100110011001100110011001100110011001100 // //d=2.000000000000000 //hex=3F FF FF FF FF FF FF FF //bin=0011111111111111111111111111111111111111111111111111111111111111 //bin=0 01111111111   1111111111111111111111111111111111111111111111111111 //  + 1023  -1023 1.1111111111111111111111111111111111111111111111111111 //  + 0           1.1111111111111111111111111111111111111111111111111111 // //d=2.200000000000000 //hex=40 01 99 99 99 99 99 99 //bin=0100000000000001100110011001100110011001100110011001100110011001 //bin=0 10000000000   0001100110011001100110011001100110011001100110011001 //  + 1024  -1023 1.0001100110011001100110011001100110011001100110011001 //  + 1           1.0001100110011001100110011001100110011001100110011001 //------------ // //d=2.000000000000000 //hex=40 00 00 00 00 00 00 00 //bin=0100000000000000000000000000000000000000000000000000000000000000 //bin=0 10000000000   0000000000000000000000000000000000000000000000000000 //  + 1024  -1023 1.0000000000000000000000000000000000000000000000000000 //  + 1           1.0000000000000000000000000000000000000000000000000000 //

1 和0.9 之类的是否相等，不仅仅看他们是否小于 e，而且还有看你的实际环境。 你处理数据的精度和误差。

1.0是可以准确表示, 所以直接用int就好了 *(int *)&a==*(int *)&b或者 *(int *)&a==0x3F800000


Question: 求推荐一个好用的C语言书籍

《C程序设计语言》徐宝文翻译的那个不错

谭浩强老师的<<C程序设计>>

引用 1 楼 单片机工程师的回复:《C程序设计语言》徐宝文翻译的那个不错 这个可不基础。。。作为入门的话肯定有很多地方不懂。


Question: 第一天学习 C 找不哪里错了，求帮忙。

引用 1 楼 a1193561652 的回复:printf ("x=%d\n",x);写这样试试。 是那么回事，谢谢啊！

是那么回事，谢谢啊！

printf ("x=%d\n",x);写这样试试。


Question: c89是不是强制规定，变量必须放在可以执行语句之前？

2个问题  顶起来

变量必须放在可以执行语句之前？这个得看标准了，不过，推荐你还是放在之前吧。 因为有些网上做题目的题库（比如，华为的上机系统，我就遇到过这个坑，程序明明要本地能跑，但是上传到华为上机系统就是报错），它就有可能会报错。

报的都是warning，应该没问题吧。

是C89标准问题，必须放在执行语句前。

是的！！！！！！！1

请参考gcc源代码相关片断。


Question: dos程序破解

在DosBox中运行。


Question: 大家好，编写了一个简单的程序涉及到浮点乘法，怎么一直错啊！

把distance(pointArray[i], pointArray[++i]);改为distance(pointArray[i++], pointArray[i]);就好。 在同一语句中，i++和++i比i优先级高，当同一语句同时出现多个i++或++i，则遵循右结合性。 另外就是i++和++i的区别，这个应该都知道的。

函数压值从右到左, 但i的求值顺序未定, 同一表达式中尽量不要用这种, %lf仅在scanf中有用, 在printf中并未定义

引用 2 楼 Evankaka 的回复:for (i = 0; i < NUMBER; ++i)     {         distance(pointArray[i], pointArray[++i]);     } 这里会数组溢出了，NUMBER=2，i=1时，pointArray[++i]会了取到pointArray[2] 谢谢！

引用 4 楼 xiaohuh421 的回复:for (i = 0; i < NUMBER; ++i)     {         distance(pointArray[i], pointArray[++i]);     }  这里的++i不知道你的目的是什么. 但最好不要写这样的自己都理解不了的方式. 修改成如下方式.  for (i = 0; i < NUMBER; ++i)     {         distance(pointArray[i], pointArray[i+1]); //++i  , 我理解成你想是要先+1, 再使用.          ++i; //这里才让i再加1.     } 我想法正确，实现错误，忘了函数的参数计算顺序了，谢谢！

引用 3 楼 u013250461 的回复:for (i = 0; i < NUMBER; ++i)     {         distance(pointArray[i], pointArray[++i]);     } 这里的函数调用错了,虽然我还没看明白为啥错了, 初步估计是++i的问题吧,  你把它改成    distance(pointArray[0], pointArray[1]); 就对了,具体原因还没搞明白,如果漏主搞明白,希望给我回一下,谢了 看了一下下大家的回复才想到，是函数压栈顺序是从右到左，这样一来先计算++i，因此两个相等，而且还会出现边界溢出！

压栈顺序，单步看反汇编吧

请看置顶贴，函数参数的求值顺序是不确定的


Question: 两个十六进制交叉合并成一个十六进制数

引用 9 楼 SXJIAKE 的回复:夹杂了中文括号左半边，一个中文逗号……  牛B，喜欢你这种爱实践的，加油！

引用 12 楼 zhao4zhong1 的回复:连例子都实现不了，何谈算法呢？ TDD  VC里不需要<inttypes.h> 还要把uint64_t  改成 _int64 输出时候要弄成printf(" %I64x \n",num);  #include "stdafx.h" #include <stdio.h>   _int64  MLGB(long x1,long x2) {     long n1=x1;     long n2=x2;       char ch[8];     char *c1=(char *)&n1;     char *c2=(char *)&n2;       ch[0]=*(c2+0);     ch[1]=*(c1+0);     ch[2]=*(c2+1);     ch[3]=*(c1+1);     ch[4]=*(c2+2);     ch[5]=*(c1+2);     ch[6]=*(c2+3);     ch[7]=*(c1+3);       return  *(_int64 *)ch;   }   int main(int argc, char *argv[]) {     _int64  num;     num=MLGB(0x12345678,0xabcdef90);     printf("%I64x\n", num);       return 0; }

引用 11 楼 gz_qmc 的回复:[quote=引用 10 楼 linjiagao052 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 楼上没有一个能达到楼主要求的。 因为十六进制中没有gh [/quote]  都这么聪明，怎么没看到”例如“两个字呢？难道智商高的人视力都不太好？[/quote] 连例子都实现不了，何谈算法呢？ TDD

引用 7 楼 zhao4zhong1 的回复:楼上没有一个能达到楼主要求的。 因为十六进制中没有gh这个好

楼上没有一个能达到楼主要求的。 因为十六进制中没有gh

引用 10 楼 linjiagao052 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 楼上没有一个能达到楼主要求的。 因为十六进制中没有gh [/quote]  都这么聪明，怎么没看到”例如“两个字呢？难道智商高的人视力都不太好？

引用 2 楼 gz_qmc 的回复:#include <stdio.h> #include <inttypes.h>  uint64_t  MLGB(long x1,long x2) {     long n1=x1; 	long n2=x2;  	char ch[8]; 	char *c1=(char *)&n1; 	char *c2=(char *)&n2;  	ch[0]=*(c2+0); 	ch[1]=*(c1+0); 	ch[2]=*(c2+1); 	ch[3]=*(c1+1); 	ch[4]=*(c2+2); 	ch[5]=*(c1+2); 	ch[6]=*(c2+3); 	ch[7]=*(c1+3);  	return  *(uint64_t *)ch;  }  int main(int argc, char *argv[]) {     uint64_t  num;     num=MLGB（0x12345678，0xabcdef90);     printf("%" PRIx64 "\n", num);      return 0; }夹杂了中文括号左半边，一个中文逗号……

using ull =unsigned long long;     unsigned int a[]={ 0x12345678, 0xabcdefaa },msk=0xff<<24;     ull c=0;     #define lsh(v,m,b) ((ull)(v&m)<<b)     for(int i=0;i<4;i++,msk>>=8){         c |=lsh(a[0],msk,32-i*8)|lsh(a[1],msk,24-i*8);     }

测试通过，谢谢。

引用 5 楼 user-8 的回复:函数名起的很霸气  嗯，总算有个识货的

移位，与，或  #include <stdio.h> #include <inttypes.h>  int main(int argc, char *argv[]) {     int i;     uint32_t n1, n2;     uint64_t n3;      n1 = 0x12345678;     n2 = 0xabcdef90;     n3 = 0;     for (i = 0; i < 4; i++) {         n3 |= (((uint64_t)n1 >> (i * 8)) & 0xFF) << ((2 * i + 1) * 8);         n3 |= (((uint64_t)n2 >> (i * 8)) & 0xFF) << ((2 * i + 0) * 8);     }      printf("%" PRIx64 "\n", n3);      return 0; } /* output: 12ab34cd56ef7890 */

引用 2 楼 gz_qmc 的回复:#include <stdio.h> #include <inttypes.h>  uint64_t  MLGB(long x1,long x2) {     long n1=x1; 	long n2=x2;  	char ch[8]; 	char *c1=(char *)&n1; 	char *c2=(char *)&n2;  	ch[0]=*(c2+0); 	ch[1]=*(c1+0); 	ch[2]=*(c2+1); 	ch[3]=*(c1+1); 	ch[4]=*(c2+2); 	ch[5]=*(c1+2); 	ch[6]=*(c2+3); 	ch[7]=*(c1+3);  	return  *(uint64_t *)ch;  }  int   main(int argc, char *argv[]) {       uint64_t  num;       num=MLGB（0x12345678，0xabcdef90);       printf("%" PRIx64 "\n", num);       return 0; } 函数名起的很霸气


Question: 这是什么回事，求大神解释！！！

#include<stdio.h> int main(void) {   int i,count1=0,count2=0;   int sum1=0,sum2=0;      printf("请输入整数：\n");   while(scanf("%d",&i) == 1)   {       if((i%2) == 0) 	  { 	     count1++; 		 sum1 += i; 	  } 	  else 	  { 	     count2++; 		 sum2 += i; 	  }   }      printf("您输入的偶数总个数为：%d，偶数的平均值为%f",count1,1.0*sum1 / count1);   printf("您输入的奇数总个数为：%d，奇数的平均值为%f",count1,1.0*sum2 / count2);   return 0; }

C式可变参数，编译时，无法直接类型匹配，这样 整型到浮点的提升（转换）就不会有 C式样可变参数，内部类型的类型提升（转换），是按照固有方式处理，而不是按照两种类型的转换规则处理

sum1 / count1 结果不是浮点数 浮点数和整数， 在 可变参数的函数中，获取和表示方法不一致 估计产生了浮点处理器错误（异常）

count1,count2,sum1,sum2;没有初始化，系统会为其分配一个随机数，这个数不可预料，你可以插断点看看

引用了不可用内存


Question: 求两百万以下质数和出问题

引用 4 楼 kamenriderdrive 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] Finding prime numbers - Kenneth Haugland  Different schemas for finding prime numbers explained with code http://www.codeproject.com/Articles/429694/Finding-prime-numbers 这么高大上的东西！！！[/quote]

明显是整数溢出了，用long long试试

引用 1 楼 zhao4zhong1 的回复:Finding prime numbers - Kenneth Haugland  Different schemas for finding prime numbers explained with code http://www.codeproject.com/Articles/429694/Finding-prime-numbers 这么高大上的东西！！！

引用 2 楼 kuangbao9 的回复:这是你程式运行的结果：1179908154。不对吗？ 我也觉得没错，但是ProjectEuler上说不对

这是你程式运行的结果：1179908154。不对吗？

引用 3 楼 kamenriderdrive 的回复:[quote=引用 2 楼 kuangbao9 的回复:] 这是你程式运行的结果：1179908154。不对吗？ 我也觉得没错，但是ProjectEuler上说不对[/quote] 是整数溢出了。。。

引用 6 楼 kuangbao9 的回复:142913828922这个结果对不对？ 对的对的

素数的个数 = π(x)≈x/Lnx 很可能溢出了

j j 过大


Question: 关于while 循环的问题？

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。

#include <stdio.h> int main() { 	long num = 0L, sum = 0L; 	while (true) { 		if (!scanf("%ld", &num)) { 			setbuf(stdin, NULL); 			printf("输入错误，请重新输入\n"); 			continue; 		} 		printf("sum = %ld\n", sum+=num); 	} 	return 0; }  这一切都是命运石之门的选择

引用 3 楼 dag617712 的回复:楼上的应该是高手，很多程式没见过 这里是C语言，他用的是C++中的STL来实现。  楼主，你是不是想说，因为用了 scanf("%ld",&num) ，然后输入非数字没反应，希望能输入非数字能给个提示？ 我觉得吧，命令行程序不是专门用于交互的，所以没必要让它多智能应对。若你的需求如我说的，就是给个提示，还是有办法的，就是用getc获取字符，如果它是数字，就ungetc回去，否则就给提示。我不是很明白，你说的不用if只用while是什么意思。

楼上的应该是高手，很多程式没见过

可以考虑这么做。输入的数据格式为:1 2 3 4 4 6中间4 空格，输完后回车就可以了。  #include<iostream> #include<vector> using namespace std; int main(){     vector<int> ivec;     int i;     char ch;    cout<<" qingshuru"<<endl;     while(cin>>i)    {         ivec.push_back(i);         ch = getchar();         if(ch=='\n')//输入回车键时接收数据结束             break;    }     for(int j=0;j<ivec.size();j++)       cout<<ivec[j];}

while(term = scanf("%ld",&num);)  {  sum=sum+num;  printf("sum=%ld\n",sum); getchar();  }


Question: 深度优先搜索问题

引用 2 楼 dcy652701 的回复:[quote=引用 1 楼 user-1 的回复:] 要输出789,象你屏蔽起点那样,把大于9的都去掉 要输出7 11 8 9, 只能改你的邻边表了  这个是邻边表，7->8->9成功了，该怎么改一下邻边表呢，才能显示7->11->8->9[/quote]7的邻边改成 7-6-11-8

引用 1 楼 user-1 的回复:要输出789,象你屏蔽起点那样,把大于9的都去掉 要输出7 11 8 9, 只能改你的邻边表了  这个是邻边表，7->8->9成功了，该怎么改一下邻边表呢，才能显示7->11->8->9


Question: 请教printf除法遇到的问题

FUCK! 问题找到。  typedef struct {    int16   degC;    int16  mV; } adc_degC_to_mV_map_type;

引用 7 楼 zilaishuichina 的回复:那我觉得  你可以试一下    printf("d:%d\r\n", d = a * b) ; printf("res:%d\r\n", d / c) ;  测试过了： d:-460 res: 0

引用 5 楼 zilaishuichina 的回复:[quote=引用 4 楼 dsoyy 的回复:] [quote=引用 3 楼 zilaishuichina 的回复:] 编译器 先算了 (-92)/(-94)   ， 再算的 5*0  ，结果等于0   printf("res:%d\r\n",( ((a)*(b))/(c) )) ;  结果还是0，因此你的推断不正确[/quote]  vs下面测试没有问题，结果为4  建议你在printf("res:%d\r\n",( a*b/c )) ;这一行下数据断点，看看是不是a,b,c中的某一个值 ， 或某几个值改变了  建议发出完整代码，因为有可能是多线程的原因导致的变量值发生变化，或者是printf("res:%d\r\n",( a*b/c )) ;这一行之前有内存写越界导致的变量值发生变化。[/quote]  我怀疑是WInTC这个编译环境，我没办法用断点，所以是打印出来的。  下面贴完整代码： #define TRUE 1 #define FALSE 0  typedef unsigned char  uint8; typedef unsigned char boolean; typedef unsigned long int uint32; typedef signed   short int16; typedef unsigned short uint16; typedef signed long int int32;  typedef struct {    int16   degC;    uint16  mV; } adc_degC_to_mV_map_type;  /*该参数表需要根据使用NTC调整*/ static const adc_degC_to_mV_map_type adc_xo_therm_map[] = {    { -45, 2160 },       { -40, 2148 },    { -35, 2132 },     { -30, 2112 },    { -25, 2088 },     { -20, 2058 },    { -15, 2023 },    { -10, 1981 },    { -5, 1932 },    {  0, 1876 },    {  5,  1813 },    {  10, 1743 },    {  15, 1666 },    {  20, 1584 },    {  25, 1497 },    {  30, 1406  },    {  35, 1312  },    {  40, 1218  },    {  45, 1125  },    {  50, 1033 },    {  55,  944 },    {  60,  860 },    {  65,  781 },    {  70,  708 },    {  75,  639 },    {  80,  577 },    {  85,  519 },    {  90,  467 } }; /*计算结果，返回值为整数*/    uint32 search_index=0;  static int32 adc_calc_degC_from_mV(    const adc_degC_to_mV_map_type   *table,    uint32                           tableSize,    int32                            mV ) {     boolean descending = TRUE;     int32 a,b,c,d = 0;     int32 mV2_buf = 0;     int32 mV3_buf = 0;     int32 Tem_buf = 0;     int32 degC_buf = 0;     if (table==NULL)     {        return ;     }     if((table[0].mV < mV) || (table[tableSize-1].mV > mV))     {        return ;     }     /* Check if table is descending or ascending */     if (tableSize>1)     {       if (table[0].mV < table[1].mV)       {         descending=FALSE;       }     }      while (search_index < tableSize)     {       if ( (descending==TRUE) && (table[search_index].mV < mV) )       {         /* table entry is less than measured value and table is descending, stop */         break;       }       else if ( (descending==FALSE) && (table[search_index].mV > mV) )       {         /* table entry is greater than measured value and table is ascending, stop */         break;       }       else       {         search_index++;       }     }        if (search_index==0)     {       return table[0].degC;     }     else if (search_index==tableSize)     {       return table[tableSize-1].degC;     }     else     {       /* result is between search_index and search_index-1 */            printf("a:%d\r\n",a = table[search_index].degC-table[search_index-1].degC);          printf("b:%d\r\n",b = (mV-table[search_index-1].mV));          printf("c:%d\r\n",c = table[search_index].mV-table[search_index-1].mV);              printf("res:%d\r\n",( ((a)*(b))/(c) )) ;       /* interpolate linearly */         return (                ( (int32)                    (                     ( table[search_index].degC-table[search_index-1].degC)                      *( mV-table[search_index-1].mV)                    )                    / ( table[search_index].mV-table[search_index-1].mV)                )                + table[search_index-1].degC              );      } }      main() {     uint32   temp = 0;     uint32   V_mv = 1314;      temp = adc_calc_degC_from_mV(adc_xo_therm_map,sizeof(adc_xo_therm_map)/sizeof(adc_xo_therm_map[0]),V_mv);     printf("%d",temp);     getch();  }

引用 4 楼 dsoyy 的回复:[quote=引用 3 楼 zilaishuichina 的回复:] 编译器 先算了 (-92)/(-94)   ， 再算的 5*0  ，结果等于0   printf("res:%d\r\n",( ((a)*(b))/(c) )) ;  结果还是0，因此你的推断不正确[/quote]  vs下面测试没有问题，结果为4  建议你在printf("res:%d\r\n",( a*b/c )) ;这一行下数据断点，看看是不是a,b,c中的某一个值 ， 或某几个值改变了  建议发出完整代码，因为有可能是多线程的原因导致的变量值发生变化，或者是printf("res:%d\r\n",( a*b/c )) ;这一行之前有内存写越界导致的变量值发生变化。

引用 3 楼 zilaishuichina 的回复:编译器 先算了 (-92)/(-94)   ， 再算的 5*0  ，结果等于0   printf("res:%d\r\n",( ((a)*(b))/(c) )) ;  结果还是0，因此你的推断不正确

编译器 先算了 (-92)/(-94)   ， 再算的 5*0  ，结果等于0

C++ Floating-Point Constants Floating-point constants specify values that must have a fractional part. These values contain decimal points (.) and can contain exponents.  Syntax  floating-constant :  fractional-constant exponent-partopt floating-suffixopt digit-sequence exponent-part floating-suffixopt  fractional-constant :  digit-sequenceopt . digit-sequence digit-sequence .  exponent-part :  e signopt digit-sequence E signopt digit-sequence  sign : one of  + –  digit-sequence :  digit digit-sequence digit  floating-suffix :one of  f l F L  Floating-point constants have a “mantissa,” which specifies the value of the number, an “exponent,” which specifies the magnitude of the number, and an optional suffix that specifies the constant’s type. The mantissa is specified as a sequence of digits followed by a period, followed by an optional sequence of digits representing the fractional part of the number. For example:  18.46 38.  The exponent, if present, specifies the magnitude of the number as a power of 10, as shown in the following example:  18.46e0      // 18.46 18.46e1      // 184.6  If an exponent is present, the trailing decimal point is unnecessary in whole numbers such as 18E0.  Floating-point constants default to type double. By using the suffixes f or l (or F or L — the suffix is not case sensitive), the constant can be specified as float or long double, respectively.  Although long double and double have the same representation, they are not the same type. For example, you can have overloaded functions like  void func( double );  and   void func( long double );

请牢记：常量也有类型！  C++ Integer Constants Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.  Syntax  integer-constant :  decimal-constant integer-suffixopt octal-constant integer-suffixopt hexadecimal-constant integer-suffixopt 'c-char-sequence'  decimal-constant :  nonzero-digit decimal-constant digit  octal-constant :  0 octal-constant octal-digit  hexadecimal-constant :  0x hexadecimal-digit 0X hexadecimal-digit hexadecimal-constant hexadecimal-digit  nonzero-digit : one of  1 2 3 4 5 6 7 8 9  octal-digit : one of  0 1 2 3 4 5 6 7  hexadecimal-digit : one of  0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F  integer-suffix :  unsigned-suffix long-suffixopt long-suffix unsigned-suffixopt  unsigned-suffix : one of  u U  long-suffix : one of  l L  64-bit integer-suffix :  i64  To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.  To specify a decimal constant, begin the specification with a nonzero digit. For example:  int i = 157;   // Decimal constant int j = 0198;  // Not a decimal number; erroneous octal constant int k = 0365;  // Leading zero specifies octal constant, not decimal  To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example:  int i = 0377;   // Octal constant int j = 0397;   // Error: 9 is not an octal digit  To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the “x” does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:  int i = 0x3fff;   // Hexadecimal constant int j = 0X3FFF;   // Equal to i  To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:  unsigned uVal = 328u;             // Unsigned value long lVal = 0x7FFFFFL;            // Long value specified                                    //  as hex constant unsigned long ulVal = 0776745ul;  // Unsigned long value


Question: C语言中怎么实现数组的缓存

引用 8 楼 g360z247j123 的回复:[quote=引用 5 楼 kuangbao9 的回复:] 我记忆中数组一旦申请了维度是不能更改的。要想改变大小，可以考虑容器，像vector,list等。那可以删除和拼接。  嗯嗯，我这2天看了下链表，刚刚也看了一下vector，好像能实现数组的删除和拼接。         我要在主循环中实现每个子函数输出时数组前面的元素被删除，后面的被保留。同时在子函数的子循环中有从后面不停拼接（不停增加，但有最大长度）的，有不停删除前面部分元素（比如200）的，也有要实现先删除前面一个，接着从后面拼接进来一个的（比如开始数组大小为2，即s[2]，然后删除第一个元素，接着从后面拼接进另一个元素，不停循环，保证数组长度不变）。更具体的要求情况可以看下面我给bear234的回复。       请问 我该采用什么结构比较好[/quote]  可以看看vector的，再看看泛型算法。

你完全可以把一个包含 500 的元素的数组看成是 5 个包含 100 的元素的数组： arr[500]; 第一个数组 &arr[0] 第二个数组 &arr[100] 第三个数组 &arr[200] 第四个数组 &arr[300] 第五个数组 &arr[400]

引用 7 楼 g360z247j123 的回复:[quote=引用 6 楼 bear234 的回复:] [quote=引用 5 楼 kuangbao9 的回复:] 我记忆中数组一旦申请了维度是不能更改的。要想改变大小，可以考虑容器，像vector,list等。那可以删除和拼接。  realloc可以  楼主你用malloc或者calloc？ 两者区别请看：(http://zhidao.baidu.com/link?url=eyTmOA33VVDCq5Qg6O3JFEEm2Sjs0olWyNqV5Rz6Cg-Jt0y8_lpLq9qq_dlxcpPbVLxhZ6Sex1D3dZL8usDBq_)  楼主，请你先把你的算法明确，然后看下如果你用malloc或者calloc是不是太多了，如果是，我建议你直接弄个大一点的数组，不要反复malloc calloc 和 realloc，这三个东西代价比较高  当然，如果你是在做嵌入式、可用空间很有限，当我没说[/quote]  你好！关于realloc( )函数，它扩大数组空间时比较好理解，当它缩小数组空间时是怎么回事？           比如有数组int a1[500]，通过它扩大空间，p = (int *)realloc(a1,600)，假如没有发生数据搬移（即p内存储的地址和a1相同）且分配成功，相当于在原有空间后增加100个int 型元素的空间；通过它缩小空间，q= (int *)realloc(a1,100)，此时缩小损失的是前400个元素还是后400个元素？如果从a1[500]中的第401个元素a1[400]开始重新分配，即令q= (int *)realloc(&a1[400],100)，这样能保留后100个元素吗？           刚刚看了一下，整个程序是这样的。最开始输入一帧数据（数组），它的长度可变（可大可小），记为SourceLen。为说明便利同上面设定SourceLen=500，即a1[500]，然后输入给子函数Fun1，处理后依次给Fun2、Fun3...Fun10，然后主循环再次给Fun1输入新的500个数据，记为a2[500]，接着给Fun2等依次处理，再主循环......总的循环次数可能有2000甚至更多。          a1[500]经过Fun1处理后输出数组大小约为500000，记为b1[5000000]，b1经过Fun2后数组大小会变为原来的4倍，即c1[20000000]，接着传递给后面的子函数，不过数组长度不会再增加，到Fun8时开始减小，最后Fun10输出长度回归500。所有子函数输入输出数组长度的变化规律不一定相同，但都是确定的（根据算法）。至于具体长度则受SourceLen的影响。         整个程序中我准备全部采用动态内存分配，malloc( )、calloc( )等。除了子函数Fun1外都需要实现类似数组缓存的功能（即去掉前面的部分元素保留后面的元素供下次循环使用）。有些数组缓存是供下次主循环用的，有些数组缓存是供该子函数内的下次子循环用的。我该怎么定义它们，固定分配or动态分配？它们的属性：比如全局数组，局部的or静态的？        开始我是采用Matlab来仿真，不过Matlab中关于数组（一维向量）的操作真的很方便，可以随意的连续赋值，置空（删除）和拼接；但是它的仿真速度实在是太慢了（好像数组的不定长拼接很耗时间），故希望采用C语言来提高速度。。。[/quote]  如此频繁使用数组  我个人建议你可以试着用c++  c++可以重载operator new   这个技术很少会用到 算是个偏一点的技术  不过可能适合你的这个问题   反复malloc realloc 也是很占用资源的

如果你要循环那么多次，并且申请的内存那么大的话，不建议一直malloc free，你如果知道整个过程中内存需要的最大值的话，可以在最外层malloc（max - 100）出这么多空间记为A，再malloc 出100记为B，你只要把（value - 100）前的数存到A中，把后100个数存入B中,每次取数据都是先读取在B中100个数据，再从指定的长度L-100中从A取，然后循环，记住每次要读取的长度L就行了，这样相对来说数据就不需要移动太多；

引用 5 楼 kuangbao9 的回复:我记忆中数组一旦申请了维度是不能更改的。要想改变大小，可以考虑容器，像vector,list等。那可以删除和拼接。  嗯嗯，我这2天看了下链表，刚刚也看了一下vector，好像能实现数组的删除和拼接。         我要在主循环中实现每个子函数输出时数组前面的元素被删除，后面的被保留。同时在子函数的子循环中有从后面不停拼接（不停增加，但有最大长度）的，有不停删除前面部分元素（比如200）的，也有要实现先删除前面一个，接着从后面拼接进来一个的（比如开始数组大小为2，即s[2]，然后删除第一个元素，接着从后面拼接进另一个元素，不停循环，保证数组长度不变）。更具体的要求情况可以看下面我给bear234的回复。       请问 我该采用什么结构比较好

引用 6 楼 bear234 的回复:[quote=引用 5 楼 kuangbao9 的回复:] 我记忆中数组一旦申请了维度是不能更改的。要想改变大小，可以考虑容器，像vector,list等。那可以删除和拼接。  realloc可以  楼主你用malloc或者calloc？ 两者区别请看：(http://zhidao.baidu.com/link?url=eyTmOA33VVDCq5Qg6O3JFEEm2Sjs0olWyNqV5Rz6Cg-Jt0y8_lpLq9qq_dlxcpPbVLxhZ6Sex1D3dZL8usDBq_)  楼主，请你先把你的算法明确，然后看下如果你用malloc或者calloc是不是太多了，如果是，我建议你直接弄个大一点的数组，不要反复malloc calloc 和 realloc，这三个东西代价比较高  当然，如果你是在做嵌入式、可用空间很有限，当我没说[/quote]  你好！关于realloc( )函数，它扩大数组空间时比较好理解，当它缩小数组空间时是怎么回事？           比如有数组int a1[500]，通过它扩大空间，p = (int *)realloc(a1,600)，假如没有发生数据搬移（即p内存储的地址和a1相同）且分配成功，相当于在原有空间后增加100个int 型元素的空间；通过它缩小空间，q= (int *)realloc(a1,100)，此时缩小损失的是前400个元素还是后400个元素？如果从a1[500]中的第401个元素a1[400]开始重新分配，即令q= (int *)realloc(&a1[400],100)，这样能保留后100个元素吗？           刚刚看了一下，整个程序是这样的。最开始输入一帧数据（数组），它的长度可变（可大可小），记为SourceLen。为说明便利同上面设定SourceLen=500，即a1[500]，然后输入给子函数Fun1，处理后依次给Fun2、Fun3...Fun10，然后主循环再次给Fun1输入新的500个数据，记为a2[500]，接着给Fun2等依次处理，再主循环......总的循环次数可能有2000甚至更多。          a1[500]经过Fun1处理后输出数组大小约为500000，记为b1[5000000]，b1经过Fun2后数组大小会变为原来的4倍，即c1[20000000]，接着传递给后面的子函数，不过数组长度不会再增加，到Fun8时开始减小，最后Fun10输出长度回归500。所有子函数输入输出数组长度的变化规律不一定相同，但都是确定的（根据算法）。至于具体长度则受SourceLen的影响。         整个程序中我准备全部采用动态内存分配，malloc( )、calloc( )等。除了子函数Fun1外都需要实现类似数组缓存的功能（即去掉前面的部分元素保留后面的元素供下次循环使用）。有些数组缓存是供下次主循环用的，有些数组缓存是供该子函数内的下次子循环用的。我该怎么定义它们，固定分配or动态分配？它们的属性：比如全局数组，局部的or静态的？        开始我是采用Matlab来仿真，不过Matlab中关于数组（一维向量）的操作真的很方便，可以随意的连续赋值，置空（删除）和拼接；但是它的仿真速度实在是太慢了（好像数组的不定长拼接很耗时间），故希望采用C语言来提高速度。。。

引用 5 楼 kuangbao9 的回复:我记忆中数组一旦申请了维度是不能更改的。要想改变大小，可以考虑容器，像vector,list等。那可以删除和拼接。  realloc可以  楼主你用malloc或者calloc？ 两者区别请看：(http://zhidao.baidu.com/link?url=eyTmOA33VVDCq5Qg6O3JFEEm2Sjs0olWyNqV5Rz6Cg-Jt0y8_lpLq9qq_dlxcpPbVLxhZ6Sex1D3dZL8usDBq_)  楼主，请你先把你的算法明确，然后看下如果你用malloc或者calloc是不是太多了，如果是，我建议你直接弄个大一点的数组，不要反复malloc calloc 和 realloc，这三个东西代价比较高  当然，如果你是在做嵌入式、可用空间很有限，当我没说

建议楼主学习循环FIFO缓冲区相关知识。

引用 2 楼 u010868023 的回复:你可以在循环外面申请100个元素的空间 来保存最后100个元素  定义全局数组吗？可它怎么和新输入的500个元素拼接呢，还有对于子函数Fun2，Fun3....都要定义全局数组吗

你可以在循环外面申请100个元素的空间 来保存最后100个元素

你可以在循环外面申请100个元素的空间 来保存最后100个元素


Question: 统计数字问题

问题是什么？


Question: 链表结点删除

仅供参考：//带表头结点的单向链表 #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-> //

你写的方法不是很好 while (num != p1->num && p1->next != NULL)这里num != p1->num不应该放在while里来判断。可以参考 下面的  Node *Delete(Node *head,int key)   {       Node *node1=head;       Node *node2=NULL;       if (head==NULL)       {           return NULL;       }        else       {           if (node1->number==key)           {               head=head->next;               free(node1);               return head;           }            else           {               while (node1!=NULL)               {                   node2=node1;                   node2=node2->next;                   if (node2->number==key)                   {                       node1->next=node2->next;                       free(node2);                       break;                   }                   node1=node1->next;               }               return head;           }       }   }

当num==head->num时，都进不了while


Question: 字符转义和字符串字面值的转义有什么区别

3 L呢？  我测试过，是不是测试不对？

引用 2 楼 caddor9100 的回复:[quote=引用 1 楼 GKatHere 的回复:] 1:   ' ' 可以括一串， ULONG a = 'dcba'; 2:   "可以单独使用？ char a = "    ????? 我问的是 字符转义和字符串中的转义[/quote] char a = '\"';  转义\"  char* a = "abcd\"def"; 中间", 必须是转义\"; char b = '"'; 中间"可以不是转义\"

第2个问题:  #include<stdio.h> int main() {     fun();     printf("\a");     printf("%d",sizeof(long int));     return 0; } void fun() { }        不是说c89规定，必须先申明后使用  c99，则没有规定。

引用 1 楼 GKatHere 的回复:1:   ' ' 可以括一串， ULONG a = 'dcba'; 2:   "可以单独使用？ char a = "    ?????   我问的是 字符转义和字符串中的转义

就是一个单引号'' 和，双引号“” 的 区别， 所以 双引号内，要写双引号字符，就需要转义，单引号内不必 反之亦然  另外可以有空串""（只包含 \0）， 不存在空字符‘’，只有序号为0 的字符，和空格字符等等

3 L


Question: 父进程如何访问子进程的私有空间？如代码所示

同意赵老师的说法 ... 不过最好是父进程以调试模式打开子进程

用管道，父子进程间用无名管道，如果无血缘关系的进程间用有名管道即可。

ReadProcessMemory

linux下，子进程可以读父进程的内存。其它不可以。 看下进程间通信方面的知识吧。

每个进程各自有不同的用户地址空间，任 何一个进程的全局变量在另一个进程中都看不到，所以进程之间要交换数据必须通过内核，在内核中开辟一块缓冲 区，进程1把数据从用户空间拷到内核缓冲区，进程2再从内核缓冲区把数据读走，内核提供的这种机制称为进程间通信（IPC，InterProcess Communication）。

内存映射文件 createfilemapping、mapviewoffile之类的。


Question: 一段c语言代码，小问题，求指出无法运行的原因

check_num( p+i )

void cheak_num(int*);//声明一个数字输入检查函数  p=(int *)malloc(quality * sizeof(int));//分配内存  printf("The %d number is: %d",i+1,  *(p+i));

楼主，你的调用声明好乱啊 首先声明函数void cheak_num(int)，可是在定义时void cheak_num(int * add)，参数就变成指针 第二函数调用cheak_num(&quality)，给函数传递一个地址；cheak_num(*(p+i));给函数传递一个整型值  敢问楼主，你用的是什么编译器，这都能通过

你好，在你提示下，我的输入可以正常，但是vc弹出对话框   DEBUG ERROR damage: after normal block (#48) at 0x007906E6 Press retry to debug  the application   我在网上查了相关关键字，说是我的内存分配小了，那个请你指正下,应该如何分配


Question: 这段代码 的插入函数 编译没有错误，运行就崩溃。

if(pre = NULL) { p->next = *hp;   //头插 *hp = p; } 改为  if(NULL == pre ) { p->next = *hp;   //头插 *hp = p; }  将常量放前面可以避免你这种漏写=的情况。


Question: 按键检测

/****************************************  键盘_不采用定时器_不延时  特点： 按键在松手后有效,灵敏度高,消耗资源少,运行效率高  独立键盘为:K01=P2^4;K02=P2^5;K03=P2^6;K04=P2^7; 矩阵键盘为:行(上到下)_P2.3_P2.2_P2.1_P2.0            列(左到右)_P2.7_P2.6_P2.5_P2.4  提供的操作函数：  //独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key extern unsigned char keyboard_self();  //矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位 extern unsigned char keyboard_matrix();  ****************************************/  . 　  先看独立键盘（和矩阵键盘的算法一样） ----------------------------------------------------------------------- #include<reg52.h> #include<intrins.h>  //独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key extern unsigned char keyboard_self() {         unsigned char num_key=0;//按键号         unsigned char temp=0;//用于读取P2线上按键值         static unsigned char temp_code=0;//保存按键值         static unsigned char num_check=0;//低电平有效次数         static unsigned char key_flag=0;//按键有效标识          temp=P2&0xF0;//读取P2线数据          if(temp!=0xF0)//低电平判断         {                 num_check++;                 if(num_check==10)//连续10次(10ms)低电平有效,则认为按键有效                 {                         key_flag=1;//使能按键有效标识                         temp_code=temp;//保存按键值                 }         }         else//松手时判断         {                 num_check=0;                  if(key_flag==1)//按键有效                 {                         key_flag=0;                          switch(temp_code)//读取按键号                         {                                 case 0xE0: num_key=1;                                            break;                                 case 0xD0: num_key=2;                                            break;                                 case 0xB0: num_key=3;                                            break;                                 case 0x70: num_key=4;                                            break;                         }                 }         }          return(num_key); } 　  现在是矩阵键盘的 ----------------------------------------------------------------------- #include<reg52.h> #include<intrins.h>    //矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位 extern unsigned char keyboard_matrix() {         unsigned char num_key=0;//按键号         unsigned char temp=0;//读取P2口线数据         static unsigned char temp_code=0;//用于保存按键值         static unsigned char temp_circle=0xFE;//保存P2线上的循环扫描值         static unsigned char num_check=0;//低电平计数         static unsigned char key_flag=0;//按键有效标识          P2=temp_circle;//0xFX         temp=P2;//读取P2口线数据         if(temp!=temp_circle)//有按键动作         {                 num_check++;//低电平计数|逢低电平加1                 if(num_check==10)//连续10次(10ms)低电平有效                 {                         key_flag=1;//按键有效标识置1                         temp_code=temp;//保存按键值                 }         }         else//松手OR无按键动作,此时应该改变扫描线         {                 num_check=0;                 if(key_flag==1)//按键有效判断                 {                         key_flag=0;                         switch(temp_code)//读取按键号                         {                                 //P2^0线                                 case 0xEE: num_key=1;                                            break;                                 case 0xDE: num_key=2;                                            break;                                 case 0xBE: num_key=3;                                            break;                                 case 0x7E: num_key=4;                                            break;                                 //P2^1线                                 case 0xED: num_key=5;                                            break;                                 case 0xDD: num_key=6;                                            break;                                 case 0xBD: num_key=7;                                            break;                                 case 0x7D: num_key=8;                                            break;                                 //P2^2线                                 case 0xEB: num_key=9;                                            break;                                 case 0xDB: num_key=10;                                            break;                                 case 0xBB: num_key=11;                                            break;                                 case 0x7B: num_key=12;                                            break;                                 //P2^3线                                 case 0xE7: num_key=13;                                            break;                                 case 0xD7: num_key=14;                                            break;                                 case 0xB7: num_key=15;                                            break;                                 case 0x77: num_key=16;                                            break;                         }                 }                 temp_circle=_crol_(temp_circle,1);//改变扫描线                 if(temp_circle==0xEF)                 {                         temp_circle=0xFE;                 }         }         return(num_key);//返回按键号 }  /*************************************************************************  未按键时,扫描线一直变化。 长按键时,扫描线不变化,使得该行按键变成了独立按键,这样的扫描效率极高。 如当按下P2.0线上的某个键时,程序将扫描到这个键,而后扫描线不变化, 当键盘程序连续10次进入时检测到10次按键有效,直到松手后扫描线才变化  *************************************************************************/

怎样让P2^6键按下时，定时器0中断停止执行，循环的去检测按键，能帮我看看我的程序吗？该怎么改   #include<reg52.h> #include<intrins.h> #define uint unsigned int #define uchar unsigned char   sbit motor_dir=P1^2;		 //方向信号  sbit motor_clksta=P1^0;	 //	脉冲信号  void Init_timer()			 //定时器0初始化 	{ TMOD=0x21; 	  TH0=0xf1; 	  TL0=0x99; 	  ET0=1; 	  TR0=1; 	  EA=1; 	        }   uint KeyScan()		         //扫描按键 { unsigned char num_key=0;//按键号         unsigned char temp=0;//用于读取P2线上按键值         static unsigned char temp_code=0;//保存按键值         static unsigned char num_check=0;//低电平有效次数         static unsigned char key_flag=0;//按键有效标识           temp=P2&0xF0;//读取P2线数据           if(temp!=0xF0)//低电平判断         {                 num_check++;                 if(num_check==10)//连续10次(10ms)低电平有效,则认为按键有效                 {                         key_flag=1;//使能按键有效标识                         temp_code=temp;//保存按键值                 }         }         else//松手时判断         {                 num_check=0;                   if(key_flag==1)//按键有效                 {                         key_flag=0;                           switch(temp_code)//读取按键号                         {                                 case 0xE0: num_key=1;                                            break;                                 case 0xD0: num_key=2;                                            break;                                 case 0xB0: num_key=3;                                            break;                                 case 0x70: num_key=4;                                            break;                         }                 }         }           return(num_key); 			 	}						          void main() { Init_timer();//定时器初始化    while(1)      {KeyState=KeyScan();//读取返回键值 	  switch(KeyState) 		 {	case 1:	motor_dir=0;//P2^4被按下，方向给0 					keydown==1 				   break; 		    case 2: motor_dir=1;	  //P2^5被按下，方向给1 				    keydown==1        				   break; 		    csae 3:  keydown==1   //P2^6被按下，不让P1^0发脉冲 					 break; 		   } 		if(keydown==1)break; 	   }    while(1);		 //执行定时器0中断 }  void timer0() interrupt 1				   //定时器0中断处理函数 	  {   	if(KeyState!=3) 			 { TH0=0xf1;		 		       TL0=0x99; 			   motor_clksta=~motor_clksta; 			 }        }


Question: 最后一个函数，输出值为什么是0  如图

引用 2 楼 Evankaka 的回复:max (a,m1,c,b);//函数调用 这里你使用的是形参，在C++里头，形参改变，实参是不会发生改变的、 直接使用max (a,&m1,&c,&b);要不就地指针来做 引用 2 楼 Evankaka 的回复:max (a,m1,c,b);//函数调用 这里你使用的是形参，在C++里头，形参改变，实参是不会发生改变的、 直接使用max (a,&m1,&c,&b);要不就地指针来做谢谢回复，想请问前面编写的函数也是用了这个思路的，但是输出的值都是有效的，是因为形参里面定义的数组，代表的是数组的首地址，所以实参是数组的话，就能够让形参的值发生改变还返回给实参了吗？

引用 1 楼 ant2012 的回复:楼主，我看你的代码，你好像不太理解数组伟参的问题 void max(float a1[10][5],float m,int i1,int j1) float a1[10][5] 后面的5是没必要的，只有前面的5有用，数组实现的底层还是通过地址偏移实现了，形参的数组并不会开辟数组空间，而只是承接实参的地址，在通过下标值和第一维的大小（也就是10来定位某个元素的位置），如a1[i][j] 其实就是*（a1 + i * 10 + j）。  其次，参数传递，如 void max(float a1[10][5],float m,int i1,int j1)  在调用这种函数时，像m, i1, j1变量，实参只会将值传给形参，但形参和实参都有自己的内存空间，子函数中对m, i1, j1变量的更改并不会同步到实参中。如果想让形参的值和实参同步，就得让它们指向一个内存单元，要么用引用，要么用指针  解决办法（采用引用） void max(float a1[10][5],float m,int i1,int j1); 改成 void max(float a1[10][5],float& m,int& i1,int& j1);抱歉，初学者，自己看书，对细节都不太懂，想请教下，引用该怎么理解？

仔细看了一遍书上，发现看的不认真，谢谢了


Question: 关于指针的调用

没见过字符的copy函数，如果是复制可以使用memcpy或者strcpy  *ip[i]  是ip这个数组里的第i个元素的第一个字符，不知楼主是不是要表达这个意思

出现 error C2228: left of '.……' must have class/struct/union type的情况有两种。 1：函数名写错了。 2：类似于 bool RemoveConditionData(int tier, char condition, string value) {     return tableBody.RemoveConditionData(tier, condition, value); } 此时会出现error C2065: 'tableBody' : undeclared identifier left of '.RemoveConditionData' must have class/struct/union type 原因是tableBody是定义出的一个类对象，不是new创建的类对象。（在相同情况下）假如返回类型是void 不会出现类似的错误。而且，这种情况只会在bool的返回类型中出现，其他类型，还没有发现

楼主，实现拷贝数据功能，可能用库函数memcpy  void *memcpy( void *dest, const void *src, size_t count );  dest  New buffer  src  Buffer to copy from  count  Number of characters to copy  不过，首先你得给dest和src实参指针开辟空间  如 char *src = "sdfsdfsds"; char *dest = new char[20]; memcpy(dest, src, strlen(src));

我是用C++写的，使用的头文件是include<iostream>include<string> 目的是实现(*ip[i]).copy(*tmpIp[j],1,j);

楼主想做什么，首先，你没有为指针数组中的每个指针元素开辟空间，第二，copy函数从何而来，char类型是普通类型，并没有copy成员函数


Question: 求助，codeblocks下指针地址怎么会突变？

弄明白了，是*temp未初始化，所分配的内存单元指向了指针变量p2，即*temp=p2，因而当*temp=*p1执行时，也有p2=*p1，所以才会突变

引用 4 楼 sholber 的回复:void swap (int * p1, int * p2) {     int * temp = p1;     p1 = p2;     p2 = temp; }  [quote=引用 2 楼 UONK1 的回复:] [quote=引用 1 楼 sholber 的回复:] 是你不懂指针，关c::B何事 那程序有什么问题呢？[/quote][/quote]  能发现上面的问题不？？ 要想与别人不同， 还要正确，唯有如此了： void swap(int * p1, int * p2) {     int * temp = & (int)  {* p1};     * p1 = * p2;     * p2 = * temp; }

void swap (int * p1, int * p2) {     int * temp = p1;     p1 = p2;     p2 = temp; } 引用 2 楼 UONK1 的回复:[quote=引用 1 楼 sholber 的回复:] 是你不懂指针，关c::B何事 那程序有什么问题呢？[/quote]

temp未初始化。  void swap(int *p1, int *p2) {     int temp;     temp = *p1;     *p1 = *p2;     *p2 = temp; }

引用 1 楼 sholber 的回复:是你不懂指针，关c::B何事 那程序有什么问题呢？

是你不懂指针，关c::B何事


Question: 写一个算法，怎样将字符串前后的0去掉

char buffer[] = "0000123123123000000"; int length = strlen(buffer); char * p = buffer; char * q = buffer + length; while (*p == '0') p++; while (*(q - 1) == '0') q--; *q = 0; char result[128]; strcpy(result, p);

引用 5 楼 yaojuntong77 的回复:首部设置一个指针，尾部设置一个指针，两头往中间扫描，然后就获取到中间要的那段了，其余的楼主自己拷贝，嘻嘻  每天回帖即可获得10分可用分！   #include <stdio.h> #include <string.h>  char *StrTrimChar(char * const cstr, const size_t strlength, const char ctrim) {     char  *head = cstr;     char  *tail = cstr + strlength - 1;      if (NULL == cstr)     {         return cstr;     }      while (*head == ctrim && '\0' != *head)     {         head ++;     }     if ('\0' == *head)     {         cstr[0] = '\0';         return cstr;     }      while (*tail == ctrim && head != tail)     {         tail --;     }     *(++tail) = '\0';      return head; }  int main (void) {     char char_to_trim = '0';     char str1_to_trim[] = "0000123123123000000";     char str2_to_trim[] = "00werwe000000000";     char str3_to_trim[] = "qwe000asdasd000";      printf("%s\n", StrTrimChar(str1_to_trim, strlen(str1_to_trim), char_to_trim));     printf("%s\n", StrTrimChar(str2_to_trim, strlen(str2_to_trim), char_to_trim));     printf("%s\n", StrTrimChar(str3_to_trim, strlen(str3_to_trim), char_to_trim));      return 0; }   ------------------------------------------------------------------------------------------------------------------------------------------------------------------ 1>------ 已启动生成: 项目: exam006, 配置: Debug Win32 ------ 1>正在编译... 1>testmain.c 1>正在链接... 1>正在嵌入清单... 1>生成时间 0:00 1>生成日志保存在“*****************************************************************************” 1>exam006 - 0 个错误，0 个警告 ========== 生成: 1 已成功, 0 已失败, 0 最新, 0 已跳过 ==========  ------------------------------------------------------------------------------------------------------------------------------------------------------------------ 123123123 werwe qwe000asdasd 请按任意键继续. . .

引用 2 楼 qq_24484465 的回复:引用 1 楼 u011673029 的回复:你把他们保存到string里面，之后从尾部查找0，找到了就删除，遇到不是的就停止，从头也是一样的中间的不用删除 对的，按照这个逻辑中间是不删除的

#include <stdio.h> #include <stdlib.h>  char *StrTrimChar(char *cstr, char ctrim) {     char *dest = cstr;      char *begin = cstr;     while (*begin == ctrim) {         begin++;     }      char *end = begin;     while (*end != 0) {         end++;     }     end--;      while (*end == ctrim) {         *end-- = 0;     }     end++;      while (begin < end) {         *cstr++ = *begin++;     }     *begin = 0;      return dest; }  int main(int argc, char *argv[]) {     char char_to_trim = '0';     char str1_to_trim[] = "0000123123123000000";     char str2_to_trim[] = "00werwe000000000";     char str3_to_trim[] = "qwe000asdasd000";      printf("%s\n", StrTrimChar(str1_to_trim, char_to_trim)); // 1231231233123     printf("%s\n", StrTrimChar(str2_to_trim, char_to_trim)); // werwewe     printf("%s\n", StrTrimChar(str3_to_trim, char_to_trim)); // qwe000asdasd      return 0; }

#include "boost/algorithm/string.hpp" #include <iostream> int main() { 	 	std::string s = "0000123123123000000"; 	boost::trim_if(s, boost::is_any_of("0"));  	std::cout << s; 	system("pause");  	return 0; }

#include <stdio.h> #include <string.h> char *trimlr0(char *s) {     int h,t;     h=0;     while (1) {         if ('0'!=s[h]) break;         h++;     }     t=strlen(s)-1;     while (1) {         if (t<0||'0'!=s[t]) break;         t--;     }     if (t>0) s[t+1]=0;     return s+h; } int main() {     char s1[]="0000123123123000000";     char s2[]="00werwe000000000";     char s3[]="qwe000asdasd000";     char s4[]="0";     char s5[]="";      printf("[%s]\n",trimlr0(s1));     printf("[%s]\n",trimlr0(s2));     printf("[%s]\n",trimlr0(s3));     printf("[%s]\n",trimlr0(s4));     printf("[%s]\n",trimlr0(s5));      return 0; } //[123123123] //[werwe] //[qwe000asdasd] //[] //[] //

从头尾各找到第一个不是0的为止

组合一下就行了     string s="qwe000asdasd000";     auto st=s.find_first_not_of('0');     auto s1 =s.substr(st,s.find_last_not_of('0')-st+1);


Question: 请 高神帮忙解析下

scanf("c%",&A); 写反了， 是%c不是c%   还是你厉害

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  关于自己是否适合编程的很简单的测试： 在报纸或杂志上随便找一段约1000字的文章，在Word中输入一遍。输完后再参考下面答案：  A里面有10处以上文字或标点错误 B里面没有文字或标点错误并敢为此跟人打赌 C里面没有文字或标点错误并且字体和排版完全与原稿一致 D打印在半透明的纸上和原稿重叠在一起检查一模一样，且自我感觉很有成就感  A不适合编程（理由：打字准确度偏低、粗心大意） B初级程序员（理由：打字准确度很高、认真细致、自信、理解全角半角概念） C高级程序员（理由：在B的基础上理解字体和排版也是电脑打印的重要因素、但相比D还不够偏执、精益求精、结果可验证） D软件项目经理（理由：能针对项目给出令人信服的细致到极点的需求说明和典型测试用例。用户几乎挑不出毛病。专业！）  如果想从A变成B的话，到我的资源http://download.csdn.net/detail/zhao4zhong1/4084259里面下载“适合程序员的键盘练习”

scanf("c%",&A); 写反了， 是%c不是c%

scanf("c%",&A); 写反了， 是%c不是c%

scanf("%c",&A); 如果不行把%c换成%s试一下， 百度一下使用%s和%c的差别，我忘了

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系  能具体指出代码中的问题吗？


Question: fprintf实现写到文件行尾字符

多谢楼上各位回复！  目前这样处理的，写入文件时，加个回车（\n），读取文件时只读取第一行，可以临时解决由2位或3位数变成1位数的问题。

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

引用 5 楼 zhao4zhong1 的回复:fopen(file,"rb+")打开 linux下用fopen打开时r+和rb+是一样的，没有区别。 这里是向文件中写入文件行尾标记$，不是普通的字符；

引用 3 楼 zhao4zhong1 的回复:所谓修改删除文件a某位置的内容，其实是读打开文件a，再将‘a中修改删除位置之前的内容＋修改删除的内容＋a中修改删除位置之后的内容’保存到文件b，关闭文件a，删除文件a，将文件b改名为与之前文件a相同的名字，仅此而已。 觉得行尾的$符号好像是自动生成？手工写入$不行？

fopen(file,"rb+")打开

引用 1 楼 ubuntu_ai 的回复: 先把文件全部内容读到缓冲区中，然后修改它，最后用fwrite/fputs/fprint把缓冲区写到文件，这样就可以了  如果你直接对文件操作，也是可以的，只是你要处理“文件光标”的问题，每一次读取或者写入光标都会移动。。。。  觉得行尾的$符号好像是自动生成？手工写入$不行？


Question: C语言程序，报内存不能读

main()中 m.p = (int*)malloc(sizeof(int)*(m.column+m.row)); 这一行应该是 m.p = (int*)malloc(sizeof(int)*(m.column*m.row)); 加号->乘号


Question: printf输出函数输出异常

你用的指针指向的都是栈地址，而栈地址函数返回就无效了，程序执行结果未知

两个指针指向同一块内存？这个我不认同……而且用他们输出本身就是不对的。

引用 7 楼 zhangxiangDavaid 的回复:看汇编，看汇编，看汇编，重要的事情说三遍。 同意！  理解和讨论之前请先学会如何观察！  计算机组成原理→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

引用 6 楼 skmagic 的回复:[quote=引用 1 楼 user-10 的回复:] 貌似两种都不对 出函数后，内存应该都释放了 内输出结果  也是错误的用法 引用 2 楼 adusuccessfully 的回复: #include <iostream> int *fun1( ) { 	int j = 5; 	int *p = &j; 	return p; } int *fun2(void) { 	int j = 10; 	int *p = &j; 	return p; }  int main( ) { 	int *p = fun1( ); 	printf("%d\n", *p); 	p = NULL; 	int *q = fun2(); 	printf("%d\n", *q); 	q = NULL; 	return 0; }  用完一个指针记着将它置空。 引用 3 楼 wang0635 的回复:函数返回后，函数中自动局部变量的地址是野指针，不能再使用它 如果用有，后果自负——什么结果都有可能 引用 4 楼 q3733353520 的回复:函数调用完毕后，都会释放内存，但是返回的指针依然指向这块释放了的内存（并不会因为这块内存释放而改变指针指向的地址） ，然后这快内存内容的变化是你所不能控制的，也许它已经被改变，也许没有，虽然你不可以改变它，但是你依然可以获得这块内存中存储的值   我知道这是不对的，只不过是因为解决别的问题这样调试的时候，发现了这个问题，现在虽然指针是野指针，但是他还是可以调用显示原存储区域的值吧，现在是调用的时候第一次可以正常显示，但是第二次现实的时候就成0了，我试了好多次都是这样，在别的机器上也是这样，现在不明白的是这里，调用printf函数之后会将存储区域的值置为0吗？按说不会吧[/quote]  是的，因为你释放内存后，执行其它语句的时候，可能，系统已经把这块内存分配出去,printf也是个函数

临时变量，数值是随机的。。。

看汇编，看汇编，看汇编，重要的事情说三遍。

引用 1 楼 user-10 的回复:貌似两种都不对 出函数后，内存应该都释放了 内输出结果  也是错误的用法 引用 2 楼 adusuccessfully 的回复: #include <iostream> int *fun1( ) { 	int j = 5; 	int *p = &j; 	return p; } int *fun2(void) { 	int j = 10; 	int *p = &j; 	return p; }  int main( ) { 	int *p = fun1( ); 	printf("%d\n", *p); 	p = NULL; 	int *q = fun2(); 	printf("%d\n", *q); 	q = NULL; 	return 0; }  用完一个指针记着将它置空。 引用 3 楼 wang0635 的回复:函数返回后，函数中自动局部变量的地址是野指针，不能再使用它 如果用有，后果自负——什么结果都有可能 引用 4 楼 q3733353520 的回复:函数调用完毕后，都会释放内存，但是返回的指针依然指向这块释放了的内存（并不会因为这块内存释放而改变指针指向的地址） ，然后这快内存内容的变化是你所不能控制的，也许它已经被改变，也许没有，虽然你不可以改变它，但是你依然可以获得这块内存中存储的值   我知道这是不对的，只不过是因为解决别的问题这样调试的时候，发现了这个问题，现在虽然指针是野指针，但是他还是可以调用显示原存储区域的值吧，现在是调用的时候第一次可以正常显示，但是第二次现实的时候就成0了，我试了好多次都是这样，在别的机器上也是这样，现在不明白的是这里，调用printf函数之后会将存储区域的值置为0吗？按说不会吧

虽然p和q地址一样，但他们都批向无效内存，执行printf("%d\n", *p)时，这块内存还未被覆盖，所以输出10，而执行printf("%d\n", *q)时，那块内存已经被上一次的print函数使用时覆盖了，所以可能出现另外的结果了

貌似两种都不对 出函数后，内存应该都释放了 内输出结果  也是错误的用法


Question: 如何使用scanf为结构变量赋值？

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

double 用%lf输入  #include <stdio.h> typedef struct  Goods { 	char  name[18];                   	double  price;                           	char  special;                     	int   num;                      	short   saled;                 }gs;       //typedef   struct  Goods   gs;                  struct  Goods 是结构类型名，gs是变量名  int  main() { 	printf("%d\n", sizeof(gs)); 	gs  gsone = { 0 };    	scanf_s("%s", &gsone.name); 	int n=scanf_s("%lf", &gsone.price); 	printf("成功输入了%d\n", n); 	printf("gsone=%s  %g", gsone.name, gsone.price ); 	return 0; }

scanf输入double的格式为%lf printf输出double和float才都是%f

#include <stdio.h> typedef struct  Goods{ char  name[18]; double  price; char  special; int   num; short   saled; }gs;       //typedef   struct  Goods   gs;                  struct  Goods 是结构类型名，gs是变量名 int  main() { printf("%d\n", sizeof(gs)); gs  gsone = { 0 }; scanf("%s", &gsone.name); int n=scanf("%f", &gsone.price); printf("成功输入了%d\n", n); printf("gsone=%s  %g", gsone.name, gsone.price ); return 0; } 结果是这样啊，，，求解，

你用是 scanf_s 不是scanf 不要把scanf_s 当成scanf 使用 这是两个不同的函数  自己搜索清楚scanf_s的用法  不要想当然的把scanf的参数抄进去


Question: c语言：求救。。。为什么会运行错误

谢谢了，问题解决！

char* aa = new char（50）; sprintf（aa,"%S","1234"）; strcat(aa,"123");

@user-1 但是我想用字符指针，该怎么做？

strcat(d,s) 中 d和s所指内存区域不可以重叠且d必须有足够的空间来容纳s的字符串。 如下即可： char aa[50]="1234"; strcat(aa,"123");


Question: 急求各位大神！！！！sim900a连接到51单片机后成功读取短信内容后，如何编程（c语言）可以得到发送该短信的手机号是多少？

真棒，楼主分享一下

看AT命令手册，读取短信部分。 AT+CMGR能获号码：  看下图

http://wenku.baidu.com/view/2a559695daef5ef7ba0d3ca8  你去把这个文档下下来看看，里面附有代码，我本科时用过这个文档


Question: Linux 操作系统下段错误问题

有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行！ 写日志到文件参考下面： #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <io.h> #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  _vsnprintf         vsnprintf #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); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } #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} int main(int argc,char * argv[]) {     int i; #ifdef WIN32     InitializeCriticalSection(&cs_log); #else     pthread_mutex_init(&cs_log,NULL); #endif     for (i=0;i<10000;i++) {         Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);     } #ifdef WIN32     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_log); #endif     return 0; } //1-78行添加到你带main的.c或.cpp的那个文件的最前面 //81-85行添加到你的main函数开头 //89-93行添加到你的main函数结束前 //在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中

在可疑的地方设置个条件断点试试，例如：条件断点： b test.c:8 if cnt == 5

http://www.0xffffff.org/?p=6 可以配合内核转储文件来找

可以通过看内核源码，或者 oops