Question: c/c++和java选择？

把C，C++，java这三门学会，其他的语言都是浮云。。。好的程序员的学习能力是很强的。

看你个人吧 就业JAVA在国内是一个方向，你看CSDN的JOB频道，搜一下就知道了 但是个人对面向对象不感冒，面向过程这种去适应机器思路的方式更感兴趣 虽然现在在用JAVA，但是有机会还是会去玩C的

有空都学会了最好，技多不压身！ 顺便说一下，人生最重要的不是努力，不是奋斗，而是抉择。当你走到人生的十字路口，不知如何辨别方向的时候，请停下来，好好想一想，你是什么星座。

不管是 c/c++ 还是 java  如果lz没打算自己当老板，只是找份工作，写写代码，语言不重要，重要的是做到让自己对于公司来说很重要，最理想的情况是你对于公司来说无可替代。  这里插一个小故事，据说之前有一个电信相关行业的老程序员，工资不算低，他负责替他们公司开发并维护了一套计费收费系统。代码写的也不定就很好，只是一直很稳定，至少在这个老程序员的维护下一直很稳定。后来这个老程序员或者是自身原因，或者是待遇的原因离职了，公司也没挽留，觉得系统很稳定，还一直开这么高工资，公司觉得养了个‘闲人’，就找个接手的人。没多久，各种问题暴露出来了，代码不规范，加新功能很困难，耦合度太高，不好扩展，重构代价很大，焦头烂额。最后的结果可想而知，公司只能再把这个员工给请回去，并开了更高的薪资。  这里不是鼓励lz去写难以维护的代码，而是告诉lz，不管你是什么语言，它只是工具，重要的你。你对一门语言掌握到了什么程度，你对一个项目掌握到了什么程度，你对软件行业的生产流程理解到什么程度。  所以与其纠结怎么选择，不如考虑怎么让自己无可替代！

引用 9 楼 SalmonRun 的回复:说点个人观点： 学习C++， 是兴趣，学吧。 要找工作， 你得考虑了， 你的目标企业是什么，也许 绝大多数的c/c++代码都是以前的， 你进去首先就是一个复杂的code base。 你想把这些代码拿起， 三思吧。 见到这些代码，本能的反映应该是逃跑。 java， 至少你在学习的短期时间内， 用一些成熟的框架， 你还能干些事情，能做一个对社会有用的人。这也代表 有工作。 javascript, ruby， 或者更新鲜语言的人， 已经开始鄙视java的庞大，复杂，开发效率低下了。 世界就是这样的循环， 程序员嘛， 都有一个鄙视链。 创业公司用c++，疯了！传统大企业用C++， 90%是遗留代码， 并且在公司内部一定有中坚的C++力量， 否则早就java化了。 偏硬件的公司， 那基本c/c++, 没有异议， 但是你得有硬件知识吧， 至少也是驱动，平台相关的吧。 也许在流行的开源技术中， 可以看到一些C++的应用， 背后也许都有一个更早的java库。 现在都云了， 换个语言，就能提升一些性能，何乐而不为。这也是C++一个可喜的地方。 不要说java的效率和C++逼近了， 你拿一个for循环100万次， 1000万次，有什么意义， 最后生成的代码都那么简单， 效率差不多那是应该的，在考虑动态利用CPU特性，超越也是应该的。 当前c++的发展状态比任何时候都好，主要的c++编译器， vc/gcc/clang 对标准的支持， 比历史上任何时候都给力， 尤其是clang提供的library，让c++工具有了依赖的基础的库。 微软的表现也是引领趋势， vs2015的跨平台支持，没有比这更有力的事情了， 同时支持windows， android， ios的编译。 鲍尔默在时，估计都搞不起来。  现在c++大会比历史上任何时候都活跃， 参加人数也创新高。 但是c++已近远不及90年代那样火了， 也正常，java不也受到了挤压。 虽然Bjarne说C++适合初学者， 但是业界的实际情况是， C++不适合初学者。 如果你功底扎实，那么也需能找到c++的一席之地。重新学习， 算了吧， 省点时间，干点更有意义的事情。  当然，爱好除外，世界不能排除超能力和天才。  创业公司不应该用c++？ 我在卢森堡一家创业公司，用的就是c++

看公司需要什么吧，要求你用JAVA你就学JAVA。 要求你用C你就用C。 要求你用C++,你就用C++。 当然这个在入职的时候就确定好了的吧。 像我就是做了三年MFC，又开始用C做服务器。

对于我来说，看工作场景需要。  一般情况下，我会优先考虑JAVA和C#，因为方便，开发效率高，可用的jar包或者.net控件也挺多的。  如下环境下，我会选择C++： 1.没办法使用JAVA和C#； 2.对执行效率要求比较高； 3.对可靠性要求比较高； 4.有较多的底层操作。  总的来说，在实际工作中，我是能用JAVA就用JAVA，若不能，退而求其次：.net，若再不能，再退，使用C++，还是不行，考虑C，C还是不行，考虑各种方言。  打死我也不用汇编----------打不死另外考虑。

桌面, 硬件 -> c/c++ 平板 -> java  在桌面程序上你不可能用 java 探索 windows 的底层 在平板程序上你有可能用 c/c++ 探索系统的底层

你来C/C++论坛问这个问题，明显只能听到一种声音

android OR ios

C/C++确实相对JAVA较难，但也并没有难到哪去，真正程序员都懂C，而且把C/C++学好了，之后想转其他任何语言都很快

看了大家的评论，都是在喷JAVA。 其实不然，每个语言都有自己的一片天地。 1.C++在底层、游戏、操作系统、通信等领域确实是一个霸主的地位。但是它在网站开发、移动开发等领域又有其不足。C++也一直在不断的发展，但是毕竟出得比较早，所以语言上的设计相对JAVA来说比较难，特别是在内存管理和指针应用方面。但是未来说不定也会有大的改进。 2.JAVA因为框架多，封装的函数多。所以很多人都会学JAVA很垃圾。会这么说的人，肯定从来没搞过JAVA深层次的东西。而只是停留在java一些简单的API的使用上。然而，在web领域，集群、高并发、负载均衡、大数据、分布式。更不用说移动领域Android,这些很多都和java相关。Java学得好的高度就是架构师，这个要求也是很高的。 学什么语言，若不考虑工资，应结合自己的兴趣。不然应该比对当前市场行情，做一个正确的选择。 另外，推荐你同时多多掌握几门语言。只能你研究得深，学哪个语言找工作都是能找到的，只不过相对的机会的多少罢了。

java是傻瓜相机  傻瓜相机也能照出不错的照片  像素够高就行   像素不够了  就等人家搞一个像素更高的jar包就ok了  c/c++是纯手动相机   能找出质量最高的相片来，但需要照相的人的水平足够高   java机会确实多，因为用得多，但这并不意味着学c/c++就没前途  c/c++如果学精通了，java这种渣渣算个毛

有时去执行一个错误的决定总比优柔寡断或者没有决定要好得多。

虽然大师兄跟我说过，不管你学的事什么语言，都是殊途同归。我们修真之人，都不要在乎这些差别，要参透的是程序的本质。然后他又说，不过，用Java的都是傻逼。大师兄跟我一样，C++的功底深厚，面向对象的各种技能用的精通，只是可惜，他还没有对象。  -----------转载自 知乎

C/C++学不好，一辈子写程序都在云里雾里，抓不住编程的核心，永远都是对封装的套用

看你喜欢哪个吧。。。反正我是看需求，需要什么学什么。。。工作需要深究某一方面，就专一死命研究，工作需要博学点，就逮啥学啥。。。。 搞得我java->c#->c/c++-->python->vb>obj-c流行点的语言全弄过了

我觉得 c或c++是 各种语言的基础。与java并不冲突。要想走得长远，还是先从c或c++入手吧！

觉得C很有深度, 可以从底层去创造. java封装了太多, 丢失了很多创造性


Question: C语言循环

TC,BC 中，可以这么做 #include<dos.h> unsigned char far * p = MK_FP(seg,ofs); p+=  rom_size seg  =  FP_SEG(p); offset = FP_OFF(p);

该怎么改呢？知道的请告诉我，谢谢！

究竟该怎么改啊？谢谢！

16Bits 代码，要确保 offset 在同一个64K范围之内 如果超过范围，必须调整段 的值，否则会出现 指针绕回现象 把两个 不同64K内存的读写，变成同一个64K内存的读写，这样读写位置就错了

段seg和 偏移offset 一块调整， 小心段折返错误

不是太明白，这个程序里没0xFFFFL 和 0xFFFFUL

其实跟汇编关系不大，主要读内存的内容

0xFFFF 和 0xFFFFL 和 0xFFFFUL 不是一回事！

自己调试吧，不会汇编


Question: 问一个多级指针的问题，这个程序报错；

引用 3 楼 weixin_29956463 的回复:q是int** 引用 1 楼 user-2 的回复:*q 是一个 int*  100是一个 int 你说呢 # include <stdio.h>  void f(int ** q) { 	int a = 100; 	*q = &a; }  void g(void) { 	int i = 10; 	int * p = &i;  	f(&p);  	printf("i = %d\n",i); }  int main(void) { 	g();  	return 0; } 这样写为什么还是改写不了i的值啊？；

q是int**

引用 1 楼 user-2 的回复:*q 是一个 int*  100是一个 int 你说呢  原来如此，多谢！

*q 是一个 int*  100是一个 int 你说呢


Question: 求教openat函数的用法

引用 3 楼 user-1 的回复:man opendir man dirfd 总算等到我要的东西了，第二个函数对我太有用了，十分感谢！

man opendir man dirfd

引用 1 楼 user-1 的回复:建议先把第一二章看明白了。  DESCRIPTION        The  openat()  system call operates in exactly the same way as open(2),        except for the differences described in this manual page.         If the pathname given in pathname is relative, then it  is  interpreted        relative  to  the  directory  referred  to by the file descriptor dirfd        (rather than relative to the current working directory of  the  calling        process, as is done by open(2) for a relative pathname).         If  the pathname given in pathname is relative and dirfd is the special        value AT_FDCWD, then pathname is interpreted relative  to  the  current        working directory of the calling process (like open(2)).         If the pathname given in pathname is absolute, then dirfd is ignored. 关键在于第一种情况，这个要给一个dirfd，可是我试了，open函数打不开目录，如果给目录的话，会报“Is a directory”的错。 如果dirfd给的是一个打开的文件描述符，会报无效的文件描述符这个错，所以现在问题是纠结于这个第一种情况下，dirfd如何赋值。这才是重点！而且关键是网上现在搜不到任何相关的例子函数！


Question: 指导一下关于深度优先搜索的问题

需要知道节点的父子关系，可以在遍历过程中保存每对节点的先后关系，也可以保存当前节点的父栈。


Question: C语言小程序（1）

#include<conio.h>去掉，void main(void)改为void main();getchar()去掉


Question: 关键字static的作用是什么

应该说，static 修饰的变量如果有初始化语句： static int a=1; 该语句只生效一次，下次进入函数，还是其之前被改变的值。 跟你在函数外声明了一个全局变量除了作用域之外没区别。

每天回帖即可获得10分可用分！  1：全局变量前加static      此时与系统默认(未显示添加)的auto自动变量关键字功能背道而驰；如果全局变量被auto修饰，则外部其它文件可用extern访问，如果加了static，为本文件内有效； 2：局部变量前加static      局部变量的存储区将由堆栈内存区移至静态存储区，和全局变量有同等生存期(从定义位置处到程序结束执行)；此时被static修饰的局部变量有局部可见性(在定义处)，会"记忆"访问它之后的最后一个最新的值，并供下次访问使用。  楼主要是觉着解答如意，要给分哟，我盼着挣点积分，都盼到太阳从南边出来了。。

在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。

维持其值不变 不是指 你调用 ++a他值仍然不变，否则这个变量还叫变量吗  维持其值不变  指的是：函数每次执行完的时候这个变量不会销毁，比如某一次执行完后值为10，下一次再调用该函数的时候，他的值仍是10，而你可以用代码改变他的值

静态变量存放在程序的静态区（又称全局区），其生命周期是整个程序， 只不过访问（可见性）受其定义位置的限制，如果定义在函数中，其可见性和一般局部变量没有区别，只不过，在函数执行结束其内存不会被销毁；如果定义在类中，其可见性属于整个类，而不是具体某个实例化对象，也就是类的所有对象共享这个变量；如果在模块外（即所谓的静态全局变量），其可见性在整个文件。 总之，静态变量在访问时，其值可以被改变，但不会随着模块的退出而释放，只要程序没有结束，它就会一直在内存中

