Question: c run-time library和 c standard library这两个概念怎么联系起来？

引用 3 楼 truexf 的回复:感谢科普！！学习了！  [quote=引用 楼主 inurlcn 的回复:]  c run-time library： http://en.wikipedia.org/wiki/C_library    c standard library： http://en.wikipedia.org/wiki/Runtime_library  如何理解C run-time library （C运行时库）  　注： 以下内容部分引自CSND中相关讨论的帖子，并结合自己的理解整理而成。仅供参考。 　　1)运行时库就是 C run-time library，是 C 而非 C++ 语言世界的概念:取这个名字就是因为你的 C 程序运行时需要这些库中的函数. 　　2)C 语言是所谓的“小内核”语言，就其语言本身来说很小（不多的关键字，程序流程控制，数据类型等）；所以，C 语言内核开发出来之后，Dennis Ritchie 和 Brian Kernighan 就用 C 本身重写了 90% 以上的 UNIX 系统函数，并且把其中最常用的部分独立出来，形成头文件和对应的 LIBRARY，C run-time library 就是这样形成的。 　　3)随后，随着 C 语言的流行，各个 C 编译器的生产商/个体/团体都遵循老的传统，在不同平台上都有相对应的 Standard Library，但大部分实现都是与各个平台有关的。由于各个 C 编译器对 C 的支持和理解有很多分歧和微妙的差别，所以就有了 ANSI C；ANSI C （主观意图上）详细的规定了 C 语言各个要素的具体含义和编译器实现要求，引进了新的函数声明方式，同时订立了 Standard Library 的标准形式。所以C运行时库由编译器生产商提供。至于由其他厂商/个人/团体提供的头文件和库函数，应当称为第三方 C 运行库（Third party C run-time libraries）。 　　4)C run-time library里面含有初始化代码，还有错误处理代码(例如divide by zero处理)。你写的程序可以没有math库，程序照样运行，只是不能处理复杂的数学运算，不过如果没有了C run-time库，main()就不会被调用，exit()也不能被响应。因为C run-time library包含了C程序运行的最基本和最常用的函数。 　　5)到了 C++ 世界里，有另外一个概念:Standard C++ Library,它包括了上面所说的 C run-time library 和 STL。包含 C run-time library 的原因很明显，C++ 是 C 的超集，没有理由再重新来一个 C++ run-time library. VC针对C++ 加入的Standard C++ Library主要包括：LIBCP.LIB, LIBCPMT.LIB和 MSVCPRT.LIB 　　6)Windows环境下，VC提供的 C run-time library又分为动态运行时库和静态运行时库。 　　动态运行时库主要是DLL库文件msvcrt.dll(or MSVCRTD.DLL for debug build),对应的Import library文件是MSVCRT.LIB(MSVCRTD.LIB for debug build) 　　静态运行时库(release版)对应的主要文件是： 　　LIBC.LIB (Single thread static library, retail version) 　　LIBCMT.LIB (Multithread static library, retail version) 　　msvcrt.dll提供几千个C函数，即使是像printf这么低级的函数都在msvcrt.dll里。其实你的程序运行时，很大一部分时间时在这些运行库里运行。在你的程序(release版)被编译时，VC会根据你的编译选项(单线程、多线程或DLL)自动将相应的运行时库文件(libc.lib,libcmt.lib或Import library msvcrt.lib)链接进来。 　　编译时到底哪个C run-time library联入你的程序取决于编译选项： 　　/MD, /ML, /MT, /LD (Use Run-Time Library) 　　你可以VC中通过以下方法设置选择哪个C run-time library联入你的程序： 　　To find these options in the development environment, click Settings on the Project menu. Then click the C/C++ tab, and click Code Generation in the Category box. See the Use Run-Time Library drop-down box. 　　从程序可移植性考虑,如果两函数都可完成一种功能，选运行时库函数好,因为各个 C 编译器的生产商对标准C Run-time library提供了统一的支持.(王朝网络 wangchao.net.cn)[/quote]

LZ贴出来的东西讲的很全面了  如果简化点想，那么就是标准库是所有标准C实现都有的一个函数集合，而CRT是其一个超集，除了标准库的实现外，还有一些和实现平台相关的东西（即多一些函数）

感谢科普！！学习了！  引用 楼主 inurlcn 的回复:c run-time library： http://en.wikipedia.org/wiki/C_library    c standard library： http://en.wikipedia.org/wiki/Runtime_library  如何理解C run-time library （C运行时库）  　注： 以下内容部分引自CSND中相关讨论的帖子，并结合自己的理解整理而成。仅供参考。 　　1)运行时库就是 C run-time library，是 C 而非 C++ 语言世界的概念:取这个名字就是因为你的 C 程序运行时需要这些库中的函数. 　　2)C 语言是所谓的“小内核”语言，就其语言本身来说很小（不多的关键字，程序流程控制，数据类型等）；所以，C 语言内核开发出来之后，Dennis Ritchie 和 Brian Kernighan 就用 C 本身重写了 90% 以上的 UNIX 系统函数，并且把其中最常用的部分独立出来，形成头文件和对应的 LIBRARY，C run-time library 就是这样形成的。 　　3)随后，随着 C 语言的流行，各个 C 编译器的生产商/个体/团体都遵循老的传统，在不同平台上都有相对应的 Standard Library，但大部分实现都是与各个平台有关的。由于各个 C 编译器对 C 的支持和理解有很多分歧和微妙的差别，所以就有了 ANSI C；ANSI C （主观意图上）详细的规定了 C 语言各个要素的具体含义和编译器实现要求，引进了新的函数声明方式，同时订立了 Standard Library 的标准形式。所以C运行时库由编译器生产商提供。至于由其他厂商/个人/团体提供的头文件和库函数，应当称为第三方 C 运行库（Third party C run-time libraries）。 　　4)C run-time library里面含有初始化代码，还有错误处理代码(例如divide by zero处理)。你写的程序可以没有math库，程序照样运行，只是不能处理复杂的数学运算，不过如果没有了C run-time库，main()就不会被调用，exit()也不能被响应。因为C run-time library包含了C程序运行的最基本和最常用的函数。 　　5)到了 C++ 世界里，有另外一个概念:Standard C++ Library,它包括了上面所说的 C run-time library 和 STL。包含 C run-time library 的原因很明显，C++ 是 C 的超集，没有理由再重新来一个 C++ run-time library. VC针对C++ 加入的Standard C++ Library主要包括：LIBCP.LIB, LIBCPMT.LIB和 MSVCPRT.LIB 　　6)Windows环境下，VC提供的 C run-time library又分为动态运行时库和静态运行时库。 　　动态运行时库主要是DLL库文件msvcrt.dll(or MSVCRTD.DLL for debug build),对应的Import library文件是MSVCRT.LIB(MSVCRTD.LIB for debug build) 　　静态运行时库(release版)对应的主要文件是： 　　LIBC.LIB (Single thread static library, retail version) 　　LIBCMT.LIB (Multithread static library, retail version) 　　msvcrt.dll提供几千个C函数，即使是像printf这么低级的函数都在msvcrt.dll里。其实你的程序运行时，很大一部分时间时在这些运行库里运行。在你的程序(release版)被编译时，VC会根据你的编译选项(单线程、多线程或DLL)自动将相应的运行时库文件(libc.lib,libcmt.lib或Import library msvcrt.lib)链接进来。 　　编译时到底哪个C run-time library联入你的程序取决于编译选项： 　　/MD, /ML, /MT, /LD (Use Run-Time Library) 　　你可以VC中通过以下方法设置选择哪个C run-time library联入你的程序： 　　To find these options in the development environment, click Settings on the Project menu. Then click the C/C++ tab, and click Code Generation in the Category box. See the Use Run-Time Library drop-down box. 　　从程序可移植性考虑,如果两函数都可完成一种功能，选运行时库函数好,因为各个 C 编译器的生产商对标准C Run-time library提供了统一的支持.(王朝网络 wangchao.net.cn)

mark一下 前段时间遇到过这类问题 还好解决了！！！

C标准库只是一个概念，表示C语言编译器应当提供的那些API。 C运行时库是实际提供的标准库，通常是一个动态模块（dll或者so文件）。


Question: 如何避免count重定义

引用 7 楼 vipcxj 的回复: //dec.h extern int a1, a2, a3, a4;  //dec.cpp #include "dec.h" int a1 = 1, a2 = 2, a3 = 3, a4 = 4;  //main.cpp #include <iostream> #include "dec.h" int main() {    std::cout << a1 << a2 << a3 << a4 << std::endl;    return 0; }  忘记给dec.cpp加上#include "dec.h"了 thank you!就打算这样写了！！！

引用 5 楼 x565244538 的回复:[quote=引用 3 楼 turingo 的回复:] 在头文件中不要去直接定义变量实体，正确的做法应该是在某个.c文件中，即使在main.c中定义int count=100也是可以的，而在头文件中应该用extern int count仅仅进行声明而已。 主要是数据太多了...50多个结构体变量又声明，又定义的嫌麻烦!就想一次搞定！小弟我想偷个懒。50多个结构体代码量有1000多行。就是想每次包含以下头文件就可以了，省的每次都要包含头文件的同时都要对每个变量extern[/quote]  还是要用extern 你弄个头文件，里面用extern声明所有你需要的变量，弄个cpp，包含上面那个头文件，在cpp里面进行变量定义，然后将此cpp加入工程。具体使用时，你压根不用管那个cpp，只要包含头文件就够了。比如下面这样  //dec.h extern int a1, a2, a3, a4;  //dec.cpp int a1 = 1, a2 = 2, a3 = 3, a4 = 4;  //main.cpp #include <iostream> #include "dec.h" int main() {    std::cout << a1 << a2 << a3 << a4 << std::endl;    return 0; }

引用 3 楼 turingo 的回复:在头文件中不要去直接定义变量实体，正确的做法应该是在某个.c文件中，即使在main.c中定义int count=100也是可以的，而在头文件中应该用extern int count仅仅进行声明而已。 主要是数据太多了...50多个结构体变量又声明，又定义的嫌麻烦!就想一次搞定！小弟我想偷个懒。50多个结构体代码量有1000多行。就是想每次包含以下头文件就可以了，省的每次都要包含头文件的同时都要对每个变量extern

对你这个程序, 完全可以把int count=100; 移到a.c中 即时其他文件中需要访问count, 只需要在q.h中增加声明 extern int count; 即可

在头文件中不要去直接定义变量实体，正确的做法应该是在某个.c文件中，即使在main.c中定义int count=100也是可以的，而在头文件中应该用extern int count仅仅进行声明而已。  引用 楼主 x565244538 的回复:小弟正在写一个C++的派生类，头文件中定义变量，在其他代码中调用出现重定义现象，代码简化如下。 麻烦看下怎么改进，才能避免count重定义！3----q! q.h  #ifndef _Q_H_ #define _Q_H_ #include <stdio.h> int count=100; #endif  a.h  #ifndef _A_H_ #define _A_H_ #include "q.h" void print(); #endif  a.c  #include "a.h" void print() {     int num=count;     printf("count=%d\n",num); }  z.h  #ifndef _Z_H_ #define _Z_H_ #include "a.h" void printz(); #endif  z.c  #ifndef _Z_H_ #define _Z_H_ #include "a.h" void printz(); #endif  w.h  #ifndef _W_H_ #define _W_H_ #include "a.h" void printw(); #endif  w.c  #include "w.h" void printw() {     printf("____WWWW____%s\n",__func__);     print(); }  test.c  #include "w.h" #include "z.h" int main() {     printz();     printw();     print(); }

引用 1 楼 hwxy502 的回复:第一行加上#pragma once 还是不行。。。。。

第一行加上#pragma once


Question: 转换算法

搜“暴雪哈希算法”

引用 9 楼 u013531919 的回复:基本上就是hash，要限定范围用%运算。  我就是这样办的，冲突太严重啦！！！

引用 5 楼 dcw0402 的回复:帮顶一个,遇到类似的问题,没有很好的办法,我默认是用md5的  md5是唯一,但出来的都是乱串啊如何映射啊？

引用 4 楼 zhenwo123 的回复:[quote=引用 3 楼 nice_cxf 的回复:] 要看字符串的长度，说实话多半是不可能完成的任务  那平常那些hash都干啥用的啊？[/quote] hash是有碰撞的，保证不了唯一 除非你字符串长度短，不然从信息论角度看，是不可能实现11对应的，就算只有8位只有大小写字母加数字，总数也已经是62^8,已经超过了整数的最大范围

帮顶一个,遇到类似的问题,没有很好的办法,我默认是用md5的

引用 3 楼 nice_cxf 的回复:要看字符串的长度，说实话多半是不可能完成的任务  那平常那些hash都干啥用的啊？

引用 10 楼 vipcxj 的回复:一一映射理论上是可以的，也就是1L说的康托展开，但这只是理论，因为数学里面自然数可以是无穷，所以你一个足够长的字符串，可能就要映射到一个几M字节的整型上，显然这是毫无意义的。至于Hash算法，那更不可能一一映射了，因为Hash算法是有冲突滴~~~  不过如果LZ限定你字符串长度足够短，康托展开还是能够办到滴，因为康托展开对于n位的序列，至多到n!，这样n不是特别大，比如20以下，用long long就能存下所有的映射

基本上就是hash，要限定范围用%运算。

哈希+链表？？

我以前在CSDN也问过这个  都说不可能  会有冲突

要看字符串的长度，说实话多半是不可能完成的任务

字符串的经典hash算法 . http://blog.csdn.net/hengyunabc/article/details/5914934

康托展开怎么样。


Question: 学习C语言时的一个小问题

使用未初始化的数据，其结果是未定义的 lz你知道z变量一开始的值么

z没有初值没有计算进去的原因。这样写 #include"stdio.h" main() { int x,y,z; for(x=0;x<=20;x++) for(y=0;y<=50;y++) for(z=0;z<=100;z++) {  if(5*x+2*y+z==100)  printf("5分硬币有%d\t2分硬币有%d\t1分硬币有%d\n",x,y,z); } }

z呢，，，没初始化 也没for 循环~~


Question: 请问怎么用VS2010在里面写代码啊？

8楼正解，新建控制台应用程序

打开的话就找那个后缀名为.dsw 的文件就OK

楼主可以看看vs2010的帮助。

win32或者空的也行，你要做MFC就选MFC

加油吧 骚年

引用 4 楼 u013470052 的回复:[quote=引用 3 楼 u013524589 的回复:] [quote=引用 1 楼 ganpengjin1 的回复:] 新建->项目 右击项目，添加文件。 然后写入代码 大神求告知在选项目的时候选什么？WIN32？常规？[/quote] win32  文件选cpp[/quote]OK,xiela

引用 3 楼 u013524589 的回复:[quote=引用 1 楼 ganpengjin1 的回复:] 新建->项目 右击项目，添加文件。 然后写入代码 大神求告知在选项目的时候选什么？WIN32？常规？[/quote] win32  文件选cpp

引用 1 楼 ganpengjin1 的回复:新建->项目 右击项目，添加文件。 然后写入代码 大神求告知在选项目的时候选什么？WIN32？常规？

无非那几步，new->application->file。

新建->项目 右击项目，添加文件。 然后写入代码


Question: 邻接多重表删除算法的问题

int DeleteVex(AMLGraph *G,VertexType v)   {       int i,j;       VertexType w;       EBox *p;          i=LocateVex(*G,v); // i为待删除顶点的序号        if(i<0)           return 0;       for(j=0;j<(*G).vexnum;j++) // 删除与顶点v相连的边(如果有的话)        {           if(j==i)               continue;           strcpy(w,*GetVex(*G,j)); // w是第j个顶点的值            DeleteArc(G,v,w);       }       for(j=i+1;j<(*G).vexnum;j++) // 排在顶点v后面的顶点的序号减1            (*G).adjmulist[j-1]=(*G).adjmulist[j];       (*G).vexnum--; // 顶点数减1        for(j=i;j<(*G).vexnum;j++) // 修改顶点的序号        {           p=(*G).adjmulist[j].firstedge;           if(p)           {               if(p->ivex==j+1)               {                   p->ivex--;                   p=p->ilink;               }               else               {                   p->jvex--;                   p=p->jlink;               }           }       }              return 1;   }    还有这个删除顶点的算法,其中第一个循环那里,为什么每次循环都要调用删除函数,不是应该是和v相连的才对吗?

while(p) // 向后查找弧<v,w>            {               if(p->ivex==i&&p->jvex!=j) // 不是待删除边                {                   q=p;                   p=p->ilink; // 找下一个邻接顶点                }               else if(p->jvex==i&&p->ivex!=j) // 不是待删除边                {                   q=p;                   p=p->jlink; // 找下一个邻接顶点                }               else // 是邻接顶点w                    break;    上面那个发的不好

while(p) // 向后查找弧<v,w>                if(p->ivex==j&&p->jvex!=i) // 不是待删除边                {                   q=p;                   p=p->ilink; // 找下一个邻接顶点                }               else if(p->jvex==j&&p->ivex!=i) // 不是待删除边                {                   q=p;                   p=p->jlink; // 找下一个邻接顶点                }               else // 是邻接顶点v                    break;    应该是这部分


Question: C99标准里面怎么没有规定C run-time library的内容

等你去加规定了，顺便把图形界面的接口、多线程的接口都加上哈，bless

引用 3 楼 jha334201553 的回复:[quote=引用 2 楼 inurlcn 的回复:] [quote=引用 1 楼 jha334201553 的回复:] 你想让C99把操作系统都定死么？这不是自掘坟墓么  在C99文档里面没找到对于 “C库初始化” 的部分内容[/quote]你能写一段代码，在各个操作系统下都能用的初始化代码？[/quote]  C99 不就是做了些规定接口的工作吗

引用 2 楼 inurlcn 的回复:[quote=引用 1 楼 jha334201553 的回复:] 你想让C99把操作系统都定死么？这不是自掘坟墓么  在C99文档里面没找到对于 “C库初始化” 的部分内容[/quote]你能写一段代码，在各个操作系统下都能用的初始化代码？

引用 1 楼 jha334201553 的回复:你想让C99把操作系统都定死么？这不是自掘坟墓么  在C99文档里面没找到对于 “C库初始化” 的部分内容

你想让C99把操作系统都定死么？这不是自掘坟墓么


Question: 结构体，函数疑惑，我老师和我已跪

引用 11 楼 u013523101 的回复:[quote=引用 6 楼 u013470052 的回复:] 在主函数中定义并调用aveger数组，把ave传进去就ok。 主函数中增加   folat aveger[5] = {0};  调用的时候 这样调用p = ave(aveger); 定义子函数加上参数  float *ave(float * aveger) 把子函数中对aveger的定义去掉 子函数中对sum数组还得清零 float sum[5] = {0}; 这样就ok~ 谢谢你，你的方法确实可以行得通。不过跟你讲的有点出入：我传入void ave（float *aveger）函数的是一个数组地址（主函数中的数组pj【5】）。ave（pj）后，printf（pj【i】）；[/quote] 条条大路通罗马，做出来总是好的。最好指针和数组分别都用下，体会下联系和区别~

引用 6 楼 u013470052 的回复:在主函数中定义并调用aveger数组，把ave传进去就ok。 主函数中增加   folat aveger[5] = {0};  调用的时候 这样调用p = ave(aveger); 定义子函数加上参数  float *ave(float * aveger) 把子函数中对aveger的定义去掉 子函数中对sum数组还得清零 float sum[5] = {0}; 这样就ok~ 谢谢你，你的方法确实可以行得通。不过跟你讲的有点出入：我传入void ave（float *aveger）函数的是一个数组地址（主函数中的数组pj【5】）。ave（pj）后，printf（pj【i】）；

在float *ave（）函数里修改      float *aveger;     aveger=(float*)malloc(20);       .       .       . *aveger=sum[0]/5;  *(aveger+1)=sum[1]/5; *(aveger+2)=sum[2]/5; *(aveger+3)=sum[3]/5; *(aveger+4)=sum[4]/5;

引用 2 楼 bbs2241 的回复:忘了你是C了，malloc吧  谢谢了，虽然你说得有点简洁。 引用 4 楼 starytx 的回复:程序有几个问题如下： 1.sum[5]未初始化，应当这样初始化一下sum[5] = {0,0,0,0,0}; 但这个不是结果不正确的原因 2.你的函数返回的是一个局部数组的地址，这样的做法结果未定义，可以把float aveger[5]改为float指针，动态malloc，然后调用ave()后，保存这个指针(在p = ave();加一句float *pTemp = p;),最后free(pTemp);释放 谢谢，我采用您的方法做好了

引用 6 楼 u013470052 的回复:在主函数中定义并调用aveger数组，把ave传进去就ok。 主函数中增加   folat aveger[5] = {0};  调用的时候 这样调用p = ave(aveger); 定义子函数加上参数  float *ave(float * aveger) 把子函数中对aveger的定义去掉 子函数中对sum数组还得清零 float sum[5] = {0}; 这样就ok~ 正解。

引用 5 楼 derekrose 的回复:你老师？？？？+1

你老师？？？？

嗯！ls正解，或者直接传递一个数组进去，建议楼主定义变量的时候对变量进行初始化

忘了你是C了，malloc吧

float aveger[5],sum[5]; 这个是临时数组，return aver能返回吗？ new一下就可以了。


Question: 运算符++的计算时间问题

i++  先执行  后++的问题 ++i  先++运算  在执行其他  比较两个 结果就能知道了

这个问题也是月经贴了, 参见C99标准6.5.2.2.10说明 The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

这个问题真没必要纠结，你用不同的编译器可能结果都不同，因为所有的参数在传递或计算时有的从左往右的顺序传，有的从右往左。 这个与你所用的编译器有很大关系

这种问题已经有很多的帖子讨论了，没必要再讨论了

跟时间有什么关系

没什么特别之处， printf("%10d%10d\n", i, i++ * i++ ); 这里输出的还是i*i，之后才是两个i++

基础问题。。。。C这边新手太多了。

引用 6 楼 wang0635 的回复:谭浩强的书看多了谭浩强的书很见过，不好意思，一般都看外国人写的书，看到一段代码，自己突发奇想改成这样的而已

引用 10 楼 jiandingzhe 的回复:[quote=引用 9 楼 u013470052 的回复:] 问题很简单，printf输出的时候，对参数列表进行从右往左的编译，而i++都会被认为是先执行当前语句的时候使用i，完了之后再对i进行自加运算。 看置顶贴。[/quote] 我就不写这种代码~，我只是打个酱油

引用 9 楼 u013470052 的回复:问题很简单，printf输出的时候，对参数列表进行从右往左的编译，而i++都会被认为是先执行当前语句的时候使用i，完了之后再对i进行自加运算。 看置顶贴。

C/C++ 语言的规定告诉我们，任何依赖于特定计算顺序、依赖于在顺序点之间实现修改效果的表达式，其结果都没有保证。程序设计中应该贯彻的规则是：如果在任何“完整表达式”（形成一段由顺序点结束的计算）里存在对同一“变量”的多个引用，那么表达式里就不应该出现对这一“变量”的副作用。否则就不能保证得到预期结果。  看看这里吧,c++类的推荐就有呀, http://bbs.csdn.net/topics/370153775

谭浩强的书看多了

标准没规定，各编译器厂家自己说了算。 怎么没看置顶贴就发了啊？是不是置顶贴的标题名字不够响亮？ 能修改下把 ++ -- ++i++ 这些符号放上去吗？

貌似没啥问题啊。都是在printf语句以后计算i+1. 哪错了。

引用 2 楼 nanjun520 的回复:楼主在关注这个问题啊 貌似一般很多人都会叫你不要纠结这个问题的。 printf函数的入参是有顺序的。 至于i++*i++是先执行*再++  这个我也有点模糊 你也一起看置顶贴吧，这个跟先++还是后++一点关系都没有。在C/C++中这个叫未定义行为。


Question: （不知如何修正，求指点）一个用C语言实现将TXT文件数据加载到链表的程序

恩，修改成wb+,后可以读了，debug1和debug2都输出了5次，但是数据没有显示出来，这边temp->item=a;是否存在不妥，修改成temp->item.name=a;时编译错误，应该如何修改？

读链表部分换成以下内容后解决while(1)	 		{ 		temp=(list)malloc(sizeof(node)); 			if(fread(&temp->item, sizeof(temp->item), 1, fp) != 1)break;//重点修改了这边， 			temp->next = L->next; 			L->next = temp; 		} 		free(temp); 	return L;

应该是文件打开方式的问题，wb方式只写不读，改成wb+试试

读写用"wb+"模式；另外，写完先fflush一下再读稳当点...

不好意思，发少一个生成空表list makeempty(list L) { 	L=(list)malloc(sizeof(node)); 	L->next=NULL; 	return L; }  list makeempty(list L) { 	L=(list)malloc(sizeof(node)); 	L->next=NULL; 	return L; }


Question: Win7下如何用代码实现捕获系统休眠事件

http://blog.csdn.net/tody_guo/article/details/21318255 这个解了。不错。


Question: 函数之间二维数组多种表示方法的传递问题

引用 47 楼 xiaopo_poxiao 的回复:[quote=引用 42 楼 mujiok2003 的回复:] [quote=引用 41 楼 xiaopo_poxiao 的回复:] sizeof(szdata[0])是COLS大小没有错，szdata[0]是指针也没有错，有错的是szdata[0]所表示的地址是错的。  你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址.[/quote] 哥们要分的话，开贴给你！[/quote]  不要.

引用 46 楼 u013470052 的回复:[quote=引用 45 楼 xiaopo_poxiao 的回复:] [quote=引用 44 楼 u013470052 的回复:] [quote=引用 43 楼 xiaopo_poxiao 的回复:] 你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址. 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？[/quote] 是的，现在就对了。[/quote] 好的，谢了哥们，还要分吗？要的话，可以开贴给你。[/quote] 不要  没意思[/quote]  我只是意思意思，哈哈。

引用 42 楼 mujiok2003 的回复:[quote=引用 41 楼 xiaopo_poxiao 的回复:] sizeof(szdata[0])是COLS大小没有错，szdata[0]是指针也没有错，有错的是szdata[0]所表示的地址是错的。  你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址.[/quote] 哥们要分的话，开贴给你！

引用 45 楼 xiaopo_poxiao 的回复:[quote=引用 44 楼 u013470052 的回复:] [quote=引用 43 楼 xiaopo_poxiao 的回复:] 你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址. 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？[/quote] 是的，现在就对了。[/quote] 好的，谢了哥们，还要分吗？要的话，可以开贴给你。[/quote] 不要  没意思

引用 44 楼 u013470052 的回复:[quote=引用 43 楼 xiaopo_poxiao 的回复:] 你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址. 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？[/quote] 是的，现在就对了。[/quote] 好的，谢了哥们，还要分吗？要的话，可以开贴给你。

引用 43 楼 xiaopo_poxiao 的回复:你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址. 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？[/quote] 是的，现在就对了。

szdata[ROWS][COLS] 传递给char *szdata[]是数组指针传递给指针数组 char *szdata[ROWS]传递给char *szdata[]就正常是因为都是指针数组   char szdata[ROWS][COLS]中，szdata也是一个数组指针，char *szdata[ROWS]中，szdata也是一个指针吧（不管说这个指针是不是数组指针）   二维数组 函数之间 传递实际是传递指针，那么这传过去应该没问题吧（当时这2个程序编译也都没问题，只是运行的时候有问题。）   也就是说在void print_alldata(char *szdata[], int rows) { for(int i = 0; i < rows; ++i) puts(szdata[i]); }这个函数内部执行的时候，运行有问题了，运行出现了崩溃。     而我如果不对szdata[i]操作的话，运行毫无问题（这是废话），操作了就会出现一个不正常，一个正常的问题。   那么，在char szdata[ROWS][COLS]中，每次执行，szdata[i]，也就是*(szdata+1)，szdata实际上每次会移动COLS个字符大小吧   那么，在char *szdata[ROWS]中，每次执行，szdata[i]，也就是*(szdata+1)，szdata实际上每次会移动的大小是不固定的，取决于szdata指向行的字符串长度,比如第一次移动的大小应该就是sizeof("this is the first line!")，这样才能指向第二行。   那么，实际上，我们从本质上面来看，这两个传递过来的指针（你刚刚也说了，我们传递的是指针，而不管这两个指针到底是不是数组指针，反正是指针。），都是没问题的吧？那为啥char szdata[ROWS][COLS]就有问题？而char *szdata[ROWS]没问题呢？我就想知道，这个地方，这是我想知道的，其他关于数组指针和指针数组的区别我知道的。   我是想从传递的实质上来看，但是从语法角度来看，你说的确实没问题，数组指针传递给了指针数组，这不合语法啊，一个指针（数组指针）怎么能传给数组（指针数组）呢，只有指针数组才能传递给指针数组，但是实际传递的不都是指针吗？他真能传递一个数组（指针数组）给数组（指针数组）吗？

引用 42 楼 mujiok2003 的回复:[quote=引用 41 楼 xiaopo_poxiao 的回复:] sizeof(szdata[0])是COLS大小没有错，szdata[0]是指针也没有错，有错的是szdata[0]所表示的地址是错的。  你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址.[/quote] 我想我应该明白你的意思了，就是szdata[0]其实表示的和szdata[0][0]这个数组元素一样，当把它传给puts的时候，puts依次往下找，找了4个元素，szdata[0][0] szdata[0][1] szdata[0][2] szdata[0][3]，它把这个（加一起正好是4字节）当成了地址。是这样吗？

引用 41 楼 xiaopo_poxiao 的回复:sizeof(szdata[0])是COLS大小没有错，szdata[0]是指针也没有错，有错的是szdata[0]所表示的地址是错的。  你也许还没有明白.szdata[0]不是指针,是数组,不过在可以隐式转换为地址.

应该是这样，此贴终结。给分！

引用 35 楼 u013470052 的回复:[quote=引用 34 楼 xiaopo_poxiao 的回复:] 哈哈，NB，你是转到**，又转回来(char *)[COLS]，哈哈。 还有，麻烦你看下mujiok2003用户说的对不对，从10L开始，谢了哥们。  szdata的类型应该是 char(*)[100]；因为数组名本身代表了首地址，至于char[2][100]这类型，是不存在的。&szdata的类型是char(*)[2][100]；至于char **p = szdata，这个直接赋值在gcc下也会有警告的，在vc之类的直接通不过。后面的野指针应该是没有问题的，我一开始也是这样想的，应该是这样，不然不会报段错误，我刚才还试了下只输出szdata[0]也是段错误，所以只有这种说法成立了。[/quote]我明白了，谢谢哥们，你看看我这么理解对不对？ char *szdata[ROWS]开辟了新的空间来正确的存储了两个字符串的地址，而char szdata[ROWS][COLS]把错误的地址赋值给了二级指针（就是野指针了），如果限制了维数（列）的大小，就能正常传递了。。。

引用 36 楼 u013470052 的回复:其实上面说的不是针对本题说的，就是就题论题说的。 又说错了，是就这个复制问题而言

擦，我讲得很清楚啦 一般的一维数组 char ct[10] = "test"; 内存里 t e s t 0 ... 所以弄个指针char *p = ct; 那么 *p == 't'; *(p+1) = 'e'; 所以一维数组和一维指针没啥两样 但对于二维数组 char ct[2][6] = {"test", "other"}; 内存里 t e s t \0 \0 o t h e r \0  int main() {     char test[2][10] = {"test", "other"};     typedef char Array[10];     Array *p = test;     std::cout << *p << std::endl; }  看上面这个例子，test对应得是Array的指针，而不是char *的指针，这就是你代码1的错误。 其实换种说法估计LZ可能会更好理解，数组作为参数传给函数，只能退化一级，也就是一维数组变成一维指针，二维数组变成指向一维数组的指针，但不能变成两维指针。因为数组变指针，只是丢失了数组长度的信息，但数组内容还是可以通过指针和整数的加法运算获得。而对两维数组，如果你变成了二维指针，那么数组内容就没办法通过指针和整数的加法获得了，因为对于 Array *p1 和 char **p2 p1 + 1 和p2 + 1根本不是一个东西 p1 + 1的地址应该是p1的地址加上sizeof(Array)，而p2的地址，是p2 + sizeof(char *)，显然是不同滴，而前者才是正确滴

引用 24 楼 xiaopo_poxiao 的回复:[quote=引用 23 楼 u013470052 的回复:] 嗯嗯,我看了下. 你把二维数组也就是 存有两个字符串的地址赋值给了 指针数组了，而指针数组中存放的都是指针，这道题目中指针数组szdata使用了两个指针，也就是元素0和1,他们分别指向自己的区域，相当于两个独立的指针，0肯定不会出错，因为szdata[0]是指向了二维数组的首地址了，而szdata[1]是指向了哪里呢？指向了一个未知区域。属于未定义的行为。你要使用szdata[1]来输出，也就是读取你没有权限的内存肯定会段错误。其实这个行为本来就是不可取的，因为不兼容的类型间赋值本身就容易出问题。 你我看不明白你说的，你说的是代码几？2？2没问题，有问题的是1，我发现10L说的有道理了。。。。[/quote] 其实上面说的不是针对本题说的，就是就题论题说的。

引用 34 楼 xiaopo_poxiao 的回复:哈哈，NB，你是转到**，又转回来(char *)[COLS]，哈哈。 还有，麻烦你看下mujiok2003用户说的对不对，从10L开始，谢了哥们。  szdata的类型应该是 char(*)[100]；因为数组名本身代表了首地址，至于char[2][100]这类型，是不存在的。&szdata的类型是char(*)[2][100]；至于char **p = szdata，这个直接赋值在gcc下也会有警告的，在vc之类的直接通不过。后面的野指针应该是没有问题的，我一开始也是这样想的，应该是这样，不然不会报段错误，我刚才还试了下只输出szdata[0]也是段错误，所以只有这种说法成立了。

引用 33 楼 u013470052 的回复:#include <stdio.h> #define ROWS 2 #define COLS 100 void print_alldata(char *szdata[], int rows); int main(void ) {     char szdata[ROWS][COLS]={         "this is the first line!",         "this is the second line!"       };     print_alldata((char **)szdata, ROWS);      return 0; }  void print_alldata(char *szdata[], int rows) {      for(int i = 0; i < rows; ++i)         puts(((char (*)[COLS])szdata)[i]); } 运行正常。 哈哈，NB，你是转到**，又转回来(char *)[COLS]，哈哈。 还有，麻烦你看下mujiok2003用户说的对不对，从10L开始，谢了哥们。

引用 30 楼 u013470052 的回复:我快疯了，哥们你continue。。。

引用 28 楼 user-3 的回复: using namespace std;  int main() {     char test[2][10] = {"test", "other"};     cout << sizeof(test) << endl; //20     cout << sizeof(test[0]) << endl; //10     cout << sizeof(test[1]) << endl; //10 }  所谓二维数组，其实本质上还是1维数组。只不过是多个一维数组拼起来  using namespace std;  int main() {     char test[2][10] = {"test", "other"};     char **pp = (char **)test;     cout << (void *)test << endl;     cout << (void *)pp << endl;     cout << (void *)(*pp) << endl; }  输出 0x7fff66a37cd0 0x7fff66a37cd0 0x74736574 可以看到这里*pp已经是个很奇怪的指针了，对它的任何操作都很引起段错误~  int main() {     char test[2][10] = {"test", "other"};     char *p0 = test[0];     //char *p0 = (char *)test; //这个也可以     char *p1 = test[1];     cout << p0 << endl;     cout << p1 << endl; }  输出 test other  事实上test是指向一个长度为10的char数组的指针，而一般的char **pp是指向一个sizeof(char *)==4的指针，显然两者根本是不同的，至少test + 1一定不等于pp + 1 而char *p[10]是一个储存char指针的数组，和上面说的东西根本不是一回事。所以LZ的代码1显然是有问题的。至于代码2，LZ之间将szdata的类型给改了，使之和那个参数匹配，自然就没问题了，但szdata已经和char[][]没关系了~ 代码3是标准写法，代码4是将二维数组看出一维数组，事实上它本质就是个一维数组，所以也木有问题 朋友，麻烦你看下mujiok2003用户说的对不对，从10L开始，不是很明白你的意思。


Question: 多程序写一个文件/文件的并行写入如何处理？

文件可以加锁(Windows,unix,linux?)， 文件可以共享读，写方式打开，共享的文件，可以锁住某一部分(文件锁)。  如果你使用DOS早期版本，另说。。。 不过早期版本的DOS， 只能同时运行一个程序，多个程序同时运行很困难。

_locking Locks or unlocks bytes of a file.  int _locking( int handle, int mode, long nbytes );  Routine Required Header Optional Headers Compatibility  _locking <io.h> and <sys/locking.h> <errno.h> Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  _locking returns 0 if successful. A return value of –1 indicates failure, in which case errno is set to one of the following values:  EACCES  Locking violation (file already locked or unlocked).  EBADF  Invalid file handle.  EDEADLOCK  Locking violation. Returned when the _LK_LOCK or _LK_RLCK flag is specified and the file cannot be locked after 10 attempts.  EINVAL  An invalid argument was given to _locking.  Parameters  handle  File handle  mode  Locking action to perform  nbytes  Number of bytes to lock  Remarks  The _locking function locks or unlocks nbytes bytes of the file specified by handle. Locking bytes in a file prevents access to those bytes by other processes. All locking or unlocking begins at the current position of the file pointer and proceeds for the next nbytes bytes. It is possible to lock bytes past end of file.  mode must be one of the following manifest constants, which are defined in LOCKING.H:  _LK_LOCK  Locks the specified bytes. If the bytes cannot be locked, the program immediately tries again after 1 second. If, after 10 attempts, the bytes cannot be locked, the constant returns an error.  _LK_NBLCK  Locks the specified bytes. If the bytes cannot be locked, the constant returns an error.  _LK_NBRLCK  Same as _LK_NBLCK.  _LK_RLCK  Same as _LK_LOCK.  _LK_UNLCK  Unlocks the specified bytes, which must have been previously locked.  Multiple regions of a file that do not overlap can be locked. A region being unlocked must have been previously locked. _locking does not merge adjacent regions; if two locked regions are adjacent, each region must be unlocked separately. Regions should be locked only briefly and should be unlocked before closing a file or exiting the program.  Example  /* LOCKING.C: This program opens a file with sharing. It locks  * some bytes before reading them, then unlocks them. Note that the  * program works correctly only if the file exists.  */  #include <io.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/locking.h> #include <share.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h>  void main( void ) {    int  fh, numread;    char buffer[40];     /* Quit if can't open file or system doesn't      * support sharing.      */    fh = _sopen( "locking.c", _O_RDWR, _SH_DENYNO,                   _S_IREAD | _S_IWRITE );    if( fh == -1 )       exit( 1 );     /* Lock some bytes and read them. Then unlock. */    if( _locking( fh, LK_NBLCK, 30L ) != -1 )    {       printf( "No one can change these bytes while I'm reading them\n" );       numread = _read( fh, buffer, 30 );       printf( "%d bytes read: %.30s\n", numread, buffer );       lseek( fh, 0L, SEEK_SET );      _locking( fh, LK_UNLCK, 30L );       printf( "Now I'm done. Do what you will with them\n" );    }    else       perror( "Locking failed\n" );     _close( fh ); }   Output  No one can change these bytes while I'm reading them 30 bytes read: /* LOCKING.C: This program ope Now I'm done. Do what you will with them   File Handling Routines  See Also   _creat, _open

改为多程序通过多个数据库连接写数据库表。

学习下 ……

这些并行的程序如果是代码可控的话,可以把文件操作封装成一个动态库,通过内核级全局锁操作文件,可以保证数据无误,这样一来,就把并行变成同步了

引用 3 楼 u011704121 的回复:其实可以把所有要写的东西排队，只有一个程序可以写，别的程序想写，就发送给他就行  可否再描述详细一点？我一会在做一般的C编程，排队、发送什么的概念有点陌生

引用 4 楼 mujiok2003 的回复:[quote=引用 2 楼 gong_xufei 的回复:] [quote=引用 1 楼 mujiok2003 的回复:] 1. 打开文件的时候可以指明是否是独占 2. 在共享模式下,由操作系统保证同步.  多谢解答。 但实现上还是不很明白，别处也没搜索到： （1）如何指明是否独占？ （2）共享模式是否需要在程序中进行实现？如何实现？ 这两个问题貌似是一个。。。 PS：我做的是linux上的C编程 谢谢！[/quote]  http://linux.die.net/man/2/open[/quote]  貌似很强大的样子，先研究一下。

引用 2 楼 gong_xufei 的回复:[quote=引用 1 楼 mujiok2003 的回复:] 1. 打开文件的时候可以指明是否是独占 2. 在共享模式下,由操作系统保证同步.  多谢解答。 但实现上还是不很明白，别处也没搜索到： （1）如何指明是否独占？ （2）共享模式是否需要在程序中进行实现？如何实现？ 这两个问题貌似是一个。。。 PS：我做的是linux上的C编程 谢谢！[/quote]  http://linux.die.net/man/2/open

其实可以把所有要写的东西排队，只有一个程序可以写，别的程序想写，就发送给他就行

引用 1 楼 mujiok2003 的回复:1. 打开文件的时候可以指明是否是独占 2. 在共享模式下,由操作系统保证同步.  多谢解答。 但实现上还是不很明白，别处也没搜索到： （1）如何指明是否独占？ （2）共享模式是否需要在程序中进行实现？如何实现？ 这两个问题貌似是一个。。。 PS：我做的是linux上的C编程 谢谢！


Question: 偶遇 c语言 小问题 望高手解答

结贴遇到   “给分与总分不符，请重新分配！”  这个怎么弄？

负数的符号位是1，右移时，进行符号扩展， 所以右移一位的时候，负数永远移入1 （保证移位后还是负数），a所以永远不为0。 于是就无穷递归了，于是栈就爆了。 PS： 关于移位运算中的右移，这些基础知识，是必须记牢的：  1）无符号数右移，0扩展。    即移入0 2）有符号数右移，符号扩展。 即移入符号位的值。 3）正数符号位为0，负数符号位为1。

负数右移我记得C是算术右移吧，前面会补1的，所以结果是（1111 1111）2 = （-1）10 正数用的是逻辑右移，前面补0，所以最后会变成0000 0000 也就是 0 你的判断条件应该改成这种： if(a==0||a==-1)

递归过深栈爆了是很正常的，如果你想用递归的话，建议改成尾递归开编译器优化就可以了。

给char类型赋值负数  然后进行位移操作  到底发生了什么

3楼的 你说的很有道理阿  可是听你的改了if(a==-128) 连正数都是断错误了 当然负数也是段错误

void banary(char a)  {  if(a==0) return 0;////我想问题出在这里，负数不能满足判断条件，递归没有退出条件，发生了段错误。可是不明白为什么？ banary(a>>1);  printf("%d ",a&1);  } //非宽字符、非unicode以及非C++11的char16_t和char32_t情形，signed char负数范围-128~-1，1Byte字节，8bit位。 //最高位符号，负数置位1，其余7位整数有效数字，那么就是1 111 1111b~1 000 0001b。 //a>>1，右移1位运算，由于负数最高位符号“-”用“1”表示，那么最终陷入-128不断右移总是等于-128的死循环中，递归不停直到资源耗尽崩溃。只要是负数，a右移位，if(a==0)修改为if(a==-128)。

其实我只是想知道  应该如何改 if（）里面的语句  或者 为什么if（a==0)不能退出递归，至少 a>>1  8次后 应该a==0能够成立啊  ！

持续递归的话，栈总是会爆掉的。  引用 楼主 A3872215 的回复:用递归写的一个打印char类型8个bit位的数值， 输入整数 结果正常，输入负数 就是段错误！！！（注释掉的代码可以正常使用）。 #include <stdio.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h>  //void banary(char,int); void banary(char); int main() { 		char a=-128; 		int i=0; 		char buf[10]={}; 		int n=0; 		while(1){ 		scanf("%d",&n); 		getchar();                 a=n; 		banary(a); 		puts(""); 		} } /*void banary(char a,int n) { 		int i=0; 		if(8==n) return; 		banary(a>>1,++n); 		printf("%d ",a&1); }*/ void banary(char a) { 		if(a==0) return 0;////我想问题出在这里，负数不能满足判断条件，递归没有退出条件，发生了段错误。可是不明白为什么？ 		banary(a>>1); 		printf("%d ",a&1); }


Question: C语言中double输出值被改变了,为什么呢?

再说一句,C语言标准,输出函数的 %lf 格式,居然是不在标准中 这个很麻烦 不同编译系统的实现对于输出 float ,double 类型数据,可能就不一致了 有些支持%lf格式的 double 可以用%lf精确输出,用%f 就精度不够了. 不支持的虽然%f格式可以同时输出float,double 但是两种系统不一致,代码就不兼容了. 这是故意的么???????????

结贴就可以给分了

引用 3 楼 lm_whales 的回复:这个很好解释，尾部和前部拼接到一起，结果自然不乐观了  实际参数类型：         char *      , double     ,double 参数传递时的长度       ：[ 4B    ] ,[8B       ] ,[8 B ] 格式串和对应的格式     ：格式串    ,  %d  , %f  输出时看作的长度       ：[ 4 B   ] ，[ 4B]，[8B   ],[4B] 最后4B是多余的，无用参数字节。 输出时直接看作的类型：const char * ,int   ,double    输出时最终看作的类型：const  char *，int  ,float    第2，3 两个个参数，被劈为两半  第2参数，前一半，对应 %d 格式 4B，后一半对应%f格式 8B  差了4B，第三个参数的前4B补上。最后4B，用不上，不管他。  PS： 输出时，不论实参是double 还是 float , %f对应 float 数据，所以要转换成 float 输出，会造成精度丢失。 所以double 不应该使用 %f 输出。  同理，%lf 对应double， float类型，没有必要用 %lf输出。 因为，float 表示精度太低； 不需要用%lf，这种高精度方式输出。谢谢.我知道你说的了.第一次用这CSDN的提问,不知道怎么给你分啊.

引用 1 楼 turingo 的回复:doule类型用%lf，否则结果难料。  [quote=引用 楼主 u013487029 的回复:] 小程序如下: #include <stdio.h>  main() { 	double dValue = 2.0; 	printf("%d\t%f",dValue, dValue); } 结果答案凶残的输出:0   0.000000 为什么呢?[/quote]  ++

printf 函数的输出方式，是依照格式数字节，来进行参数匹配的。 实参传递则是，按照数据类型，参数传递占用的字节数，传递数据(由C调用约定决定)。 Win32:    bool,char,int,long ,void * (32Bits 4Bytes) long long (64Bits--8Bytes) float,double(64Bits--8Bytes) PS:     实参传递的字节数，和数据类型的字节数并不相同。 参数传递的时候，会隐性的进行类型转换（类型提升）。

刚测试了一下 确实很凶残 http://www.cnblogs.com/yangyh/archive/2011/10/03/2198631.html "%d"打印出0是很好解释的。但是写在一起的时候%f输出也为0我还没弄明白， 不过你如果改成 printf("%f\t%d\n",dValue, dValue);居然%f会输出正确。这个我只是在windosxp 的vs2008下测试的，不清楚与编译器是否有关

doule类型用%lf，否则结果难料。  引用 楼主 u013487029 的回复:小程序如下: #include <stdio.h>  main() { 	double dValue = 2.0; 	printf("%d\t%f",dValue, dValue); } 结果答案凶残的输出:0   0.000000 为什么呢?


Question: HDU 1007代码老是出错 求大神解答 已经对x 和y分别排序了

看错了，上面代码是poj的

C++代码可以参考下 #include <iostream> #include <algorithm> using namespace std;  struct f{     int num;     char w[50]; }s[101];  bool cmp(struct f a, struct f b) {     return a.num < b.num; }  int main() {     int i, len, n, j, k;     cin>>len>>n;     for(i = 0; i < n; i++) 	{         s[i].num = 0;         cin>>s[i].w;         for(j = 1; j < len; j++)             for(k = 0; k < j; k++)                 if(s[i].w[j] < s[i].w[k])                     s[i].num++;     }      sort(s, s+n, cmp);     for(i = 0; i < n; i++)         cout<<s[i].w<<endl;     return 0; }


Question: linux下编译代码后同时启动

放makefile里不行吗？编译完成后直接运行程序。

shell脚本。。

那你的1.o和2.o还不是可执行程序，先连接，然后到控制台  $ ./1 & $ ./2 &  这里假定你连接后生成的可执行程序分别对应叫1和2，而且两个都不从stdin读入。如果其中一个要读stdin, 你可以后执行它，去掉后面的&, 如果两个都要读stdin, 你就开两个控制台，把&都取消掉。  如果程序的生命期极端，你想让它们活着的时候能彼此相遇，可以放到一个bash script中。这样要求只有一个会读stdin, 另一个就像一个服务一样。  当然，也可能我完全没弄懂你的意思。

引用 1 楼 ALNG 的回复:你说的是把1.o和2.o一起连接出一个可执行文件吧？如果是，那么  g++ -omyprogram 1.o 2.o  其中myprogram是你想要的可执行程序的名字。你也可以跳过生成*.o的过程，直接  g++ -omypgrogram 1.cpp 2.cpp 不是，同时启动两个程序

g++ -c 1.o 1.cpp g++ -c 2.o 2.cpp g++ -oall 1.o 2.o

./prog1 & ./prog2    ？？？

首先.o文件是目标文件，并不是可执行文件！其次，写一个makefile文件，完成编译；最后，若要编译之后立即启动，可以考虑使用脚本，在linux下写个shell脚本就可以完成；该脚本同时兼顾执行makefile文件！

引用 3 楼 boyhailong 的回复:[quote=引用 1 楼 ALNG 的回复:]  你说的是把1.o和2.o一起连接出一个可执行文件吧？如果是，那么  g++ -omyprogram 1.o 2.o  其中myprogram是你想要的可执行程序的名字。你也可以跳过生成*.o的过程，直接  g++ -omypgrogram 1.cpp 2.cpp 不是，同时启动两个程序[/quote] 首先，你不可能“同时启动两个程序”，在哪个操作系统都一样。它们的进程空间是分离的。 然后，1.o和2.o肯定不是程序。


Question: HDU 1007题目求救 老是Runtime Error (STACK_OVERFLOW)

引用 1 楼 user-2 的回复:while (*head  <  middle)             head++;       tail--;        while (*tail  >  middle)             tail--;  你确定这里不会越界？ 不会的  快排没有问题哦  是最近点的问题

引用 2 楼 logiciel 的回复:为避免程序崩溃,建议不要把全局变量xy传递到函数div_meg中,改为直接操作xy:  double div_meg(int i,int j){ //double div_meg(cor xy,int i,int j){   int mid=(int)(i+j)/2;   double m,mm,b;   if(i>=j){     return -1;   }   m=div_meg(i,mid);//m=div_meg(xy,i,mid);   mm=div_meg(mid+1,j);//mm=div_meg(xy,mid+1,j);  另外,LZ程序没有对y座标排序.以下是一个反例: 3 1 5 1 1 1 7 谢谢了 没有崩溃了 但是为什么就超时了呀。。。无语了

引用 楼主 guo1105094218 的回复:附代码：求大神赐教 貌似递归写的不好 估计20的规模就会崩 无语了 #include<stdio.h> #include<math.h> #define SIZE 100100  typedef struct cor_x_y{     double cor_x[SIZE];     double cor_y[SIZE]; }cor;  cor xy; int q,w;  void swap(double *a,double *b){     double s;     q=a-xy.cor_x;     w=b-xy.cor_x;     s=xy.cor_x[q];     xy.cor_x[q]=xy.cor_x[w];     xy.cor_x[w]=s;     s=xy.cor_y[q];     xy.cor_y[q]=xy.cor_y[w];     xy.cor_y[w]=s; }  double *split (double *head , double *tail) {    double middle = *(head + (tail  -  head) / 2);    while (1)    {        while (*head  <  middle)             head++;       tail--;        while (*tail  >  middle)             tail--;        if (head >= tail)             return head;        swap (head , tail);       head++;    } } //快速排序 , 递归调用 void QuickSort(double * first , double *last) {      if (last  >  first+1)     {          double *t=split(first, last);          if (last -t < t - first)          {               QuickSort(t, last);               QuickSort(first , t);          }          else          {               QuickSort(first , t);               QuickSort(t, last);          }     } }  double div_meg(cor xy,int i,int j){     int mid=(int)(i+j)/2;     double m,mm,b;     if(i>=j){         return -1;     }     m=div_meg(xy,i,mid);     mm=div_meg(xy,mid+1,j);     b=(xy.cor_x[mid]-xy.cor_x[mid+1])*(xy.cor_x[mid]-xy.cor_x[mid+1])+(xy.cor_y[mid]-xy.cor_y[mid+1])*(xy.cor_y[mid]-xy.cor_y[mid+1]);     if(m<0&&mm>=0){         if(mm>b)             return b;         else             return mm;     }     if(m>=0&&mm<0){         if(m>b)             return b;         else             return m;     }      if(m<0&&mm<0){             return b;     }     if(m>=0&&mm>=0){         if(mm>b){             if(b>m){                 return m;             }else{                 return b;             }         }else{              if(m>mm){                 return mm;             }else{                 return m;             }         }     } } int  main(){     int n,i;     scanf("%d",&n);     while(n){         for(i=0;i<n;i++){             scanf("%lf",&xy.cor_x[i]);             scanf("%lf",&xy.cor_y[i]);         }         QuickSort(xy.cor_x,xy.cor_x+n);         printf("%.2lf\n",sqrt(div_meg(xy,0,n-1))/2);         scanf("%d",&n);     }     return 0; } 不是 快排的问题 是随后的找最近点的问题


Question: select内存拷贝问题

几乎所有的系统调用都会发生内核态和用户态的数据交换。干嘛要关心这个？ 简单地说，你自己代码中定义的变量，申请的内存，都在用户态内存中保存。调用系统调用时，一定需要把你的内存数据传递给内核，或者把内核从i/o得到的数据传递给你的程序。

select poll  二者都要kernel把状态返回给用户空间，由用户空间进行下一步调用，二者需要轮询 epoll则是类似于向内核注册回调的方式，不需要轮询


Question: 关于 图的十字链表 的问题

我觉得你说的很有道理，head->tail这样一条有向的边，对head而言是出边，对tail而言才是入边。得到(tail,head)这样一条边后，应该是向tail顶点添加入边，head顶点添加出边。你可以直接向博客作者留言查询。


Question: LMS 自适应滤波的问题

fread(numb1,sizeof(short),n,fp1); 这个没问题，读n字符每个字符大小（sizeof(shout)）放入numb1中


Question: 关于一个函数指针数组（error: array type has incomplete element type）

引用 3 楼 JieWinli 的回复: typedef double (*FUN)(double);  void transform(double , double , int, FUN func); double twice(double); double half(double);  int main(void)  {     int i,j;      double source[NUM] = {0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0}; 20     	double target[NUM];     FUN abc[VAR] = {sqrt, sin, twice, half};       for(i = 0; i < VAR; i++) 	{          for(j = 0; j < NUM; j++)         {              transform(source[j], target[j],  NUM, abc[i]);         }      }     return 0;  }  void transform(double source, double target, int n, FUN func)  {     for(int i = 0; i < n; i++)         target = func(source); } double twice(double x) {     return 2.0 * x; } double half(double x) {     return x/2.0; }  谢谢，你指出的跟楼上两位一样都很准确，就是typedef那里的问题了！

引用 2 楼 KenZhang1031 的回复:typedef double (*FUN)(double);  for(int i = 0; i < VAR; i++) 	{ 		if(funcs[i] != NULL) 		{ 			for(int j = 0; j < NUM; j++) 			{ 				transform(source[j], target[j], NUM, funcs[i]); 			} 		} 	} 谢谢，你指出的问题很准确，果然就是typedef那里的问题！

引用 1 楼 user-3 的回复:不知道是不是这个效果 /* ex11, ch 14 */  #include <stdio.h> #include <math.h>   #define NUM		10 #define VAR		 4  typedef double (*FUN)(double);   void transform(double* , double* , int, double (*)(double)); double twice(double); double half(double);  int main(void) { 	double source[NUM] = {0.1, 1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0}; 	double target[NUM]; 	FUN funcs[VAR] = {sqrt, sin, twice, half};          int i; 	for( i = 0; i < VAR; i++)        	    transform(source, target, NUM, funcs[i]);     return 0; }  void transform(double* source, double* target, int n, double (*func)(double)) {     int i;     for( i = 0; i < n; i++)         target[i] = func(source[i]); }  double twice(double x) {     return 2.0 * x; } double half(double x) {     return x/2.0; }  是的，应该就是typedef那里出了问题，应该先定义指针类型为函数指针而非直接定义成函数指针数组。谢谢！

不知道是不是你想要的结果


Question: 一个奇怪的现象。调试（无端点）状态下通过，结果正确；正式运行程序自动终止

引用 6 楼 derekrose 的回复:[quote=引用 4 楼 darksworld 的回复:] [quote=引用 3 楼 derekrose 的回复:] [quote=引用 2 楼 darksworld 的回复:] [quote=引用 1 楼 derekrose 的回复:] 这 有可能是debug的时候把什么东西broken了 可以用注释来排出问题所在地方 大概不是软件的问题吧，因为我在不同的电脑上都试过，其他程序都行，就这个。。[/quote]  什么编译器 你试过的都是什么编译器[/quote] VC6.0 编程只用这一种。。。[/quote] 看你楼下 帮你找出错误了[/quote] 是的。。眼盲了。。。。已成功解决

引用 5 楼 user-2 的回复:错误很多      int *Mean = (int*)malloc(sizeof(int)*BandNum);     memset(Mean,0,sizeof(Mean));     Mean = GetMeanNum(band,pixelNum,BandNum); 内存泄露，下面Dij处同理     Dij = (double*)malloc(sizeof(double)*BandNum);             Dij[m*3+n] = tmp / pixelNum; m*3+n超出了Dij指向的可用内存的大小 谢谢。。我太粗心了。。。  Dij = (double*)malloc(sizeof(double)*BandNum); 少乘了一个BandNum..... Mean均值向量没有问题吧。。。 改完运行ok~

引用 4 楼 darksworld 的回复:[quote=引用 3 楼 derekrose 的回复:] [quote=引用 2 楼 darksworld 的回复:] [quote=引用 1 楼 derekrose 的回复:] 这 有可能是debug的时候把什么东西broken了 可以用注释来排出问题所在地方 大概不是软件的问题吧，因为我在不同的电脑上都试过，其他程序都行，就这个。。[/quote]  什么编译器 你试过的都是什么编译器[/quote] VC6.0 编程只用这一种。。。[/quote] 看你楼下 帮你找出错误了

引用 3 楼 derekrose 的回复:[quote=引用 2 楼 darksworld 的回复:] [quote=引用 1 楼 derekrose 的回复:] 这 有可能是debug的时候把什么东西broken了 可以用注释来排出问题所在地方 大概不是软件的问题吧，因为我在不同的电脑上都试过，其他程序都行，就这个。。[/quote]  什么编译器 你试过的都是什么编译器[/quote] VC6.0 编程只用这一种。。。

引用 2 楼 darksworld 的回复:[quote=引用 1 楼 derekrose 的回复:] 这 有可能是debug的时候把什么东西broken了 可以用注释来排出问题所在地方 大概不是软件的问题吧，因为我在不同的电脑上都试过，其他程序都行，就这个。。[/quote]  什么编译器 你试过的都是什么编译器

引用 1 楼 derekrose 的回复:这 有可能是debug的时候把什么东西broken了 可以用注释来排出问题所在地方 大概不是软件的问题吧，因为我在不同的电脑上都试过，其他程序都行，就这个。。


#include<stdio.h> int main() {  char c[100];  char* p, *pm, *head;  int sh;    p = c;  pm = c;  head = c;    while(gets(c))  {   pm =c;   if(*p <= 'Z')   {    sh = 1;   }   else   {    sh = 0;   }      while(*p != '\0')   {    if(((*p+32) > *pm) && sh == 0)    {     if('A' <= *p && *p <= 'Z')     {      pm = p;      sh = 1;     }    }    if((*p > *pm) && sh == 1)    {     if('A' <= *p && *p <= 'Z')      {      pm = p;      sh = 1;     }    }    if(*p > *pm && sh == 0)    {     if(*p >= 'a')     {      pm = p;      sh = 0;     }    }    if(((*p-32) > *pm) && sh == 1)    {     if(*p >= 'a')     {      pm = p;      sh = 0;     }        }    p++;   }      p = c;      while(*p != '\0')   {    printf("%c", *p);    if(*p == *pm || ((*p+32) == *pm) || ((*p-32) == *pm))    {     printf("(max)");    }    p++;       }   printf("\n");   p = c;  }    return 0; }   提交总是wrong answer

按答案的意思应该是ASCLL的顺序。。。

引用 1 楼 ALNG 的回复:嗯，有点不严谨。最大没有定义ASCII, 字典方式？ 你可以都试试，从你认为最可能的开始。是的是的，就是这个意思

引用 3 楼 ALNG 的回复:z>Z z<Z z==Z 都试过了吗？是的啊，应该是z〉Z的，但是说最大字母不该不分大小写么

acm.hdu.edu.cn 杭州电子科技大学acm的online juge 其实不止一个题目，杭电的OJ题量比较多，难度分布不是很均匀，很多是入门级别水题。 很久没去了，也许有改进。

杭电oj2025  是神马？  google都没有呢

z>Z z<Z z==Z 都试过了吗？

都试过，把大写字母考虑进去答案是错的。所以这题目应该改成只含小写字母。


Question: vs2012生成的exe文件执行失败以及打包lib的问题

用depends.exe查看exe文件依赖的dll，再将这些dll拷贝到exe相同目录下（系统dll除外）


Question: openg超级宝典第五版，第七章的点精灵实例黑屏

不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？

书本源代码没有开启点精灵那句话。坑爹的书

没光照？ 相机没对准要观察的目标？ 三角形顶点次序反了？ 材质完全透明或和背景颜色一样？ 显示器亮度太暗？ 显示器电源没开？ 墨镜没摘？ ……

找到问题了。解决了，

我不知道


Question: [C]文件读写

xcode是MAC和IOS下用的吧？用得不是object-c吗？我不熟这个。你要找个专门讨论这个的地方问， 引用 11 楼 u013190286 的回复:那我运行这段程序的时候，它并没有生成新的文件，我也不太明白是怎么回事。我用的是xcode [quote=引用 10 楼 KenZhang1031 的回复:] 我没刻意放哪，文件原来没有的，fopen("table.txt","w")会生成新文件。 [quote=引用 9 楼 u013190286 的回复:] 最后再问下，你的text文件是跟.c文件放在一起的，是这样吧？谢谢了 [quote=引用 8 楼 KenZhang1031 的回复:] 可能你在fprintf之后看的，文件可能还在缓冲区里，没更新到文件里，你在fclose之后再看。 [quote=引用 6 楼 u013190286 的回复:] [quote=引用 3 楼 KenZhang1031 的回复:] 你怎么知道文件没打开？应该这么写吧？  if（(fic=fopen("table.txt","w")) != NULL) {     printf("file opened\n");  // 文件打开 } else {     printf("file open error\n");  // 文件打开错误 }   先谢谢各位，改完之后试了下，并没有把test的值写入到文件里，麻烦各位再指点下[/quote][/quote][/quote][/quote][/quote]

那我运行这段程序的时候，它并没有生成新的文件，我也不太明白是怎么回事。我用的是xcode 引用 10 楼 KenZhang1031 的回复:我没刻意放哪，文件原来没有的，fopen("table.txt","w")会生成新文件。 [quote=引用 9 楼 u013190286 的回复:] 最后再问下，你的text文件是跟.c文件放在一起的，是这样吧？谢谢了 [quote=引用 8 楼 KenZhang1031 的回复:] 可能你在fprintf之后看的，文件可能还在缓冲区里，没更新到文件里，你在fclose之后再看。 [quote=引用 6 楼 u013190286 的回复:] [quote=引用 3 楼 KenZhang1031 的回复:] 你怎么知道文件没打开？应该这么写吧？  if（(fic=fopen("table.txt","w")) != NULL) {     printf("file opened\n");  // 文件打开 } else {     printf("file open error\n");  // 文件打开错误 }   先谢谢各位，改完之后试了下，并没有把test的值写入到文件里，麻烦各位再指点下[/quote][/quote][/quote][/quote]

我没刻意放哪，文件原来没有的，fopen("table.txt","w")会生成新文件。 引用 9 楼 u013190286 的回复:最后再问下，你的text文件是跟.c文件放在一起的，是这样吧？谢谢了 [quote=引用 8 楼 KenZhang1031 的回复:] 可能你在fprintf之后看的，文件可能还在缓冲区里，没更新到文件里，你在fclose之后再看。 [quote=引用 6 楼 u013190286 的回复:] [quote=引用 3 楼 KenZhang1031 的回复:] 你怎么知道文件没打开？应该这么写吧？  if（(fic=fopen("table.txt","w")) != NULL) {     printf("file opened\n");  // 文件打开 } else {     printf("file open error\n");  // 文件打开错误 }   先谢谢各位，改完之后试了下，并没有把test的值写入到文件里，麻烦各位再指点下[/quote][/quote][/quote]

最后再问下，你的text文件是跟.c文件放在一起的，是这样吧？谢谢了 引用 8 楼 KenZhang1031 的回复:可能你在fprintf之后看的，文件可能还在缓冲区里，没更新到文件里，你在fclose之后再看。 [quote=引用 6 楼 u013190286 的回复:] [quote=引用 3 楼 KenZhang1031 的回复:] 你怎么知道文件没打开？应该这么写吧？  if（(fic=fopen("table.txt","w")) != NULL) {     printf("file opened\n");  // 文件打开 } else {     printf("file open error\n");  // 文件打开错误 }   先谢谢各位，改完之后试了下，并没有把test的值写入到文件里，麻烦各位再指点下[/quote][/quote]

可能你在fprintf之后看的，文件可能还在缓冲区里，没更新到文件里，你在fclose之后再看。 引用 6 楼 u013190286 的回复:[quote=引用 3 楼 KenZhang1031 的回复:] 你怎么知道文件没打开？应该这么写吧？  if（(fic=fopen("table.txt","w")) != NULL) {     printf("file opened\n");  // 文件打开 } else {     printf("file open error\n");  // 文件打开错误 }   先谢谢各位，改完之后试了下，并没有把test的值写入到文件里，麻烦各位再指点下[/quote]

我试了，能写进去。 引用 6 楼 u013190286 的回复:[quote=引用 3 楼 KenZhang1031 的回复:] 你怎么知道文件没打开？应该这么写吧？  if（(fic=fopen("table.txt","w")) != NULL) {     printf("file opened\n");  // 文件打开 } else {     printf("file open error\n");  // 文件打开错误 }   先谢谢各位，改完之后试了下，并没有把test的值写入到文件里，麻烦各位再指点下[/quote]

引用 3 楼 KenZhang1031 的回复:你怎么知道文件没打开？应该这么写吧？  if（(fic=fopen("table.txt","w")) != NULL) {     printf("file opened\n");  // 文件打开 } else {     printf("file open error\n");  // 文件打开错误 }   先谢谢各位，改完之后试了下，并没有把test的值写入到文件里，麻烦各位再指点下

先谢谢各位，改完之后试了下，并没有把test的值写入到文件里，麻烦各位再指点下

问题呢 是因为你把赋值符号= 写成了比较号==。

好好看书或例子

FILE * fic=fopen("table.txt","w"); if(NULL!=fic)   printf("file open");


Question: windows调用OpenSSL的问题

我把代码拿到linux去编译，发现可以用，那我就没什么好担心的了，搞个宏定义把windows.h半酣进来就好了。还是谢谢以上两位

引用 4 楼 Sealional 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。 这个工作量好大我的代码关系比较复杂，main就调用了一个函数，但是后面有千千万万函数。。。[/quote]  知不知道有个东西叫二分法

同时在http://hi.baidu.com/mingyuejingque/item/41f6603ee951d085c2cf29ee空间中有说到这个问题，但是也必须包含windows.h

引用 3 楼 zhao4zhong1 的回复:偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。 找到错误了，X509_NAME *name = NULL;这句出错。（包含windows.h就不会出错）。我发帖的时候说的就是这个问题，融合避免OpenSSL库中的名字和windows库中的名字重复的问题。（也可能没必要这样，主要是我完全没有调用windows的库）。 出错信息是这样的： error C2065: “name”: 未声明的标识符 error C2296: “*”: 非法，左操作数包含“LPCSTR”类型  我看了一下，windows中的X509_NAME的定义是这样的： #define X509_NAME   ((LPCSTR) 7)

引用 3 楼 zhao4zhong1 的回复:偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。 这个工作量好大我的代码关系比较复杂，main就调用了一个函数，但是后面有千千万万函数。。。

引用 1 楼 Sealional 的回复:没有人遇到过这样的问题么？是这样的错误如果最开始就包含了windows.h就不会有错  还补充一个问题，工程中我并没有包含wincrypt.h


Question: 如何将 C  语言中获取的参数值，传递给shell脚本中使用？

#include <stdlib.h>  int main() {   setenv("ipaddr", "192.168.0.1", 1);   system("./run.sh");   return 0; }   echo $ipaddr

多谢楼上的几位朋友，但是我在 shell 这个脚本里想得到这个值比取到IP是 192.168.0.1 如：   #/bin/bash  iptables -t nat 192.168.0.1 .......  iptables -t nat 192.168.0.1 .......  iptables -t nat 192.168.0.1 .......  192.168.0.1这里是变量如何传递到这里使用呢    sprintf(cmd,"/root/run.sh %s",ip);    system(cmd);  sprintf(cmd,"/root/run.sh %s",ip); 这个是否在run.sh 这个shell脚本把 ip 这个以 $1 来代替

多谢了几种方法都可以用了

++  引用 1 楼 user-5 的回复:sprintf(cmd,"/root/run.sh %s",ip);   system(cmd);

必须把值传到字符串里

char buf[1024] = "/root/run.sh "; strcat(buf, ipaddr); system(buf);    #/bin/bash ipaddress=%1

char buf[1024] = "/root/run.sh"; strcat(buf, ipaddr); system(buf);    #/bin/bash ipaddress=%1


Question: 将文件中UTF8编码格式转为UNICODE问题请大家指教

引用 9 楼 sjmicosoft 的回复:如果不用vc只用纯C实现呢？  string是stl你可以把类型换成相应类型，再试试~

utf-8 只是 unicode 的一种实现形式，其他的 unicode 要涉及字节序，像 UTF16BE、UTF16LE 或者使用 BOM，LZ 你确定了吗？看 LZ 的代码好像是 UTF16LE，这种形式可不常见哦。 另外 LZ 的代码好像只转码了最后一行。

引用 8 楼 wb117908406 的回复: string UTF8_To_String(const char* szSrc) { 	if(NULL==szSrc || 0==strlen(szSrc)) 	{ 		return ""; 	}  	int nLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)szSrc, -1, NULL, 0); 	unsigned short *wszGBK = new unsigned short[nLen+1]; 	memset(wszGBK, 0, nLen*2+2); 	MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)szSrc, -1, (LPWSTR)wszGBK, nLen);  	nLen = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)wszGBK, -1, NULL, 0, NULL, NULL); 	char* szGBK = new char[nLen+1]; 	memset(szGBK, 0, nLen+1); 	WideCharToMultiByte(CP_ACP, 0, (LPWSTR)wszGBK, -1, szGBK, nLen, NULL, NULL);  	string strTemp(szGBK); 	delete []wszGBK;  	wszGBK = NULL; 	delete []szGBK;   	szGBK = NULL;  	return strTemp; }  string String_To_UTF8(const string& strSrc) { 	if (strSrc.empty()) 	{ 		return ""; 	}  	int nLen=MultiByteToWideChar(CP_ACP, 0, strSrc.c_str(), -1, NULL,0); 	WCHAR* pwBuf = new WCHAR[nLen+1]; 	memset(pwBuf, 0, nLen * 2 + 2); 	MultiByteToWideChar(CP_ACP, 0, strSrc.c_str(), strSrc.length(), pwBuf, nLen);  	nLen = WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, 0, NULL, NULL); 	char *pBuf=new char[nLen + 1]; 	memset(pBuf, 0, nLen + 1); 	WideCharToMultiByte (CP_UTF8, 0, pwBuf, -1, pBuf, nLen, NULL,NULL);  	string strTemp(pBuf); 	delete[] pBuf; 	pBuf = NULL; 	delete[] pwBuf; 	pwBuf = NULL; 	return strTemp; }  如果不用vc只用纯C实现呢？