在函数体，一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 这里的说法是对的。 void fun(){ static int a=1; //改为int a=1比较下 printf("%d\n",a);  ++a; } 这里如果 没有++a。a确实一直是不变的。 可以这样认为，静态变量只会初始化一次。所以以后每次调用都在原来的基础a上来++

看到这么多大神回复.我只纯顶顶吧.

因为历史的原因，C中的一些东西在术语的使用上乱得很，实在看不下去。  1)在函数体，一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 --->>>真实的情况是，在函数体内用存储类指定符static声明的标识符是无链接的，它所指示的对象具有静态存储期，在程序启动时创建（并初始化为0），而且仅具有块作用域，所以只能在函数体内的某些部分可见（或者使用）。 2) 在模块内（但在函数体外），一个被声明为静态的变量可以被模块内所用函数访问，但不能被模块外其它函数访问。它是一个本地的全局变量。 －－－>>>问题在于，函数参数列表不是函数体，难道参数也是静态的？再说，因为作用域的关系，它也未必能被当前模块内的函数访问： void f (int x)  {      a = 1;     //可以？？ } int main (void) {      f (a);     //可以？？ } static int a; 3) 在模块内，一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是，这个函数被限制在声明它的模块的本地范围内使用。 ==>>>>>竟然有静态函数？闻所未闻。static作用于函数，我们说此函数是“具有内部链接属性”的。  最后，光这3条还总结得不够。比如， void f (int a[static 3]); 这里的static又是什么意思涅？

如果去掉static，每次执行函数都会是全新的局部变量，输出结婚始终是1;如果加了static，变量会在每次调用函数时继承下去，而且只进行第一次初始化为1,之后会累加

这个说法是错的  局部 static 变量 只保证函数调用完毕不会销毁 至于变量的值 就不是 static 能管得着的了


Question: C语言多线程问题求助！！！

楼主这个sleep也太长了吧

引用 5 楼 xian_wwq 的回复:多线程运行的时候，不能按照串行的思维去考虑 在both中添加  printf("%d\n",i);  可以看到i不是你想象的方式在逐次增加，而是这样 我的是顺序+1的

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

可以执行的楼主

可能是main() 中执行了getchar()之后主线程退出了，导致创建的线程也随之推出，可以在getchar()加个几秒延时试下

多线程访问同一数据要加锁的啊，多线程里面最重要的部分

追加，我是用vs2010的。


Question: C语言中sizeof( )能不能测一个确切的double数的位数，例如sizeof（3.1415）

引用 15 楼 SXJIAKE 的回复:#define charsize(a) (sizeof(#a) - 1) 则 charsize(3.14) = 4

不可以，因为浮点数是不精确的。

自己写函数实现吧

常量也有类型

引用 2 楼 wanghaha_ 的回复:那该怎样求一个确切数的位数呢？？求解答  如果真想返回位数，可以将double转成字符串，判断字符串在小数点后的长度

double a=3.0f; sizeof（a）; lz期望返回值为几？？ double a=3.000000f ; sizeof（a）; lz期望返回值为几？？ double a=.3f; sizeof（a）; lz期望返回值为几？？  unsigned __int64 na = 0x4008000000000000; double a = *((double*)&na);  sizeof（a）; lz期望返回值为几？？

小数点后面是没有数值的情况下全是0吧

不能吧，浮点数本来就不是精确数值

可以这么做。将double转换成String,然后判断string和长度、小数符号等

奥，     谢谢你

引用 2 楼 wanghaha_ 的回复:那该怎样求一个确切数的位数呢？？求解答没有现成的函数，但可以自己写算法去实现。

引用 2 楼 wanghaha_ 的回复:那该怎样求一个确切数的位数呢？？求解答 不能。也无意义。几乎所有的double都不准确

那该怎样求一个确切数的位数呢？？求解答

double型占8字节，不管里面实际记录的是什么数。


Question: c语言  新手求解答

啊  谢谢两位 是我忽略了  汗~

一个是double，一个是float，损失了精度，所以就不一样了。

.........都变成double就一样了


Question: 关于BORLANDC编译问题

按F7单步调试。

引用 1 楼 user-4 的回复:没问题啊 接下来应该是link了吧 我自己搞错了。。太长时间不用 快捷键按错了。可是为什么compile会出现错误，而run就可以成功呢？ compile和run的区别在哪里

press any key 退出这个界面 press Alt +R 运行观察结果

看前面写success，应该没问题，你看看这一步有没有生成什么。

没问题啊 接下来应该是link了吧


Question: 如何编写一个post的日志，记录http协议中post发送的信息的

引用 1 楼 user-1 的回复:把暂时不能发送成功的数据保存到数据库，或者文件中 啊，这个我明白，把记录存到txt就可以，但是我是学嵌入式的，对网页完全不懂，不知道怎么实现日志功能

把暂时不能发送成功的数据保存到数据库，或者文件中


Question: 关于sprintf 的缓冲区溢出

引用 6 楼 lc316546079 的回复:这种情况运行结果本来就是未知的，何必呢，自己小心不要有这种问题就好了么；不然程序里突然在个未知的地方崩溃了，问题定位都烦死 烦死的原因是“和你一样的99%的码农都不会看Call Stack和使用Data Breakpoint”

sprintf要慎用， 推荐使用sprintf_s

我的例子代码已经明确地演示了如何利用数据断点捕获越界错误发生的代码行了。

引用 9 楼 zhao4zhong1 的回复:[quote=引用 8 楼 lc316546079 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] [quote=引用 6 楼 lc316546079 的回复:] 这种情况运行结果本来就是未知的，何必呢，自己小心不要有这种问题就好了么；不然程序里突然在个未知的地方崩溃了，问题定位都烦死 烦死的原因是“和你一样的99%的码农都不会看Call Stack和使用Data Breakpoint”[/quote]  Call Stack和Data Breakpoint 都没有呢，以前对内存没留意，不小心破坏以后，崩溃的地方和造成内存破坏的地方天各一方呢[/quote] 崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  发现某个变量值或某段内存值莫名其妙发生改变，请在该变量或该段内存设置数据改变断点后重新开始调试运行。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }  [/quote]  这些都知道，主要就那时候是c# 与 c/c++ 协作导致的内存问题，出得最多的就是越界，和破坏了申请到的内存的头部，崩溃通常在最终free处，所以看堆栈无效，后来发现原因，从哪以后才每次的内存操作谨慎起来

引用 8 楼 lc316546079 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] [quote=引用 6 楼 lc316546079 的回复:] 这种情况运行结果本来就是未知的，何必呢，自己小心不要有这种问题就好了么；不然程序里突然在个未知的地方崩溃了，问题定位都烦死 烦死的原因是“和你一样的99%的码农都不会看Call Stack和使用Data Breakpoint”[/quote]  Call Stack和Data Breakpoint 都没有呢，以前对内存没留意，不小心破坏以后，崩溃的地方和造成内存破坏的地方天各一方呢[/quote] 崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  发现某个变量值或某段内存值莫名其妙发生改变，请在该变量或该段内存设置数据改变断点后重新开始调试运行。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

引用 7 楼 zhao4zhong1 的回复:[quote=引用 6 楼 lc316546079 的回复:] 这种情况运行结果本来就是未知的，何必呢，自己小心不要有这种问题就好了么；不然程序里突然在个未知的地方崩溃了，问题定位都烦死 烦死的原因是“和你一样的99%的码农都不会看Call Stack和使用Data Breakpoint”[/quote]  Call Stack和Data Breakpoint 都没有呢，以前对内存没留意，不小心破坏以后，崩溃的地方和造成内存破坏的地方天各一方呢

引用 3 楼 ant2012 的回复:的确有溢出，但不报错是因为其越界访问只是发生在程序自己内存地址空间内 程序结果出现这个问题是因为src和buf的地址空间是相邻的，而且src的地址比buf高，当进行sprintf时，此函数直到遇到src字符串中的'\0'才会结束（除非程序崩溃），因此sprintf只将abcdefghij（你会发现其长度等于buf的长度）拷到buf中，而将后面的字符串klmnopqrstuvwxyz拷到src中（因为src与buf的地址相邻）。 所以在printf时，该函数也是通过'\0'判断结尾的，所以会输出abcdefghijklmnopqrstuvwxyz，而src的数据已被更改，所以是klmnopqrstuvwxyz  明白了，多谢！

栈破坏，是未定义行为。可能正确，可能错误，可能马上崩溃，可能运行到某个毫无关联的地方修改了数据。所有情况都可能发生。而且编译器基本帮不上忙，只能自己小心。

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。


Question: 计算机网络和数据库看哪本书好？

还在用vc6.0，真是执着。《unix网络编程(第一卷)》《tcp/ip详解(第一卷)》，vc的数据库没什么经典书，随便找本看看就行。

计算机网络： 不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545  数据库： 通览SQL Server中文版联机帮助

使用VC6  偶遇到莫名其妙的编译错误都是用 工程、设置、C/C++、分类：Preprocessor、附加包含路径：填写附加头文件所在目录 逗号间隔多项 和 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。  偶遇到莫名其妙的链接错误都是用 工程、设置、Link、分类：Input、附加库路径：填写附加依赖库所在目录 分号间隔多项 工程、设置、Link、分类：Input、对象/库模块：填写附加依赖库的名字.lib 空格间隔多项 的方法解决的。


Question: 求助，输出不了

#include<stdio.h> int main() { 	int a, b, c, kase = 0; 	while(scanf("%d%d%d", &a, &b, &c) == 1) 	{ 		for(int i = 10; i < 100; i++) 		  if(i % 3 ==a && i % 5 == b && i % 7 == c) 		  printf("Case %d:%d\n", ++kase, i); 		  else 		  printf("Case %d:No answer\n", ++kase); 	} }

#include <stdio.h> int main() {     double a, b, c;      printf("Input 3 float number:\n");     if (3==scanf("%lf%lf%lf", &a, &b, &c)) {         printf("sum:%g\n", a + b + c);         printf("avg:%g\n", (a + b + c) / 3.0);     } else {         printf("format error!\n");     }      return 0; } //C:\test>test //Input 3 float number: //1.1 2.22 3.333 //sum:6.653 //avg:2.21767 // //C:\test>test //Input 3 float number: //a b c //format error! // //C:\test>

有人解答吗？

平均数呢？嗯？

ok，呵呵呵。

楼主你的输入写的有问题，double类型的用    lf，     float类型的用   f，而你在 f  前加了一个数字是想让输入的数占固定的位数还是怎么样？这种写法据我所知是错误的！

浮点型和整形在二进制存储格式不同

scanf("%d", &r); 改成 scanf("%f", &r); %d是整形格式，%f才是双精度型

#include<stdio.h> int main() { 	double r, c, s; 	scanf("%d", &r); 	c = 6.28*r; 	s = 3.14*r*r; 	printf("c = %.2f, ", c); 	printf("s = %.2f.\n", s); 	return 0; }

还有一个什么问题？

谢谢。还有一个呢？

printf("%d", ABC); 改成  printf("%d\n", ABC);  将多个输出结果分开再看看

#include<stdio.h>  int main()  {  for (int a = 1; a <= 9; a++)  for (int b = 0; b <= 9; b++)  for (int c = 0; c <= 9; c++)  {  int ABC = a * 100 + b * 10 + c;  if (ABC < 100) continue;  if (ABC > 999) break;  if (ABC == a * a * a  + b * b * b + c * c * c) printf("%d", ABC);  }  return 0;  }  这个输出153370371407。

输出为0.000 是这个 #include<stdio.h>  int main()  {  double a, b, c;  scanf("%1f%1f%1f", &a, &b, &c);  printf("%.3f\n", (a + b + c) / 3.000);  return 0;  }

只有"%d\n"才出正常的数。

printf("%d", ABC); 怎么会输出0.000？？？

重新 #include<stdio.h> int main() { 	double a, b, c; 	scanf("%1f%1f%1f", &a, &b, &c); 	printf("%.3f\n", (a + b + c) / 3.000); 	return 0; }

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  scanf Width Specification width is a positive decimal integer controlling the maximum number of characters to be read from stdin. No more than width characters are converted and stored at the corresponding argument. Fewer than width characters may be read if a white-space character (space, tab, or newline) or a character that cannot be converted according to the given format occurs before width is reached.  The optional prefixes h, l, I64, and L indicate the “size” of the argument (long or short, single-byte character or wide character, depending upon the type character that they modify). These format-specification characters are used with type characters in scanf or wscanf functions to specify interpretation of arguments as shown in the Table R.7. The type prefixes h, l, I64, and L are Microsoft extensions and are not ANSI-compatible. The type characters and their meanings are described in Table R.8.  Table R.7   Size Prefixes for scanf and wscanf Format-Type Specifiers  To Specify Use Prefix With Type Specifier  double l e, E, f, g, or G  long int l d, i, o, x, or X  long unsigned int l u  short int h d, i, o, x, or X  short unsigned int h u  __int64 I64 d, i, o, u, x, or X  Single-byte character with scanf h c or C  Single-byte character with wscanf h c or C  Wide character with scanf l c or C  Wide character with wscanf l c, or C  Single-byte – character string with scanf h s or S  Single-byte – character string with wscanf h s or S  Wide-character string with scanf l s or S  Wide-character string with wscanf l s or S    Following are examples of the use of h and l with scanffunctions and wscanf functions:  scanf( "%ls", &x );    // Read a wide-character string wscanf( "%lC", &x );    // Read a single-byte character  To read strings not delimited by space characters, a set of characters in brackets ([ ]) can be substituted for the s (string) type character. The corresponding input field is read up to the first character that does not appear in the bracketed character set. If the first character in the set is a caret (^), the effect is reversed: The input field is read up to the first character that does appear in the rest of the character set.  Note that %[a-z] and %[z-a] are interpreted as equivalent to %[abcde...z]. This is a common scanf function extension, but note that the ANSI standard does not require it.  To store a string without storing a terminating null character ('\0'), use the specification %nc where n is a decimal integer. In this case, the c type character indicates that the argument is a pointer to a character array. The next n characters are read from the input stream into the specified location, and no null character ('\0') is appended. If n is not specified, its default value is 1.  The scanf function scans each input field, character by character. It may stop reading a particular input field before it reaches a space character for a variety of reasons:   The specified width has been reached.   The next character cannot be converted as specified.   The next character conflicts with a character in the control string that it is supposed to match.    The next character fails to appear in a given character set.  For whatever reason, when the scanf function stops reading an input field, the next input field is considered to begin at the first unread character. The conflicting character, if there is one, is considered unread and is the first character of the next input field or the first character in subsequent read operations on stdin.