还有 ，这个要用C语言实现，不用VC，还需要改哪些地方呢？

引用 1 楼 jha334201553 的回复:// 多字节转宽字节，内存需要自行释放 PWSTR MulToWide( PSTR str ) { 	PWSTR  pElementText; 	int    iTextLen;  	iTextLen = MultiByteToWideChar( CP_ACP, 		0, 		(PCHAR)str, 		-1, 		NULL, 		0 ); 	 	pElementText =  		(PWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (iTextLen+1)*sizeof(WCHAR));  	MultiByteToWideChar( CP_ACP, 		0, 		(PCHAR)str, 		-1, 		pElementText, 		iTextLen );  	return pElementText; }用完自己HeapFree掉内存  请问为什么要转宽字节呢？我程序中直接加上这个函数可以吗？

引用 楼主 sjmicosoft 的回复:我现在需要将一个文件转换编码格式，即将UTF8转为UNICODE，900.txt文件中有“测试文件”几个汉字，将其执行结果存到result1.txt文件中。但是转换后发现汉字的转换并不对，不知该怎么改，请大家指教。以下是我的程序：   //逐行读取文件函数 bool ReadLine(FILE *fp,char words[]) { 	char *ptr = words; 	if(fp==NULL)  	{ 		puts("The file is not exist!"); 		return false; 	} 	if(feof(fp)) 	{ 		puts("The end of the file!"); 		return false; 	} 	*ptr ='\0'; 	char vChar=getc(fp); 	while(!feof(fp)&&vChar!='\n') 	{ 		*(ptr++)=vChar; 		*ptr='\0'; 		vChar=getc(fp); 	} 	//printf("%s\n",words); 	printf("%d",strlen(words));  	return true; } //转换函数UTF8->UNICODE int Utf82Uni(char *str, int * ptr)  {   int byte;   byte = *((unsigned char *) str);   //单字节处理   if (byte < 0xC0)   {       *ptr = (int) byte;       return 1;   }   //双字节处理   else if (byte < 0xE0)   {       if ((str[1] & 0xC0) == 0x80) 	  { 	   	   //两个字节情况：低字节以10开头，形式为110xxxxx 10xxxxxx  	    *ptr = (int) (((byte & 0x1F) << 6) | (str[1] & 0x3F)); 	    return 2; 	  }          *ptr = (int) byte;         return 1;   }   //三字节处理   else if (byte < 0xF0)   {       if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) 	  { 	  //三字节情况：后两个字节都已10开头，形式为：1110xxxx 10xxxxxx 10xxxxxx  	    *ptr = (int) (((byte & 0x0F) << 12)| ((str[1] & 0x3F) << 6) | (str[2] & 0x3F)); 	    return 3;  	  }         *ptr = (int) byte;         return 1;   }    else    { 	  *ptr = (int) byte;       return 1;    } }   int main() {         char words[MAX]; 	char *next = words; 	int uni; 	int len = 0;//转unicode后字节长度 	 	FILE *fp,*fp1; 	         int i=1,CountNum=0; 	fp = fopen("E:\\AIX\\900","rb"); 	fp1 = fopen("E:\\AIX\\result1.txt","wb"); 	 	if (fp == NULL) 	{ 		printf("Open this file failed!"); 		exit(1); 	} 	 	while(ReadLine(fp,words)) 	{ 		CountNum++; 		printf("%s\n",words);	 	}              //将文件中字符转码 	for (int j=0; *next; j++) 	{ 		len = Utf82Uni(next, &uni); 		next += len; 		printf("unicode长度：%d\nunicode格式：%x\n", len, uni);        	}      	fclose(fp); 	fclose(fp1); }  为什么要转宽字节呢？我那程序中再加上这个函数可以吗？