Question: 请问下gtk的一些问题

引用 6 楼 king_2007 的回复:[quote=引用 5 楼 zhaowech 的回复:] 1.c语言写gui程序用什么东西并没有必然的限定，这和操作系统有关，linux下用gtk+和qt比较流行 2.gtk是c写的，可移植性好，但是是面向对象的，通过使用宏来实现继承和多态，面向对象不等于c++，并且谁也不包含谁 3.我了解的范围内没都是gtk+，并没有gtk，你也不用纠结，直接用gtk+就好了 4.gtk+编写界面程序在linux下用得多，具体需要你自己摸索了，不是几句话能说清的，路已经明确了 5.同4 那我对c++不了解，如果用单纯的c语言编写windows应用程序，使用gtk库相对于gtk+来说比较容易些，如果用gtk+我想使用它的库会比较困难吧？。请问如何安装gtk库，现在的gtk库版本是多少？如何安装呢？[/quote] 去gtk官方网站，看它的说明，关键字“get start”

引用 5 楼 zhaowech 的回复:1.c语言写gui程序用什么东西并没有必然的限定，这和操作系统有关，linux下用gtk+和qt比较流行 2.gtk是c写的，可移植性好，但是是面向对象的，通过使用宏来实现继承和多态，面向对象不等于c++，并且谁也不包含谁 3.我了解的范围内没都是gtk+，并没有gtk，你也不用纠结，直接用gtk+就好了 4.gtk+编写界面程序在linux下用得多，具体需要你自己摸索了，不是几句话能说清的，路已经明确了 5.同4 那我对c++不了解，如果用单纯的c语言编写windows应用程序，使用gtk库相对于gtk+来说比较容易些，如果用gtk+我想使用它的库会比较困难吧？。请问如何安装gtk库，现在的gtk库版本是多少？如何安装呢？

好像一个是c用的一个是python用的

...........?????等待，高手的解答

blog.csdn.net/mydo

参考本猫csdn的blog


Question: 求大神解答问题  算法向 分类与组合

IPV4 有四类地址，按照地址范围分类就可以了 至于 IPV6 还是查查文档吧

排序， mask从小到大， mask相同的ip从小到大

map

先排序，再提出


Question: C语言，刚刚学到malloc，有很大的疑问；

引用 6 楼 lc316546079 的回复:～～你不强转试试咯，不一定要强转，有的平台是不会报错的，报错才需要显示的强转 引用 7 楼 paschen 的回复:malloc只是分配需要大小的空间，这空间你可以用于任何类型，分配出来是void*类型，所以需要转成int*  谢谢，我已经明白了！；

～～你不强转试试咯，不一定要强转，有的平台是不会报错的，报错才需要显示的强转

引用 2 楼 baijiaheizhiganmao 的回复:[quote=引用 1 楼 user-5 的回复:] man一下malloc，可以看到malloc的返回值类型为（void*)，所以要进行类型转化 一楼的说法是对的。但是1楼应该不用说man一下（可能引起新的疑惑），因为要考虑到楼主使用的是Windows系统。此时楼主应该去百度一下malloc的函数原型。就能验证一楼的说法是正确的。[/quote]  多谢，多谢；

多谢诸位详解！

c语言可以不用强制转换，但c++必须

引用 1 楼 user-5 的回复:man一下malloc，可以看到malloc的返回值类型为（void*)，所以要进行类型转化 一楼的说法是对的。但是1楼应该不用说man一下（可能引起新的疑惑），因为要考虑到楼主使用的是Windows系统。此时楼主应该去百度一下malloc的函数原型。就能验证一楼的说法是正确的。


Question: 如何实现不在双击消息里面存储文件，改为每隔一段时间自动存储文件。代码贴在下面，求大神解决啊