#define _CRT_SECURE_NO_WARNINGS  #include <cstdlib> #include <clocale> #include <cstdio>  int main() { 	setlocale(LC_CTYPE, "chs"); 	char mbs[] = "你好,c++"; 	wchar_t  wcs[32]; 	mbstowcs(wcs, mbs, 32); //multibyte string to wide char string 	printf("%s-->%ls\n", mbs, wcs); 	return 0; }

Linux：iconv Windows：MultiByteToWideChar

转码用iconv库。   引用 楼主 sjmicosoft 的回复:我现在需要将一个文件转换编码格式，即将UTF8转为UNICODE，900.txt文件中有“测试文件”几个汉字，将其执行结果存到result1.txt文件中。但是转换后发现汉字的转换并不对，不知该怎么改，请大家指教。以下是我的程序：   //逐行读取文件函数 bool ReadLine(FILE *fp,char words[]) { 	char *ptr = words; 	if(fp==NULL)  	{ 		puts("The file is not exist!"); 		return false; 	} 	if(feof(fp)) 	{ 		puts("The end of the file!"); 		return false; 	} 	*ptr ='\0'; 	char vChar=getc(fp); 	while(!feof(fp)&&vChar!='\n') 	{ 		*(ptr++)=vChar; 		*ptr='\0'; 		vChar=getc(fp); 	} 	//printf("%s\n",words); 	printf("%d",strlen(words));  	return true; } //转换函数UTF8->UNICODE int Utf82Uni(char *str, int * ptr)  {   int byte;   byte = *((unsigned char *) str);   //单字节处理   if (byte < 0xC0)   {       *ptr = (int) byte;       return 1;   }   //双字节处理   else if (byte < 0xE0)   {       if ((str[1] & 0xC0) == 0x80) 	  { 	   	   //两个字节情况：低字节以10开头，形式为110xxxxx 10xxxxxx  	    *ptr = (int) (((byte & 0x1F) << 6) | (str[1] & 0x3F)); 	    return 2; 	  }          *ptr = (int) byte;         return 1;   }   //三字节处理   else if (byte < 0xF0)   {       if (((str[1] & 0xC0) == 0x80) && ((str[2] & 0xC0) == 0x80)) 	  { 	  //三字节情况：后两个字节都已10开头，形式为：1110xxxx 10xxxxxx 10xxxxxx  	    *ptr = (int) (((byte & 0x0F) << 12)| ((str[1] & 0x3F) << 6) | (str[2] & 0x3F)); 	    return 3;  	  }         *ptr = (int) byte;         return 1;   }    else    { 	  *ptr = (int) byte;       return 1;    } }   int main() {         char words[MAX]; 	char *next = words; 	int uni; 	int len = 0;//转unicode后字节长度 	 	FILE *fp,*fp1; 	         int i=1,CountNum=0; 	fp = fopen("E:\\AIX\\900","rb"); 	fp1 = fopen("E:\\AIX\\result1.txt","wb"); 	 	if (fp == NULL) 	{ 		printf("Open this file failed!"); 		exit(1); 	} 	 	while(ReadLine(fp,words)) 	{ 		CountNum++; 		printf("%s\n",words);	 	}              //将文件中字符转码 	for (int j=0; *next; j++) 	{ 		len = Utf82Uni(next, &uni); 		next += len; 		printf("unicode长度：%d\nunicode格式：%x\n", len, uni);        	}      	fclose(fp); 	fclose(fp1); }


Question: 关于scanf缓冲区问题

第二个scanf的时候，除去%c，其他格式说明符都忽略前面的空白（包括空格、回车、制表等），从第一个非空白字符读取。

"%s"读数据的时候会跳过所有的空格，tab和回车 "%c"则会读入任何字符， 包括空格， tab和回车  顺便说一下， LS说的rewind(stdin)和fflush(stdin)一样， 是一种不可移植的写法， 被微软支持， 但不被gcc支持。 通用的写法是 char ch; while ( (c = getchar()) != '\n' && c != EOF ) ;

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

直接忽略  区别在于 %c 会读取 空白字符 而 %s 不会 %d %f %x %i %o 等等都不会读取空白字符  所以 前面有没有滞留 空白字符无所谓

引用 楼主 missheaven2011 的回复:疑问是：第一次读取a时，残留的'\n'没有被b获取，是直接被忽略了么？  空格（'\n', '\t', ' ')是字符串的分割符，会被%s忽略的。

不推荐这样用，两个scanf()加一个getchar()


Question: 《c和指针》里的一个疑问

贴题目呀。。。

限定columns[col]+nchars<=len 方法是，如果超过，减少nchars数量  比如columns[col] = 10 len=20 如果nchars = 5，没有关系，它还是5 如果nchars=15，那么让它等于10，保证它和columns[col]相加等于len

避免nchars的取值过大导致越界访问。


Question: 怎样把字符数组里的内容拷贝到字符串里？

memcpy可行

strcpy  记得A要有所指。

A=(char *)B; 或 strcpy(A,B);//A指向的内存空间已提前分配，并足够长以放得下B 或 strncpy(A,B,n);A[n]=0;//A指向的内存空间为n+1个字节，将B的前n个字符拷贝到A中。

memcpy

strcpy不保险啊，数组里面，不一定有结束符，还是知道长度来增加判断条件用memcpy保险点。

memcpy

要拷贝，memcpy可以拷贝任何数据，strcpy可以拷贝字符串 但如果楼主不理解字符指针char*是什么东西，那什么拷贝都没用


Question: Linux下检测网卡与网线连接状态，使用ioctl向socket发送SIOCETHTOOL命令字

先确认你运行的环境中是否有eth0网卡。用ifconfig查看。 另外把这句话改成strncpy(ifr.ifr_name,if_name,sizeof(ifr.ifr_name)-1);

if((skfd=socket(AF_INET,SOCK_DGRAM,0)<0)) 这句话有问题。。。。

虚拟机和实体机总该有区别，否则就不叫虚拟机了。 纯打酱油的路过……

引用 2 楼 ForestDB 的回复:printf("eth0_data=%d\n",get_netlink_status("eth0")); 确定没有少0？加了也是一样的！！


Question: 指针问题

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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

引用 10 楼 derekrose 的回复:[quote=引用 8 楼 bijiaoben 的回复:] [quote=引用 2 楼 derekrose 的回复:] 之前学java的吧 为什么呢？Java会产生这种结果？[/quote]  java是引用[/quote] 领教了。之前我一直很纳闷为什么不少人都会得出这种结果。看来还是要多学学其他的语言才能触类旁通答疑解惑啊。

引用 8 楼 bijiaoben 的回复:[quote=引用 2 楼 derekrose 的回复:] 之前学java的吧 为什么呢？Java会产生这种结果？[/quote]  java是引用

引用 2 楼 derekrose 的回复:之前学java的吧 为什么呢？Java会产生这种结果？

引用 楼主 boyhailong 的回复:今天在看 二叉查找树的delete节点时候，看到一段代码： 不过可以简化成下面： #include <iostream>  struct TreeNode{ 	TreeNode(int aVal){ 		value = aVal; 		pLeft = NULL; 		pRight = NULL; 	} 	int value; 	TreeNode* pLeft; 	TreeNode* pRight; };  int main(){ 	TreeNode* node1 = new TreeNode(1); 	TreeNode* node2 = new TreeNode(2); 	printf("node1:%lld,node2:%lld\n ", node1,node2); 	TreeNode* node3 = NULL; 	node3 = node1; 	node1 = node2; 	printf("node1:%lld,node2:%lld, node3:%lld\n ", node1,node2,node3); }  无视内存泄露，看关键问题： node3 = node1; 此时node3指向node1; node1 = node2;此时node1指向node2 我之前觉得node3此时也会指向node2，但结果不是。指针的赋值到底是怎么回事，发现我根本没有理解指针，球解释 node3不指向node1，它指向node1所指的物体。 指针变量存储一个数字，那个数字是一个内存位置。没有任何自动或神奇的过程。

node3 = node1; 此时node3指向node1; node1 = node2;此时node1指向node2  两个地址而已，node3指向了node1的初始位置，注意，node3一直会指向该地址，而node1改变了地址方向，指向了node2，但是Node3并没有修改，当然还是node1的原始位置了。

指针也是一个变量（保存的是一个地址值）而已，这样看的话，a=b,b=c,a怎么会等于c呢？或者将指针理解为一个可以装钥匙的盒子(钥匙就是地址值，可以通过钥匙打开对应的放东西的柜子)，a=b,表示在a盒子里放进了一个和b盒子里的钥匙一模一样的钥匙，然后又把b盒子里的钥匙换成了和c盒子里一模一样的钥匙，那么a盒子里的钥匙和c盒里的钥匙有什么关系呢？

int i=3; int* ptr = &i; int** pptr = &ptr;  // pptr是二级指针，指向ptr。  sorry 笔误。

node3 = node1; 此时node3指向node1; node1 = node2;此时node1指向node2 ========== 指针赋值的结果是两个指针指向共同区域。 int i=3; int* ptr = &i; int* pptr = &ptr;  // pptr是二级指针，指向ptr。

设想，开始是 node1=0x100, node2=0x200; node3=0x00; node3=node1, 此句完成后node3和node1同为0x100; node1=node2, 此句完成后node1和node2同为0x200;  没有任何出人意表之处。

这有什么不好理解的。比如 int a = 0; int b = 1; int* p2 = &b; int* p1 = &a; int* p3 = p1; int* p1 = p2;  p1指向的是a的地址，p3这时也指向a的地址，最后一句使p1指向p2所指的地址，也就是b的地址。 那这么一来，p3指向不指向p2是猫关系都没有。又没有传递性。  懂了吧。

之前学java的吧

node3 = node1;     node1 = node2;  把原来node1的值赋给node3, 再把原来node2的值赋给node1, 动作完成后node1和node2都指向原来node2指向的位置，而node3孤标一格，指向原node1所指的地址。  不多不少，刚刚好。


Question: PDU短信的发送与接收

那就得看USC2是如何编解码的。

////////////////////////////////////////////////////////////////////////// //函数名：            gsmEncodeUcs2 //功能描述：          UCS2编码 //入口参数:           pSrc:                  源字符串指针 //			          nSrcLength:            源字符串长度 //出口参数:           pDst :                 目标编码串指针 //函数返回值：目标编码串长度 ////////////////////////////////////////////////////////////////////////// int gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength) { 	int nDstLength;		// UNICODE宽字符数目 	U8 wchar[128];	// UNICODE串缓冲区  	// 字符串-->UNICODE串 	nDstLength = MultiByteToWideChar(0, 0, pSrc, nSrcLength, wchar, 128);  	// 高低字节对调，输出 	for(int i=0; i<nDstLength; i++) 	{ 		*pDst++ = wchar[i] >> 8;		// 先输出高位字节 		*pDst++ = wchar[i] & 0xff;		// 后输出低位字节 	}  	// 返回目标编码串长度 	return nDstLength * 2; } //////////////////////////////////////////////////////////////////////// // 函数名：            gsmDecodeUcs2 // 功能描述：          UCS2解码 // 入口参数:           pSrc:                  源编码串指针 // 			          nSrcLength:            源编码串长度 // 出口参数:           pDst :                 目标字符串指针 // 函数返回值：目标字符串长度 //////////////////////////////////////////////////////////////////////// int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength) { 	int nDstLength;		// UNICODE宽字符数目 	U8 wchar[128];	// UNICODE串缓冲区  	// 高低字节对调，拼成UNICODE 	for(int i=0; i<nSrcLength/2; i++) 	{ 		wchar[i] = *pSrc++ << 8;	// 先高位字节 		wchar[i] |= *pSrc++;		// 后低位字节 	}  	// UNICODE串-->字符串 	nDstLength = WideCharToMultiByte(0, 0, wchar, nSrcLength/2, pDst, 160, NULL, NULL);  	// 输出字符串加个结束符 	pDst[nDstLength] = '\0';  	// 返回目标字符串长度 	return nDstLength; } 现在MultiByteToWideChar和WideCharToMultiByte两个函数用不了，不知道如何改

pdu格式里面就两种编码格式，一种用UTF8,一种用USC2,单片机一般都支持USC2编码，所以把UTF8的编码转换成USC2 UTF8转USC2很好转，可根据协议自己写一个

主要是字符转宽字符不知道怎么写，网上一般都是用MultiByteToWideChar(或WideCharToMultiByte)这个库函数，但是单片机上用不了这个函数


Question: 求教

test（char *p） {  p = ”555“； } p是地址，是不能被赋值的！ 建议你看一下我曾写过的一篇关于c程序学习的总结博客，上边有关于指针的介绍，并附有程序，希望对你的学习有所帮助！ http://blog.csdn.net/ztzi321/article/details/17024559

p记录的是一个地址，是十六进制记录的，不可能被赋值，而*p记录的是这个地址里面的值。

我认为这两函数执行没问题。首先p和p1没有初始化，但是p="555";指是把形参p指向了常量字符串的首地址，这个常量字符串是编译时就开辟了静态内存的，这个改变的是形参的指针值，相当于定义一个局部指针变量p，你初始化为NULL也行，初始化为指向一个常量字符串也行，这不会有任何问题，仅仅是这个test函数不会让实参p改变而已，实参的p还是野指针，相当于没初始化，这个时候去用p才有可能造成错误（如果只是给指针赋初值则不会），如果后面不使用p，仅仅执行test函数，什么问题都不会有，使用才会有问题,比如给*p赋值，则会出问题。test1 函数一样，但改变的是实参p1的指针值指向常量字符串，此时p1指向了常量字符串，使用它则不会有问题。

因为p和p1在调用test和test1函数之前都是野指针，但是p经过调用test后，p还是一个野指针，并没有改变p指向的位置，但是p1经过test1之后，p1就指向了字符串“555”。

我咋感觉2个都没问题呢？ test是传递的指针本身的值，改变的是test局部变量指针本身的值，所以test实际没有改变什么。 test1传递的是二级指针的值，改变的是p1指针本身的值，所以test1会改变p1本身的值。 2个函数都没有动p和p1指向内存的值，为啥会有错误呢。不解ing

引用 7 楼 starytx 的回复:[quote=引用 5 楼 u013431701 的回复:] [quote=引用 1 楼 user-14 的回复:] 因为你改变的只是p1的值 而不是他指向的内存  哦，原来是这样的，没分配内存，不可以赋值，但是可以重新指向其它的内存地址.[/quote]重点不在分配不分配空间的问题，重点是你的p和p1没有初始化，如此一来，第一个test()函数没有出错是因为，你并没有改变实参的内容，而test1()你通过传入实参的地址，改变了实参p1指向的内容的值(但是你的p1没有初始化，他此时指向哪里呢？这是一个未定义行为，也许指向一个其他程序的内存空间，而你传入地址要改变这个空间的数据，故而引起错误)[/quote] test1改变的不是p1本身的值吗？你怎么说是p1指向的内容的值？函数参量是二级指针的呢。

其实电脑开机后物理内存的每个字节都是可读写的，区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

这题目写的,理解了好半天才看明白阿 我还以为那段代码运行时已经崩溃了呢  去看指针.

引用 3 楼 ALNG 的回复:sorry, 因为是传值调用，test中改变的p是原来p的一个副本，原来的p始终没变，而且没有初始化，你引用它时可能访问非法内存导致程序失败。  这个才是正解！

内存非法访问

引用 5 楼 u013431701 的回复:[quote=引用 1 楼 user-14 的回复:] 因为你改变的只是p1的值 而不是他指向的内存  哦，原来是这样的，没分配内存，不可以赋值，但是可以重新指向其它的内存地址.[/quote]重点不在分配不分配空间的问题，重点是你的p和p1没有初始化，如此一来，第一个test()函数没有出错是因为，你并没有改变实参的内容，而test1()你通过传入实参的地址，改变了实参p1指向的内容的值(但是你的p1没有初始化，他此时指向哪里呢？这是一个未定义行为，也许指向一个其他程序的内存空间，而你传入地址要改变这个空间的数据，故而引起错误)

指针没赋值，当然就不能使用了