很感激楼上的你们（jack960330；忘世麒麟）如此热心给予的解答，特别感谢西伯利亚冰给我修改了代码，我把它贴上去。 void CClient_FileTransferDlg::Download() {     int nCount = m_ListFile.GetItemCount();     for (int i = 0; i < nCount; i++)     {         int iSel = i;          CString strFileName = m_ListFile.GetItemText(iSel, 0);         CString str2;         str2.Format("D:\\zhao.txt");         //得到客户端保存路径         CFile file;         BOOL bOpen = file.Open(str2, CFile::modeCreate|CFile::modeWrite, NULL);          if(!bOpen)         {             MessageBox("文件创建或打开失败！请确认路径再重试！");             continue;         }         file.Close();          MSGREQUEST msgRequest;//通信语言结构体         msgRequest.iCommand = FILEDATA;         msgRequest.lFileLength = m_ListFile.GetItemData(iSel);         msgRequest.lFileOffset = 0;         strcpy(msgRequest.sClientPath, str2.GetBuffer(0));         strcpy(msgRequest.sServerPath, m_ListFile.GetItemText(iSel, 5));          //子项目，第6列          DWORD dwStartTick = GetTickCount();         char sStartTick[20];         sprintf(sStartTick, "%u", dwStartTick);         //格式：Unsigned decimal integer         m_ListFile.SetItemText(iSel, 6, sStartTick);          m_pClient->RequestFile(msgRequest);//调用请求线程     }      SetTimer(TIMER_ID_SAVE, 4000, NULL); }

你接收实际就是下载，只要把路径定死，自动接收就行了

发你了      。

引用 3 楼 zhao1209 的回复:谢谢楼上的回复，移动上面那段程序到timer消息里，我试过了，因为涉及到线程以及结构体的问题，所以我一直没有解决掉，您能否下载我的代码帮我看看，谢谢您啦 自己写个小程序测试一下该控件的用法,然后将代码加到模块中去.你始终也要学会这个非常常用的控件啊,为什么不在这一次学会尼?

你注册一个timer时间 -——>你注册一个timer事件

你注册一个timer时间，当时间到了的时候触发一个存储文件操作。 你百度一下“MFC timer”这两个关键字。不会太难的。


Question: 关于结构体数组循环问题  忘大神解决下！3Q

谢谢各位大神了  问题解决了

引用 5 楼 q3733353520 的回复: getchar(); //把这句放到for循环的最后，也就是scanf("%s",Family[i].mother);的后面  另外最好这样  People Family[COUNT] = {0};//最好这样，然后定义个j用来计算你输入的人数，在第二个for循环中使用

字符串比较改为strcmp()试试

#include <stdio.h>   2 #include <ctype.h>   3 #define COUNT 50   4    5 typedef struct People People;   6 struct People   7 {   8     int age;   9     int high;  10     char name[20];  11     char father[20];  12     char mother[20];  13 };  14   15 int main()  16 {  17     People Family[COUNT];  18     int i;  19     char a = '\0';  20     for(i = 0; i < sizeof(Family)/sizeof(People); ++i)  21     {  22         printf("if stop this enter,please enter n or N!,if continue, enter y     or Y");  23         scanf("%c",&a);  24         getchar();  25         if(tolower(a) == 110)  26         {  27             break;  28         }  29         printf("enter name: ");  30         scanf("%s",Family[i].name);  31   32         printf("enter age: ");  33         scanf("%d",&Family[i].age);  34   35         printf("enter high: ");  36         scanf("%d",&Family[i].high);  37   38   39         printf("enter father: ");  40         scanf("%s",Family[i].father);  41   42   43         printf("enter mother: ");  44         scanf("%s",Family[i].mother);  45     }  46   47     for(i = 0; i < sizeof(Family)/sizeof(People); ++i)  48     {  49         printf("%s is %d years old, %d high, and has %s is %s father, %s is %    s mother\n ",Family[i].name,Family[i].age,Family[i].high,Family[i].father,Fam    ily[i].name,Family[i].mother,Family[i].name);  50     }  51   52     return 0;  53 } 程序我改了，主要问题在按下enter键，出现了垃圾字符。。 但是 输入 n 也不跳出循环 怎么回事？

手机看着好乱啊

问题主要在第一个人for循环哪里   ~~~


Question: OPENMP并行程序，并行之后与串行耗时总是差不多

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


Question: 两个小程序输出结果不同的原因是什么？

第一个printf返回的是函数局部变量的地址，函数局部变量的生存周期在函数返回时结束，因此，当函数结束时，函数内局部变量中的值是不可信的（就是说可能还是原值，也可能已经变成了未知的值）  第二个没问题

面试遇到过，哈哈

第一个"hello world"是字符数组局部变量，第二个则指向常量区（不变），而局部的在函数结束后就销毁了

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

第一个是标准的返回 自动变量地址的问题  返回自动数组名  其实就是返回数组第一个元素地址. 这个地址对应的内存，在函数返回后，被系统回收，不再是可以自由访问的了，结果未定义。  第二个 返回 字符串字面值 本身没有问题 不过 字符串字面值 是个常量，其中每个字符，都是不能修改的  它不应该 是 char *类型的，而应该是 const  char *类型的。 所以函数返回类型是错误的。 因为，这个数据是不能修改的。

第二个程序 定义的char*pcStr="hello world"; hello world 是放在常量区的，指针相当于野指针；

第一个是错误的，使用了 野指针 char acStr[]="hello world";      数组后面没有自动加‘\0’, 字符串会一直往后读直到读到‘\0’结束，但数组出了函数就自动释放了，再使用是错误的用法  第二个 是对一个常字符串 读， 常量字符串在程序结束才会清除，同时，字符串后面会自动加一个‘\0’

第一个返回的是局部数组的首地址，局部数组跟任何局部变量一样，随着函数的调用在栈上分配。 执行到数组定义那一句时，这个局部数组是用存储在常量区的一个字符串来初始化，也就是把那个常量字符串的内容拷贝到这个局部数组里来了。 尽管如此，可函数返回后局部变量的地址不再有效，所以程序1是有问题的。 还要注意数组名在C程序中基本上就是表示地址，数组所占内存的首地址。  第二个是在函数内部定义了一个指针变量，这个指针直接指向了常量区一个字符串的首地址，然后函数返回这个指针变量（而不是这个变量的地址），也就相当于返回了常量区那个字符串的地址。 常量区是静态的，不会随着函数的调用和返回产生什么变化，所以这个程序没啥问题。


Question: 运行结果正确，oj总是WA，大家帮忙找找原因

楼主请记住，以后用二维数组，先y，后x 。a[y][x]

播种机屁股底下那块地也能正常长庄稼？！

说这样 ..... SSSS. ...S. .SSS. .....  也YES的人，我倒要问问你：播种机今年就放地中间就当报废不动了吗？万一下场雨机油流到地里还影响收成呢？

引用 10 楼 fly_dragon_fly 的回复:这里搞混 了吧 if(nx>=0 && nx<m && ny>=0 && ny<n && map[nx][ny]=='.') 你的x是行,y是列, 所以应该是nx<n && ny<m, 另外你的dfs在找到结果就不要再搜了. 不过n,m比较小可能性能影响不大 佩服！比我眼还尖。  不过我的猜想也应该有那么一点点符合实际吧。

引用 10 楼 fly_dragon_fly 的回复:这里搞混 了吧 if(nx>=0 && nx<m && ny>=0 && ny<n && map[nx][ny]=='.') 你的x是行,y是列, 所以应该是nx<n && ny<m, 另外你的dfs在找到结果就不要再搜了. 不过n,m比较小可能性能影响不大 对对对，是这里错了非常感谢

引用 12 楼 zhao4zhong1 的回复:[quote=引用 10 楼 fly_dragon_fly 的回复:] 这里搞混 了吧 if(nx>=0 && nx<m && ny>=0 && ny<n && map[nx][ny]=='.') 你的x是行,y是列, 所以应该是nx<n && ny<m, 另外你的dfs在找到结果就不要再搜了. 不过n,m比较小可能性能影响不大 佩服！比我眼还尖。  不过我的猜想也应该有那么一点点符合实际吧。  [/quote]要是迷宫,就对上了,这个你没细看吧, 刚好这个x,y和笛卡尔的x,y刚好不一样

引用 8 楼 zhao4zhong1 的回复:[quote=引用 5 楼 q3733353520 的回复:] [quote=引用 2 楼 zhao4zhong1 的回复:] 我猜是楼主忽略了一个隐含条件： 最后播种机必须位于田地边缘。否则也应输出NO 赵老师是哪里看到题目的。。。[/quote] 楼主给的链接明显前面多了http:///，去掉就可以上了。[/quote]

引用 5 楼 q3733353520 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] 我猜是楼主忽略了一个隐含条件： 最后播种机必须位于田地边缘。否则也应输出NO 赵老师是哪里看到题目的。。。[/quote] 楼主给的链接明显前面多了http:///，去掉就可以上了。

题目：   Seeding  --------------------------------------------------------------------------------  Time Limit: 2 Seconds      Memory Limit: 65536 KB   -------------------------------------------------------------------------------- It is spring time and farmers have to plant seeds in the field. Tom has a nice field, which is a rectangle with n * m squares. There are big stones in some of the squares.  Tom has a seeding-machine. At the beginning, the machine lies in the top left corner of the field. After the machine finishes one square, Tom drives it into an adjacent square, and continues seeding. In order to protect the machine, Tom will not drive it into a square that contains stones. It is not allowed to drive the machine into a square that been seeded before, either.  Tom wants to seed all the squares that do not contain stones. Is it possible?   Input  The first line of each test case contains two integers n and m that denote the size of the field. (1 < n, m < 7) The next n lines give the field, each of which contains m characters. 'S' is a square with stones, and '.' is a square without stones.  Input is terminated with two 0's. This case is not to be processed.    Output  For each test case, print "YES" if Tom can make it, or "NO" otherwise.   Sample Input  4 4 .S.. .S.. .... .... 4 4 .... ...S .... ...S 0 0   Sample Output  YES NO

引用 2 楼 zhao4zhong1 的回复:我猜是楼主忽略了一个隐含条件： 最后播种机必须位于田地边缘。否则也应输出NO 除非这个农户有大吊车或大型直升机支援！

引用 2 楼 zhao4zhong1 的回复:我猜是楼主忽略了一个隐含条件： 最后播种机必须位于田地边缘。否则也应输出NO 赵老师是哪里看到题目的。。。

仅供参考（不一定对）： //http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1100 //It is spring time and farmers have to plant seeds in the field. Tom has a nice field, which is a rectangle with n * m squares. //There are big stones in some of the squares. //Tom has a seeding-machine. At the beginning, the machine lies in the top left corner of the field. //After the machine finishes one square, Tom drives it into an adjacent square, and continues seeding. //In order to protect the machine, Tom will not drive it into a square that contains stones. //It is not allowed to drive the machine into a square that been seeded before, either. //Tom wants to seed all the squares that do not contain stones. Is it possible? // //Input //  The first line of each test case contains two integers n and m that denote the size of the field. (1 < n, m < 7) //  The next n lines give the field, each of which contains m characters. //  'S' is a square with stones, and '.' is a square without stones. //  Input is terminated with two 0's. This case is not to be processed. //Output //  For each test case, print "YES" if Tom can make it, or "NO" otherwise. //Sample Input //4 4 //.S.. //.S.. //.... //.... //4 4 //.... //...S //.... //...S //0 0 //Sample Output //YES //NO #include <cstdio> int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; int n,m,sum,flag; char map[10][10]; void dfs(int y, int x) {     if (sum==0) {         if (x==0 || x==m-1 || y==0 || y==n-1) flag=1;         return;     }     for (int i=0;i<4;i++) {         int nx=x+dx[i];         int ny=y+dy[i];         if (0<=nx && nx<m && 0<=ny && ny<n && map[ny][nx]=='.') {             map[ny][nx] = 'S';             sum--;             dfs(ny,nx);             sum++;             map[ny][nx] = '.';         }     } } int main() {     while (scanf("%d%d",&n,&m),n&&m) {         sum=n*m;         flag=0;         for (int y=0;y<n;y++) {             scanf("%9s",map[y]);             for(int x=0;x<m;x++) {                 if(map[y][x]=='S') sum--;             }         }         map[0][0] ='S';         sum--;         dfs(0,0);         if (flag) printf("YES\n");         else      printf("NO\n");     }     return 0; }

scanf("%s",map[i]);//至少要确保map[i]能装得下吧

我猜是楼主忽略了一个隐含条件： 最后播种机必须位于田地边缘。否则也应输出NO

打不开链接哟


Question: 请问undefined reference to `_splitpath'这个错误怎么回事？怎么处理？

感谢大家回复，这个问题解决了，编译的时候加个-Wall调出更多的警告，把那些警告一一解决后就好了

引用 2 楼 cjqpker 的回复:报错函数_splitpath未定义，需要加下头文件 #include <stdlib.h> #include <stdio.h> 加了的

_splitpath, _wsplitpath Break a path name into components.  void _splitpath( const char *path, char *drive, char *dir, char *fname, char *ext );  void _wsplitpath( const wchar_t *path, wchar_t *drive, wchar_t *dir, wchar_t *fname, wchar_t *ext );  Routine Required Header Compatibility  _splitpath <stdlib.h> Win 95, Win NT  _wsplitpath <stdlib.h> or <wchar.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  None  Parameters  path  Full path  drive  Optional drive letter, followed by a colon (:)  dir  Optional directory path, including trailing slash. Forward slashes ( / ), backslashes ( \ ), or both may be used.  fname  Base filename (no extension)  ext  Optional filename extension, including leading period (.)  Remarks  The _splitpath function breaks a path into its four components. _splitpath automatically handles multibyte-character string arguments as appropriate, recognizing multibyte-character sequences according to the multibyte code page currently in use. _wsplitpath is a wide-character version of _splitpath; the arguments to _wsplitpath are wide-character strings. These functions behave identically otherwise.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tsplitpath _splitpath _splitpath _wsplitpath    Each argument is stored in a buffer; the manifest constants _MAX_DRIVE, _MAX_DIR, _MAX_FNAME, and _MAX_EXT (defined in STDLIB.H) specify the maximum size necessary for each buffer. The other arguments point to buffers used to store the path elements. After a call to _splitpath is executed, these arguments contain empty strings for components not found in path. You can pass a NULL pointer to _splitpath for any component you don’t need.  Example  /* MAKEPATH.C */  #include <stdlib.h> #include <stdio.h>  void main( void ) {    char path_buffer[_MAX_PATH];    char drive[_MAX_DRIVE];    char dir[_MAX_DIR];    char fname[_MAX_FNAME];    char ext[_MAX_EXT];     _makepath( path_buffer, "c", "\\sample\\crt\\", "makepath", "c" );    printf( "Path created with _makepath: %s\n\n", path_buffer );    _splitpath( path_buffer, drive, dir, fname, ext );    printf( "Path extracted with _splitpath:\n" );    printf( "  Drive: %s\n", drive );    printf( "  Dir: %s\n", dir );    printf( "  Filename: %s\n", fname );    printf( "  Ext: %s\n", ext ); }   Output  Path created with _makepath: c:\sample\crt\makepath.c  Path extracted with _splitpath:   Drive: c:   Dir: \sample\crt\   Filename: makepath   Ext: .c   File Handling Routines  See Also   _fullpath, _getmbcp, _makepath, _setmbcp

楼主看看这个 http://blog.csdn.net/aiwoziji13/article/details/7330333


Question: 做一个超市的管理系统

没那么夸张。一步一步实现，先想想大致，然后有什么功能不对自己再加。学会重构

数据库，表结构，存储结构，设计架构，操作流程

先说说你要做成什么样的？什么程度的？不然太宽泛了。没有重点是大忌

设计给出来（要解决什么问题，解决这些问题需要做哪些事，分模块的话，有哪些模块，每个模块的输入是什么，输出什么，理清各个模块之间的关系，用什么方式实现等），再用语言实现，语言只是工具，只要会用及熟练程度，C语言也可以做面向对象的东西

如果你只会c语言，说实话，做一个超市管理系统还是有难度的，并不是说你需要掌握别的语言，而是说你欠缺设计系统的能力～～～～～  做一个系统，首先要形成精准的需求分析，然后进行分布式系统的设计，然后根据设计去模块化地实现～～～  技术层面上，会用到编程语言（比如你用c语言），还有模块之间交互信息的库（类似socket），还要用到数据库～～～   所以如果你只会c语言，要做这样一个系统是有难度的，除非你肯花时间，去一点点搞定～～

超市的管理系统 主要抓住2点： 1 列出主要功能模块，实现之 2 保存数据的方式，如使用文件或者数据库保存超市管理的数据。

管理信息系统的重点不是用什么语言，而是流程


Question: Python调用C的共享库，如何调试调用的共享库

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

用gdb调试。


Question: 哪位大神能帮编写个程序啊！！！c或c++

仅供参考：#include <stdio.h> #include <string.h> #include <stdlib.h> #include <locale.h> const int  DIGIT=1; const int MAXLEN=16384; char s[MAXLEN],*endss; int calc(char *expr,char **addr) {     int ST[10]={0}; //数字栈     char op[10]={'+'}; //运算符栈     char c,*pp;     int ist=1,iop=1,last;     char cc;      pp=expr;     last = !DIGIT;     if ((c=*pp)=='!') {         op[0] = c;         pp++;     }     while (1) {         c=*pp;         if (c==0) break;         if (c=='(') {             ST[ist++]=calc(++pp,addr);             pp = *addr;             last = DIGIT;         } else if (c==')') {             pp++;             break;         } else if (c=='+'||c=='*') {             if (last != DIGIT) {                 printf("运算符粘连\n");exit(5);             }             pp++;             if (c=='+') {                 do {                     cc = op[--iop];                     --ist;                     switch (cc) {                     case '+':  ST[ist-1] |= ST[ist];break;                     case '*':  ST[ist-1] &= ST[ist];break;                     case '!':  ST[ist-1] =1-ST[ist];break;                     }                 } while (iop);                 op[iop++] = c;             } else if (c=='*') {                 cc = op[iop-1];                 if (cc=='+') {                     op[iop++] = c;                 } else {                     --ist;                     op[iop-1] = c;                     switch (cc) {                     case '*':  ST[ist-1] &= ST[ist];break;                     case '!':  ST[ist-1] =1-ST[ist];break;                     }                 }             }             last = !DIGIT;         } else if (c=='!') {             op[iop++] = c;             ST[ist++] =0;             pp++;         } else {             if (last == DIGIT) {                 printf("两数字粘连\n");exit(7);             }             if (!(pp[0]=='0'||pp[0]=='1')) {                 printf("非法字符\n");exit(8);             }             ST[ist++]=pp[0]-'0';             pp++;             last = DIGIT;         }     }     *addr=pp;     if (iop>=ist) {         printf("表达式有误\n");exit(9);     }     while (iop) {         --ist;         switch (op[--iop]) {         case '+':  ST[ist-1] |= ST[ist];break;         case '*':  ST[ist-1] &= ST[ist];break;         case '!':  ST[ist-1] =1-ST[ist];break;         }     }     return ST[0]; } int main() {     setlocale(LC_ALL,"chs");     while (1) {         printf("请输入布尔表达式，比如!(1+1)*1：");fflush(stdout);         rewind(stdin);         gets(s);         if (s[0]==0) break;//         printf("%d\n",calc(s,&endss));     }     return 0; }

参考Tiny C Compiler源代码。


Question: 如何动态获取汇编语言指令的机器码

这个最好用反汇编器来做。 网上有很多开源的反汇编器，其中的反汇编行为还可以通过选项参数来定制。 可以参考一下本猫的blog。

再这句汇编前面搞个地址比如:      int a=0;     __asm ("mov %eax,%ebx");     int* p = &a;     p++;     void* asmP = p;  asmP就是你要的地址

谢谢回答。很有效


Question: 深入c语言宏

引用 5 楼 u011493488 的回复:[quote=引用 2 楼 baijiaheizhiganmao 的回复:] 这可没有深入.宏展开仅仅是做了一次替换而已.展开的过程中你用来替换apps的变量是经过声明的,否则一样报错. 我全局搜索了apps没经过申明，只是一个标示而已[/quote] 可能我说的不是非常清楚,我的意思是这样的: #define ADD(x,y) (x+y) .... void show(int a,int b){ cout<<ADD(a,b)<<endl; } 你看你的x,y有什么意义嘛?没有,他们仅仅是为将来替换a b做准备而已.在上面的例子中,x y都是没有声明的,但是你做替换的a b 是在其他地方声明过的. 回到你的apps,因为你是在使用宏的过程中传入的,所以你的程序中肯定有地方声明了apps,不然通不过编译器的.

引用 1 楼 user-4 的回复:宏在语法处理前, 它本来就不知道有声明这回事. 带括号就称为象函数一样的宏 那apps要制定类型吗？当我没有在使用apps时候，应该不会报错吧，

引用 2 楼 baijiaheizhiganmao 的回复:这可没有深入.宏展开仅仅是做了一次替换而已.展开的过程中你用来替换apps的变量是经过声明的,否则一样报错. 我全局搜索了apps没经过申明，只是一个标示而已

VC编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E http://bbs.csdn.net/topics/391003898

你的程序在其他地方有定义 apps 。 很多这个名字的变量，几乎都是系统定义的。

宏在语法处理前, 它本来就不知道有声明这回事. 带括号就称为象函数一样的宏


Question: 求大神

这都是文章，没有程序代码，只需程序代码


Question: 怎么通过标准I/O技术而不是命令行参数来获取文件名？

//赋值文本文件 #include <stdio.h> int main(void) { 	FILE *fi, *fo; 	fi = fopen("1.txt", "rb"); 	fo = fopen("2.txt", "wb"); 	char buf[128]; 	while (1) 	{ 		if (NULL == fgets(buf, sizeof(buf), fi)) break; 		fprintf(fo, "%s", buf); 	} 	fclose(fi); 	fclose(fo); 	return 0; }

#include <stdio.h> #include <string.h>  #ifndef PATH_MAX #define PATH_MAX    255 #endif  char * strchop(char *s) {     size_t len;      if (s) {         len = strlen(s);         if (len > 0 && ('\n' == s[len - 1] || '\r' == s[len - 1]))             s[len - 1] = '\0';         len--;         if (len > 0 && ('\n' == s[len - 1] || '\r' == s[len - 1]))             s[len - 1] = '\0';     }     return s; }  int main(int argc, char *argv[]) {     char source[PATH_MAX] = {0};     char target[PATH_MAX] = {0};      if (1 == argc) {         /* 通过标准 I/O 获取文件名 */         printf("source: ");         strchop(fgets(source, sizeof(source), stdin));         printf("target: ");         strchop(fgets(target, sizeof(target), stdin));     } else {         /* 通过命令行参数获取文件名 */         strcpy(source, argv[1]);         strcpy(target, argv[2]);     }      printf("source=[%s]\n", source);     printf("target=[%s]\n", target);      return 0; }

Again, it is a simple matter to modify this program to use standard I/O techniques instead of command-line arguments to provide filenames. 粗略地翻译一下，就是让你修改程序，使用标准I/O（技术）来提供文件名，而不是用命令行参数来提供文件名。  所谓的标准I/O，就是scanf这些东西了。  使用命令行提供文件名运行起来是这样的： process.exe foo.txt 对于int main(int argc, char * argv[])来说，argv[1]即为"foo.txt"  使用I/O，运行起来就是这样： cmd> process.exe please input the file you want to process: foo.txt ... 所以代码中大概会有这样的语句： char filename[80]; printf("please input the file you want to process: "); scanf("%s", filename); process(filename): ...  所以说，英语也是一种语言。

谢谢了  各位

引用 2 楼 user-4 的回复:获取什么文件名？运行此程序的文件名？  就一个简单的小程序 把一个文件中的内容复制到另一个文件中

获取什么文件名？运行此程序的文件名？

人呢


Question: 关于字符指针作为形参如何传递

char *buffer没有指定指向是很危险的，最好先char *buffer = null，后面再分配内存

第一个程序，唯一有问题的是msg 不确定多长， 所以可能会有安全问题，（缓冲区溢出）。 但从逻辑上看，不是错误，只是没有考虑代码安全。 早期，这种代码很多。  第二个程序，直接就是逻辑错误。 某些情况下，会导致运行时错误， 但是并不是所有编译器，都能保证运行时错误的，起码早期的不会。

這個帖子怎麼越看越瘆的慌

引用 22 楼 zilaishuichina 的回复:LogPrint(“hello, world”); 调用第二种LogPrint，导致strcat修改常量区的内存，出错  char info[] = "hello,world"; LogPrint((char *)info); 调用第二种LogPrint，导致strcat虽然修改的是栈上内存，但是会越界，这种行为是危险的   char info[] = "hello,world"; LogPrint((char *)info);  我试了一下，确实 有 越界 提示： *** stack smashing detected ***: ./sdata terminated

确实是我忽略了 常量字符串 是在只读区域，   现在明白了，多谢大家！

第一段程序，唯一有点小问题的地方是，如果 msg 太长，会出现错误

第一个逻辑和写法都正确 第二个逻辑错误 因为你只是想 log msg 而已(把字符串msg，写到文件中)，并不想修改 msg 这块内存中的任何内容。 buffer = msg  二者指向同一位置（指针的值相同，表示同一地址，而且类型也几乎相同,只有可写与不可写的区别）  strcat(buffer, "\r\n"); 向msg 后面添加 "\r\n" 回车换行符， 这和这段程序的逻辑严重背离 从参数看 const char * msg  表示不希望修改字符串msg的内容 从   buffer = msg  strcat(buffer, "\r\n");  看 又修改了字符串msg 的内容 代码的逻辑是有问题的  上面这个逻辑错误，是程序本身的功能设计错误 不符合，这段程序要实现的目标，不是报错的直接原因  至于出现段错误，是因为 msg 对应的实参本身，指向的内容，也是不可改写，例如是个字符串字面值（串常量）， 这种数据，有时候会分配在只读区（段），所以就会在运行时，报出段错误。  C参数传递，不论是指针，还是其他数据，都是值传递，实参复制（可能有类型提升等情况）到形参中 但是传递指针，我们可以修改 指针指向的内容，因为这个 实参和形参指向同一个位置。 这是指针的性质，功能，和C的参数传递无关。

引用 7 楼 teachin88 的回复:[quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间； 而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？[/quote]  msg是一个对象，它的值是一个字符串的首地址。buffrt=msg后，buffer对象的值也是那个字符串的首地址。 *buffer=*msg的功能等效于buffer[0]=msg[0]

void LogPrint(const char *msg) //msg 指向代码段 只读 | (可能，具体看你调用情况，msg分配足够内存) { char *buffer; buffer = msg; strcat(buffer, "\r\n"); write_log_file("/usr/log.txt", FILE_MAX_SIZE, buffer, strlen(buffer)); }

引用 18 楼 momollll 的回复:[quote=引用 17 楼 momollll 的回复:] [quote=引用 7 楼 teachin88 的回复:] [quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？    [/quote] 是这个意思，而如果char *buffer在没有new一个新的内存空间一般在VC下面默认是0xCCCCCCC这些地址等等，所以你在使用这个地址的时候会出错，而如果你要使用buffer  = msg的话，那么buffer就得指向一个正确的用户空间地址。[/quote] 另外一个问题应该我说错了，buffer = msg,当buffer是数组是，是将msg数据移动到buffer，类似于文件剪贴，而不是复制，其它的我还是坚持我的看法。[/quote]  先回去学习学习吧

两份代码语法都没有问题， 问题应该是你传的实参，你应该是传的常量字符串做实参， 所以第一份代码没有问题，后面的strcat将添加的字符串写入了buff内存中，  第二段代码 传常量字符串时，strcat会将字符写入了常量字符串后面的内存中， 这就会造成内存越界报段错误 推荐第一份代码

引用 17 楼 momollll 的回复:[quote=引用 7 楼 teachin88 的回复:] [quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？    [/quote] 是这个意思，而如果char *buffer在没有new一个新的内存空间一般在VC下面默认是0xCCCCCCC这些地址等等，所以你在使用这个地址的时候会出错，而如果你要使用buffer  = msg的话，那么buffer就得指向一个正确的用户空间地址。[/quote] 另外一个问题应该我说错了，buffer = msg,当buffer是数组是，是将msg数据移动到buffer，类似于文件剪贴，而不是复制，其它的我还是坚持我的看法。

引用 7 楼 teachin88 的回复:[quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？    [/quote] 是这个意思，而如果char *buffer在没有new一个新的内存空间一般在VC下面默认是0xCCCCCCC这些地址等等，所以你在使用这个地址的时候会出错，而如果你要使用buffer  = msg的话，那么buffer就得指向一个正确的用户空间地址。

const const。。。。。。

const char* 无法分配的char* 编译都过不了吧

引用 5 楼 teachin88 的回复:[quote=引用 3 楼 jiqiang01234 的回复:] [quote=引用 2 楼 teachin88 的回复:] 你的意思是  第二个代码中  形参 去掉 const 就不会报错了？  我觉得 buffer = msg;  这句代码本身很别扭，应该是有问题，但是我又说不出具体原因。 这么用，没有问题，语法上允许。我指的是，“语义”上是不对的。关键是看调用端是怎么传入参数引起的崩溃[/quote]   前端调用的话，就是 把字符串作为参数：  LogPrint(“hello, world”);  或者：  char info[] = "hello,world"; LogPrint((char *)info);  类似这样吧。  [/quote]  LogPrint(“hello, world”);调用第二个函数 与 char info[] = "hello,world"; LogPrint((char *)info); 调用第二个函数，结果是不一样的  LogPrint(“hello, world”)中的"hello, world"字符串，分配在常量区，是不能进行写操作的。 而char info[] = "hello,world";是分配在栈区，可以进行可操作。  所以，第一种调用会崩溃，第二种正常。

2楼得解释我还支持，4楼。。。解释错了吧

引用 7 楼 teachin88 的回复:[quote=引用 4 楼 momollll 的回复:] 亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？    [/quote] 你把const去掉试一下不就知道了？

引用 4 楼 momollll 的回复:亲，很高兴为你解答这个问题。 char *buffer;   此时的字符指针是没有内存空间的，是一个错误的指针 char buffer[20]; 这是有内存空间的 buffer = msg;当将数据赋值给数组时，是直接将msg数据复制到buffer，比如buffer数组的首地址是123456 msg的指针地址是654321，那么此时123456的数据就是msg的数据 而当buffer = msg;当将数据赋值给指针时，是直接将msg数据复制到buffer，而现在的buffer指针是一个错误的 指针，那么当然就会出错。 *buffer = *msg;  这样的话就可以让buffer指针批向msg，也就是说msg地址是654321，那么赋值之后buffer也是654321 这样是可以的。 当然你在申请buffer指针时就分配了内存空间的话就可以使用这样的赋值了：buffer = msg;    多谢你的分析。  我原先理解的是：比如：   char *p; char i = 1; p = &i;  于是 p 就指向了 i    p 存的是 i 的地址；   类似的...  char *buffer; buffer = msg   我的理解是  msg 是一个字符串的首地址， 那么 buffer 也就等于 字符串的首地址， 相当于有了内存空间；   而你的意思是 ，*buffer = *msg  才能使  buffer 等于 msg 所指向的地址？


Question: 这段关于鼠标的代码看不懂，求帮助

将其中的十六进制数翻译成二进制数在一张坐标纸上逐位点上点。


Question: 老师布置银行排队系统，队列的元素老不走

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  将复杂数据结构的整个内容在处理它的每一步使用一小段代码按自己很容易理解的格式输出，非常有助于调试！或者可以说是“基础设施”： 仅供参考：//带表头结点的单向链表 #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-> //

引用 5 楼 zhao4zhong1 的回复:float CLOCK; 应改为 int CLOCK;      for (CLOCK = 0.0; CLOCK <= CloseTime; CLOCK += 1) { 应改为     for (CLOCK = 0; CLOCK <= CloseTime; CLOCK += 1) {  我把Windows_Depature();这个从窗口删除客人的函数删了就变这样了，现在是三个窗口貌似只循环了一次，就没人进来了

引用 3 楼 zhao4zhong1 的回复:在0～CloseTime即50之间，怎么才能产生flow即100个互不相同的随机数？ CloseTime在主函数里用scanf_s给输入了新的值

CLOCK += 1 和 CLOCK += 1.0 不是一回事！

窗口那里的三个数分别是客人的ID号、到达时刻、办理业务的时间 主队里的数分别是客人的ID号、到达时刻。 有一个时间轴一直在加1，时刻一到就执行相应的出队进队的操作 改了一个下午都没改出来。

#include <stdio.h> #include <time.h> #include <stdlib.h> #include<malloc.h> #include <math.h> #include <graphics.h> #include<conio.h>   #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0  typedef struct Customer { 	int ID; 	int arrivetime; 	int duringtime; 	struct Customer *next; }Customer; typedef struct { 	Customer *front;//头指针 	Customer *rear;//尾指针 }LinkQueue;  //排队主操作函数 void CustomerArrived();//顾客达到队列 //void CustomerDepature();//顾客离开队列 void Windows_Arrived();//顾客来到窗口 void Windows_Depature();//顾客离开窗口 void Bank_Simulation(); //银行排队模拟  //队列基本操作函数 int InitQueue(LinkQueue *Q); //初始化队列Q int EmptyQueue(LinkQueue *Q); //若队列Q为空，返回TRUE，否则返回FALSE int DelQueue(LinkQueue *Q, Customer *memrroy); //若队列Q不为空，首结点出队，用memrroy返回，并返回OK；否则返回ERROR int EnQueue(LinkQueue *Q, Customer e);//结点e入队Q int QueueLength(LinkQueue *Q);//返回队列Q的长度，即元素个数 //int GetHead(LinkQueue *Q, Customer *memorry);//若队列Q不为空，用memrroy返回其首结点，并返回OK,否则返回ERROR int QueueTraverse(LinkQueue *Q);//遍历队列Q int QueueTraverseMain(LinkQueue *Q);//遍历队列Q void PrintQueue();//显示当前窗口队列  /****************************全局变量*****************************************/ #define M 10000   #define MAXSIZE 20  //宏定义 #define R 5 LinkQueue q[MAXSIZE],MainQ;//队列指针结构体数组 Customer customer;//队列节点 int windows_num;//窗口个数 int CloseTime = 50;//关闭时间，即营业时间长度 int flow;//客流量 int a[M]; int b[20][M]; float CLOCK;  /*******************************主函数*******************************************/ int main() { 	int n, j, i, t; 	srand((unsigned)time(NULL)); //控制在不同时间内生成不同的随机数 	printf("请输入顾客流量："); 	scanf_s("%d", &flow); 	printf("请输入银行关闭时间："); 	scanf_s("%d", &CloseTime); 	printf("请输入窗口个数："); 	scanf_s("%d", &windows_num); 	while (windows_num<1 || windows_num>MAXSIZE) 	{ 		printf("请输入1到20之间的数："); 		scanf_s("%d", &windows_num); 	} 	for (i = 0; i < windows_num; i++) 		InitQueue(&q[i]);//初始化windows_no个窗口队列 	InitQueue(&MainQ);//初始化排队队列  	//客流量的散布 	for (int k = 0; k<flow;)   //生成N个随机数 	{ 		n = rand();   //用随机函数给赋值 		if (n <= CloseTime)  //筛选在[0,480]之间的 		{ 			for (j = 0; j<k;) 			if (a[j] != n)      //判数本次循环中，生成的随机数是否与数组中已有的相等 			{ 				j++; 			} 			else 			{ 				break; 			} 			if (j >= k)//如果j=k则，本次生成的随机数，不与已存在的相等，放入到数组中 			{ 				a[k] = n; 				k++; 			} 		} 	} 	for (i = 0; i<flow; i++) 	{ 		for (j = i + 1; j<flow; j++) 		{ 			if (a[j]<a[i]) 			{ 				t = a[j]; 				a[j] = a[i]; 				a[i] = t; 			} 		} 	} 	//srand((unsigned)time(NULL));//设置随机种子 	/*for (i = 0; i < windows_num; i++) 	{ 		for (j = 0; j < M; j++) 			b[i][j] = 32767; 	}*/ 	for (CLOCK = 0.0; CLOCK <= CloseTime; CLOCK += 1) 	{ 		CustomerArrived(); 	    Windows_Arrived(); 		Windows_Depature(); 		PrintQueue(); 	} 	return 0; }  /*******************银行排队主操作函数****************************************/ void CustomerArrived() { 	int i; 	Customer e; 	for (i = 0; i < flow; i++) 	{ 		if (a[i] == CLOCK) 		{ 			e.arrivetime = a[i]; 			e.ID = i + 1; 			EnQueue(&MainQ, e); 		} 		//break; 	} }  void Windows_Arrived() { 	Customer e; 	int i,j; 	for (i = 0; i < windows_num;i++) 	if (QueueLength(&q[i])==0) 	{ 		DelQueue(&MainQ, &e); 		e.duringtime = rand() % (2+i) + 1; 		for (j = 0; b[i][j] < e.ID; j++); 		b[i][j] = e.ID; 		EnQueue(&q[i], e); 	} } void Windows_Depature() { 	Customer e; 	int i; 	for (i = 0; i < windows_num; i++) 	{ 		if ((q[i].front->next->arrivetime)+(q[i].front->duringtime)==CLOCK) 			DelQueue(&q[i], &e); 	} } /**********************队列相关函数******************************************/  //初始化队列Q int InitQueue(LinkQueue *Q) { 	Q->front = Q->rear = (Customer *)malloc(sizeof(Customer)); 	if (!Q->front) 	{ 		printf("内存分配失败！\n"); 		exit(-1); 	} 	Q->front->next = NULL; 	return OK; }  //若队列Q为空，返回TRUE，否则返回FALSE int EmptyQueue(LinkQueue *Q) { 	if (Q->front == Q->rear) 		return TRUE; 	else 		return FALSE; }  //若队列Q不为空，首结点出队，用memorry返回，并返回OK；否则返回ERROR int DelQueue(LinkQueue *Q, Customer *memorry) { 	Customer *p;//节点指针  	if (EmptyQueue(Q)) 	{ 		printf("队列为空，不能再进行出列操作！\n"); 		return ERROR; 	} 	else 	{ 		p = Q->front->next; 		*memorry = *p; 		Q->front->next = p->next; 		if (Q->rear == p) 		{ 			Q->rear = Q->front; 		} 		free(p); 		return OK; 	}  }   //结点e入队Q int EnQueue(LinkQueue *Q, Customer e) { 	Customer* p;//节点指针  	p = (Customer *)malloc(sizeof(Customer)); 	if (NULL == p) 	{ 		printf("内存分配失败！\n"); 		exit(-1); 	} 	else 	{ 		*p = e; 		p->next = NULL; 		Q->rear->next = p; 		Q->rear = p; 		return OK; 	} }   //返回队列Q的长度，即元素个数 int QueueLength(LinkQueue *Q) { 	Customer  * p;//队列节点指针 	int count;  	count = 0; 	p = Q->front->next;//得到队列第一个节点的地址 	while (p) 	{ 		count++; 		p = p->next; 	} 	return count; }   //若队列Q不为空，用memorry返回其首结点，并返回OK,否则返回ERROR int GetHead(LinkQueue *Q, Customer *memorry) { 	if (EmptyQueue(Q)) 		return ERROR;  	*memorry = *(Q->front->next);  	return OK; }   //遍历队列Q int QueueTraverse(LinkQueue *Q) {  	Customer *p = Q->front->next;  	if (!p) 	{ 		printf("无人\n"); 		return ERROR; 	} 	while (p) 	{ 		printf("(%d,%d,%d)",p->ID, p->arrivetime, p->duringtime); 		p = p->next; 	} 	printf("\n"); 	return OK; } int QueueTraverseMain(LinkQueue *Q) {  	Customer *p = Q->front->next; 	printf("主队列："); 	if (!p) 	{ 		printf("无人\n"); 		return ERROR; 	} 	while (p) 	{ 		printf("(%d,%d)", p->ID, p->arrivetime); 		p = p->next; 	} 	printf("\n"); 	return OK; } void PrintQueue() { 	int i; 	printf("\n队列状态:\n"); 	for (i = 0; i < windows_num; i++) 	{ 		printf("窗口 %d :", i + 1); 		QueueTraverse(&q[i]); 	} 	QueueTraverseMain(&MainQ); 	printf("\n"); } //这是完整程序


Question: 一个我觉得很奇怪的C语言问题 求高手解答

引用 15 楼 mymtom 的回复:[quote=引用 14 楼 SCP_0000 的回复:] 唉 还是不怎么明白 看来还是得研究下底层的东西... 这个不是什么底层的东西啊，就是一个规范： 函数调用前要声明[/quote] 好吧 我还得努力学习呀 你的回答最靠谱分就给你吧  其他的各位不好意思了

引用 14 楼 SCP_0000 的回复:唉 还是不怎么明白 看来还是得研究下底层的东西... 这个不是什么底层的东西啊，就是一个规范： 函数调用前要声明

唉 还是不怎么明白 看来还是得研究下底层的东西...

我也不知道，pi反正不是3.1414，建议多试几次。

引用 6 楼 wbx779139218 的回复:编译器处理浮点数的模块是被"动态"加载的，也就是说，如果你没有显式地定义一个变量(只是声明)，那么这个处理浮点数的模块就可能不被编译器加载，从而不能正确的处理浮点数。  例如: float a;                 //编译器可能没有加载模块 float b = 1.0f;      //编译器加载模块 float c = 1;           //不知编译器是否加载模块  我的猜测是：math.h头文件中显式使用浮点数定义，所以编译器加载了浮点数处理模块(在模块加载后，编译器可以正确处理后续的浮点数) 我的建议:去掉math.h头文件后在你的porc函数中浮点类型变量使用显式定义,例如float n=0.0f,t,pi;并且将浮点定义放到函数作用域的最前端试试  个人意见，仅供参考 这个纯粹是主观臆测了，根本就没有这回事。 真实的情况是fabs的原型是double fabs(double x); 如果没有 #include <math.h> 对于fabs(t)这个函数调用有些编译器会假定fabs的原型是int fabs(float); 也就是所谓的隐式声明； 而有的编译器会警告，更严格的编译器会报错。  在楼主的例子里，#include <math.h> 的作用就是为fabs提供函数原型， 自己写个声明也有同样的作用 double fabs(double x);  当然，推荐的方法是包含头文件。

理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

楼主，是这样的，我告诉你，c如果没有函数的完整声明，编译器是有可能对函数的声明形式进行猜测 猜测的声明形式是 int func()，表示int返回值，参数不确定 这个声明形式是不准确的 所以有可能出现这个问题，我们不能依赖编译器的声明猜测，所以，千万要记住写声明（如果没有声明猜测就报错啦）

vs2013编译不包括math头文件 变异不过 gcc有没有math头文件结果都是3.1414

不好意思 忘了说了 编译环境是VC 6  我按6L所说换了显式定义 结果也一样 按7L所说看了一下fabs(t)的返回值 一直为4991.00 那它为何会退出循环 而且在n=15，t=-0.0666667时退出。

LZ可以说说环境，如果是VC6的话，多半就是这个问题了，6L类似见解。

没有加math.h有可能导致没有初始化浮点运算

问题出在 fabs函数这里，你不把声明这个函数的头文件包括进来，编译器就默认这个函数的返回值类型为int 的。这样你调用它返回得到的将是一个不确定的值。我试了一下我的fabs（f）f为任意浮点数，结果都得到4991。   建议LZ 用个变量保存fabs的值然后单步运行对比一下 fabs(t) 和 t  是否满足绝对值相等。

我调试了一下 发现当n=15.0000，t=-0.0666667时退出了循环，前面还是没问题的，为什么会这样呢？

浮点不是实数，是对实数的一种近似模拟， 这个求PI的方法对于实数成立，不过对浮点就不成立了，因为有误差的积累


Question: 一段c程序

引用 10 楼 char_c 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 仅供参考：#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End. 第二次扫描数组的时候，p指针应该是指向s[3]的吧，空格，那v应该度不到值才对啊，怎么还会是123呢？既然k==0了，不就代表没有存储到东西？不懂啊，求指教。[/quote] v保持原值不变。

引用 7 楼 zhao4zhong1 的回复:仅供参考：#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End. 第二次扫描数组的时候，p指针应该是指向s[3]的吧，空格，那v应该度不到值才对啊，怎么还会是123呢？既然k==0了，不就代表没有存储到东西？不懂啊，求指教。

引用 8 楼 ant2012 的回复: 我这没问题啊，第三次由于有个A出的问题 完全正确呀，不过你用的是VC++， 我用gcc。难道是编译器的问题？

我这没问题啊，第三次由于有个A出的问题

书中源程序是采用scanf_s()可选函数，因为我的编译器不完全支持C11，所以没法用。只能用回scanf(),不知代是否是这个原因，三次调用的过程互相干扰了？

引用 3 楼 user-3 的回复:第二次try_input 中： 第一个格式控制符%4f， 也就是接收一个包含4个字符的浮点数， -2.35包含5个字符，所以只截断到-2.3， 第二个格式控制符%4d，接收了最后一个5  第三次try_input，我测试没有问题，只是接收的数据不对 因为第二个格式控制符%4d，接收了那个A，因为格式不正确，输入结束，后面的数字和字符串没有得到输入内容 嗯，书中也是这样解释的啊，只是第二次测试byte_count应该是19，我得出20；第三次测试很奇怪，根本没有给我输入的机会，调用直接结束程序。

引用 1 楼 ant2012 的回复:楼主%4f应该改成%.4f吧，4前面加一个点 我也是桉书上的例子做的。书上说%4f说的是提取前4个字符，就把-2.3提出，然后再用浮点数表示了。

%4d, %*d等这些格式是格式化输出数据宽度的，在输入数据时，好像没个必要吧

楼主%4f应该改成%.4f吧，4前面加一个点


Question: 求助！Mac使用什么开发工具查看内存地址

hopper debugger 也不错

xcode Debug->Debug Workflow->view memory  address输入内存地址   就能看

Mac都是有Xcode开发的，Xcode的功能和Vs人功能基本上差不多。  Xcode设置断点后就能看到变量的地址和值。


Question: 关于调用linux下的daemon函数出现的线程退出问题。

引用 1 楼 zxhuser-2 的回复:http://blog.csdn.net/hunhunzi/article/details/6094719谢谢了

引用 2 楼 lgbxyz 的回复: int main(void) {    	if(daemon(1,0) < 0)	 	{ 		perror("daemon:"); 		return -1; 	} 	 	aa();     pthread_join(tid, NULL);      	return 0;  }  谢谢，明白了此中的奥秘


Question: 求一个c或c++程序，能够求解逻辑表达式求真假的问题，思路和程序要是都有就最好了！

楼主应该是想在运行的时候输入字符串：((3<2)  ||  (1 > 0)) && ( "abc"=="a")) ， 然后可以给用户一个结果？  这个需要分割字符串，从优先级高的开始逐层处理，可能还需要检查下字条串是否正确等，步骤还是有点繁琐，不过不是很难

c++ 运算符重载

参考Tiny C Compiler源代码。

gcc开源的,里面有这个代码的

直接输出布尔表达式，不就知道结果了吗？


Question: 字符串比较，找出不同项

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

这个题目会涉及到：1）文件读写，文件操作：打开，读取，关闭；2）字符串比较，strcmp，memcmp，strncmp；3）字符串比较策略，即拿1.txt中的一个字符串和2.txt中字符串一一比较，不相同的即标记输出；

引用 5 楼 user-3 的回复:gcc可以，但需要加上-std=c++11  多谢，终于OK了，应该是这样子编译：g++ -std=c++11 exp01.cpp -o exp01 可怜我还在创建C源文件呢！

引用 3 楼 user-3 的回复:这是c++代码。std::set_difference()就是找出两个已排序容器中不同的不同元素。 怪不得， 我说怎么gcc、vc6.0、在线编译器都编译不通过！！！

引用 1 楼 user-3 的回复: #include <iostream> #include <set> #include <vector> #include <algorithm>  int main() {     std::set<std::string> s1 = {"ab","abc","abcd","abcde","abcdef"};     std::set<std::string> s2 = {"abc","abcd","abcdex","abcdey"};      std::vector<std::string> v(std::min(s1.size(), s2.size()));     std::set_difference(s1.begin(), s1.end(), s2.begin(), s2.end(), v.begin());      for(const std::string& s: v)     {         std::cout << s << "  ";     }     return 0; }   求注释，刚看完C入门的书，代码还看不明白！！！


Question: 指针变量与一维数组

指针可以使用[index]方式引用，这种引用时基于首地址的便宜，如楼主的描述（a是野指针哦）：a[0]即首地址便宜0*1个字节，a[1]即首地址偏移：1*1个字节。

unsigned char *a=new char [10]; //或者 unsigned char b[10]; //unsigned char *a=b; 不过是用函数调用表达式，给 a[0],a[1] 赋值罢了； 函数调用表达式的值，就是函数返回值。

编译器对 a[i] 的解释是 *(a + i * sizeof(a[0])), ，这种方式被称为语法糖，用来简化书写


Question: 问下关于 fopen 函数的问题

引用 2 楼 q3733353520 的回复:1、确定路径正确 2、确定文件是否存在  确实是路径弄错了   唉

#include <errno.h>这个别忘了加

引用 3 楼 a1141644656 的回复:[quote=引用 1 楼 lgbxyz 的回复:] 看errno 是什么  怎么看？  [/quote] printf("Can't open %s\n", argv[1]); 这句后面打印 printf("errno = %d\n", errno);

引用 2 楼 q3733353520 的回复:1、确定路径正确 2、确定文件是否存在  同路径的 .c  .exe 文件都能打开的

引用 1 楼 lgbxyz 的回复:看errno 是什么  怎么看？

1、确定路径正确 2、确定文件是否存在

看errno 是什么


Question: switch季节判断时 case 08 09报错

直接1，2，3，4，5，6，7，8，9，10，11，12就好了。 因为int，你输入01，只会接收1(内存0是否存储不知道)，然后对应case 1，程序一样会运行。

1.常数已0开头是八进制0~7 2.如果你非要case里有两位，那得看你编译器了，把m声明成字符，有些编译器对‘08’类似字符是取后面最后一个字符的

引用 5 楼 J1101460678 的回复:case后面直接写8,9！！不加零！ +1

case后面直接写8,9！！不加零！

switch (m) {         case 0x0C:         case 0x01:         case 0x02:             printf("Winter\n");             break;         case 0x03:         case 0x04:         case 0x05:             printf("Sprin\n");             break;         case 0x06:         case 0x07:         case 0x08:             printf("Summer\n");             break;         case 0x09:         case 0x0A:         case 0x0B:             printf("Autumn\n");             break;         default:             break;     }

case 08:  改为 case 010 其他以此类推

整型常量如果以0开头表示是8进制数，08 09当然不存在了

因为是以0开头，所以会是8进制

知道了第一点... 八进制是0～7 来表示数的。 照这样说我所有case后的数都被理解为八进制了。那第二个问题还是求大神帮忙看下。虽然两位没啥卵用，不过看起来舒服...


Question: 考研狗请教数据结构问题，

参考代码： https://github.com/707wk/Senior-middle-school/blob/master/Filling%20in%20the%20gaps.c

引用 4 楼 baijiaheizhiganmao 的回复:看到你发这个问题,我对你的考研表示担心.对你考研的动机表示怀疑. 原谅我上面的废话. 我的建议是把C语言学好. 实在人说实在话。

严蔚敏的数据结构方面的书，就有C语言版的。你非要买个C++语言版的，搞毛？

《算法精解（C语言描述）》

《数据结构（C语言描述）》

有考过的，哈哈。 归并排序 http://blog.csdn.net/zhangxiangdavaid/article/details/34463409

有没有考研的？


Question: pipe管道 传值 链表 怎么不行啊

69行打印结果不对，请大神相助！！

修改如下：  #include <unistd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { 	char *string1, *string2; 	int ret, myPipe[2]; 	char buffer[80 + 1];  	typedef struct protocal 	{ 		char ptype; 		int len; 		struct protocal *next; 	} PRO, *PPRO;  	string1 = malloc(50); 	string2 = malloc(50); 	strcpy(string1, " hjj23 "); 	strcpy(string2, " hjj24 "); 	int length = sizeof(PRO);  	/*create a pipe */ 	ret = pipe(myPipe); 	if (ret == -1) 	{ 		perror("pipe error"); 		exit(-1); 	} 	else if (ret == 0) 	{ 		/*write to pipe */ 		PPRO p = (PPRO)malloc(sizeof(PRO)); 		p->ptype = 'A';/*表示姓名*/ 		p->len = 3; 		p->next = NULL; 		printf("123\n"); 		int bytes_write = write(myPipe[1], p, length); 		if (bytes_write == -1) 		{ 			perror("write pipe error"); 			exit(-1); 		} 		/*write to pipe again */ 		bytes_write = write(myPipe[1], string1, strlen(string1)); 		if (bytes_write == -1) 		{ 			perror("write pipe error"); 			exit(-1); 		} 		bytes_write = write(myPipe[1], string2, strlen(string2)); 		if (bytes_write == -1) 		{ 			perror("write pipe error"); 			exit(-1); 		} 		/*read from pipe */ 		PRO a; 		read(myPipe[0], (void *)&a, sizeof(PRO)); 		printf("a.ptype=%c,a.len=%d\n", a.ptype, a.len); 		int bytes_read = read(myPipe[0], buffer, sizeof(buffer)); 		if (bytes_read == -1) 		{ 			perror("read pipe error"); 			exit(-1); 		} 		buffer[bytes_read] = 0; 		printf("%s\n", buffer); 	} 	return 0; } //123 //a.ptype = A, a.len = 3 // hjj23  hjj24


Question: c语言中奇怪的初始化赋值导致的错误

一直以为ＣＳＤＮ还是片净土，没想到也被*污*染了。这就好比说你*有*罪，就是不告诉你哪里*有*罪，反正你就是*有*罪。

蛋

引用 1 楼 king191923157 的回复:把return  FALSE ;   改了   你函数的返回类型是gboolean 而return FALSE; FALSE 的类型不是 gboolean 你返回一个gboolean  FALSE 的定义是  ＃define  FALSE 0  typedef int gint; typedef gint gboolean; FALSE就是0，怎么能说FALSE不是gboolean ？？ VS支持C99？个人表示不相信。

gboolean的类型是？

老工程能编译，估计是编译器对以前的代码为了加快编译速度，没有全部重新编译 你点击下清除解决方案，重新生成试试

https://msdn.microsoft.com/zh-cn/library/d3ct4kz9.aspx  Visual Studio 2013 其他版本  “function”未定义；假设外部返回 int 编译器遇到对未定义函数的调用。 通过检查以下可能的原因进行修复 函数名称拼写不正确 原型非 extern 的外部函数  这是我从msdn获取到的信息，依然不懂啥意思？  我只知道，你妹包含， 丫的，编译器怎么能放过去呢？

引用 1 楼 king191923157 的回复:把return  FALSE ;   改了   你函数的返回类型是gboolean 而return FALSE; FALSE 的类型不是 gboolean 你返回一个gboolean  FALSE 的定义是  ＃define  FALSE 0 引用 3 楼 sholber 的回复:[quote=引用 1 楼 king191923157 的回复:] 把return  FALSE ;   改了   你函数的返回类型是gboolean 而return FALSE; FALSE 的类型不是 gboolean 你返回一个gboolean  FALSE 的定义是  ＃define  FALSE 0  typedef int gint; typedef gint gboolean; FALSE就是0，怎么能说FALSE不是gboolean ？？ VS支持C99？个人表示不相信。[/quote]  我是用vs2013  刚才又发现一个奇怪的语法，注意，所有代码都是纯c   我用到了strlen string.h里的一些函数，  注意：我没有包含string.h  居然可以编译过去，但是有警告：  Warning	29	warning C4013: 'strlen' undefined; assuming extern returning int	 Warning	30	warning C4013: 'memcpy' undefined; assuming extern returning int	 Warning	31	warning C4013: 'strcat' undefined; assuming extern returning int	   当然你们肯定不信，我也不信，是啊，头文件都不包含，能编译就见鬼了。  为此我新建一个工程，试一试，果然无法编译。  那么，为什么我的老工程可以编译，只简单的出现警告呢？   为此，通过搜索来解答问题：  http://bbs.csdn.net/topics/110078687  看这个帖子，我居然没看懂。  擦， 没头文件，只是警告？   这是什么理由？  百思不得其解


Question: c语言 数据存储的问题

写的时候你的写入格式不对吧

由于结构体对齐的问题， struct Stu类型的变量会有些多余的字节，改变文件类型进行查看，就会暴露这些多余字节。 建议读写时，模式一致。 要么"w"、"r" 或者"wb"、"rb"


Question: 为什么C语言标准库中的字符相关函数都用int作参数与返回类型？

如果不是整形，那你觉得应该是什么类型。库函数的执行结果一般是几种情况，用整形来表示应该会比较方便吧。

引用 楼主 qq_30244069 的回复:为什么C语言标准库中的字符相关函数都用int作参数与返回类型？ 那楼主觉得该用什么类型？

getchar: The return type is int to accommodate for the special value EOF, which indicates failure: If the standard input was at the end-of-file, the function returns EOF and sets the eof indicator (feof) of stdin. If some other reading error happens, the function also returns EOF, but sets its error indicator (ferror) instead.

返回类型，由函数功能决定

返回错误用的

具体哪个函数？


Question: c语言难道可以不包含头文件，就直接使用函数?

楼上都说的很详细了，这是编译器帮你做的事，默认包含常用的头文件（正确的说，应该是链接，对于找不到的符号，到常用库中搜一下），说白了就是让你写代码方便一些，想一想你写这么多程序，有几个是不用printf等常用的函数，不过推荐是包含的， 一般都要做到没有warning，这对代码排错和后期维护很重要。

没有用到的函数不连接，很正常啊。 不连接，也就不用考虑，是否有连接错误了。 这是C语言（连接器）的重要功能，可以减小代码大小。  printf ,和 scanf 这两个函数，可以不必include  任何头文件，直接用 这在早期的编译器，是很平常的事情 因为任何有点意义的完整的简单程序，都离不开输入输出。，，，， （复杂程序，可以借助各种类型的通讯手段，DLL等等，不必直接输入输出，这里不谈） 所以开了特例，方便学习C语言的时候，使用这两个函数。

test.h:  int a;  void show();  #define  BUFSIZE 100   test1.c:  #include "test.h" #include <stdio.h> int fun() {  	printf("Hello World\n"); 	return 0;  }  void show() {  }  test2.c:  #include<stdio.h>  #include "test.h" #include "test.h" //注意我故意写了2行  int  main(void)  { 	//return 0;  	//printf("%s", a); }  也可以编译链接。  顿时崩溃!!!   用gcc试试，结果也如此，人生信念彻底毁灭。

为了再次看c和c++的区别，做个实验：  test.h:    int a;  void show(void);  test1.c:  #include "test.h" #include <stdio.h> int fun() {  	printf("Hello World\n"); 	return 0;  }  void show() {  }   test2.c:   #include<stdio.h>  #include "test.h"  int  main(void)  { 	//return 0;   }  毫无压力，编译。链接都没错误，且无警告。   看到变量 int a没有!!!!     确实让我吃了一惊。

有些库会被编译器自动链接 再加上楼上的说法， 即是解释

gcc 试试：   #include <stdio.h>  int main() {     printf("Hello World!\n");     strlen("123");     return 0; }  warning: incompatible implicit declaration of built-in function ‘strlen’   答案已经知晓。  c和c++有个区别： 后者严格申明后使用。 前者，编译器去猜测且假设函数为 int strlen(void)。  当链接的时候，编译器在c库函数里找到了strlen，所以就成功了。  可见c语言非常恐怖！！！

应该是编译器问题吧

up 起来

http://bbs.csdn.net/topics/391380244  这是姊妹篇


Question: 求高手指点一下，已经调试出错误在哪了

楼主你的代码看得我蛋都疼，另外当w = 12 时， v = 12，west_visited[w]==1，所以判断失败，楼主，你在调用每个函数后，测一下数据是不是对的，你的内存开辟在乱了

for(k=0;k<18;k++) 	{ 		i=WestYard[k][0]; 		j=WestYard[k][1];  		//将west_alGraph->west_vertices[1~19].west_firstedg指向新开辟的堆内存 		//由于k = 7 和 k = 8时，i值都为8；以及k = 12 和 k = 13时，i值为13 		//west_vertices[8]和west_vertices[13]的west_firstedg之前指向的内存被放弃，然而没有释放，内存泄露 		west_newnode=(west_EdgeNode*)malloc(sizeof(west_EdgeNode)); 		west_newnode->west_adjvex=j; 		west_newnode->west_weight=0; 		west_newnode->west_nextedge = west_alGraph->west_vertices[i].west_firstedge; 		west_alGraph->west_vertices[i].west_firstedge=west_newnode; 		 		//将west_alGraph->west_vertices[2~19].west_firstedg指向新开辟的堆内存 		//由于下标值2~19与1~19有很大重合，造成之前的内存被放弃，然而没有释放，内存泄露 		west_newnode=(west_EdgeNode*)malloc(sizeof(west_EdgeNode)); 		west_newnode->west_adjvex=i; 		west_newnode->west_weight=0; 		west_newnode->west_nextedge = west_alGraph->west_vertices[j].west_firstedge; 		west_alGraph->west_vertices[j].west_firstedge=west_newnode; 	}

领接表dfs,看起来这里根本不往下走 while(west_vexNode!=NULL)     {         w=west_vexNode->west_adjvex;              //当w=12时，开始死循环，不执行if里的WEST_DFS函数         if(!w) break; // w==0 meas end         if(west_visited[w]==0)             WEST_DFS(west_alGraph,w);         west_vexNode =west_vexNode->west_nextedge; // next     }

会执行啊，是不是流程没搞好，单步执行就进去了。

看的好忧桑····


Question: window用C语言怎么可以把字节数据写进声卡播放

auxGetDevCaps auxGetNumDevs auxGetVolume auxOutMessage auxSetVolume PlaySound sndPlaySound waveInAddBuffer waveInClose waveInGetDevCaps waveInGetErrorText waveInGetID waveInGetNumDevs waveInGetPosition waveInMessage waveInOpen waveInPrepareHeader waveInProc waveInReset waveInStart waveInStop waveInUnprepareHeader waveOutBreakLoop waveOutClose waveOutGetDevCaps waveOutGetErrorText waveOutGetID waveOutGetNumDevs waveOutGetPitch waveOutGetPlaybackRate waveOutGetPosition waveOutGetVolume waveOutMessage waveOutOpen waveOutPause waveOutPrepareHeader waveOutProc waveOutReset waveOutRestart waveOutSetPitch waveOutSetPlaybackRate waveOutSetVolume waveOutUnprepareHeader waveOutWrite

查MSDN是Windows程序员必须掌握的技能之一。


Question: 实参到形参赋值时怎么进行的

根据字面值判断你给的数是什么类型，C++新标准可以使用auto关键字，你可以写如：auto a = 1;、auto b = 3UL;然后看a是什么类型

int 形参 = 实参; 其实就是这样而已 没多复杂 别想太多

给形参开辟多大空间，取决于函数声明时的形参类型，就跟在函数体定义一样的，只不过是在函数调用的时候，用实参的数据对形参进行初始化，至于是否会发生强制转换，得看函数声明的类型与实参类型是否一致以及是两种类型是否支持隐式强制转换

参数如何传递，要看函数调用是否受原型控制。 如果函数是采用传统K&R形式声明的，则执行缺少参数转换；否则按原型中指定的类型传递。 void f (char c; float f); void g ();  f ('x', 0.01);     //'x'从int转换为char类型的值传递；0.01从double转换为float传递。 f (1, 2.0, 3);     //非法。 g ();     //合法； g (1);     //合法； g (0.01f);     //合法，0.01f从float转换为double传递； g ((short)3, 8);     //合法，(short)3从short类型转换为int类型传递。 楼主你写了那么多，基本没有任何价值。

没有啊, 我是"希望"啊

"最后希望你们从下面几个方面给我一个清晰的形参赋值总结." 语气很强硬

引用 14 楼 love1code 的回复:那么是这个目的的话，你就不必用函数来做实验了。 直接用赋值语句。2个不同类型的变量相互赋值。 这个涉及到类型得提升和二进制码。 一般编程时是不会这样做的。 这个不一样, 一般的赋值 int a = 3.0; //肯定是强转    而函数形参赋值,涉及到3种类型: 函数定义  函数声明  实参字面值类型 我测试了很多 反正感觉从实参到函数声明的过程,好像都是强转的, 也就是把实参的值强转函数成声明类型的值, 然后非强转的赋给形参(函数定义里的类型)

引用 12 楼 love1code 的回复:int Add(double x, char y); //如果声明该成这样 我想问：为什么要声明成这样？ 函数的声明就是为了函数的调用做准备，什么准备呢？告诉编译器函数的接口和返回值特性。以免调用时函数使用不当。 函数定义时，2个参数都是int型，而你声明的时候，却改为double 和char   并且你传递的参数都是 int型，类型不配，肯定报错呢！  我这个是想测试类型错误,然后形参具体赋的是什么值, 错误的一步一步的结果是什么样子, 当然我真要程序肯定不会这样声明的

引用 7 楼 love1code 的回复:# include <stdio.h> /*C语言都是按值传递的参数*/  int Add(int x,int y); int Sub(int x,int y); //一个简单的例子，执行流程如下：   int main(void)   //一。操作系统调用main函数，程序开始运行。  { 	int a=1,b=2; //操作系统为main及里面的变量分配栈空间。也就是main函数入栈。  	int c=5,d=7; 	            //a,b,c,d都在main函数里定义，只要main函数在，他们也就在。                   	 	Add(a,b); 	         //二。发现函数调用指令，操作系统为Add函数临时分配栈空间。Add函数入栈  	        // main函数处于"挂起"状态,执行流程进入Add函数。x，y分别获得a，b的值！！ 			//x，y完成运算return结果，Add函数执行完毕，系统收回Add函数的栈空间，  	        // Add函数内部的局部变量x，y消失。 Add函数出栈  	 	 	       //三，执行流程回到main函数。  	 	Sub(c,d); 	       //四。发现函数调用指令，操作系统为Sub函数临时分配栈空间。Sub函数入栈 	       // main函数再次处于"挂起"状态,执行流程进入Sub函数。x，y分别获得c,d的值！！           //函数内的局部变量x，y完成运算，return回结果， Sub函数结束。x,y被销毁。 		  //系统回收Sub函数的栈空间。Sub出栈。 		   		  //五。执行流程再回到main函数  		    		  //六。遇到return 指令，main函数返回 0给操作系统。main函数执行完毕  	     //系统回收main函数的栈空间，a,b,c,d消失。main出栈。程序结束。  	return 0; }  int Add(int x,int y) { 	      return x+y;	 	 }  int Sub(int x,int y) { 	 	return x-y; }  函数调用顺序你讲的很清楚, 可是我还想想知道在函数调用参数赋值的那一段,栈里各个变量的内存大小和值分别是多少?  如果把你的例子改成这样:  # include <stdio.h> int Add(double x, char y); //如果声明该成这样 int main(void)   //一。操作系统调用main函数，程序开始运行。  { 	int a = 1, b = 2; // 	int c = Add(a, b); 	printf("%d\n", c); //结果是1072693248, 这个结束是怎么一步步错误得到的??  	system("pause"); 	return 0; }  int Add(int x, int y) // 这里的x和y, 在main中调用int c = Add(a, b)时, 它们的值分别是多少 为什么?? {  	return x + y;  }

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


Question: c语言 数据存储问题 书中的例子 可是出现了问题 小白一名谢谢帮忙

用文本方式操作

既然要用二进制的方式读取，就得先按二进制的方式写入  #include<stdio.h> #include<stdlib.h> #include<errno.h> #define SIZE 5 struct Stu { 	char name[10]; 	int num; 	int age; 	char addr[15]; }w_stu[SIZE], r_stu[SIZE]; int i; char *file = "D:\\out.dat"; FILE *fp; void write_data() { 	fp = fopen(file, "wb"); 	for (i = 0; i < SIZE; i++) 		fwrite(w_stu + i, sizeof(struct Stu), 1, fp); 	fclose(fp); } void read_data() { 	fp = fopen(file, "rb"); 	for (i = 0; i < SIZE; i++) 	{ 		//fseek(fp, i*sizeof(struct Stu), 0); 		fread(r_stu + i, sizeof(struct Stu), 1, fp); 		printf("%s,%d,%d,%s\n", r_stu[i].name, r_stu[i].num, r_stu[i].age, r_stu[i].addr); 	} 	fclose(fp); } int main() { 	char name[10], addr[15]; 	//构造数据 	for (i = 0; i < SIZE; i++) 	{ 		sprintf(name, "stu_%d", i); 		sprintf(addr, "addr_%d", i); 		strcpy(w_stu[i].name, name); 		strcpy(w_stu[i].addr, addr); 		w_stu[i].age = rand() % 20 + 1; 		w_stu[i].num = rand() % 20 + 1; 	} 	write_data(); 	read_data(); 	return 0; }

不要太迷信书本了


Question: 布尔函数，请问它带出的值是什么？0吗

引用 4 楼 ant2012 的回复:typedef unsigned char boolean; #define FALSE               0 可见，在C++中boolean其实就是无符号字符型  此话怎么说？

对C语言来说 这段代码无法通过编译  更别提什么运行结果了

C语言中是没有关键字boolean的，一般编译器是将false宏定义为0，如在linux中头文件stdbool.h 有 #define false 0


Question: getch()和ungetch()看不懂，新人求指导

引用 9 楼 a339299936 的回复:int charch(void); void ungetch(int); int getine(int *pn) {     int c, sign;     while (isspace(c = getch()))         ;     if (!isdigit(c) && c != EOF && c != '+' && c != '-'){         ungetch(c);         return 0;     }     sign = (c == '-') ? -1 : 1;     if (c == '+' || c == '-')         c = getch();     for (*pn = 0; isdigit(c); c = getch())         *pn = 10 * *pn + (c - '0');     *pn *= sign;     if (c != EOF)         ungetch(c);     return c;  教科书上的这段代码写的是什么啊 没看懂 求大神指点

不过楼主想自定义一个数据缓冲区，也可以像你写的那两个函数样，char buf[BUFSIZE];就像数据缓冲区

直接调用，无需定义，能用系统库的最好用系统库，自己写的代码稳健性在待检测

引用 5 楼 a339299936 的回复:执行后提示 1>------ 已启动生成:  项目: lainxi5, 配置: Debug Win32 ------ 1>  main.c 1>f:\bclx\lainxi5\lainxi5\main.c(8): warning C4013: “getine”未定义；假设外部返回 int 1>f:\bclx\lainxi5\lainxi5\main.c(12): error C2371: “ungetch”: 重定义；不同的基类型 1>          e:\办公软件\vc\include\conio.h(140) : 参见“ungetch”的声明 ========== 生成:  成功 0 个，失败 1 个，最新 0 个，跳过 0 个 ==========  去掉这两个函数的定义，库里面已经实现了它们

getch()会读取你输入的第一个字符   就结束该语句 ungetch();   是把一个字符退回到键盘缓冲区中

引用 2 楼 ant2012 的回复:楼主可以include <conio.h>头文件，直接使用这两个函数，无需自己定义 添加 include <conio.h>头文件后 提示错误啊 提示这个void ungetch(int);错误

你自己定义的吗，库函数中，getch()是从缓冲区中无回显地读字符， ungetch()是把一个字符退回到键盘缓冲区中


Question: c语言新手求助

#include <stdio.h> int main() {     int a,b;     scanf("%d%d",&a,&b);     printf("a=%d, b=%d/n",a,b）； } 而在scanf后写a=%d b=%d,属于语法错误。。

可怎么输入啊 引用 3 楼 wu2304211 的回复:#include<stdio.h> int main() {   int a,b;   scanf("%d%d",&a,&b);   printf("%d %d",a,b); } 这样就行啦！

引用 4 楼 pengyw的回复:可怎么输入啊 [quote=引用 3 楼 wu2304211 的回复:] #include<stdio.h> int main() {   int a,b;   scanf("%d%d",&a,&b);   printf("%d %d",a,b); } 这样就行啦！[/quote] scanf那里不就是用来输入的嘛

scanf()的格式控制串可以使用其它非空白字符，但在输入时必须输入这些字符。  例：  scanf("%d,%d",&a,&b);  输入： 3，4 ↙（逗号与"%d,%d"中的逗号对应）  scanf("a=%d,b=%d",&a,&b);  输入： a=3，b=4 ↙（"a=","b=",逗号与"%d,%d"中的"a=","b="及逗号对应）   检查你的输入是不是符合你定义的要求

对应的输入应该是这个样子的 a=12b=34  正常人没有这样用scanf的


Question: 提示编译不成功，求解

是%d 不是d%


Question: c语言 getchar()函数问题 找不到问题出在哪里

这个处理缓冲区残留确实是个头疼而且重要的问题，因为它影响你的数据的输入。最典型的就是输入完成后按下回车键，回车产生副作用：在缓冲区留下一个'\n'换行符。 我的建议是：尽量不要使用getchar，因为他什么字符都会读取。包括空白符，如\n  解决办法：1.将getchar替换成scanf("   %c",&ch)   //%c前加一个空格，这样ch就只能读取非空白符了。也就是你输入的有效数据                      2.你会问，那读取其他的数据，如字符串，整数，浮点数怎么处理空白符残留那？                         使用scanf() 时，scanf会清理开始的空白符。不会有影响。                      3.清理错误的输入。有时候输入的数据是错误的，你不能不理他，因为他会残留在缓冲区，需要清理他。                         你使用的是fflush()函数，据我所知，这个函数是为stdout设计的，不建议对stdin使用。                         可以这样：                         void Clear_buf(void)\                         {                               while(getchar()!='\n')                                 ;                           }                         这是通用的清理输入缓冲的办法。


Question: c语言 文件读写问题 各位大神帮忙

引用 1 楼 user-1 的回复:检查fopen_s返回值的表达式错了吧我很抱歉 我想给您40点 因为您帮助我解决了问题 可是这个网站有点bug 他总告诉我与总点数不符合 可是我问题点数就是40点 真的抱歉 也真的谢谢您


Question: 函数的调用，求大神讲解

这个应该查操作手册吧

呃，感谢