其实也对，地址变了，内容当然变了。   #include <stdio.h> void test(char * p); void test1(char ** p); int main(void ) {     char *p = "it's cotent of pointer p!";     char *p1= "it's cotent of pointer p1!";      //测试test     printf("before calling test(p), address of p is %p\n", p);     printf("before calling test(p), content of p is %s\n", p);     test(p);     printf("after calling test(p), address of p is %p\n",p);     printf("after calling test(p), content of p is %s\n", p);     //测试test1     printf("-------------\n下面测试test1\n--------------\n");     printf("before calling test1(p), address of p is %p\n", p1);     printf("before calling test1(p), content of p is %s\n", p1);     test1(&p1);     printf("after calling test1(p), address of p is %p\n", p1);     printf("before calling test1(p), content of p is %s\n", p1);      return 0; } void test(char *p) {      printf("Now it's in test function\n");      p = "555"; } void test1(char ** p) {     printf("Now it's in test1 function\n");     *p = "555"; }

#include <stdio.h>  void test(const char *p) {      printf("Just so you know, test() has modified a char * at memory location %p\n"            "Please check if it's the pointer you intended to modify!\n", &p);      p="Changed in test!"; }  int main() {      const char* q="Origninal text!";      printf("Address of q is %p\n", &q);      printf("before calling test(q), address contained in q is %p\n", q);      test(q);      printf("after calling test(q), address contained in q is %p\n",q); }

引用 1 楼 user-14 的回复:因为你改变的只是p1的值 而不是他指向的内存  哦，原来是这样的，没分配内存，不可以赋值，但是可以重新指向其它的内存地址.

引用 1 楼 user-14 的回复:因为你改变的只是p1的值 而不是他指向的内存  这样没有分配内存空间，也可以赋值吗？ 这样应该有问题才对啊.

是吗，应该没问题啊？

因为你改变的只是p1的值 而不是他指向的内存


Question: unsigned int 赋值负数

“%d会按照int来打印，%u才是按照unsigned打印的。”+++

当你把一个超过2^31-1的unsign int传给int的时候，int接收到的就是一个负值。

printf中%d就会把参数当int解释，%u就会把参数当unsinged int解释。

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

因为你printf里又转回int格式了。

-10 32位机 原码为1000 0000 0000 0000 0000 0000 0000 1010 即0x8000 000A, 补码为1111 1111 1111 1111 1111 1111 1111 0110 即0xFFFF FFF6 计算机把负数是用被码存储的.如果你把它当成unsigned int看就是0xFFFF FFF6  数据还是哪个数据,就看你用什么角度去用.

%d又作了一次转换改为%u

%d这个格式会按照带有符号位的打印出来

%d会按照int来打印，%u才是按照unsigned打印的。  引用 楼主 u013431701 的回复:看了一段代码有点疑问.  void test（unsigned int a） { printf（"the a value is = %d\n",a）； }  void main（） {   int c = -10；  test（c）；  } 结果是-10； 有如下几个问题点. 1.unsigned int的取值范围不是0~2^32吗？为什么可以是负数呢， 2.test函数的参数是unsigned int，把int传进来的时候，会有隐式的类型转换吗?如果有也是转到unsigned int啊. 3.如果定义unsigned char型，结果就是一个正数.为什么呢？  拜托大家给我普及一下，

强制转换了。其实正如10楼说的,对于cpu来说，是没有数据类型的概念的，都是内存中的字节

数据类型是编译器给的一个限定。基于c的传统，c++编译器对这个的限制有些宽松。 实际对于cpu来说，是没有数据类型的概念的，存储的只是寄存器或内存中的字节，本质没有区别。 至于负数，正数在内存中怎么存储你看看基础书籍


Question: pos机开发相关问题

aa[0]=aa[0]&0xF0|0x08;//将aa[0]的低4位修改为0x8，高4位不变 //或者 aa[0]=aa[0]&0x0F|(0x08<<4);//将aa[0]的高4位修改为0x8，低4位不变

你的意思是把那个16进制的串赋给你的aa数组吗？如果是这样  aa[0]=0x1f; aa[1]=0xff; aa[2]=0xf0; ...


Question: scanf小问题

长知识了 ...

这是我认同的写法，用getchar感觉有点凑的感觉，不喜欢。 引用 10 楼 IAccepted 的回复:确实楼上都给出了正确解答，无限输出是因为缓冲中存在换行符。字符数组输入时不必取地址，temp就代表了数组首地址。 另外我给出我通常的写法：  #include<stdio.h> int main() {     char temp[1000];     while(scanf("%[^\n]%*c",temp)!=EOF)     {         printf("%s\n",temp);     }     return 0; }

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

引用 10 楼 IAccepted 的回复:确实楼上都给出了正确解答，无限输出是因为缓冲中存在换行符。字符数组输入时不必取地址，temp就代表了数组首地址。 另外我给出我通常的写法：  #include<stdio.h> int main() {     char temp[1000];     while(scanf("%[^\n]%*c",temp)!=EOF)     {         printf("%s\n",temp);     }     return 0; }    雷同，纯属巧合。

#define _CRT_SECURE_NO_WARNINGS  #include<stdio.h> int main() { 	char temp[1000];	 	while (scanf("%[^\n]%*c", temp) != EOF) //%*c will read \n and ignored 	{ 		printf("%s\n",temp); 	}  	return 0; }

//input: hello\n      while(scanf("%[^\n]",&temp)!=EOF)     {       //temp ---> hello\0                printf("%s\n",temp);       //next char to read is '\n'       //scanf("%[^\n]",&temp) will return 0, and temp is unchanged          }

#include <stdio.h> int main() { 	char temp[1000]; 	while(scanf("%[^\n]", temp) != 0) 			printf("%s\n", temp); 	return 0; }

引用 5 楼 u013211088 的回复:问个问题，输入需要给temp取地址吗？temp本身不就代表一个地址么。 个人感觉无影响，因为temp和&temp指向同一地址，但是指向类型是不一样的，建议还是用temp。。

引用 5 楼 u013211088 的回复:问个问题，输入需要给temp取地址吗？temp本身不就代表一个地址么。好仔细 这里的确不需要 &  算是一个错误的写法

问个问题，输入需要给temp取地址吗？temp本身不就代表一个地址么。

引用 3 楼 lin5161678 的回复:[quote=引用 2 楼 lin5161678 的回复:] 接 #1 楼  所以 你可以 把EOF 换成 0 这样删除getchar 就不会出问题 纠正 != EOF 换成 != 1[/quote] 再纠正 != EOF 换成 == 1

引用 2 楼 lin5161678 的回复:接 #1 楼  所以 你可以 把EOF 换成 0 这样删除getchar 就不会出问题 纠正 != EOF 换成 != 1

scanf("%[^\n]",&temp)，这条语句在第一次调用时，返回值为1，即成功获取字符串，存到temp中，但'\n'依然残留在缓存区内 第二次调用scanf("%[^\n]",&temp)，由于缓存区内残留'\n'，字符串读取失败，返回0，导致循环打印 getchar();用于吃掉残留在缓存区中的'\n'


Question: 明天考C语言 求助攻

引用 3 楼 KenZhang1031 的回复:条件判断都是判断表达式的逻辑结果，为真就执行为假就不执行，比如while(条件),if(条件)，表示条件==真就执行，等价于while(条件==真),if(条件==真)，对C语言来说，真就是不等于0，假就是等于0。所以对C语言而言，也等价于while(条件!=0),if(条件!=0) 引用 2 楼 u011638252 的回复:引用 1 楼 KenZhang1031 的回复:答案为CCCCC恭喜    求解释 谢谢耐心解答！

引用 1 楼 KenZhang1031 的回复:答案为CCCCC恭喜    求解释

答案为CCCCC


Question: 再问除数为0的问题

我是来学习的

n=0/PI/(i-14);这样写n应该等于0啊？  n = (0/PI) / (i-14) 为什么你会觉得这个n是0呢?

1.#INF / inf：这个值表示“无穷大 (infinity 的缩写)”，即超出了计算机可以表示的浮点数的最大范围（或者说超过了 double 类型的最大值）。例如，当用 0 除一个整数时便会得到一个1.#INF / inf值；相应的，如果用 0 除一个负整数也会得到 -1.#INF / -inf 值。  -1.#IND / nan：这个的情况更复杂，一般来说，它们来自于任何未定义结果（非法）的浮点数运算。"IND"是 indeterminate 的缩写，而"nan"是 not a number 的缩写。产生这个值的常见例子有：对负数开平方，对负数取对数，0.0/0.0，0.0*∞, ∞/∞ 等。

除0错误在整数除以整数零的时候必然出现，但在浮点运算中则不一定出现 因为浮点运算得到的零不一定是精确的零，可能是一个极小的小数，因此浮点运算时的除零可能会变成除以绝对值极小的小数，从而得到一个绝对值极大的大数 数学运算时，会将低表示范围的数先提升为高表示范围的数，再进行运算，因此当被除数为PI时，除数的i-14被提升为浮点数


Question: 我这个一元多项式的加减法为何只能执行加法

仅供参考//假设带表头结点的单向链表头指针为head，试编写一个算法将值为5的结点插入到连接表的第k个结点前，删除第k个节点，并对该链表进行排序。 #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-> //

pa=La->next;pb=Lb->next;     Lc=pc=La;  楼主所有的操作都在改动2个源链表，一次加法处理之后两个链表面目全非，能再进行减法处理才怪了。 建议楼主多准备几组测试用例，分别进行加法处理后再看看内存里面两个源链表的数据，你就知道问题在哪里了。 另外说一下，楼主你把减法的代码屏蔽掉，加法执行完了直接去销毁两个源链表，可能程序会崩掉哦

加法结果正确 ，但是之后不能运行减法！

结果不正确？


Question: 拉丁方

就是想象行或者列是可以首位相接的，然后依次转一位，。。。  比如第一行是 1,2,3....N  第二行就是 2,3,4,..N,1  第三行就是 3，4,.N,1,2  依此类推。  按列也一样。它具体的字面意思或者表达方式你就没必要去抠了。


Question: 关于 图 有个地方不是很懂

邻接表后面的边表只是指的它前面的顶点对应的节点，后面边表之间没有什么关系

引用 8 楼 ALNG 的回复:[quote=引用 4 楼 u013160932 的回复:] [quote=引用 3 楼 ALNG 的回复:] 上面最后一句话应该是: 下面的两行，V2,V3都各只有2个邻接顶点，所以比V0,V1的少1列。  再补充一点，最左边的一列，格子是连在一起的，它隐含的意思是他们在内存中的表达是连续的(比如放在数组，向量之类的容器中的)，第2，3，4列的格子是离散的，因为它们的物理表达很可能就是单链表的节点，彼此在内存中的位置关系并不确定。 那就是说v0->1->2->3中的2->3不是指2和3连在一起,而是说2和3分别和0连在一起?[/quote]  刚才没看到这个，这个理解就对路了。[/quote]嗯好的,谢谢大神

引用 4 楼 u013160932 的回复:[quote=引用 3 楼 ALNG 的回复:] 上面最后一句话应该是: 下面的两行，V2,V3都各只有2个邻接顶点，所以比V0,V1的少1列。  再补充一点，最左边的一列，格子是连在一起的，它隐含的意思是他们在内存中的表达是连续的(比如放在数组，向量之类的容器中的)，第2，3，4列的格子是离散的，因为它们的物理表达很可能就是单链表的节点，彼此在内存中的位置关系并不确定。 那就是说v0->1->2->3中的2->3不是指2和3连在一起,而是说2和3分别和0连在一起?[/quote]  刚才没看到这个，这个理解就对路了。

那第一行中的2->3是什么意思?  ============== 1（vertex id）是0(v0)的第一个邻接顶点，2是1的下一个兄弟，所以也是v0的邻接顶点，3是2的下一个兄弟，所以它也是v0的邻接顶点。3的下一个兄弟的指针式空指针，意味着v0没有更多的邻接顶点了。

不是。知道树的左儿子右兄弟表示法吗？这里的链表就是一些sibling（兄弟顶点)的链表。  你看，一个顶点的邻接顶点的个数是不确定的，可以一个都没有，也可能有好几百个。一种方法就是把它的所有的邻接顶点用一个单链表组织起来，这样不管你有多少的邻接顶点，那个Node的定义都是一样的  struct AdjvertexNode{     int nodeid;     AdjvertexNode *nextSibling; // 指向下一个兄弟，如果是一组邻接顶点中的最后一个，指正为NULL };

引用 2 楼 fq553165833 的回复:下面的边表2和3没连上啊。0和1都有三条联通线，2和3明显只写了两条啊！你好好看看！ 那第一行中的2->3是什么意思?

引用 3 楼 ALNG 的回复:上面最后一句话应该是: 下面的两行，V2,V3都各只有2个邻接顶点，所以比V0,V1的少1列。  再补充一点，最左边的一列，格子是连在一起的，它隐含的意思是他们在内存中的表达是连续的(比如放在数组，向量之类的容器中的)，第2，3，4列的格子是离散的，因为它们的物理表达很可能就是单链表的节点，彼此在内存中的位置关系并不确定。 那就是说v0->1->2->3中的2->3不是指2和3连在一起,而是说2和3分别和0连在一起?

看了下，第一行第一栏是定点0，后面是以单链表来描述的其邻接顶点，v0和v1,v2,v3都有边相连，所以这三个顶点都是其邻接的顶点。最右边 3+^, 意思是3这个邻接顶点之后，没有其它邻接顶点了。  类似的，V2也有3个邻接顶点，与V0类似；  线面的两行，V2,V3都各只有2个邻接顶点，所以比V0,V1的少两行。


Question: 变量赋值后（用=赋值），变量仍不变，怎么回事？？

在你怀疑的地方打个断点，F5调试一下。 ps：把你的代码缩进调好一点，这样看着太费劲

显然没有走到这个if分支里

感觉不太可能吧？  把那个地方改成      printf("Before assignment, (%c,%c)\n", compare, compare1);     compare = compare1;     printf("After assignment, (%c,%c)\n", compare, compare1);   把程序输出贴出来看看。

你有2个printf，要先看下是从那边输出的

你调试了吗？


Question: 新人求教—有关一道字符串题目的问题

引用 3 楼 Automation_dmu 的回复:不过出错的 应该是printf的那句，没有'\0' 。  引用 2 楼 Automation_dmu 的回复:name[index][10]=buffer[i];// 这行有问题 今天自己又看了下，发现了问题然后自己改了下，后来成功了 主要问题是：1.二维的字符串没有赋值；2.name[index][10]=buffer[i]这个语句问题； 下面是我自己修改的程序：  输出：  还是要谢谢你，给的思路啊~

引用 1 楼 fq553165833 的回复:现成函数char *strtok(char *str, const char *delim);不是更好麽？ 今天自己又看了下，发现了问题然后自己改了下，后来成功了 主要问题是：1.二维的字符串没有赋值；2.name[index][10]=buffer[i]这个语句问题； 下面是我自己修改的程序：  输出：  还是要谢谢你，给的思路啊~

引用 2 楼 Automation_dmu 的回复:name[index][10]=buffer[i];// 这行有问题 的确是这行有问题，buffer的值赋不进去~~

大概看了下你的代码。printf("%s",name[i][10]);后面的参数只是一个字符，而name[i]才是字符串。其它没怎么看了。还是建议用strtok函数来分割字符串，很方便的。

name[index][10]=buffer[i];// 这行有问题


Question: c语言----指针偏移问题

引用 2 楼 derekrose 的回复: 说明你的电脑 是小端的 +3.1415926

引用 2 楼 derekrose 的回复: 说明你的电脑 是小端的+3

你们说，咱们说的小端这事，楼主明白了吗？

引用 2 楼 derekrose 的回复: 说明你的电脑 是小端的 +4

引用 2 楼 derekrose 的回复: 说明你的电脑 是小端的 +2

引用 2 楼 derekrose 的回复: 说明你的电脑 是小端的 +1

说明你的电脑 是小端的

不要企图依赖输出指针相关表达式的值【比如printf("%p\n",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。 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对应的汇编并单步执行观察相应内存和寄存器变化。）  1:    int main() { 00401000 55                   push        ebp 00401001 8B EC                mov         ebp,esp 00401003 83 EC 54             sub         esp,54h 00401006 53                   push        ebx 00401007 56                   push        esi 00401008 57                   push        edi 2:        short s = 0x2001; 00401009 66 C7 45 FC 01 20    mov         word ptr [ebp-4],offset main+0Dh (0040100d) 3:        char *p = (char *)&s; 0040100F 8D 45 FC             lea         eax,[ebp-4] 00401012 89 45 F8             mov         dword ptr [ebp-8],eax 4:        void *vp; 5: 6:        vp=(void *)p; 00401015 8B 4D F8             mov         ecx,dword ptr [ebp-8] 00401018 89 4D F4             mov         dword ptr [ebp-0Ch],ecx 7:        vp=(void *)(p+1); 0040101B 8B 55 F8             mov         edx,dword ptr [ebp-8] 0040101E 83 C2 01             add         edx,1 00401021 89 55 F4             mov         dword ptr [ebp-0Ch],edx 8:        vp=(void *)(p+2); 00401024 8B 45 F8             mov         eax,dword ptr [ebp-8] 00401027 83 C0 02             add         eax,2 0040102A 89 45 F4             mov         dword ptr [ebp-0Ch],eax 9:        vp=(void *)(p+3); 0040102D 8B 4D F8             mov         ecx,dword ptr [ebp-8] 00401030 83 C1 03             add         ecx,3 00401033 89 4D F4             mov         dword ptr [ebp-0Ch],ecx 10:       vp=(void *)(&s); 00401036 8D 55 FC             lea         edx,[ebp-4] 00401039 89 55 F4             mov         dword ptr [ebp-0Ch],edx 11:       vp=(void *)(&s+1); 0040103C 8D 45 FE             lea         eax,[ebp-2] 0040103F 89 45 F4             mov         dword ptr [ebp-0Ch],eax 12: 13:       unsigned char c1 = *((unsigned char *)&s); 00401042 8A 4D FC             mov         cl,byte ptr [ebp-4] 00401045 88 4D F0             mov         byte ptr [ebp-10h],cl 14:       vp=(void *)((unsigned char *)&s); 00401048 8D 55 FC             lea         edx,[ebp-4] 0040104B 89 55 F4             mov         dword ptr [ebp-0Ch],edx 15: 16:       unsigned char c2 = *((unsigned char *)&s + 1); 0040104E 8A 45 FD             mov         al,byte ptr [ebp-3] 00401051 88 45 EC             mov         byte ptr [ebp-14h],al 17:       vp=(void *)((unsigned char *)&s + 1); 00401054 8D 4D FD             lea         ecx,[ebp-3] 00401057 89 4D F4             mov         dword ptr [ebp-0Ch],ecx 18: 19:       return 0; 0040105A 33 C0                xor         eax,eax 20:   } 0040105C 5F                   pop         edi 0040105D 5E                   pop         esi 0040105E 5B                   pop         ebx 0040105F 8B E5                mov         esp,ebp 00401061 5D                   pop         ebp 00401062 C3                   ret  1:    int main() { 00401000 55                   push        ebp 00401001 8B EC                mov         ebp,esp 00401003 83 EC 54             sub         esp,54h 00401006 53                   push        ebx 00401007 56                   push        esi 00401008 57                   push        edi 2:        short s = 0x2001; 00401009 66 C7 45 FC 01 20    mov         word ptr [ebp-4],offset main+0Dh (0040100d) 3:        char *p = (char *)&s; 0040100F 8D 45 FC             lea         eax,[ebp-4] 00401012 89 45 F8             mov         dword ptr [ebp-8],eax 4:        void *vp; 5: 6:        vp=(void *)p; 00401015 8B 4D F8             mov         ecx,dword ptr [ebp-8] 00401018 89 4D F4             mov         dword ptr [ebp-0Ch],ecx 7:        vp=(void *)(p+1); 0040101B 8B 55 F8             mov         edx,dword ptr [ebp-8] 0040101E 83 C2 01             add         edx,1 00401021 89 55 F4             mov         dword ptr [ebp-0Ch],edx 8:        vp=(void *)(p+2); 00401024 8B 45 F8             mov         eax,dword ptr [ebp-8] 00401027 83 C0 02             add         eax,2 0040102A 89 45 F4             mov         dword ptr [ebp-0Ch],eax 9:        vp=(void *)(p+3); 0040102D 8B 4D F8             mov         ecx,dword ptr [ebp-8] 00401030 83 C1 03             add         ecx,3 00401033 89 4D F4             mov         dword ptr [ebp-0Ch],ecx 10:       vp=(void *)(&s); 00401036 8D 55 FC             lea         edx,[ebp-4] 00401039 89 55 F4             mov         dword ptr [ebp-0Ch],edx 11:       vp=(void *)(&s+1); 0040103C 8D 45 FE             lea         eax,[ebp-2] 0040103F 89 45 F4             mov         dword ptr [ebp-0Ch],eax 12: 13:       unsigned char c1 = *((unsigned char *)&s); 00401042 8A 4D FC             mov         cl,byte ptr [ebp-4] 00401045 88 4D F0             mov         byte ptr [ebp-10h],cl 14:       vp=(void *)((unsigned char *)&s); 00401048 8D 55 FC             lea         edx,[ebp-4] 0040104B 89 55 F4             mov         dword ptr [ebp-0Ch],edx 15: 16:       unsigned char c2 = *((unsigned char *)&s + 1); 0040104E 8A 45 FD             mov         al,byte ptr [ebp-3] 00401051 88 45 EC             mov         byte ptr [ebp-14h],al 17:       vp=(void *)((unsigned char *)&s + 1); 00401054 8D 4D FD             lea         ecx,[ebp-3] 00401057 89 4D F4             mov         dword ptr [ebp-0Ch],ecx 18: 19:       return 0; 0040105A 33 C0                xor         eax,eax 20:   } 0040105C 5F                   pop         edi 0040105D 5E                   pop         esi 0040105E 5B                   pop         ebx 0040105F 8B E5                mov         esp,ebp 00401061 5D                   pop         ebp 00401062 C3                   ret


Question: 迷惑的双**指针

test(s);还是值传递，只不过这个值刚好是个char *类型的，所以在test函数中只是产生了一个副本，不会对原来的s内容有影响。 test1（&s1）才是真正的地址传递，所以操作s1会导致值改变

引用 1 楼 tnt230 的回复:s传的是指针。而指针是值COPY。所有void test(char *p)中的p是copy了一份s s1传的是指针地址。所有不是值COPY。改变了指针指向。所以结果是对的  恩，有点明白了. 那再追加一个问题，请教你. int **p; int a[10]; p = &a；//提示错误，不能够把 int*[]转换为int **， 这个为什么呢，不都是地址吗？[/quote]  int *[]和int **是不同的类型。 可以：p = &a[0];

引用 8 楼 u013431701 的回复:又发现一个问题，还需请教.  char *p; char *p1;  test(p); test1(&p1);  test（char *p） {  p = ”555“； } test1（char ** p） {  *p = ”555“；  } p和p1都没有动态的分配内存空间，但是p就会导致程序崩溃，而p1就不会，为什么呢？ 我没发现错误，用valgrind查过了。  char *p; char *p1;  int main() {     test(p);     test1(&p1); }  test(char *p) {  p = "555"; } test1(char ** p) {  *p = "555";  }  而且，你这个跟动态内存分配没有关系。你只是往指针变量上赋了一个地址。

引用 楼主 u013431701 的回复:在用到**指针时，有些迷惑的地方.还请大家帮忙解答. 1.我想要把一个字符数组通过参数传递给一个函数，然后在函数中修改该字符数组. 程序如下. void main {  char * s;  char * s1  s = "woshishui";  test(s); test1（&s1） printf("s= %s\n",s); }  void test(char *p) {  char * s = "hahahah";  p = s; } void test1(char **p) {  char * s = "hahahah";  *p = s; } s打印出来的结果是不正确的. s1打印出来的结果是正确的.  有点疑惑. s传就去的是字符数组的首地址，在test函数中通过修改s的指向，不就相当于改变了字符数组s吗？ s1吧地址的地址传进去就可行，更不明白了，地址的地址，哪位高手能形象的说明下，真的很难懂啊. 拜托了. lz char *********************************************s；

引用 5 楼 u013431701 的回复:[quote=引用 1 楼 tnt230 的回复:] s传的是指针。而指针是值COPY。所有void test(char *p)中的p是copy了一份s s1传的是指针地址。所有不是值COPY。改变了指针指向。所以结果是对的  恩，有点明白了. 那再追加一个问题，请教你. int **p; int a[10]; p = &a；//提示错误，不能够把 int*[]转换为int **， 这个为什么呢，不都是地址吗？[/quote]  偷懒下不打字了，http://bbs.csdn.net/topics/370236512

//在堆中开辟一个4×5的二维int数组 #include <stdio.h> #include <malloc.h> int **p; int i,j; void main() {     p=(int **)malloc(4*sizeof(int *));     if (NULL==p) return;     for (i=0;i<4;i++) {         p[i]=(int *)malloc(5*sizeof(int));         if (NULL==p[i]) return;     }     for (i=0;i<4;i++) {         for (j=0;j<5;j++) {             p[i][j]=i*5+j;         }     }     for (i=0;i<4;i++) {         for (j=0;j<5;j++) {             printf(" %2d",p[i][j]);         }         printf("\n");     }     for (i=0;i<4;i++) {         free(p[i]);     }     free(p); } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19

引用 3 楼 saber_vsgoto 的回复:void test(char *p) {  char * s = "hahahah";  p = s; } void test1(char **p) {  char * s = "hahahah";  *p = s; }   值有test1 是改变了指针的值  test中没有改变 要改变应该 *p="asdfsdf" *p="asdfsdf"这个是编译不过的，字符指针是不能这样赋值的.

转   By-Value:        The value of a variable is sent to function. The actual parameter cannot be changed by function. "In" parameter   By-Reference   An address gets sent to function.                         The function can change the values at that address                         "Out" or "In-Out"   Sending by reference in C requires the use of the pointer symbol (*).               void f (int x)  // x is an integer             {                         x=x+1;             }             void h(int* p_x) // p_x is an address where an integer is stored.             {                         *p_x = *p_x + 1;             }   Can call a by-reference function using the address operator &               int x=9;             f(x) ;   // f cannot change value of x.             h(&x);  // h can change the value of x   Array parameters are similar to Java in effect                           int array[10];                                        void g(int arr[])                         //  put some stuff in it                         // ...                         g (array);                               Trace the following:                void f(int z)             {                         z=z+1;             }             void g(int a[])             {                         a[2]=8;             } void h(int *z) {                         *z = *z+1;             }             void main()             {          int x=6;                         int arr[5]                         for (int i=0;i<5;i++)                                     arr[i]=i;                         f(x);                         g(arr);                         h(&x);                         h(&(arr[4]));             }


Question: 字母计数问题

终于弄明白了，谢谢。

这个差不多 (a | 0x20 ) - ‘a'

比如说输入字母  char b; char index; char *pUp; scanf("%c", &b);  if(b < 'a') {   b += 0x20;   pUp = "大"; } else {   pUp = "小"; }  index = b - 'a' + 1; if(index >= 1 && ret <= 26) {   printf("你输入的是%s写字母\n该字母在字母表中处于的位置是：%d\n", pUp, index); } else {   printf("你输入的不是字母"); }

if(x >= 'a' && x <= 'z')  // 小写     printf("x在第%d的位置\n" ,x-'a'+1);  // x所在位置 else if(x >= 'A' && x <= 'Z')  // 大写     printf("x在第%d的位置\n" ,x-'A'+1);  // x所在位置

先判断是大写还是小写，然后再减去'A'或'a'， 然后再加上'A'或'a'的固定位置。不用循环


Question: 总是出现写入位置发生冲突，到底是怎么回事呢？（线性单链表，一维数组 ，游标）

该函数是实现（A-B）并（B-A）的，多谢各位，特别是3楼，就是那么一个小小错。。感谢5楼的赵老师的教导

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

引用 3 楼 u010800064 的回复: #include <stdio.h> #include <stdlib.h> #include <malloc.h>  #define MAXSIZE 1000  typedef struct { 	int data; 	int cur; }component, SLinkList[MAXSIZE];  void InitSpace(SLinkList &space) { 	for(int i = 0; i<MAXSIZE-1; ++i)  		space[i].cur = i+1;  	space[MAXSIZE-1].cur = 0; }  int Malloc(SLinkList &space) { 	int i = space[0].cur; 	if(i)  		space[0].cur = space[i].cur;  	return i; }  void Free(SLinkList &space, int k) { 	space[k].cur = space[0].cur; 	space[0].cur = k; }  void difference(SLinkList &space) { 	InitSpace(space); 	int s = Malloc(space); 	 	int r = s; 	int m, n; 	scanf("%d%d",&m,&n);  	for(int i = 0;i < m;++i) 	{ 		int j = Malloc(space); 		scanf("%d",space[j].data);  // 首先这就有错 改为 scanf("%d",&space[j].data); 		space[r].cur = j; 		r = j; 	}  	space[r].cur = 0;  	for(int i = 0;i < n;++i) 	{ 		int b; 		scanf("%d",&b); 		int p = s; 		int k = space[p].cur; 		while(k!=space[r].cur&&space[k].data!=b) 		{ 			p = k;k = space[k].cur; 		} 		if(k==space[r].cur) 		{ 			int j = Malloc(space); 			space[j].data = b; 			space[j].cur = space[r].cur; 			space[r].cur = j; 		} 		else 		{ 			space[p].cur = space[k].cur; 			Free(space,k); 			if(r == k) r=p; 		}  	}  }   int main() { 	SLinkList space; 	difference(space);  	system("pause"); 	 	return 0; }  水平有限看着耗费劲，  // 首先 scanf("%d",space[j].data) 就有错 改为 scanf("%d",&space[j].data);

能不能把函数想实现的目的简单说明一下, 比如different函数是坐什么用的，有什么问题

楼主？写入位置冲突是什么意思呢？


Question: 字符串指针疑问

在VC上面是相同的地址 常量区

"ab"存在于某个区域 p1和p2都指向这个区域

.rdata是常量区，不是分配在堆空间。

字符串“ab”分配在堆空间，可以理解为全局变量，指针相同是因为编译器优化的结果

编译器的优化处理，如今多数编译器皆如此

就是一个指针,严格来说应该写成const char* p1 = "xxxx" 两个指针相同就说明指向同一个地址空间呗,有啥不理解的呢? 这是一个编译器的行为,去纠结这个事情没有意义

可以相同 可以不同  为什么你觉得不能相同

因为字符串“abc”是一个放在一个常量地址处。指向该字符串，就是指向该常量地址。

搜“常量折叠”

你把"ab"看成是一个全局变量（静态字符串）即可理解。

相同的字符串常量只会有一个副本，所以p1和p2都指向了相同的地方，你可以改用下面的试试： char p1[] = "ab"; char p2[] = "ab";   引用 楼主 boyhailong 的回复:大家看下面代码 #include <iostream> int main(){ 	char* p1 = "ab"; 	char* p2 = "ab"; 	 }  为什么p1,p2指向为什么是相同的？怎么解释呢？

具体不了解编译器怎么处理，我想为了效率应该如上所说。

"ab"会保存在常量区, 一般的编译器都会优化, 相同的常量只保存一份.

编译器有优化，相同常量字符串用只存一次。


Question: 一个Makefile示例中的一些疑问

引用 5 楼 bai_hei1025 的回复:[quote=引用 3 楼 hnwyllmm 的回复:] http://www.google.com.hk/#newwindow=1&q=Makefile&safe=strict 这里很多介绍很详细  你好，这个之前有看过，但还是有些问题  编译的目标文件是：$(ALL_OBJS) $(ALL_PRGS) 最终输出的目标程序是： $(ALL_PRGS)  这段是否可以简化成： all: $(ALL_OBJS) $(ALL_PRGS)  .c.o: //即.c依赖于.o $(COMPILE) -c -o $@ $< $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH)  不明白为啥写了这么多，特别红色部分有什么用途？ all: $(ALL_OBJS) $(ALL_PRGS) .o: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c.o: $(COMPILE) -c -o $@ $<  $(INC_PATH) .c.lo: $(COMPILE) -c -fPIC -o $@ $<  $(INC_PATH)[/quote] “.c.o”是一个目标的名字。

引用 7 楼 bijiaoben 的回复:[quote=引用 5 楼 bai_hei1025 的回复:] [quote=引用 3 楼 hnwyllmm 的回复:] http://www.google.com.hk/#newwindow=1&q=Makefile&safe=strict 这里很多介绍很详细  你好，这个之前有看过，但还是有些问题  编译的目标文件是：$(ALL_OBJS) $(ALL_PRGS) 最终输出的目标程序是： $(ALL_PRGS)  这段是否可以简化成： all: $(ALL_OBJS) $(ALL_PRGS)  .c.o: //即.c依赖于.o $(COMPILE) -c -o $@ $< $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH)  不明白为啥写了这么多，特别红色部分有什么用途？ all: $(ALL_OBJS) $(ALL_PRGS) .o: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c.o: $(COMPILE) -c -o $@ $<  $(INC_PATH) .c.lo: $(COMPILE) -c -fPIC -o $@ $<  $(INC_PATH)[/quote] 楼主真的看了吗？ http://scc.qibebt.cas.cn/docs/linux/base/%B8%FA%CE%D2%D2%BB%C6%F0%D0%B4Makefile-%B3%C2%F0%A9.pdf 搜索一下SUFFIXES关键字，好好读一下老式风格的后缀规则。 还有.c.o:是指的.o依赖于.c[/quote] 这位大侠，这个我还真没有看过，领教啊，老式风格..........

引用 5 楼 bai_hei1025 的回复:[quote=引用 3 楼 hnwyllmm 的回复:] http://www.google.com.hk/#newwindow=1&q=Makefile&safe=strict 这里很多介绍很详细  你好，这个之前有看过，但还是有些问题  编译的目标文件是：$(ALL_OBJS) $(ALL_PRGS) 最终输出的目标程序是： $(ALL_PRGS)  这段是否可以简化成： all: $(ALL_OBJS) $(ALL_PRGS)  .c.o: //即.c依赖于.o $(COMPILE) -c -o $@ $< $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH)  不明白为啥写了这么多，特别红色部分有什么用途？ all: $(ALL_OBJS) $(ALL_PRGS) .o: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c.o: $(COMPILE) -c -o $@ $<  $(INC_PATH) .c.lo: $(COMPILE) -c -fPIC -o $@ $<  $(INC_PATH)[/quote] 楼主真的看了吗？ http://scc.qibebt.cas.cn/docs/linux/base/%B8%FA%CE%D2%D2%BB%C6%F0%D0%B4Makefile-%B3%C2%F0%A9.pdf 搜索一下SUFFIXES关键字，好好读一下老式风格的后缀规则。 还有.c.o:是指的.o依赖于.c

引用 5 楼 bai_hei1025 的回复:[quote=引用 3 楼 hnwyllmm 的回复:] http://www.google.com.hk/#newwindow=1&q=Makefile&safe=strict 这里很多介绍很详细  你好，这个之前有看过，但还是有些问题  编译的目标文件是：$(ALL_OBJS) $(ALL_PRGS) 最终输出的目标程序是： $(ALL_PRGS)  这段是否可以简化成： all: $(ALL_OBJS) $(ALL_PRGS)  .c.o: //即.c依赖于.o $(COMPILE) -c -o $@ $< $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH)  不明白为啥写了这么多，特别红色部分有什么用途？ all: $(ALL_OBJS) $(ALL_PRGS) .o: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c.o: $(COMPILE) -c -o $@ $<  $(INC_PATH) .c.lo: $(COMPILE) -c -fPIC -o $@ $<  $(INC_PATH)[/quote]  我也不明白，一起研究下，有结果贴出来看看

引用 3 楼 hnwyllmm 的回复:http://www.google.com.hk/#newwindow=1&q=Makefile&safe=strict 这里很多介绍很详细  你好，这个之前有看过，但还是有些问题  编译的目标文件是：$(ALL_OBJS) $(ALL_PRGS) 最终输出的目标程序是： $(ALL_PRGS)  这段是否可以简化成： all: $(ALL_OBJS) $(ALL_PRGS)  .c.o: //即.c依赖于.o $(COMPILE) -c -o $@ $< $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH)  不明白为啥写了这么多，特别红色部分有什么用途？ all: $(ALL_OBJS) $(ALL_PRGS) .o: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c: $(COMPILE) -o $@ $<  $(SHARED_OBJS) $(LIB_PATH) $(INC_PATH) .c.o: $(COMPILE) -c -o $@ $<  $(INC_PATH) .c.lo: $(COMPILE) -c -fPIC -o $@ $<  $(INC_PATH)

搜“跟我一起写makefile”

加美元符号的都是宏定义，前面已经定义过的。

Makefile里面的变量使用，楼主了解多少？


Question: C语言参数入栈顺序为什么是从右向左？

一是为了支持可变参数 二来猜测即使参数固定，也方便编译器实现

膜拜了，这个问题真心没考虑过

这是历史原因造成的。 历史上，C语言的参数个数，并不是固定的。 和Fortran，Basic，Pascal相比  C是函数式的语言，而非命令式的语言。 C除了控制语句外，没有命令，只有声明（定义）和表达式。  C只有函数调用，没有输入输出命令（语句）；输入输出，不是语言的一部分。 早期的Fortran，Basic，Pascal 都有，输入输出命令（语句）；他们是语言的一部分。  C的函数调用，也是一个表达式，即函数调用表达式。  这样C函数，就是仅有的程序结构了。  这样，C 既有不确定类型和个数参数表的 scanf，printf 也有，其他类型的不确定个数参数的函数；  用一个，统一的调用约定处理的话。  自然是，从右向左入栈，调用者清栈比较好。  同时，这样可以保证： 1）第一个参数，是最接近栈顶的。其他，参数依序排列。 2）传递的参数长度过大（参数过多），不会出错。

google calling convention

没有为什么 爱怎么做就怎么做 看谁写的编译器了

引用 楼主 armfpga123 的回复:哪位大虾详细解释下？之前在网上找了不少资料，一直没得到令人信服的理由。 编译器这样做效率高而已

1L说得没错，可变参数最有名的例子就是printf

支持变参可能是原因之一。另外就是传统了。cdecl只是默认，你可以可以选stdcall或pascal呀。

编译出来的c/c++程式的参数压栈顺序只和编译器相关!

引用 楼主 armfpga123 的回复:哪位大虾详细解释下？之前在网上找了不少资料，一直没得到令人信服的理由。 C语言没有规定，是编译器自己定义的 x64下就不是这样子了

看看printf的实现

为了支持可变参数


Question: VS2012中如何将文件夹及文件添加到动态链接库？

搜“资源型DLL” ？

看看.rc文件

rdb打包工具

引用 3 楼 zhuobattle 的回复:添加到rc文件中，编译到dll里面。 另外你的资源是很多界面图片吗？如果是这样就不建议加到rc中了。 图片不是很多，还有一些.txt文件，以及一些其它文件。


Question: [C语言书籍]《C语言程序设计》谭浩强

引用 16 楼 supermegaboy 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] //char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。  // //x和[3]结合说明是一个大小为3的数组，该数组指向了一个指针，该指针指向一个函数，该函数的无参数，返回一个指针，该指针指向一个大小为5的char型数组 #include <stdio.h> #incl ude <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*x000)[5];//返回值     char (*(x00)())[5];//函数原型，参数为空，返回值为指针     char (*(*x0)())[5];//数组的元素，是个函数指针     char (*(*x[3])())[5];//是个数组，大小为3      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  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",...)】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=...】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “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  而这位未定义行为大师，一直以来都在对着一匹鹿高呼：上帝啊！终于让我发现一只身上有大园花印的大肥马了！！！[/quote] +1

引用 41 楼 supermegaboy 的回复:[quote=引用 34 楼 mmns 的回复:] [quote=引用 15 楼 supermegaboy 的回复:] [quote=引用 3 楼 mmns 的回复:] 虽然很多人都说这本书不好,但我却不这么觉得。在上世纪90年代初计算机书籍缺乏的时候,它带我走进了C语言的世界，直到今日，我的日常工作都是使用C语言。每次翻看都百感交集。  这只能说明一点：你的C没有获得进步。[/quote] 非常感谢您老人家给的批评指定。 从1999年开始到现在一直在做C语言的工作，现在是公司的构架师，主要工作领域是做高精度与高动态性卫星信号接收机，主要的用的语言就是C，上位机工具都用C++,真是是很久没来CSDN了，今年这两个月上来看了看，发现真的是大神辈出啊，特别是C语言方面的大神，这里膜拜一下。[/quote]  谈起工作，其实我公司的工作与你这个行业有一定的关联性，一定程度上是你这个行业的用户，你这个行业为我们服务，而我们则为政府和人民服务。你99年开始用C，到现在都有14年了，是个完全的老手了，应用上积累了相当多的经验。如果从我真正开始使用C/C++的时候算起（不算大学那个阶段），你用C的时间比我还要多几年，资历上我要尊称你一声前辈。但是，从一个14年的老手口里，一句“每次翻看都百感交集”却让人不得不想到，是否在语言的修炼上忽略了些什么呢？  初学者看谭教授的书，大赞好书，这不奇怪，初学者是无辨识能力的，你指着一只鹿告诉初学者，它叫马，初学者就会认为那是一匹马。但对于一个老手，不要说14年，即使只有几年，再回过头看谭教授的书，好歹都应该看得出一些问题了吧。我这里给你看一个链接，虽然我对链接中那个人的行为并不完全赞同，但至少可以让你对谭书出现的问题有个观感。  http://bbs.chinaunix.net/thread-1686753-1-2.html  为什么有这么多人指责谭书的错误？是因为谭教授的书容不得有错，谭叫兽、谭叫瘦、谭叫肥的书可以有错，但你谭教授的书就是不能有错，这与谭教授的水平无关，而是因为这书几千万的销量，即使书中出现一个小错，都会通过这个销量无限放大。书的质量要对得起销量，为什么几乎无人谈论《c++ primer》有错？两本书的差距实在太大了。[/quote]     我觉得你想多了，每次翻看这本书就百感交集，更多的出于感情因素，就像你的启蒙老师可能水平没那么高，但依旧能让你尊重， 另外说一句，这本书没你说的那么糟，一个问题有很多种理解方式，你可以说你的理解更高，但没必要非要把别的理解方式都说成是垃圾，你让C语言之父来告诉你指针是什么，他能告诉你的答案也只有一个：地址变量。白马难道非马吗。你骂这本书的时候，你知道有多少高手的第一本入门书都是这本书吗。按你的说法几千万的销量应该造成很坏的影响了才对，事实不是吧，没见谁看这本书看傻了，或者看这本书造成了什么不可逆的坏影响吧，相反很多高手都是从这本书开始学C的。     我这个岁数实在是不愿与人辩论了，今天算个特例。但我想我们不管是从治学也好，从做人也好，是否应该谦虚一点。

我用DNA的4种碱基对来理解所有生命。

引用 15 楼 supermegaboy 的回复:[quote=引用 3 楼 mmns 的回复:] 虽然很多人都说这本书不好,但我却不这么觉得。在上世纪90年代初计算机书籍缺乏的时候,它带我走进了C语言的世界，直到今日，我的日常工作都是使用C语言。每次翻看都百感交集。  这只能说明一点：你的C没有获得进步。[/quote] 哈哈

<The C Programming Language>Brian W.Kernighan,Dennis M.Ritchie觉得这本做教材不错

引用 44 楼 lwouyang 的回复:引用 43 楼 l1095260368 的回复:[quote=引用 21 楼 supermegaboy 的回复:] [quote=引用 19 楼 l1095260368 的回复:] [quote=引用 14 楼 supermegaboy 的回复:] [quote=引用 6 楼 u011530143 的回复:] [quote=引用 2 楼 u010653211 的回复:] 我就是看这本教材入门的老谭的书还是不错的，特别事指针，讲得那个深度还是足够应付工作了。  谭叫兽不过是以为自己写的是指针而已，而你也不过是以为自己看的是指针而已。[/quote] 看了下那书的指针部分。没什么不对啊，是我指针思想浅薄了吗？ [/quote]  那你说说，你看了谭教授的书后，你认为什么是指针。[/quote] 指针是地址？[/quote] 又一个受害者。 C 设计之初确实是从方便实用角度用指针这个概念来包装了一个个地址值，也确保了 C 语义的精简度。复杂组织大都借助指针来构造。确实，什么样的程序最后编译汇编后不都得回归到机器指令的寻址。但若将高级语言的许多语义的本质都理解为地址，则这些高级语言都不复存在了。你用机器语言的思想去编程？[/quote]

引用 43 楼 l1095260368 的回复:引用 21 楼 supermegaboy 的回复:[quote=引用 19 楼 l1095260368 的回复:] [quote=引用 14 楼 supermegaboy 的回复:] [quote=引用 6 楼 u011530143 的回复:] [quote=引用 2 楼 u010653211 的回复:] 我就是看这本教材入门的老谭的书还是不错的，特别事指针，讲得那个深度还是足够应付工作了。  谭叫兽不过是以为自己写的是指针而已，而你也不过是以为自己看的是指针而已。[/quote] 看了下那书的指针部分。没什么不对啊，是我指针思想浅薄了吗？ [/quote]  那你说说，你看了谭教授的书后，你认为什么是指针。[/quote] 指针是地址？[/quote] 又一个受害者。 C 设计之初确实是从方便实用角度用指针这个概念来包装了一个个地址值，也确保了 C 语义的精简度。复杂组织大都借助指针来构造。确实，什么样的程序最后编译汇编后不都得回归到机器指令的寻址。但若将高级语言的许多语义的本质都理解为地址，则这些高级语言都不复存在了。你用机器语言的思想去编程？

引用 21 楼 supermegaboy 的回复:引用 19 楼 l1095260368 的回复:[quote=引用 14 楼 supermegaboy 的回复:] [quote=引用 6 楼 u011530143 的回复:] [quote=引用 2 楼 u010653211 的回复:] 我就是看这本教材入门的老谭的书还是不错的，特别事指针，讲得那个深度还是足够应付工作了。  谭叫兽不过是以为自己写的是指针而已，而你也不过是以为自己看的是指针而已。[/quote] 看了下那书的指针部分。没什么不对啊，是我指针思想浅薄了吗？ [/quote]  那你说说，你看了谭教授的书后，你认为什么是指针。[/quote] 指针是地址？

依我看，谭教授的书还是可以的啊，虽然有一些小问题，代码格式也不太标准，但对相关知识的普及的确有不小的贡献

引用 34 楼 mmns 的回复:[quote=引用 15 楼 supermegaboy 的回复:] [quote=引用 3 楼 mmns 的回复:] 虽然很多人都说这本书不好,但我却不这么觉得。在上世纪90年代初计算机书籍缺乏的时候,它带我走进了C语言的世界，直到今日，我的日常工作都是使用C语言。每次翻看都百感交集。  这只能说明一点：你的C没有获得进步。[/quote] 非常感谢您老人家给的批评指定。 从1999年开始到现在一直在做C语言的工作，现在是公司的构架师，主要工作领域是做高精度与高动态性卫星信号接收机，主要的用的语言就是C，上位机工具都用C++,真是是很久没来CSDN了，今年这两个月上来看了看，发现真的是大神辈出啊，特别是C语言方面的大神，这里膜拜一下。[/quote]  谈起工作，其实我公司的工作与你这个行业有一定的关联性，一定程度上是你这个行业的用户，你这个行业为我们服务，而我们则为政府和人民服务。你99年开始用C，到现在都有14年了，是个完全的老手了，应用上积累了相当多的经验。如果从我真正开始使用C/C++的时候算起（不算大学那个阶段），你用C的时间比我还要多几年，资历上我要尊称你一声前辈。但是，从一个14年的老手口里，一句“每次翻看都百感交集”却让人不得不想到，是否在语言的修炼上忽略了些什么呢？  初学者看谭教授的书，大赞好书，这不奇怪，初学者是无辨识能力的，你指着一只鹿告诉初学者，它叫马，初学者就会认为那是一匹马。但对于一个老手，不要说14年，即使只有几年，再回过头看谭教授的书，好歹都应该看得出一些问题了吧。我这里给你看一个链接，虽然我对链接中那个人的行为并不完全赞同，但至少可以让你对谭书出现的问题有个观感。  http://bbs.chinaunix.net/thread-1686753-1-2.html  为什么有这么多人指责谭书的错误？是因为谭教授的书容不得有错，谭叫兽、谭叫瘦、谭叫肥的书可以有错，但你谭教授的书就是不能有错，这与谭教授的水平无关，而是因为这书几千万的销量，即使书中出现一个小错，都会通过这个销量无限放大。书的质量要对得起销量，为什么几乎无人谈论《c++ primer》有错？两本书的差距实在太大了。

要说，学究式地认真出版，清华大学出版社，随便抓几个壮丁来，就能修正谭浩强的书的错误了。  谭浩强，那年代的过来人，老谋深算了。看着长江后浪推前浪似地，都来挑谭浩强的错，他背后笑了。“人家英语老师拼命让学生做英语句子改错题，想提高学生英语水平，难啊。老谭一出手，无数人，主动挑错，挑毛病挑着挑着，学生主动地提高了自己的水平”

有时候，老人家，故意卖个错误， 是迎合年轻人挑毛病的习惯，多少学生为了挑错而一头扎进去C语言.

引用 36 楼 u013344873 的回复:空间和时间的局限性。     q = f(空间xyz，时间t，其它参数)... ∂q/∂t ≠ 常数  一个现象，不同的空间地方，时间，环境背景，个人背景，自然有不同的结论...  今天，洋人的书，国产的书，多如牛毛的背景下，又或者评论者已不再是对计算机一无所知的状态下，又或者..... 在当年，有几台电脑，有几本书？  今天，毛都没长齐的孩子，恐怕都能玩python了。当年，人家娃都能上街打酱油了，娃他爹还没玩过电脑。  谭浩强的书，面向的是谁？ 恐怕不是软件学院或者计算机系， 而是广大的，工科必修课C语言（这类人，根本就没打算用C语言或者说IT来作为主业。）  面对水平参差不齐，有些可能是大学才第一次接触计算机。 如何能写本更经得起考验的教科书？  其读者，本来就是为了拿两三个学分的《必修C语言》... 如果充满高级的学究式的内容，想来会是挂科一片，骂声一片...可能其结果，会向必修的《军事理论》一样，一点收获都没有

不否认这本书曾经起到的启蒙作用。就像没饭吃时啃窝窝头都觉得挺香。 批评这边书是因为其品质不高，代码和思路质量粗滥。就像喝吃惯了鲜鱼嫩肉，面对馒头如何下咽？ 要知道作为教育，特别是启蒙，传授落伍或者错误知识的毒害作用其后果有多严重。一个人得长到多大才明白“哦，原来我不是从垃圾堆里捡来的。” 不知道是此书的作者不在意不愿意，还是有心无力，都出了这么多版了没见改善。想想，那些真正写了本好书的人是多么的了不起和不容易。

真心膜拜大牛的同时，还是觉得纳闷，为啥这么多人都说老谭的那本书不好呢，我是真心不觉得，我是94年上的大学，那时候我能买到的C语言的书只有这本，记得95年我的一个外地同学还专门让我在北京买了一本寄给他，他现在在Intel。我本人是学完汇编以后自己用这本书学的C语言，真是觉得没啥问题啊，几天就看完了，就开始用这个写东西了，而且我认识的几个技术不错的岁数差不多的哥们，也没见谁说这本书垃圾，顶多也就是说这书不太全面，但给入门的人看还是不错的，是我自己太怀旧了还是现在优秀的书太多了。

引用 15 楼 supermegaboy 的回复:[quote=引用 3 楼 mmns 的回复:] 虽然很多人都说这本书不好,但我却不这么觉得。在上世纪90年代初计算机书籍缺乏的时候,它带我走进了C语言的世界，直到今日，我的日常工作都是使用C语言。每次翻看都百感交集。  这只能说明一点：你的C没有获得进步。[/quote] 非常感谢您老人家给的批评指定。 从1999年开始到现在一直在做C语言的工作，现在是公司的构架师，主要工作领域是做高精度与高动态性卫星信号接收机，主要的用的语言就是C，上位机工具都用C++,真是是很久没来CSDN了，今年这两个月上来看了看，发现真的是大神辈出啊，特别是C语言方面的大神，这里膜拜一下。

引用 11 楼 user-11 的回复:引用 6 楼 u011530143 的回复:[quote=引用 2 楼 u010653211 的回复:] 我就是看这本教材入门的老谭的书还是不错的，特别事指针，讲得那个深度还是足够应付工作了。 请问楼主是做什么工作的？[/quote]我以前是程序员，现在跑鞋客户，也偶尔写点demo吧，搞嵌入式消费类电子。

引用 6 楼 u011530143 的回复:引用 2 楼 u010653211 的回复:我就是看这本教材入门的老谭的书还是不错的，特别事指针，讲得那个深度还是足够应付工作了。 请问楼主是做什么工作的？


Question: 除数竟然可以是0？

谢谢！！！！！！！！！！！！！！！！

具体的编译器有具体的解释。在gcc下会输出-nan  猜测DEV C++处理w[i]=sin((i-14)*0.25*PI)/PI/(i-14);两种可能，一种是当被除数为0，既sin((i-14)*0.25*PI)=0时，不计算除数就输出0；令一种是两个除号分解为sin((i-14)*0.25*PI) * (i - 14) / PI;  自己写两个表达式验证一下就可以了。第一种可以用0/（i-14）；第二种可以验证 0/PI/（i-14）;

编译器也是人写的

w[i]=sin((i-14)*0.25*PI)/PI/(i-14); i=14时，i-14=0,0*0.25*PI=0 sin(0)=0,0/PI=0 i-14=0,0/(i-14)不是0/0么？

别逗了好么，你那是浮点数在运算。你怎么得出的0/0.


Question: 调用API函数，编译后出现链接错误！

http://technet.microsoft.com/zh-cn/library/ee488255  Requirements Header oleauto.h Library oleaut32.lib  有设置链接oleaut32.lib库么？

1，检查一下oleaut32.lib是否确定已经加好了 2，看看那个头文件是否声明C规范 #ifdef  __cplusplus extern "C" { #endif 。。。。。。。。 #ifdef  __cplusplus } #endif

把库指定给指令参与链接就可以了.

很明显是光包含了头文件,而没有引用库,才导致了这样的错误

cvi工程的代码源文件就是*.C啊！

把ZDXLCOMM·c后缀改成·cpp也许可以解决问题。 个人意见，仅供参考。

大概是c/c++混合编程引起的吧。


Question: 这是怎么算出来的?

恩  ,64位计算器把-1看成0xFFFF FFFF FFFF FFFF就好.不然是算不出正确的结果的.

0xFFFFFF就是16777215, -1*16777215 = -16777215 = 0xFFFFFFFFFF000001

证明: 令 Sum = -1 * 0xFF FFFF, 即 Sum = 0xFFFF FFFF * 0xFF FFFF,两边同时加上0xFF FFFF,得 Sum + 0xFF FFFF = (0xFFFF FFFF + 1) * (0xFF FFFF),即 Sum + 0xFF FFFF = 0 * 0xFF FFFF,即 Sum + 0xFF FFFF = 0,得 Sum = 0 - 0xFF FFFF,即 Sum = 0 + (-0xFF FFFF) 令beta=(-0xFF FFFF) 则beta的反码为0xFF00 0001 代入得Sum = 0 + beta = 0 + 0xFF00 0001 = 0xFF00 0001  有错误没?

呃,那啥  能给个简单的演算过程不...


Question: c语言的windows程序如何访问sqlserver数据库

LS正解！！

难道一年一度的毕业设计又来了！！！