Question: CRT detected that the application wrote to memory after end of heap buffer

3楼写错了，应该是  sizeof(*pHead)

先把这个改了 PNODE pHead = (PNODE)malloc(sizeof(*PNODE));

引用 4 楼 user-1 的回复:3楼写错了，应该是  sizeof(*pHead)  sizeof应该是结构体的大小,是吧. 的定义结构体为: typedef struct node { 	int data; 	struct node * pNext; } NODE, * PNODE; 所以应该为: PNODE pCur = (PNODE)malloc(sizeof(NODE));

引用 5 楼 user-1 的回复:sizeof(PNODE)  // 指针的大小，32位系统的话就是4字节 sizeof(*pHead)  // 结构的大小，至少是一个pNext加上一个data PNODE pCur = (PNODE)malloc(sizeof(PNODE)); // 这里分配了4个字节的空间，然后写了8个字节的数据  真的对了... 厉害...

在2楼打错了字, '貌似是没有错的'

我测试的时候,录入是4个元素,调试的时候,发现即将free的元素,就是第三个.没有就是没有错的,但是总报错. 这是辅助代码: void main() { 	PNODE pHead = Create(); 	Traverse(pHead); 	int v; 	Delete(pHead, 2, &v); 	Traverse(pHead); }  PNODE Create() { 	int len;	//total count of nodes to be created. 	int i; 	int val; //temp value for the current node. 	printf("enter the size of nodes:"); 	scanf("%d", &len); 	PNODE pHead = (PNODE)malloc(sizeof(PNODE)); 	pHead->pNext = NULL; 	PNODE pTail = pHead;  	if(NULL == pHead) { 		printf("allocate memory failed!"); 		exit(0); 	} 	for (i = 0; i < len; i++) 	{ 		PNODE pCur = (PNODE)malloc(sizeof(PNODE)); 		if(NULL == pCur) { 			printf("allocate memory failed!"); 			exit(0); 		} 		printf("enter the %d-th value : ", i + 1); 		scanf("%d", &val); 		pCur->data = val;  		//set the new node as the tail node. 		pTail->pNext = pCur;	 		pCur->pNext = NULL; 		pTail = pCur; 	} 	return pHead; }  void Traverse(PNODE pHead) { 	PNODE pCur = pHead->pNext; 	while(NULL != pCur) { 		printf("%d ", pCur->data); 		pCur = pCur->pNext; 	} 	printf("\n"); 	return; }


Question: 关于崩溃情况下的文件映射

TerminateProcess进程模拟一下，看看结果如何

会 我猜


Question: VS2010 使用库函数max，能编译、运行，但提示未定义标识符

引用 1 楼 zhao4zhong1 的回复:用__max  我的遇到了相似的问题，我将COM中的dll文件import后，提示未定义标识符，COM中的函数也提示未定义，但是程序能运行。   请问您说将max换成__max，这是什么意思呢？我是小白，请指教。


Question: C语言scanf输入

9楼已给出答案了。我觉得。

唉，这个就不清楚了，没听说过这样的用法，楼主要是能找到，麻烦说一下啊

引用 12 楼 u012421456 的回复:楼主是想输入时自动有左边的1234还是自己输入？   右边两列数字才是要输入的，第一串数字占五列，然后空一格，第二个数字占两列，并且向右靠齐

引用 4 楼 user-4_ 的回复:原来scanf还可以这么用。 发现你的C语言老师是二把刀了吧。

原来scanf还可以这么用。

引用 1 楼 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.   没怎么看懂

楼主是想输入时自动有左边的1234还是自己输入？

引用 10 楼 u012421456 的回复:有点不太懂楼主的图片，右边两列是输入吗？ 恩 是的 右边的两列是要求输入的数据

有点不太懂楼主的图片，右边两列是输入吗？

引用 7 楼 u014245881 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] #include <stdio.h> struct D {     double f;     int n; } d[4]; int i,j; int main() {     for (i=0;i<4;i++) {         while (1) {             printf("\nPlease input %d #.# #:",i+1);             fflush(stdout);             rewind(stdin);             if (3==scanf("%d%lf%d",&j,&(d[i].f),&(d[i].n))) {                 if (j==i+1) break;             }         }     }     return 0; }   主要有严格的格式控制，第一串数字占五列，然后空一格，第二个数字占两列，并且向右靠齐[/quote] 没实际编译链接调试，不保证对，仅供参考： #include <stdio.h> int i,j,n,r; char s1[6]; char s2[3]; char c1,c2; double d; int main() {     for (i=0;i<4;i++) {         while (1) {             printf("\nPlease input ##### ##:");             fflush(stdout);             rewind(stdin);             if (4==scanf("%5[0-9.]%c%2[0-9 ]%c",s1,&c1,s2,&c2)) {                 if (c1==' ' && c2=='\n') {                     if (1==sscanf(s1,"%lf%n",&d,&n)) {                         if (n==5) {                             if (1==sscanf(s2,"%d%n",&j,&n)) {                                 if (n==2) {                                     break;                                 }                             }                         }                     }                 }             }         }     }     return 0;

引用 6 楼 chuai1609 的回复:不论是scanf还是cin，都有个输入缓冲区，而在你多次输出间隔符，主要是回车的时候，很容易发生缓冲区数据的错误，所以，为了避免一些不必要的情况，需要每次输入完之后，自己处理一下缓冲区，思想就是这样，scanf有scanf的处理方法，cin有cin的处理方法。 我一般参考这个： #if 0     // safty method to absorb scanf buffer     int i,c;     while (1)     {         printf("input:");         if(scanf("%d",&i)!=EOF)         {             while((c=getchar())!='\n'&&c!= EOF){}         }         printf("out:%d\n",i);         //i here hold the last value     } #endif #if 0     // safty method to absorb cin buffer     int i;     while(1)     {         cout<<"input:";         cin>>i;         cin.clear();         cin.ignore( std::numeric_limits<std::streamsize>::max( ), '\n' );         cout<<"out:"<<i<<endl;         //i here hold the last value     } #endif   这个只能实现多个输入吧，还要有严格的格式控制，第一串数字占五列，然后空一格，第二个数字占两列，并且向右靠齐

引用 3 楼 zhao4zhong1 的回复:#include <stdio.h> struct D {     double f;     int n; } d[4]; int i,j; int main() {     for (i=0;i<4;i++) {         while (1) {             printf("\nPlease input %d #.# #:",i+1);             fflush(stdout);             rewind(stdin);             if (3==scanf("%d%lf%d",&j,&(d[i].f),&(d[i].n))) {                 if (j==i+1) break;             }         }     }     return 0; }   主要有严格的格式控制，第一串数字占五列，然后空一格，第二个数字占两列，并且向右靠齐


Question: 我是超级菜鸟 帮我看看这个代码啊  谢谢了

正像一楼说的，不要这样x>y>z写，你看哪本书是这样写的，改了吧，楼主你用什么课本，我记得我那个教材（谭浩强的）上好像有这个例子，还有就是注意代码格式

参考代码： #include <stdio.h>  int max(int x,int y,int z) { 	x=x>y?x:y; 	x=x>z?x:z; 	return x; }  int main() { 	int a,b,c;	 	scanf("%d%d%d",&a,&b,&c); 	printf("最大值为%d\n",max(a,b,c)); 	return 0; }

if(x>y>z||x>z>y)m=x; 改成 if(x>y && x>z)     m=x; 其他的几个类似

引用 1 楼 u013491662 的回复:不要写 x>y>z 因为x>y的值不是0就是1 0>z 或 1>z 显然是错的 要写成 x>y&&y>z+1


Question: 求助，两个代码片段功能一样，为什么后者会出错

copy完了，旧源的内容都变了，谁觉得copy成功我跟谁急！

引用 6 楼 Zzy_ZhangZeyu_ 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] 因为： copy的意思是操作完成后，新目标和旧源内容相同，且旧源内容不变。 move的意思是操作完成后，新目标和旧源内容相同，旧源内容不一定不变。  所以： 当新目标和旧源内容保存的位置有重叠时，根本不可能实现copy，只能实现move！  不对啊，我在我自己电脑上运行的时候即使有重叠，memcpy用起来也没问题。只有在提交到网上后，在oj上会出错[/quote]  都说了这段代码是只达不到你的逻辑要求。在release的版本，被重叠的内存如果是可以写入的，当然不会出错了。如果是只读内存，肯定会出错。你搞个const内存试试看吧。

引用 4 楼 zhao4zhong1 的回复:因为： copy的意思是操作完成后，新目标和旧源内容相同，且旧源内容不变。 move的意思是操作完成后，新目标和旧源内容相同，旧源内容不一定不变。  所以： 当新目标和旧源内容保存的位置有重叠时，根本不可能实现copy，只能实现move！  不对啊，我在我自己电脑上运行的时候即使有重叠，memcpy用起来也没问题。只有在提交到网上后，在oj上会出错

release版本应该不会有runtime error吧。

引用 2 楼 Zzy_ZhangZeyu_ 的回复:[quote=引用 1 楼 user-4 的回复:] The memcpy function copies count bytes of src to dest. If the source and destination overlap, this function does not ensure that the original source bytes in the overlapping region are copied before being overwritten. Use memmove to handle overlapping regions.  我靠，大哥，你太给力了 虽然我以前也知道memcpy处理重叠情形的时候会出问题，但没想到居然是RUNTIME ERROR这类错误，谢谢了，长个教训！[/quote] 使用memmove

引用 1 楼 user-4 的回复:The memcpy function copies count bytes of src to dest. If the source and destination overlap, this function does not ensure that the original source bytes in the overlapping region are copied before being overwritten. Use memmove to handle overlapping regions.  我靠，大哥，你太给力了 虽然我以前也知道memcpy处理重叠情形的时候会出问题，但没想到居然是RUNTIME ERROR这类错误，谢谢了，长个教训！


Question: 分析程序

引用 3 楼 u013491662 的回复:这个是运算符优先级问题 优先级： 等于运算符（==）>逻辑或运算符（||）>赋值运算符（=） 所以if语句里的表达式相当于  iParam1 = (2 || (iParam2 == 2))  因为iParam2等于2，所以表达式iParam2 == 2的值为1 2||1的值为1 iParam1 = 1这个赋值表达式的值为1，此时iParam1的值为1 所以if语句相当于if(1) 执行 iRet = iParam1 + iParam2; 因为iParam1的值为1， iParam2的值为2，所以iRet的值为3！  按照你的分析，我去试了下，变化不同的值，得到的自己分析的结果。所以你的分析正确，谢谢！

既然代码正确，那就是iParam1 变成1了呗，至于为什么变成1而不是2，你可以自己再查查

引用 1 楼 banshichiqinglangzi 的回复:iParam1 = 2不是iParam1 = =2？  确定是iParam1 = 2

iParam1 = 2不是iParam1 = =2？


Question: 纯C语言求改正，由于受编译环境限制，不能用c++的引用“&”符号

引用 6 楼 Idle_ 的回复:引用int CreateListR_Link(LinkList *L,int elem[],int n){   LNode *p,*q;   int i;   L=(LinkList *)malloc(sizeof(LinkList));  <<--L变量被替换，它不再指向传入的LinkList内存块，而是指向了新malloc的内存 ...  return OK;   <<-- 原始传入的LinkList并未改变，新malloc的内存泄漏  }   int main(){   ...  CreateListR_Link(&LL,a,5);  <<--调用完后LL中的内容未改变，所以LL.next != NULL (栈变量，LL.next多半是个非0的无效数)  printf("%d\n",LengthList_Link(&LL));  <<-- LengthList_Link中判断p=p->next; p != NULL为TRUE, 但是p已指向非法内存，所以报错  return 0;  }   谢谢，学习了

引用 3 楼 zxhuser-2 的回复:这样？ 嗯嗯，对的，感谢大神，由于自学数据结构，虽然有些时间了，但好像总停留在理论层面，现在想弄精通点，一较真就出现各种问题了

链表创建、插入、删除、排序、反向代码 在这堆代码中有http://pan.baidu.com/s/17yIcQ

这样？ #include <stdlib.h> #include <stdio.h>  typedef struct LNode { 	int data; 	struct LNode *next; }LNode,LinkList;  LinkList* CreateListR_Link(int elem[],int n); int LengthList_Link(LinkList *L);  LinkList* CreateListR_Link(int elem[],int n) { 	LNode *head,*p,*q; 	int i=0; 	head=p=(LinkList *)malloc(sizeof(LinkList)); 	p->data=elem[i]; 	printf("%d\t",p->data); 	for(i++;i<n;i++) 	{ 		q=(LNode *)malloc(sizeof(LNode)); 		q->data=elem[i]; 		printf("%d\t",q->data); 		p->next=q; 		p=q; 	} 	p->next=NULL; 	return head; }  int LengthList_Link(LinkList *p) { 	int n=0; 	while(p!=NULL) 	{ 		n++; 		p=p->next; 	} 	return n; }  int main() { 	LinkList* LL; 	int i; 	int a[5]; 	for(i=0;i<5;i++) 		a[i]=11+i; 	LL=CreateListR_Link(a,5); 	printf("\nnode num:%3d\n",LengthList_Link(LL)); 	return 0; };

引用 1 楼 zxhuser-2 的回复:没弄懂lz的意思  能直接调试代码吗？ 把LengthList_Link(LinkList *L)这函数里的cc=getchar();全部注释起来你就会发现问题了

没弄懂lz的意思


Question: 单链表的定义的问题

单链表是由节点通过指针构成的，每个节点包含一个数据和一个指针（单链表），所以必然是指针类型了

定义指针。。。

引用 2 楼 Edward2Jason 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 因为LinkList的类型是struct Node *而不是struct Node 我们用指针指向单链表，所以必须是用struct Node *，是这样吗？[/quote] 是的，意思就是说以后可以用LinkList来代替typedef struct Node *了

引用 1 楼 zhao4zhong1 的回复:因为LinkList的类型是struct Node *而不是struct Node 我们用指针指向单链表，所以必须是用struct Node *，是这样吗？


Question: WinPcap编程出现丢包的问题

@周文钰 ，楼主你的问题解决了吗？

丢包也可能出现在交换上，你降低码流还会丢包么？

接收的速度太慢。 试试开一个足够大的内存区作FIFO缓冲，用一个线程专门负责接收最新到达的数据并放进该缓冲。 其它线程从该缓冲中取数据并在时间允许的条件下显示数据或将数据保存到磁盘。 缓冲满时输出错误信息到日志文件。 可能最终需要考虑换一个转速快点的硬盘或干脆用固态硬盘。  多线程操作FIFO缓冲的经典例子代码： //循环向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; }  如果楼主实际使用以上代码时写日志影响速度，可将日志写到一个RAMdisk上或将无用写日志部分注释掉。

谢谢大家的回答！经过自己的研究，这个函数算是彻底明白了。不过接收的数据还是出现了丢包的现象，，不知道如何解决啊，，，，，发送的数据量太大了，太快了，，，，头痛啊！

引用 1 楼 zhao4zhong1 的回复:不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545 赵老师，我没有用TCP协议，要是用这个就好了，我就不用这么苦逼了！发送端是雷达，不能建TCP协议栈，是直接发过来的，面向无连接的而且数据量很大（每秒40MB左右），所以我用得是WinPcap的API在MFC下做的接收端，即使不对数据处理只是将一个完整地数据包大小打印出来都出来了数据包大小的值波动的现象（数据包都是一样大的），，关于提问中的那个函数我已经理解了

int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data); 说明：捕获数据包，与pcap_ dispatch()   pcap_loop()很相似。pcap_next_ex()允许直接调用来接收包，它的参数和pcap_loop()相同：有一个网卡描述副，和两个指针，这两个指针会被初始化并返回给用户，一个是pcap_pkthdr结构，另一个是接收数据的缓冲区。 参数:        p是由pcap_open_live()返回的所打开网卡的指针        pcap_pkthdr型的结构体，存储时间，包的长度         pkt_data存储数据包的内容，为一个char型数组 struct pcap_pkthdr {         struct timeval ts;                bpf_u_int32 caplen;                bpf_u_int32 len;        };  返回值：当等于1时成功；等于0时超时；等于-1时说明发生错误，错误信息用pcap_geterr(adhandle)获得

引用 10 楼 bubu8633 的回复:[quote=引用 9 楼 aaa763602742 的回复:] [quote=引用 7 楼 bubu8633 的回复:] 丢包也可能出现在交换上，你降低码流还会丢包么？ 降低码流的确没有丢包现象了（降低了5倍），但是不能这么干啊，实际需要那么大的数据量，，，有什么好办法呢？？顺便问一下winpcap的MAC地址过滤是怎么写的？？[/quote]  你先得确保在链路上不丢,然后再优化代码才有意义.  WinPcap过滤规则[/quote] 你说的也是！但是我想先把数据过滤出来也是好的，，然后再慢慢的解决丢包的问题

引用 10 楼 bubu8633 的回复:[quote=引用 9 楼 aaa763602742 的回复:] [quote=引用 7 楼 bubu8633 的回复:] 丢包也可能出现在交换上，你降低码流还会丢包么？ 降低码流的确没有丢包现象了（降低了5倍），但是不能这么干啊，实际需要那么大的数据量，，，有什么好办法呢？？顺便问一下winpcap的MAC地址过滤是怎么写的？？[/quote]  你先得确保在链路上不丢,然后再优化代码才有意义.  WinPcap过滤规则[/quote] 我是这么定义的：char *filter = "ether src 20-1A-06-8A-2B-0E";  20-1A-06-8A-2B-0E是发送端的MAC地址，结果反而什么都收不到了，收到了的都是乱七八糟的数据！

引用 9 楼 aaa763602742 的回复:[quote=引用 7 楼 bubu8633 的回复:] 丢包也可能出现在交换上，你降低码流还会丢包么？ 降低码流的确没有丢包现象了（降低了5倍），但是不能这么干啊，实际需要那么大的数据量，，，有什么好办法呢？？顺便问一下winpcap的MAC地址过滤是怎么写的？？[/quote]  你先得确保在链路上不丢,然后再优化代码才有意义.  WinPcap过滤规则

引用 7 楼 bubu8633 的回复:丢包也可能出现在交换上，你降低码流还会丢包么？ 降低码流的确没有丢包现象了（降低了5倍），但是不能这么干啊，实际需要那么大的数据量，，，有什么好办法呢？？顺便问一下winpcap的MAC地址过滤是怎么写的？？

引用 7 楼 bubu8633 的回复:丢包也可能出现在交换上，你降低码流还会丢包么？ 目前发送端是固定的，数据量不会改变，我现在的任务就是测试大数据量下接收端的稳定性，不过后期貌似数据量会大大减少


Question: c语言高手来下，帮我看几个宏定义什么意思

引用 2 楼 zxh707wk 的回复:1.判断两个字符串是否相同 2.求出数组的长度 3.判断x最后一位是否为1（x应该是一个字节，判断第8位是否为1） 4.自定义头文件   [quote=引用 1 楼 zhao4zhong1 的回复:] 编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E +1[/quote] 非常感谢   你这一说我瞬间明白多了   谢谢

1.判断两个字符串是否相同 2.求出数组的长度 3.判断x最后一位是否为1（x应该是一个字节，判断第8位是否为1） 4.自定义头文件  引用 1 楼 zhao4zhong1 的回复:编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E +1

编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E


Question: fgets问题

引用 5 楼 w7390348 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] for(i=0;i<3;i++) {  fgets(str[i],20,stdin);if ('\n'==str[i][strlen(str[i])-1];str[i][strlen(str[i])-1]=0; }  感谢，赵老师[/quote] if后第一个;应替换为)

引用 1 楼 zhao4zhong1 的回复:for(i=0;i<3;i++) {  fgets(str[i],20,stdin);if ('\n'==str[i][strlen(str[i])-1];str[i][strlen(str[i])-1]=0; }  感谢，赵老师

for(i=0;i<3;i++) {  fgets(str[i],20,stdin);  int L1=(int)strlen(str[i])-1;  if ('\n'==str[i][L1]) str[i][L1]=0; }

[code=for(i=0;i<3;i++) {  fgets(str[i],20,stdin);if ('\n'==str[i][strlen(str[i])-1];str[i][strlen(str[i])-1]=0; }c][/code]  引用 1 楼 zhao4zhong1 的回复:for(i=0;i<3;i++) {  fgets(str[i],20,stdin);if ('\n'==str[i][strlen(str[i])-1];str[i][strlen(str[i])-1]=0; }  可读性呀，赵老师

fgets(str[i],20,stdin); 文件指针用成stdin即可。


Question: 用c语言写了个解析文件并写入到数据库，求大师指导！

迟来的幸福！

突然回来结个贴。不好意思，问题解决了。

先将demo目录下插入数据的例子编译链接调试通过，再将其中操作数据库相关部分照搬到自己的代码中。

引用 13 楼 zhao4zhong1 的回复:参考oracle中的例子代码demo\*.*  参考了demo例子，还是出现那个问题，在引入sql头文件时， #include <sqlca.h> 和 EXEC SQL include "sqlca.h" 和 EXEC SQL include sqlca 这三者有什么区别吗？ 始终报 DzxxHB.c: In function 'main': DzxxHB.c:30: error: 'EXEC' undeclared (first use in this function) DzxxHB.c:30: error: (Each undeclared identifier is reported only once DzxxHB.c:30: error: for each function it appears in.) DzxxHB.c:30: error: expected ';' before 'SQL' DzxxHB.c:32:50: warning: multi-character character constant DzxxHB.c: In function 'parseFileToSQL': DzxxHB.c:111: error: 'EXEC' undeclared (first use in this function) DzxxHB.c:111: error: expected ';' before 'SQL' 这个错，崩溃了。

参考oracle中的例子代码demo\*.*

引用 11 楼 zhao4zhong1 的回复:你代码中：  	// 连接数据库并插入数据 EXEC SQL CONNECT GAPS/GAPS; 需要进一步编写函数完成对应功能。 参考oracle中的例子代码demo\*.*  fprintf(sql,"insert into yw_dsdf_dzxx_hb values('%s','%s','%s','%s','%s','%d','%s','%d')",yhbh,gyh,yhlsh,yhbh_1,jfrq,sfje,sfqd,isznbsf);  EXEC SQL INSERT INTO yw_dsdf_dzxx_hb values(sql); 这个算是吗？写了个insert 函数

对于头文件的引用，不晓得下面这些正确吗？ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <dirent.h> #include <time.h> #include <sqlca.h>

[quote=引用 7 楼 zhao4zhong1 的回复:] [quote=引用 4 楼 xiaolubian 的回复:] [quote=引用 3 楼 zhao4zhong1 的回复:] [code=c]#include <stdio.h> #include <windows.h> char *getYesterday() {     FILETIME ft;     SYSTEMTIME st;     static char yesterday[9];  我新手，感谢指导，自己也在不断编译调试中，现在的问题如下： DzxxHB.c:31:50: warning: multi-character character constant DzxxHB.c: In function 'parseFileToSQL': DzxxHB.c:68: error: 'EXEC' undeclared (first use in this function) DzxxHB.c:68: error: (Each undeclared identifier is reported only once DzxxHB.c:68: error: for each function it appears in.) DzxxHB.c:68: error: expected ';' before 'SQL' DzxxHB.c:74: warning: passing argument 1 of 'strstr' from incompatible pointer type /usr/include/string.h:342: note: expected 'const char *' but argument is of type 'struct FILE *' DzxxHB.c:75: error: 'BUFFSIZE' undeclared (first use in this function) DzxxHB.c:75: error: 'file' undeclared (first use in this function) DzxxHB.c:76: error: incompatible types when assigning to type 'char[1024]' from type 'int' DzxxHB.c:77: error: incompatible types when assigning to type 'char[1024]' from type 'int' DzxxHB.c:80: error: incompatible types when assigning to type 'char[4]' from type 'char *' DzxxHB.c:81: error: incompatible types when assigning to type 'char[8]' from type 'char *' DzxxHB.c:82: error: incompatible types when assigning to type 'char[6]' from type 'char *' DzxxHB.c:83: error: incompatible types when assigning to type 'char[4]' from type 'char *' DzxxHB.c:84: error: incompatible types when assigning to type 'char[8]' from type 'char *' DzxxHB.c:85: error: incompatible types when assigning to type 'double[20]' from type 'char *' DzxxHB.c:86: error: incompatible types when assigning to type 'char[3]' from type 'char *' DzxxHB.c:87: error: incompatible types when assigning to type 'int[1]' from type 'char *' DzxxHB.c:89: warning: passing argument 1 of 'fprintf' from incompatible pointer type /usr/include/stdio.h:355: note: expected 'struct FILE * __restrict__' but argument is of type 'char *' DzxxHB.c:92: error: expected ';' before 'SQL' DzxxHB.c:97: error: incompatible types when assigning to type 'char[1024]' from type 'int' DzxxHB.c:98: error: incompatible types when assigning to type 'char[1024]' from type 'int' DzxxHB.c:101: error: incompatible types when assigning to type 'char[4]' from type 'char *' DzxxHB.c:103: error: incompatible types when assigning to type 'char[8]' from type 'char *' DzxxHB.c:104: error: incompatible types when assigning to type 'char[1024]' from type 'char *' DzxxHB.c:111: error: incompatible types when assigning to type 'char[4]' from type 'char *' DzxxHB.c:112: error: incompatible types when assigning to type 'double[20]' from type 'char *' DzxxHB.c:113: error: incompatible types when assigning to type 'char[3]' from type 'char *' DzxxHB.c:114: error: incompatible types when assigning to type 'int[1]' from type 'char *' DzxxHB.c:115: warning: passing argument 1 of 'fprintf' from incompatible pointer type /usr/include/stdio.h:355: note: expected 'struct FILE * __restrict__' but argument is of type 'char *' DzxxHB.c:118: error: expected ';' before 'SQL'

引用 5 楼 xiaolubian 的回复:在请教下哈  GetSystemTimeAsFileTime(&ft);     *(__int64 *)&ft-=864000000000i64;     FileTimeToSystemTime(&ft,&st); 这个是个什么意思？ GetSystemTimeAsFileTime(&ft);//取当前系统时间放在ft中 *(__int64 *)&ft-=864000000000i64;//将ft减去86400秒 FileTimeToSystemTime(&ft,&st);//将ft转为st

引用 4 楼 xiaolubian 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] #include <stdio.h> #include <windows.h> char *getYesterday() {     FILETIME ft;     SYSTEMTIME st;     static char yesterday[9];      GetSystemTimeAsFileTime(&ft);     *(__int64 *)&ft-=864000000000i64;     FileTimeToSystemTime(&ft,&st);     sprintf(yesterday,"%4d%02d%02d",st.wYear, st.wMonth, st.wDay);     return (char *)yesterday; } int main() {     printf("%s\n",getYesterday());     return 0; }   如果是在Linux下就不能用了吧，我看这边引了windows.h [/quote] 说 “跨平台一定比不跨平台好” 就和说 “双性恋一定比异性恋好” 一样！

引用 4 楼 xiaolubian 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] #include <stdio.h> #include <windows.h> char *getYesterday() {     FILETIME ft;     SYSTEMTIME st;     static char yesterday[9];      GetSystemTimeAsFileTime(&ft);     *(__int64 *)&ft-=864000000000i64;     FileTimeToSystemTime(&ft,&st);     sprintf(yesterday,"%4d%02d%02d",st.wYear, st.wMonth, st.wDay);     return (char *)yesterday; } int main() {     printf("%s\n",getYesterday());     return 0; }   如果是在Linux下就不能用了吧，我看这边引了windows.h [/quote] 你一楼给的代码里面不是也用了SYSTEMTIME吗？linux下有SYSTEMTIME？

引用 3 楼 zhao4zhong1 的回复:#include <stdio.h> #include <windows.h> char *getYesterday() {     FILETIME ft;     SYSTEMTIME st;     static char yesterday[9];      GetSystemTimeAsFileTime(&ft);     *(__int64 *)&ft-=864000000000i64;     FileTimeToSystemTime(&ft,&st);     sprintf(yesterday,"%4d%02d%02d",st.wYear, st.wMonth, st.wDay);     return (char *)yesterday; } int main() {     printf("%s\n",getYesterday());     return 0; }   如果是在Linux下就不能用了吧，我看这边引了windows.h

引用 1 楼 zhao4zhong1 的回复:获取前一天不能简单地将日期减一。 那要怎么做？

获取前一天不能简单地将日期减一。


Question: C 指针问题

a是指针变量， 一个变量名可以理解成内存地址，而且这个地址的存储单元内存了相对应使用时类型的值。对于指针变量，变量名的地址内存了是一个地址值，而且是指针类型的。指针变量在使用时分为左值和右值，这里是有区别的相同的写法放到其使用时的区别里就会有不同的用法。printf()是一个定义了可变参数的函数，使用的时候有他的规则，不同的格式化字符需要相应的类型的参数。

这下明别了 大家以后往里面发代码时，先编辑好， 然后选着C/C++ 代码格式， 再把代码剪贴到里面去，在内；  然后跳出写文字； 这样对大家都好，号召大家发规范代码， 读起来舒心。。

#include<stdio.h> int main(int argc, char* argv[]) { 	char  *a = "this"; 	printf("string a address is %02x\n",a); 	printf("string value is %c\n",*a); 	return 0; }  怎么代码没有缩进呀， 看着别扭

#include<stdio.h> int main(int argc, char* argv[]) { 	char  *a = "this"; 	printf("string a address is %02x\n",a); 	printf("string value is %s\n",a); 	return 0; } 运行正确。。。 a 是一个指针，即是地址 ，打印a 指向的值不是该*a吗？为什么运行时会出错呢？ 如果是一个字符或者一个整数， *a，是表示a所指的值；正确。 但是，%s 格式的， 要求就是一个数组的的首地址。。 #include<stdio.h> int main(int argc, char* argv[]) { 	char  *a = "this"; 	printf("string a address is %02x\n",a); 	printf("string value is %c\n",*a); 	return 0; } 也是正确的， 但是是输出一个字符：t...

puts(a)

%p

%s格式化字符需要一个字符指针，如果是%c则需要一个字符（*a）

printf("string value is %s\n",*a); ------------------------------------------ 是%s只要给出，指针即可。 *a是‘t’这个字符。由于%s这个要求的是指针，你给个字符，肯定会出错。


Question: 同样的代码在不同的C语言运行平台上得出的结果不同

不同的平台在数值范围方面可能不一样。

相同的代码不同的平台得出不同的结果没什么奇怪的，LZ还是把自己的算法描述一下，别人才能分析。

试了，还是一样的

把有sizeof的地方仔细看一下。

理论上不会出现这种情况，建议用平台自己的相关功能查看一下大小是否相同。


Question: linux 下c 宽窄字符问题

引用 7 楼 xhu_eternalcc 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] 学习NCURSES库。  能详细的回答下我的问题不？ [/quote] 通常我不负责回答问题，只负责指明解决问题的方向和思路。

理解和讨论之前请先学会如何观察！

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

引用 10 楼 zhao4zhong1 的回复://iconv_linux下字符集编码转换轻松实现 (1) iconv_t iconv_open(const char *tocode, const char *fromcode); //此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。 (2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft); //此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。 (3) int iconv_close(iconv_t cd); //此函数用于关闭转换句柄,释放资源。  //例子1: 用C语言实现的转换示例程序  /* f.c : 代码转换示例C程序 */ #include <iconv.h> #define OUTLEN 255 main() { char *in_utf8 = "姝ｅ?ㄥ??瑁?"; char *in_gb2312 = "正在安装"; char out[OUTLEN];  /*unicode码转为gb2312码*/ rc = u2g(in_utf8,strlen(in_utf8),out,OUTLEN); printf("unicode-->gb2312 out=%sn",out); //gb2312码转为unicode码  rc = g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN); printf("gb2312-->unicode out=%sn",out); } /*代码转换:从一种编码转为另一种编码*/ int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen) { iconv_t cd; int rc; char **pin = &inbuf; char **pout = &outbuf;  cd = iconv_open(to_charset,from_charset); if (cd==0) return -1; memset(outbuf,0,outlen); if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1; iconv_close(cd); return 0; } /*UNICODE码转为GB2312码*/ int u2g(char *inbuf,int inlen,char *outbuf,int outlen) { return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen); } /*GB2312码转为UNICODE码*/ int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen) { return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen); }  //例子2: 用C++语言实现的转换示例程序  /* f.cpp : 代码转换示例C++程序 */ #include <iconv.h> #include <iostream>  #define OUTLEN 255  using namespace std;  // 代码转换操作类  class CodeConverter {  private: iconv_t cd; public:  // 构造 CodeConverter(const char *from_charset,const char *to_charset) { cd = iconv_open(to_charset,from_charset); }   // 析构 ~CodeConverter() { iconv_close(cd); }   // 转换输出 int convert(char *inbuf,int inlen,char *outbuf,int outlen) { char **pin = &inbuf; char **pout = &outbuf;  memset(outbuf,0,outlen); return iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen); } };  int main(int argc, char **argv) { char *in_utf8 = "姝ｅ?ㄥ??瑁?"; char *in_gb2312 = "正在安装"; char out[OUTLEN];  // utf-8-->gb2312 CodeConverter cc = CodeConverter("utf-8","gb2312"); cc.convert(in_utf8,strlen(in_utf8),out,OUTLEN); cout << "utf-8-->gb2312 in=" << in_utf8 << ",out=" << out << endl;  // gb2312-->utf-8 CodeConverter cc2 = CodeConverter("gb2312","utf-8"); cc2.convert(in_gb2312,strlen(in_gb2312),out,OUTLEN); cout << "gb2312-->utf-8 in=" << in_gb2312 << ",out=" << out << endl; }    二、利用iconv命令进行编码转换  iconv命令用于转换指定文件的编码,默认输出到标准输出设备,亦可指定输出文件。  用法： iconv [选项...] [文件...]  有如下选项可用:  输入/输出格式规范： -f, --from-code=名称 原始文本编码 -t, --to-code=名称 输出编码  信息： -l, --list 列举所有已知的字符集  输出控制： -c 从输出中忽略无效的字符 -o, --output=FILE 输出文件 -s, --silent 关闭警告 --verbose 打印进度信息  -?, --help 给出该系统求助列表 --usage 给出简要的用法信息 -V, --version 打印程序版本号  例子: iconv -f utf-8 -t gb2312 aaa.txt >bbb.txt 这个命令读取aaa.txt文件，从utf-8编码转换为gb2312编码,其输出定向到bbb.txt文件。  小结: Linux为我们提供了强大的编码转换工具,给我们带来了方便。    // UTF-8 编码字符理论上可以最多到 6个字节长，但目前全世界的所 // 有文字和符号种类加起来也只要编到 4个字节长就够了。 // 　　UTF-8 是以 8位（即 1个字节）为单元对原始码进行编码（注意一 // 点：这里所讲的原始码都是指Unicode码），并规定：多字节码（2个字 // 节以上才称为多字节）以转换后第1个字节起头的连续“1”的数目（这 // 些连续“1”称为标记位），表示转换成几个字节：“110”连续两个 // “1”，表示转换结果为2个字节，“1110”表示3个字节，而“11110” // 则表示4个字节……跟随在标记位之后的“0”，其作用是分隔标记位和 // 字符码位。第2～第4个字节的起头两个位固定设置为“10”，也作为标 // 记，剩下的6个位才做为字符码位使用。 // 　　这样，2字节UTF-8码剩下11个字符码位，可用以转换0080～07FF的 // 原始字符码，3字节剩下16个字符码位，可用以转换0800～FFFF的原始字 // 符码，由此类推。编码方式的模板如下： // // 原始码（16进制）　UTF－8编码（二进制） // -------------------------------------------- // 0000 - 007F       0xxxxxxx // 0080 - 07FF       110xxxxx 10xxxxxx // 0800 - FFFF       1110xxxx 10xxxxxx 10xxxxxx // …… // -------------------------------------------- // // 　　模板中的“x”表示字符码。 // 　　Ascii码＜007F，编为1个 // 字节的UTF－8码。汉字的 Unicode编码范围为0800－FFFF，所以被编为 // 3个字节的UTF－8码。 // 　　例如“汉”字的Unicode编码是6C49，6C49在0800-FFFF之间，所以 // 要用3个字节的模板：1110wwww 10xxxxyy 10yyzzzz。  //    6    C    4    9 // 0110 1100 0100 1001 // wwww xxxx yyyy zzzz //     wwww   xxxxyy   yyzzzz // 1110wwww 10xxxxyy 10yyzzzz。 // 11100110 10110001 10001001 //    E   6    B   1    8   9 //“汉”字的UTF-8编码是E6 B1 89  我知道这种实现，我只是想问下，我上面的理解是对的不！

引用 8 楼 Idle_ 的回复:引用比如现在我要读入utf-8格式保存的文件内容，然后程序中需要判断每个字符在终端的显示宽度，那么我在写程序的时候，读入文件的时候，先按字节读入，然后再根据本地编码情况，转换为宽字符,再判断这个字符的宽度？ 感觉这样有点繁琐了  UTF-8是可变宽度编码（1-6字节），而linux下宽字符是定长的UTF-32, 所以必须要经历读入->转换->使用->转换->写出的步骤 嗯，下面的描述是对的吧？ 比如：文件test.txt的编码是××，locale设为和文件编码一致       （1）那么fgetwc（以他为例）就将输入的字节流按照编码格式×× 转换成 wchar_t宽字符，保存到wchar_t buf_wc1 []，       （2）使用窄字符处理函数fgetc、fread等将文件中字节读入到char buf_c[]中，然后通过mbtowc（按照locale）将其转换成宽字符，保存到buf_wc2[]，       我认为 这两种方法得到的结果是一样的吧

引用 6 楼 zhao4zhong1 的回复:学习NCURSES库。  能详细的回答下我的问题不？

学习NCURSES库。

引用 3 楼 zhao4zhong1 的回复:事实是单字节字符是大多数键盘的输出，大多数操作系统或驱动程序的内部的默认字符。 比如现在我要读入utf-8格式保存的文件内容，然后程序中需要判断每个字符在终端的显示宽度，那么我在写程序的时候，读入文件的时候，先按字节读入，然后再根据本地编码情况，转换为宽字符,再判断这个字符的宽度？ 感觉这样有点繁琐了

甚至你现在就根本找不到一款只输出宽字符，不输出窄字符的键盘。

事实是单字节字符是大多数键盘的输出，大多数操作系统或驱动程序的内部的默认字符。

引用 1 楼 zhao4zhong1 的回复:参考fgetwc和fgetc的源代码。 感觉你在论坛里面很积极的，嘿， 能先给我说说，我这样做可以不？我后面再去翻源码

参考fgetwc和fgetc的源代码。


Question: c语言程序设计总结[复习专用]

不错!!!!!!!!

C Cheat Card

已下，mark

想表达什么？


Question: 请问变址运算的规则到底是什么？

只看不用，很难懂。懂也是假懂。

引用 3 楼 k91191 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] 学汇编你不学Windows下的WinDbg？Linux下的GDB？ 但是我得首先掌握汇编的规则吧，您说是不是？要不然怎么看得懂[/quote] 边看，边用，边懂。

引用 2 楼 zhao4zhong1 的回复:学汇编你不学Windows下的WinDbg？Linux下的GDB？ 但是我得首先掌握汇编的规则吧，您说是不是？要不然怎么看得懂

学汇编你不学Windows下的WinDbg？Linux下的GDB？

计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？


Question: void (*save)(struct ControlTag *ctrl);什么意思

结构体类型Control 成员是一个指针变量save，这是一个函数指针，指向 参数为struct ControlTag *类型变量，无返回值的函数

函数指针啦，返回 void， 参数是struct ControlTag *ctrl


Question: setwritemode

http://www.baidu.com/s?wd=setwritemode&rsv_bp=0&ch=&tn=baidu&bar=&rsv_spt=3&ie=utf-8&inputT=3063  http://www.easyx.cn

函数调用方式为 void setwritemode()(int mode); 说明： 参数mode只有两个取值0和1，若mode为0，则新画的线将复盖屏幕上原有的图形，此为缺省画线输出模式。如果mode为1，那么新画的像素点与原有图形的像素点先进行异或(XOR)运算，然后输出到屏幕上，使用这种画线输出模式，第二次画同一图形时，将擦除该图形。调用setwritemode()设置的画线输出模式只影响函数line(),lineto(),linerel(),rectangle()和drawpoly()。 setwritemode()函数对应的头文件是graphics.h 返回值： 无 例： 设置画线输出模式为0： setwritemode(0);


Question: unsigned table_id: 8;这是啥意思

#include <stdio.h> #include <stdlib.h> char buf[17]; union U {   unsigned short int aa;   struct S {     unsigned int bb:7;//(bit 0-6)     unsigned int cc:6;//(bit 7-12)     unsigned int dd:3;//(bit 13-15)   } s; } u; void main() {                 //bbbbbbbbbbbbbbbb                 //iiiiiiiiiiiiiiii                 //tttttttttttttttt                 //111111                 //5432109876543210                 //::::::::::::::::     u.aa=0xE07F;//1110000001111111     printf("bb==%d,cc==%d,dd==%d\n",u.s.bb,u.s.cc,u.s.dd);     u.s.bb=0x41;     u.s.cc=0x21;//dddccccccbbbbbbb     u.s.dd=5;   //1011000011000001     printf("aa==0x%04X==%016s(2)\n",u.aa,itoa(u.aa,buf,2)); } //bb==127,cc==0,dd==7 //aa==0xB0C1==1011000011000001(2)

#include <stdio.h> #pragma pack(push,1) union U {     unsigned char byte;     struct BF {         unsigned int b0:1;//a         unsigned int b1:1;//b         unsigned int b2:1;//c     } bf; } u; #pragma pack(pop) unsigned char bt; int a,b,c; int main() {     for (bt=0;bt<8;bt++) {         u.byte=(unsigned char)bt;         a=u.bf.b0;         b=u.bf.b1;         c=u.bf.b2;         printf("byte 0x%02x -- c:%d b:%d a:%d\n",bt,c,b,a);     }     for (c=0;c<2;c++)     for (b=0;b<2;b++)     for (a=0;a<2;a++) {         u.bf.b0=a;         u.bf.b1=b;         u.bf.b2=c;         bt=u.byte;         printf("c:%d b:%d a:%d -- byte 0x%02x\n",c,b,a,bt);     }     return 0; } //byte 0x00 -- c:0 b:0 a:0 //byte 0x01 -- c:0 b:0 a:1 //byte 0x02 -- c:0 b:1 a:0 //byte 0x03 -- c:0 b:1 a:1 //byte 0x04 -- c:1 b:0 a:0 //byte 0x05 -- c:1 b:0 a:1 //byte 0x06 -- c:1 b:1 a:0 //byte 0x07 -- c:1 b:1 a:1 //c:0 b:0 a:0 -- byte 0x00 //c:0 b:0 a:1 -- byte 0x01 //c:0 b:1 a:0 -- byte 0x02 //c:0 b:1 a:1 -- byte 0x03 //c:1 b:0 a:0 -- byte 0x04 //c:1 b:0 a:1 -- byte 0x05 //c:1 b:1 a:0 -- byte 0x06 //c:1 b:1 a:1 -- byte 0x07

unsigned 等同unsigned int  table_id: 8，表示占位8bit


Question: 关于共享线程cond 初始化失败，

引用 7 楼 ForestDB 的回复:那就是windows下的pthread没有实现这个函数。  不是吧.....

引用 6 楼 user-4 的回复:大哥，你调用的是linux下的线程库，windows下编译当然报错了，请参考赵老师  编译没有报错，  这个库已经跨平台了，windows下是可以使用这个库的，  只是设置 这个  共享内存的时候  返回值不对

引用 10 楼 angel_su 的回复:function翻译成功能吧，就是说是没实现cv进程共享功能，win下pthread_cond_init(&m_cond, NULL)吧...  PTHREAD_PROCESS_SHARED  就是设置这个参数 不能成功，其他都可以  如果真的没实现，又难搞了

仅供参考//循环向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; }

对了，说一下，我的平台是win7 VS2010

那就是windows下的pthread没有实现这个函数。

引用 4 楼 angel_su 的回复:Function not implemented 你不是自己找到答案了，还是e文看不懂？  直译就是  函数未能实现，但是为什么不能实现呢？  同样的代码，我在linux和mac  都是没问题的  就是win32下面有问题，我还专门去下载了几个最新的pthread，还是一样的  求指点

...我说的是vs2010设置共享 线程共享的条件变量  初始化失败，  你给我贴的？？？...我看不懂


Question: linux 命令行程序绘制表格问题 通过Box-drawing character

绘制表格的库我可以帮你定制, 有需要的短我

其实就是表格里面的字符没有对齐,不是统一的编码  Unix, CP/M, BBS[edit] On many Unix systems, and on early dial-up bulletin board systems the only common standard for box-drawing characters was the VT100 alternate character set. The sequence "<Esc>(0" switched the codes for lower-case ASCII letters to draw this set, and "<Esc>(B" switched back:  0	1	2	3	4	5	6	7	8	9	A	B	C	D	E	F 6											┘	┐	┌	└	┼	 7		─			├	┤	┴	┬	│							 Bash script using display of all semigraphic characters:  char=( 6a 6b 6c 6d 6e 71 74 75 76 77 78 ) for i in ${char}; do printf "0x$i \x$i \e(0\x$i\e(B\n"; done And on some terminals, they are not available at all, and the complexity of the escape sequences discouraged their use, so often only ASCII characters that approximate box drawing characters are used, such as - (hyphen-minus), | (vertical bar), _ (underscore), = (equal sign) and + (plus sign) in a kind of ASCII art fashion.  Modern Unix terminal emulators use Unicode and thus have access to the line drawing characters listed above.

因为其空格用得是一个半角空格而非全角空格或连续两个半角空格。

引用 7 楼 zhao4zhong1 的回复:非汉字表格字符需要先 system("chcp 437"); 再输出。  汉字和ASCII小于32或大于127的字符同时显示.cpp 仅供参考#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <windows.h> wchar_t a2w[256]={ 0x0020,0x263a,0x263b,0x2665,0x2666,0x2663,0x2660,0x2022, 0x25d8,0x25cb,0x25d9,0x2642,0x2640,0x266a,0x266b,0x263c, 0x25ba,0x25c4,0x2195,0x203c,0x00b6,0x00a7,0x25ac,0x21a8, 0x2191,0x2193,0x2192,0x2190,0x221f,0x2194,0x25b2,0x25bc, 0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027, 0x0028,0x0029,0x002a,0x002b,0x002c,0x002d,0x002e,0x002f, 0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037, 0x0038,0x0039,0x003a,0x003b,0x003c,0x003d,0x003e,0x003f, 0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047, 0x0048,0x0049,0x004a,0x004b,0x004c,0x004d,0x004e,0x004f, 0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057, 0x0058,0x0059,0x005a,0x005b,0x005c,0x005d,0x005e,0x005f, 0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067, 0x0068,0x0069,0x006a,0x006b,0x006c,0x006d,0x006e,0x006f, 0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077, 0x0078,0x0079,0x007a,0x007b,0x007c,0x007d,0x007e,0x2302, 0x00c7,0x00fc,0x00e9,0x00e2,0x00e4,0x00e0,0x00e5,0x00e7, 0x00ea,0x00eb,0x00e8,0x00ef,0x00ee,0x00ec,0x00c4,0x00c5, 0x00e9,0x00e6,0x00c6,0x00f4,0x00f6,0x00f2,0x00fb,0x00f9, 0x00ff,0x00d6,0x00dc,0x00a2,0x00a3,0x00a5,0x20a7,0x0192, 0x00e1,0x00ed,0x00f3,0x00fa,0x00f1,0x00d1,0x00aa,0x00ba, 0x00bf,0x2310,0x00ac,0x00bd,0x00bc,0x00a1,0x00ab,0x00bb, 0x2591,0x2592,0x2593,0x2502,0x2524,0x2561,0x2562,0x2556, 0x2555,0x2563,0x2551,0x2557,0x255d,0x255c,0x255b,0x2510, 0x2514,0x2534,0x252c,0x251c,0x2500,0x253c,0x255e,0x255f, 0x255a,0x2554,0x2569,0x2566,0x2560,0x2550,0x256c,0x2567, 0x2568,0x2564,0x2565,0x2559,0x2558,0x2552,0x2553,0x256b, 0x256a,0x2518,0x250c,0x2588,0x2584,0x258c,0x2590,0x2580, 0x03b1,0x00df,0x0393,0x03c0,0x03a3,0x03c3,0x00b5,0x03c4, 0x03a6,0x0398,0x03a9,0x03b4,0x221e,0x03c6,0x03b5,0x2229, 0x2261,0x00b1,0x2265,0x2264,0x2320,0x2321,0x00f7,0x2248, 0x00b0,0x2219,0x00b7,0x221a,0x207f,0x00b2,0x25a0,0x00ff, }; extern "C" HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     wchar_t ws[256];     unsigned char s[256];     int i;       system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hfont = CreateFont(16,  0, 0, 0, 0, 0, 0, 0, 0           , 0, 0, 0, 0, "Lucida Console");     SelectObject(hdc,hfont);     TextOutW(hdc,10,10,L"你好",2);     for (i=0;i<256;i++) s[i]=i;     for (i=0;i<256;i++) ws[i]=a2w[s[i]];     TextOutW(hdc,10, 40,ws    ,32);     TextOutW(hdc,10, 80,ws+ 32,32);     TextOutW(hdc,10,120,ws+ 64,32);     TextOutW(hdc,10,160,ws+ 96,32);     TextOutW(hdc,10,200,ws+128,32);     TextOutW(hdc,10,240,ws+160,32);     TextOutW(hdc,10,280,ws+192,32);     TextOutW(hdc,10,320,ws+224,32);     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }   thx，linux下有什么好的方法没？

引用 8 楼 user-3 的回复:看看mysql 客户 断如何实现的  mysql> select curdate() as today; +------------+ | today      | +------------+ | 2014-07-16 | +------------+  嗯，mysql值得参考，thx

引用 3 楼 Cnwanglin 的回复:绘制表格的库我可以帮你定制, 有需要的短我 我需要使用上面的问题中的制表符来实现绘制表格，定制可有难度？

引用 1 楼 zhao4zhong1 的回复:因为其空格用得是一个半角空格而非全角空格或连续两个半角空格。 我还以为就是这种风格呢， 那么说来就是我画了红线的那些竖线需要平移对齐是吧

引用 1 楼 zhao4zhong1 的回复:因为其空格用得是一个半角空格而非全角空格或连续两个半角空格。 蜗牛，我还以为就是这种风格呢， 那么说来就是我画了红线的那些竖线需要平移对齐是吧


Question: 求大神帮忙  有关结构体指针作为函数参数的问题

我不知道楼上和的那个编绎器，我用了C——FREE也过不了。。。。

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。

我晕倒了我，我这里用DEVC\C++提示了N 个错误出来。。。。。。。。

结构体定义大括号后边的那个分号我也忘打了，代码中都是有的。

代码没有问题啊，我这里编译可以通过

对不起各位大哥们，刚我在发帖的时候那个分号忘打上去了，还有代码中的scanf我也没有拼错拉，对不起哦。

scnaf("%d %s %.2f",&p[i].no,p[i].name,&p[i].score); 也拼错了。scanf

struct student {     unsigned int no;     char name[16];     float score; };  void input(struct student *p);  后面要加分号


Question: fgetc（）或者getc（）问题请教

引用 8 楼 zhao4zhong1 的回复:[quote=引用 6 楼 cjy0000 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] 不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了 那就说是不是我应该用后者，fopen("...","...b") ？？？[/quote] 楼主心有灵犀！[/quote] Thanks，我试试！

引用 7 楼 lm_whales 的回复:[quote=引用 3 楼 cjy0000 的回复:] [quote=引用 2 楼 lm_whales 的回复:] 如果用 ch==EOF 判断文件结束，而ch 是unsigned char类型的，就会出现这种情况 此时ch用 int 类型比较好。 因为fget或者getc 返回int 类型， 包含除了字符(一个字节数据)之外的额外信息，可以用来判断文件是否结束。 unsigned char只有一个字节，不能判断文件是否结束。 除非，刻意用一个字节的数据，表示文件结束。、  那就说我可以将ch直接定义为int型，然后再直接用fgetc或者getc读取字符？ 另外再追问一下，那如果我将ch直接定义为char的话可以嘛？会不会读出的数据有错误的？谢谢[/quote] 如果是二进制文件，一般就可以了。 如果是别的格式，要考虑如何打开文件，以及如何解析读出来的字符。[/quote] 好的，谢谢，我先试试

引用 6 楼 cjy0000 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了 那就说是不是我应该用后者，fopen("...","...b") ？？？[/quote] 楼主心有灵犀！

引用 3 楼 cjy0000 的回复:[quote=引用 2 楼 lm_whales 的回复:] 如果用 ch==EOF 判断文件结束，而ch 是unsigned char类型的，就会出现这种情况 此时ch用 int 类型比较好。 因为fget或者getc 返回int 类型， 包含除了字符(一个字节数据)之外的额外信息，可以用来判断文件是否结束。 unsigned char只有一个字节，不能判断文件是否结束。 除非，刻意用一个字节的数据，表示文件结束。、  那就说我可以将ch直接定义为int型，然后再直接用fgetc或者getc读取字符？ 另外再追问一下，那如果我将ch直接定义为char的话可以嘛？会不会读出的数据有错误的？谢谢[/quote] 如果是二进制文件，一般就可以了。 如果是别的格式，要考虑如何打开文件，以及如何解析读出来的字符。

引用 5 楼 zhao4zhong1 的回复:不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了 那就说是不是我应该用后者，fopen("...","...b") ？？？

对了，这个是raw格式的文件，不是dat类型的~

引用 2 楼 lm_whales 的回复:如果用 ch==EOF 判断文件结束，而ch 是unsigned char类型的，就会出现这种情况 此时ch用 int 类型比较好。 因为fget或者getc 返回int 类型， 包含除了字符(一个字节数据)之外的额外信息，可以用来判断文件是否结束。 unsigned char只有一个字节，不能判断文件是否结束。 除非，刻意用一个字节的数据，表示文件结束。、  那就说我可以将ch直接定义为int型，然后再直接用fgetc或者getc读取字符？ 另外再追问一下，那如果我将ch直接定义为char的话可以嘛？会不会读出的数据有错误的？谢谢

这样读取的字符数目就始终是全部字符的一半，所以我怀疑字符没有读取完整

int ch; 应该这样定义ch。

希望你的ch的类型是int

该说的都说了，我就打打酱油算了


Question: linux 程序设计上的一个例子，打印当前目录下的文件名，文件夹

就是指定了一个缩进为 4 的宽度，你换成别的也行，显示的格式问题

引用 3 楼 ForestDB 的回复:这是如果碰到子目录时，多4个空格的缩进。 ++

这是如果碰到子目录时，多4个空格的缩进。

printf("%*s%s/\n",depth,"",entry->d_name);  这一举的depth " "空格  就是有几个空格  目录1     目录1.1         目录1.1.1


Question: 请达人们解读一下这个赋值代码

引用 11 楼 ForestDB 的回复:搜下gcc的特殊扩展。 引用 12 楼 Intel0011 的回复:这里用到一个GNU C的赋值扩展，即使用({...})的形式。这种形式的语句在顺次执行之后，会将最后一次的表达式的赋值作为返回。 int a = ({       int b = 1;     int c = 2;     b + c; }); // => a is 3  3Q，阁下见多识广，牛

引用 17 楼 zgszlhtao 的回复:这样的代码你都能写出来，果然奇葩  来源详见16楼

这样的代码你都能写出来，果然奇葩

这个问题源自我看linux内核的一段container_of宏的源码： #define container_of(ptr, type, member) ({             /          const typeof( ((type *)0)->member ) *__mptr = (ptr);     /          (type *)( (char *)__mptr - offsetof(type,member) );}) //container_of在Linux Kernel中的应用非常广泛,它用于获得某结构中某成员的入口地址  引用 10 楼 user-8 的回复:没什么意义的东西哦。 引用 15 楼 zxh707wk 的回复:[quote=引用 14 楼 Intel0011 的回复:] [quote=引用 13 楼 zxh707wk 的回复:] [quote=引用 12 楼 Intel0011 的回复:] 这里用到一个GNU C的赋值扩展，即使用({...})的形式。这种形式的语句在顺次执行之后，会将最后一次的表达式的赋值作为返回。 int a = ({       int b = 1;     int c = 2;     b + c; }); // => a is 3那不和逗号表达式一样了吗[/quote] 注意赋值扩展中有分号，是语句，且可以声明类型，比逗号表达式强大多了[/quote]功能差不多。。。[/quote]

引用 14 楼 Intel0011 的回复:[quote=引用 13 楼 zxh707wk 的回复:] [quote=引用 12 楼 Intel0011 的回复:] 这里用到一个GNU C的赋值扩展，即使用({...})的形式。这种形式的语句在顺次执行之后，会将最后一次的表达式的赋值作为返回。 int a = ({       int b = 1;     int c = 2;     b + c; }); // => a is 3那不和逗号表达式一样了吗[/quote] 注意赋值扩展中有分号，是语句，且可以声明类型，比逗号表达式强大多了[/quote]功能差不多。。。

引用 13 楼 zxh707wk 的回复:[quote=引用 12 楼 Intel0011 的回复:] 这里用到一个GNU C的赋值扩展，即使用({...})的形式。这种形式的语句在顺次执行之后，会将最后一次的表达式的赋值作为返回。 int a = ({       int b = 1;     int c = 2;     b + c; }); // => a is 3那不和逗号表达式一样了吗[/quote] 注意赋值扩展中有分号，是语句，且可以声明类型，比逗号表达式强大多了

引用 12 楼 Intel0011 的回复:这里用到一个GNU C的赋值扩展，即使用({...})的形式。这种形式的语句在顺次执行之后，会将最后一次的表达式的赋值作为返回。 int a = ({       int b = 1;     int c = 2;     b + c; }); // => a is 3那不和逗号表达式一样了吗

引用 7 楼 syrchina 的回复:赵老师这段话几乎每个分论坛了里都贴了。。。我要好好学习啊。。。 引用 6 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构…… 加油。以下常用DOS命令先练练：  C:\>help 有关某个命令的详细信息，请键入 HELP 命令名 ASSOC          显示或修改文件扩展名关联。 ATTRIB         显示或更改文件属性。 BREAK          设置或清除扩展式 CTRL+C 检查。 BOOTCFG        设置 boot.ini 文件的属性以便控制启动加载。 CACLS          显示或修改文件的访问控制列表(ACL)。 CALL           从另一个批处理程序调用这一个。 CD             显示当前目录的名称或将其更改。 CHCP           显示或设置活动代码页数。 CHDIR          显示当前目录的名称或将其更改。 CHKDSK         检查磁盘并显示状态报告。 CHKNTFS        显示或修改启动时间磁盘检查。 CLS            清除屏幕。 CMD            打开另一个 Windows 命令解释程序窗口。 COLOR          设置默认控制台前景和背景颜色。 COMP           比较两个或两套文件的内容。 COMPACT        显示或更改 NTFS 分区上文件的压缩。 CONVERT        将 FAT 卷转换成 NTFS。您不能转换                当前驱动器。 COPY           将至少一个文件复制到另一个位置。 DATE           显示或设置日期。 DEL            删除至少一个文件。 DIR            显示一个目录中的文件和子目录。 DISKCOMP       比较两个软盘的内容。 DISKCOPY       将一个软盘的内容复制到另一个软盘。 DISKPART       显示或配置磁盘分区属性。 DOSKEY         编辑命令行、调用 Windows 命令并创建宏。 DRIVERQUERY    显示当前设备驱动程序状态和属性。 ECHO           显示消息，或将命令回显打开或关上。 ENDLOCAL       结束批文件中环境更改的本地化。 ERASE          删除一个或多个文件。 EVENTQUERY     显示指定准则的事件日志项目。 EXIT           退出 CMD.EXE 程序(命令解释程序)。 FC             比较两个文件或两个文件集并显示它们之间的不同。 FIND           在一个或多个文件中搜索一个文字字符串。 FINDSTR        在多个文件中搜索字符串。 FOR            为一套文件中的每个文件运行一个指定的命令。 FORMAT         格式化磁盘，以便跟 Windows 使用。 FSUTIL         显示或配置文件系统的属性。 FTYPE          显示或修改用在文件扩展名关联的文件类型。 GOTO           将 Windows 命令解释程序指向批处理程序                中某个带标签的行。 GPRESULT       显示机器或用户的组策略信息。 GRAFTABL       启用 Windows 在图形模式显示扩展字符集。 HELP           提供 Windows 命令的帮助信息。 IF             在批处理程序中执行有条件的处理过程。 LABEL          创建、更改或删除磁盘的卷标。 MD             创建一个目录。 MKDIR          创建一个目录。 MODE           配置系统设备。 MORE           逐屏显示输出。 MOVE           将一个或多个文件从一个目录移动到另一个目录。 OPENFILES      显示远程用户为了文件共享而打开的文件。 PAGEFILECONFIG 显示或配置页面文件的属性。 PATH           为可执行文件显示或设置搜索路径。 PAUSE          停止批处理文件的处理并显示信息。 POPD           还原由 PUSHD 保存的当前目录上一次的值。 PRINT          打印一个文本文件。 PROMPT         改变 Windows 命令提示。 PUSHD          保存当前目录，然后对其进行更改。 RD             删除目录。 RECOVER        从损坏的磁盘中恢复可读取的信息。 REM            记录批处理文件或 CONFIG.SYS 中的注释。 REN            重新命名文件。 RENAME         重新命名文件。 REPLACE        替换文件。 RMDIR          删除目录。 SET            显示、设置或删除 Windows 环境变量。 SETLOCAL       开始用批文件改变环境的本地化。 SC             显示或配置服务(后台处理)。 SCHTASKS       安排命令和程序在一部计算机上按计划运行。 SHIFT          调整批处理文件中可替换参数的位置。 SHUTDOWN       让机器在本地或远程正确关闭。 SORT           将输入排序。 START          打开单独视窗运行指定程序或命令。 SUBST          将驱动器号与路径关联。 SYSTEMINFO     显示机器的具体的属性和配置。 TASKLIST       显示包括服务的所有当前运行的任务。 TASKKILL       终止正在运行的进程或应用程序。 TIME           显示或设置系统时间。 TITLE          设置 CMD.EXE 会话的窗口标题。 TREE           以图形显示启动器或路径的目录结构。 TYPE           显示文本文件的内容。 VER            显示 Windows 的版本。 VERIFY         告诉 Windows 验证文件是否正确写入磁盘。 VOL            显示磁盘卷标和序列号。 XCOPY          复制文件和目录树。 WMIC           在交互命令外壳里显示 WMI 信息。  有关工具的详细信息，请在联机帮助查看命令行参考。

计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  理解和讨论之前请先学会如何观察！

就是最后一个表达式计算得到的值 1+2;3+4; 最后得到了一个 7 ， 只不过赋给一个变量而已 如果 int func() {     return 100; }  1+2;3+4;func(); 得到的就是 100  if (3+4) { }  if (func()) { }  if ({1+2;3+4;}) { }

VC的确编译不过，要GCC才行，这是从linux里发现的一种用法，求解释 引用 3 楼 mrlgy 的回复:vs2010 编译不过

vs2010 编译不过

gcc编译器。。。 引用 1 楼 Intel0011 的回复:你用的是什么编译器，竟然可以通过编译

你用的是什么编译器，竟然可以通过编译

搜下gcc的特殊扩展。

没什么意义的东西哦。

虽然编译通过，但有警告信息 gcc -Wall -c "001.c"  001.c: In function ‘main’: 001.c:5:9: warning: statement with no effect [-Wunused-value]          1+2;          ^ 编译成功结束。


Question: 为什么我用vc编写FTP程序在两台电脑之间传输压缩文件的时候文件损坏了

问题解决了，还是我的经验不够啊，因为我在文件发送端发送完所有数据后就用closesocket（）马上关闭了套接字，这样做的后果就是接收端在接收到发送端套接字关闭的消息后，也就停止了数据的收发，关闭自己的套接字。如果此时还有数据在线路上传输，那这些数据就会丢失了，无法被正确接收。在同一台电脑上测试的时候没有发现问题是因为同一台电脑上传输数据是很快的，几乎没有时延，在接收端收到发送端套接字关闭的时候，数据也已经接收完毕，此时发送端关闭套接字也不会造成数据的丢失。当在两台电脑之间传数据时，问题就暴露出来了。后来 解决办法就是，发送端发送完数据后没有马上关闭套接字，在接收端接收完所有数据后，给发送端发送一个确认接收完毕的字符串，发送端在接收到这个字符串的时候再关闭自己的套接字。这样就解决了我所有的问题。另外，在实践中还发现，发送数据的时候不必设置延时，发送端可以一直用send（）循环发送数据直到数据发送完毕。不用担心发送过快的问题。因为受链路的限制，send函数会阻塞，也就是它会自己调整你发送数据的速率，这个是根据你发送端到接收端的的带宽来定的。这些流量控制和拥塞控制都是底层的tcp协议帮你做好了的。程序只管发送和接收，而不必考虑传输的问题。 我想说的就这么多，谢谢两位大虾的指点，也希望能给在研究文件传输的朋友们一点帮助，如果说的有什么不对的请见谅。

引用 9 楼 hacker_lpy 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] Sleep(1000);//延时1000毫秒，保证不了发送和接收的同步。只能通过接收对方的应答的方法保证发送和接收的同步 if(SOCKET_ERROR==send(s,size,strlen(size)+1,0)) 那发送文件的时候要不要两边同步？我是说发送端直接用循环一次性把数据全部发送到接收端的缓冲区里，然后接收端再慢慢接收，从接收缓冲区中读取数据。这样接收到的数据会出错吗？[/quote] 接收端接收到一半断网了咋办？

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

引用 6 楼 zhao4zhong1 的回复:2楼链接里面已经说的非常清楚了。 另外提醒： 不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了 那个链接里的内容看不大懂，具体出在什么问题上你可以说的简洁一点吗？我去查资料看看。另外你说的注意那个几个函数，难道跟读写有关？

引用 7 楼 zhao4zhong1 的回复:Sleep(1000);//延时1000毫秒，保证不了发送和接收的同步。只能通过接收对方的应答的方法保证发送和接收的同步 if(SOCKET_ERROR==send(s,size,strlen(size)+1,0)) 那发送文件的时候要不要两边同步？我是说发送端直接用循环一次性把数据全部发送到接收端的缓冲区里，然后接收端再慢慢接收，从接收缓冲区中读取数据。这样接收到的数据会出错吗？

你这个代码不支持超过2GB的文件传送。 参考 __int64 _telli64( int handle ); int _fileno( FILE *stream );

引用 3 楼 zhao4zhong1 的回复:推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了  我发送文件的代码是这样的  void sendfile(SOCKET s,char *path) { FILE *pt; long filesize; int byte; char *filename=NULL,senbuff[M],size[32];  if((pt=fopen(path,"rb"))==NULL) {   printf("打开文件时出现错误"); exit(1); } //send the filename  filename=getfilename(path); if(SOCKET_ERROR==send(s,filename,strlen(filename)+1,0))//发送字符窜的时候要格外注意，strlen函数返回的大小不包含字符窜结束符，因此需要加1 { printf("发送文件名时出现错误\n"); exit(1); } //send the length of file  fseek(pt,0L,SEEK_END);//文件指针移到尾再用ftell函数读出从头到尾的字节数，则为文件大小 filesize=ftell(pt); fseek(pt,0L,SEEK_SET);//再把文件指针移到开头  printf("传输的文件大小为:%ld\n",filesize); sprintf(size,"%ld",filesize); if(SOCKET_ERROR==send(s,size,32,0)) { printf("发送文件大小时出现错误\n"); exit(1); } printf("文件正在传输……\n"); while(1) { Sleep(1000);//延时1000毫秒，保证发送和接收的同步 byte=fread(senbuff,1,M,pt); if(byte<=0) break; if(SOCKET_ERROR==send(s,senbuff,byte,0)) {printf("网络连接中断\n"); exit(1); } } printf("文件传输完毕\n"); fclose(pt); closesocket(s); return; } 能看出是什么问题吗？

引用 1 楼 user-2 的回复:能单步跟踪一下传输过程是最好的，或者把每次发送的日志打印出来，看看是不是发送的数据有问题。 或者对比一下两个文件的字节数，如果不一致就是传输的时候漏发了一部分。 传一个内容是数字的txt文件试试，看看传过去后是那部分没法送成功。  我没有试过单步跟踪。另外接收到的压缩文件大小跟发送的大小一样，只是在我解压的时候就提示压缩文件损坏 了，解压不了。还有我试过了能正常传输文本文件，发送的文本文件和接收到的文本文件是一样的。还有一个现象就是我在同一台电脑测试的时候又可以正常解压不会出错，在两台电脑间传送就会损坏  问题是不是出在发送大二进制文件的时候因为要多次调用send，每次调用的时候都要有一个延时，等到接受端接受完毕后才进行第二次发送？是不是要保证发送和接收的同步，遵守一发一收的规则？还有，在发送大文件的时候一定要先进行分块再发送出去吗？我刚接触文件传输的东西，还不大懂，谢谢大神的解答

不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545


Question: 代码应该这样写

楼主你的原始代码怎么不用代码格式啊，看着不方便

对于这种刚发的帖子，我总是毫不犹豫的顶了。如果火了就是个前排，可以混个脸熟，说不定谁好心就给粉了…稳赚不赔；如果沉了就感觉是我弄沉的，很有成就感，还能捞经验。

每天回帖即可获得10分可用分！小技巧：教您如何更快获得可用分 ！ 每天回帖即可获得10分可用分！     小技巧：     教您如何更快获得可用分 ！

没仔细看.看不出区别


Question: putchar()参数问题

谢谢各位，懂了，涨姿势了

'0'和0不是一回事。

putchar接收的是ascii码, '0' 的ascii码是48, 所以putchar(48)输出'0' 类似地pubchar(49)输出'1',  也就是 putchar('0'+1)输出'1'  如果直接putchar(1)那输出的肯定不对了.

putchar函数要求一个int型参数 这个参数代表ASCII码； 根据楼主的代码，putchar(r),输入的r显然在0-9范围内 那就是输出ASCII码值为0-9的控制字符显然不符合楼主的逻辑 putchar('0'+r)相当于putchar(48+r); 也就是48-57对应0-9字符。 我提供一下我写的代码供楼主参考  #include <stdio.h> int main() { 	void conversion(int, int); 	int num, mode, flag = 1; 	do 	{ 		printf("请输入要转换的数值和进制(输入n退出)："); 		if (scanf("%d%d", &num, &mode) == 2) 		{ 			printf("结果是："); 			if (num < 0) 			{ 				num = -num; 				putchar('-'); 			} 			conversion(num, mode); 			putchar('\n'); 		} 		else 			flag = 0; 	} while (flag); 	return 0; } void conversion(int num, int mode) { 	int quotient, remainder; 	quotient = num / mode; 	remainder = num%mode; 	if (quotient != 0) 		conversion(quotient, mode); 	if (remainder > 9) 		putchar(55 + remainder); 	else 		putchar('0' + remainder); }


Question: 有办法把一个项目中不同文件都用到的变量只定义一份吗？

可以把变量写到共享内存里，供不同的进程使用

可以把写到共享内存里，供不同的进程使用

参考 Microsoft SDK\samples\winbase\SharedMem\Consumer.Cpp Microsoft SDK\samples\winbase\SharedMem\Makefile Microsoft SDK\samples\winbase\SharedMem\Producer.Cpp Microsoft SDK\samples\winbase\SharedMem\Queue.h Microsoft SDK\samples\winbase\SharedMem\ReadMe.Txt Microsoft SDK\samples\winbase\SharedMem\Common.h

引用 16 楼 xunfeng0862 的回复:我这有一解法相当好用。 在main.h中如下定义： #ifdef ROOT #define EXTR #else #define EXTR extern #endif  然后在main函数中如下定义： #define ROOT #include "main.h"   其他的.c文件中直接 #include "main.h"  把你要定义的所有全局变量都申明放在各自的.h文件中，如EXTR unsigned char num;    这样所有的文件都可以使用了。 谢谢！这和楼上网友的推荐方法完全相同，只是你知道，如果一些变量需要初始化，怎么办？ 还有一些变量，是放在共享数据段里的，就是各进程共享的，这些变量有办法这样做吗？

哦，我看错了，对不起，在头文件里调用了。谢谢！

引用 4 楼 lhl1158612009 的回复:单独把变量放在一个源文件中。假定文件名为 var.h ， var.c  var.h 代码如下  #ifndef   _VAR_H_ #define _VAR_H_  #ifdef   VAR_T #define TYPE_D #else #define TYPE_D extern #endif  TYPE_D  int  test_var;  // 定义你自己的变量  //...  void Var_Init(void); //变量初始化函数，整个工程中调用一次就可以了   #endif  在 var.c 中，代码如下  #define VAR_T #include "var.h"  void Var_Init(void) { //.... }  在其他文件中要引用这些变量直接 include "var.h" 就可以了。  我已经用你的方法了，很好。只是最后有一点不明白，就是那个变量初始化函数。放在主程序的.cpp文件里面，可是它什么时候会被调用呢？好象没有看到调用它的语句。

#pragma declspec(selectany)

引用 5 楼 zxh707wk 的回复:[quote=引用 2 楼 xiaohuh421 的回复:] 你的全局变量的定义就放在.cpp/.c文件中不变.  然后使用一个总的.h文件, 把所有这些全局变量的extern声明都放在其中.  比如:   a.cpp有变量  int a = 2; b.cpp有变量  int  b = 3; c.cpp有变量  int   c = 4;  可定义头文件声明: define.h extern int a; extern int b; extern int c;  使用的时间包含define.h即可.+1[/quote] +1

VC共享段一般是，在DLL中定义的数据，各个进程共享的数据。 exe 也许也可以这样，不过如何引用是个问题。  通常，共享数据的定义和声明分开，这样问题会很简单。  也有人，试图只定义一次，但是要用点手段 μOS2就采用了一种办法，但是感觉还是不如，定义和声明分开简单。 详细的请看μOS2 源码，或者μOS2相关书籍。

public int a = 0;

引用 8 楼 Intel0011 的回复:#ifndef   _VAR_H_ #define _VAR_H_  这两行后面似乎没有用到啊。  意思是，如果前面没有定义_VAR_H_，那么现在定义_VAR_H_ 它不需要有值，只是表明是否被定义过，它是为了防止头文件的重复定义 哦！明白了，非常感谢！ 那个变量放在共享数据段中的，如果也用这种方法定义，这样就会在每个文件中都定义一份，结果每个文件中都定义了一个同名共享数据段，恐怕不行，是吗？

主c文件中放置 int a = 0;  在共用头文件中放置 extern int a;  所有的c文件中包含共用头文件

引用 7 楼 screen12 的回复:另外还有我的一些全局变量是各进程共享的，放在一个共享段中：  #pragma data_seg("shared") 。。。 。。。 。。。 #pragma data_seg() #pragma comment(linker,"/SECTION:shared,RWS")  而且这个共享段中的数据还必须初始化，否则就不会放在这个共享段中。不知道这里面的全局变量有没有办法用上面的方法只定义一次？ 这个不能使用那种方法

引用 4 楼 lhl1158612009 的回复:单独把变量放在一个源文件中。假定文件名为 var.h ， var.c  var.h 代码如下  #ifndef   _VAR_H_ #define _VAR_H_  #ifdef   VAR_T #define TYPE_D #else #define TYPE_D extern #endif  TYPE_D  int  test_var;  // 定义你自己的变量  //...  void Var_Init(void); //变量初始化函数，整个工程中调用一次就可以了   #endif  在 var.c 中，代码如下  #define VAR_T #include "var.h"  void Var_Init(void) { //.... }  在其他文件中要引用这些变量直接 include "var.h" 就可以了。  谢谢！你这个方法很好，我大致看懂了，只是不知道最开头两行的用途：  #ifndef   _VAR_H_ #define _VAR_H_  这两行后面似乎没有用到啊。

引用 2 楼 xiaohuh421 的回复:你的全局变量的定义就放在.cpp/.c文件中不变.  然后使用一个总的.h文件, 把所有这些全局变量的extern声明都放在其中.  比如:   a.cpp有变量  int a = 2; b.cpp有变量  int  b = 3; c.cpp有变量  int   c = 4;  可定义头文件声明: define.h extern int a; extern int b; extern int c;  使用的时间包含define.h即可.+1

楼上正解,用的时候还需要包含该头文件


Question: C语言函数地址传递问题？

//假设带表头结点的单向链表头指针为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-> //

在这堆代码中有链表的建立、删除、增加、排序、反向范例 http://pan.baidu.com/s/17yIcQ

zxh707wk：恩恩，原来调用函数时不会改变实参指针变量的值。如果我修改代码，让m_stack自己改变地址（m_stack=m_stack->next），为什么还是有问题呀？

lz要搞清楚 单向传值 和 双向传值 的区别

你这里对指针s来说是值拷贝，并没有值传递，所以你修改它的指向是无用的，你改成这样试试： void pop(stack **s) { stack *p; if(empty(*s)) printf("The stack is empty!"); else { p=*s; char c=p->data; (*s)=(*s)->next; char cc=(*s)->data; free(p); } }  其实，你这个操作无非就是遍历一个单向链表打印出来，并删除这个结点。你完全可以在main函数里的那个while循环当中去修改m_stack的指向.............这样就不会出现值拷贝、值传递的问题了！！！


Question: 调用remove函数失败，返回-1，错误码erron=17.求大神帮忙！

用GetLastError函数看看错误；；

引用 13 楼 mujiok2003 的回复:[quote=引用 12 楼 lyq7713 的回复:] [quote=引用 11 楼 mujiok2003 的回复:] [quote=引用 10 楼 lyq7713 的回复:] [quote=引用 9 楼 mujiok2003 的回复:] if(remove("f:\\employee.txt")==0) printf("The file has been deleted!\n"); else //printf("Sorry!The file cannot be deleted!\n"); perror("Sorry!The file cannot be deleted!\n");  perror会告诉你原因  错误码有两个。调用remove是permission denied，调用rename是file exist  [/quote] 你都有啥权限？ 试试用较高权限的账户运行[/quote]  这要怎么用？？[/quote]  右键->以管理员身份运行 (win7)[/quote]  原谅我是小白，程序怎么以管理员身份运行。。TAT

引用 12 楼 lyq7713 的回复:[quote=引用 11 楼 mujiok2003 的回复:] [quote=引用 10 楼 lyq7713 的回复:] [quote=引用 9 楼 mujiok2003 的回复:] if(remove("f:\\employee.txt")==0) printf("The file has been deleted!\n"); else //printf("Sorry!The file cannot be deleted!\n"); perror("Sorry!The file cannot be deleted!\n");  perror会告诉你原因  错误码有两个。调用remove是permission denied，调用rename是file exist  [/quote] 你都有啥权限？ 试试用较高权限的账户运行[/quote]  这要怎么用？？[/quote]  右键->以管理员身份运行 (win7)

引用 11 楼 mujiok2003 的回复:[quote=引用 10 楼 lyq7713 的回复:] [quote=引用 9 楼 mujiok2003 的回复:] if(remove("f:\\employee.txt")==0) printf("The file has been deleted!\n"); else //printf("Sorry!The file cannot be deleted!\n"); perror("Sorry!The file cannot be deleted!\n");  perror会告诉你原因  错误码有两个。调用remove是permission denied，调用rename是file exist  [/quote] 你都有啥权限？ 试试用较高权限的账户运行[/quote]  这要怎么用？？

引用 10 楼 lyq7713 的回复:[quote=引用 9 楼 mujiok2003 的回复:] if(remove("f:\\employee.txt")==0) printf("The file has been deleted!\n"); else //printf("Sorry!The file cannot be deleted!\n"); perror("Sorry!The file cannot be deleted!\n");  perror会告诉你原因  错误码有两个。调用remove是permission denied，调用rename是file exist  [/quote] 你都有啥权限？ 试试用较高权限的账户运行

引用 9 楼 mujiok2003 的回复:if(remove("f:\\employee.txt")==0) printf("The file has been deleted!\n"); else //printf("Sorry!The file cannot be deleted!\n"); perror("Sorry!The file cannot be deleted!\n");  perror会告诉你原因  错误码有两个。调用remove是permission denied，调用rename是file exist

引用 6 楼 Cnwanglin 的回复:#include<stdio.h> int main(){     char filename[80];     printf("The file to delete:");     gets(filename);     if( remove(filename) == 0 )         printf("Removed %s.", filename);     else         perror("remove"); }  错误代码： EROFS  欲写入的文件为只读文件。 EFAULT  参数filename 指针超出可存取内存空间。 ENAMETOOLONG  参数filename 太长。 ENOMEM  核心内存不足。 ELOOP  参数filename 有过多符号连接问题。 EIO I/O  存取错误。

#include<stdio.h> #include <fcntl.h> int main(void) {     char oldname[100], newname[100];     /* prompt for file to rename and new name */     printf("请告诉我一个文件的完整路径: ");     gets(oldname);     printf("您想修改为: ");     gets(newname);     /* 更改文件名 */     if (rename(oldname, newname) == 0)         printf("已经把文件 %s 修改为 %s.\n", oldname, newname);     else         perror("rename");     return 0; }

引用 3 楼 zhao4zhong1 的回复:系统无法将文件移到不同的驱动器。  请问怎么解决

引用 2 楼 user-5 的回复:这个你可以去看看错误码代表啥意思撒。让后再看看哪不对  错误码有两个。调用remove是permission denied，调用rename是file exist

系统无法将文件移到不同的驱动器。

总不至于是你fclose后紧接if(remove("f:\\employee.txt")==0)太快吧。 试试在if(remove("f:\\employee.txt")==0)前面加Sleep(5000);//延迟5秒，需要#include <windows.h>

引用 16 楼 zhao4zhong1 的回复:没准f:\\employee.txt文件属性是只读的。   不是哦，只读的那一栏没有勾起来

没准f:\\employee.txt文件属性是只读的。

顶一顶，因为问题还没解决……

这个你可以去看看错误码代表啥意思撒。让后再看看哪不对


Question: void(*x(int,void(*y)(int)))(int);大家看看这个，

//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*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]

#include <typeinfo> #include <iostream>  typedef void(*PF)(int); PF foobar(int a, PF pf) {   pf(a);   return pf; }   int main() {   void (*  x(        int, void(*y)(int)       ) )     (int);   std::cout << typeid(x).name() << std::endl;   std::cout << typeid(foobar).name() << std::endl;   return 0; } /* void (__cdecl*__cdecl(int,void (__cdecl*)(int)))(int) void (__cdecl*__cdecl(int,void (__cdecl*)(int)))(int) */   所以x和foobar一样， 是一个函数， 其第一个参数是int,第二个参数是函数指针void(*)(int)； 其返回值是一个函数地址void(*)(int)  推荐使用typedef， 增加代码可读性， 就像foobar那样。

typedef void (*fun1)(int); typedef  fun1 fun2( int, fun1 ); fun2 x;

void (*x(int,void(*y)(int)))(int); x是一个函数，它有两个参数，第一个参数的类型是int，第二个参数的类型是一个函数指针，该函数指针所指向的函数只有一个int类型的参数，返回类型是void 函数x的返回类型也是一个函数指针，其类型与它的第二个参数类型一致，即该函数指针所指向的函数只有一个int类型的参数，返回类型是void 验证代码为 #include <stdio.h>  void f1(int a) {    printf("f1\n"); }  void f2(int a) {    printf("f2\n"); }  void (*x(int a,void(*b)(int)))(int c) {    b(1);    return &f2; }  int main(void) {     x(1, f1)(1);     return 0; }

这是一个函数声明 x函数 他的参数有两个：第一个是一个int型，第二个是指向函数的指针，此函有一个int型参数，无返回值 x函数的返回值为：指向函数的指针，此函数有一个int型参数，无返回值

当个参考吧 因为我也不确定我说的具体准确

再补充下代码：void(*x(int,void(*y)(int)))(int);


Question: 时间复杂度为什么是O(nlgn)

二分搜索一次复杂度O(lgn)，搜索之后一次遍历复杂度最坏情况下是n，然后每次搜索之后每次都要遍历。就是O(nlgn)


Question: CObject* (PASCAL* m_pfnCreateObject)();

pascal calling convention

PASCAL是一种调用惯例。

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

PASCAL 是一个宏，就是 __stdcall, 指明这个函数的参数传递以及平栈方式


Question: 新手求帮忙

有个置顶贴，可以一看。  个人不建议研究即书写这样的代码。

用 DEBUG 调试

引用 楼主 qq_17586651 的回复:如有 int i=3,j; j=(++i)+(++i)+--i; 执行后i,j的值是多少    这题给详细过程及说明，每一步都要  和使用编译器有关， 死扣这些没啥意义， 多学点别的知识吧

这根本不算一个题，出题的人显然对C语言是无知的。  科普下：http://www.guokr.com/blog/471312/

引用 楼主 qq_17586651 的回复:如有 int i=3,j; j=(++i)+(++i)+--i; 执行后i,j的值是多少 这题给详细过程及说明，每一步都要 编译，设置断点，单步调试，查看汇编代码，如下：  4:        int i=3,j; 00401028   mov         dword ptr [ebp-4],3       //设置i为3 5:        j=(++i)+(++i)+--i; 0040102F   mov         eax,dword ptr [ebp-4]    00401032   add         eax,1                                 //自增1，为4 00401035   mov         dword ptr [ebp-4],eax 00401038   mov         ecx,dword ptr [ebp-4] 0040103B   add         ecx,1                                 //自增1，为5 0040103E   mov         dword ptr [ebp-4],ecx 00401041   mov         edx,dword ptr [ebp-4] 00401044   add         edx,dword ptr [ebp-4]     //计算加法 00401047   mov         eax,dword ptr [ebp-4] 0040104A   sub         eax,1                                 //自减1 0040104D   mov         dword ptr [ebp-4],eax 00401050   add         edx,dword ptr [ebp-4]     //计算加法 00401053   mov         dword ptr [ebp-8],edx 6:        printf("%d\t%d\n", i, j); 00401056   mov         ecx,dword ptr [ebp-8] 00401059   push        ecx 0040105A   mov         edx,dword ptr [ebp-4] 0040105D   push        edx 0040105E   push        offset string "%d\t%d\n" (00422e80) 00401063   call        printf (0040d690) 00401068   add         esp,0Ch


Question: 看不懂下面这个小程序

输出0-999 #define在编译的时候就全部替换掉了

打了一遍 感觉真的是bt的啊

没想法,真的是没想法

一共是三层，就是10的m³

楼主，这个可以把跳用替换过程看做多叉树的遍历，只是不清楚是深度优先，还是广度优先；按照嵌套替换规则的话，应该是深度优先

要不要这么为难编译器啊

宏替换而已，没什么大不了的

本来想贴展开后的代码的，不过貌似超过字符限制了。 那么自己用gcc -E执行下把。

A(printf("%d ",n++)); A(printf("%d ",n++));	 A(printf("%d ",n++));	 A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));	 A(printf("%d ",n++));	 A(printf("%d ",n++));	 A(printf("%d ",n++)); A(printf("%d ",n++));	 A(printf("%d ",n++));	 A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));	 A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));  A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));  A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));  A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));  A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));  A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));  A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));  A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));  A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++)); A(printf("%d ",n++));  上门所有100个A(printf("%d ",n++));再用printf("%d ",n++);替换十次，总共10*100个printf("%d ",n++); 写个for循环搞定的事情为啥要搞这么变态···· 哪里找来的问题···

这是考试题目吗？只有考试题目才会出这些。。。

估计又是哪个的测试题目吧

宏嵌套。给编译器找麻烦。。。

宏替换而已。

暴力输出0-999,。 一下子真还看不懂吧？  哈哈

哈哈，经过测试，确实是输出0-999个数字，楼主加个空格或换行啊，满满一屏幕。

每一个x，相当于一个printf("%d ",n++)，所以打印出来是10的3次方个数字，编号从0开始

这个程序确实很变态。 最后结果是输出0-999个数。 先将内层A展开，是10个printf 再将第二层A展开，是10*10个printf 再将第三层展开，是10*10*10个printf.

编译选项加/EP /P，重新编译，查看宏展开后对应的.i文件。gcc加-E

这程序这变态呢?  直接把 #define A(x) x;x;  这么改了  把A(x) 的格式替换为 x;x;


Question: 新手求帮忙

是不是如果 x=x-(++n) 条件如上题 x=6,n=6

自加或自减括不括号无所谓，楼主需要明白是使用前自加（++i）还是使用后自加（i++）

n++ 本身的定义,就是先使用n的值    然后将n的值再加1


Question: 我是初学者，求大牛帮我看一下哪里错了？

#include <iostream> void main() {    int a=0,b=0,z=0;   std::cin>>a>>b;   z=((a>=b)?a:b);   std::cout<<z<<std::endl; }

你要注意的你输入，代码没有问题，在输入 scanf() 函数的时候要明白 scanf 的格式，你这里用的是逗号作为分隔符，所以在输入时要严格按照 scanf 的格式输入。然后就是在写代码的时候要注意中文标点符号，随便出现一个都会报错。

我觉得，你编译的时候有提示吧。。。而且很明显。。。。。对于这种逗号，分号在大程序中用错了就是要命。。。因为很难找出来。。。。。。。注意啦。。。 LZ

修改上楼 printf("Max=%d\n",max( *a, *b ) );改为printf("Max=%d\n",max( &a, &b ) );  按错了。。

#include <stdio.h> int max( int* a, int* b) {     return *a > *b ? *a : *b; } int main() {    int a=0,b=0;     printf("请输入2个数\n");     scanf("%d,%d",&a,&b);     printf("Max=%d\n",max( *a, *b ) );     return 0; } 这个代码是最简洁的，没有值的传递，直接操作地址，效率最快。

改过的代码： #include<stdio.h> //主函数 void main() { int max(int x,int y);                 //此处的分号改为英文的分号 int a,b,c; scanf("%d,%d",&a,&b);         c=max(a,b); printf("max=%d\n",c); } //求两个整数中的较大的max函数 int max(int x,int y) { int z; if(x>y)z=x; else z=y; return(z); }

我觉得还有一点就是你的int max函数的定义应该放在main函数之前，因为C语言是顺序执行的，它不象C++当系统遇到一个函数调用时会自动寻找。  在大型程序要么就是在main函数之前先声明，然后就可以在任意位置去定义，要么就是声明和定义都放在要调用这个函数的代码之前，这个习惯可以避免好多未知的错误

编译通过了么？没通过，就按错误提示进行修改。要是编译过了，那你要关注一下scanf格式串中的那个逗号，你在输入的时候必须给它匹配一个逗号，其他地方感觉不出有错。

int max(int *x,int *y) { int z; if(*x>*y)z=*x; else z=*y; return(z); } c=max(&a,&b);

有个分号是中文的？ 明显和其它的不一样

#include<stdio.h> //主函数 void main() { int max(int x,int y)；最后的那个；是中文的，因该改写成英文的;（这种错误在编译之前就会报错） int a,b,c; scanf("%d,%d",&a,&b); c=max(a,b); printf("max=%d\n",c); }

主函数当中的声明语句：int max(int x,int y)；，最后一个分号用英文的，不要用中文全角


Question: 消息处理  key……事件

VC6：  Setting a Breakpoint on a Message Received by a Windows Function You can set message breakpoints to stop the debugger when a particular WndProc function message is received.  Note   Message breakpoints work only on x86- or Pentium-based systems.  To set a breakpoint on a message   From the Edit menu, click Breakpoints.  The Breakpoints dialog box appears.  Click the Messages tab.   In the Break At WndProc text box, type the name of the Windows function.  If you are setting a breakpoint during a debug session, the list contains the exported functions in your project.   In the Set One Breakpoint For Each Message To Watch list box, select the message.   To set another breakpoint, press ENTER, and then repeat steps 3 and 4.  The Breakpoints list displays the currently active breakpoints.  Click OK to set the breakpoints.  Note If you interrupt execution while Windows or other system code is running, the results can be unpredictable.

是我太贪心了，我想几天搞完api就学mfc，所以没看书只看视频，以前学习也从来没看过书，看来我得好好改正了

这是七个数组：     char key[][30]={         "WM_KEYUP",         "WM_CHAR",         "WM_DEADCHAR",         "WM_SYSKEYDOWN",         "WM_SYSKEYUP",         "WM_SYSCHAR",         "WM_SYSDEADCHAR",     }; 这是八个下标      case WM_KEYDOWN:     case WM_KEYUP:     case WM_CHAR:     case WM_DEADCHAR:     case WM_SYSKEYDOWN:     case WM_SYSKEYUP:     case WM_SYSCHAR:     case WM_SYSDEADCHAR:  key[uMsg-WM_KEYFIRST] 这个下标计算把WM_KEYDOWN去掉了。自己改下这个逻辑

真心的，楼主去看一下《windows 程序设计》这本书再来提问好吗？你问的基础知识书本都有写的，为什么不去看呢？

引用 5 楼 zhao4zhong1 的回复:建议楼回族学习使用Spy++跟踪消息。 看到了很多窗口，怎么跟踪消息呢？

引用 6 楼 user-3 的回复:sprintf(temp,"LCONTROL+%c",wParam); 改成 sprintf(temp,"LCONTROL+%c",wParam+('a'-1));  为什么呢

建议楼回族学习使用Spy++跟踪消息。

为了验证char消息中wParam代表字符的ASC码，我改了程序，但按下左ctrl再按其他字母显示的都是ctrl+l,求正解 #include <Windows.h> #include <stdio.h>  int i=0; LRESULT CALLBACK WinSunProc( 	HWND hwnd,      // handle to window 	UINT uMsg,      // message identifier 	WPARAM wParam,  // first message parameter 	LPARAM lParam   // second message parameter 	); #define WM_MYMESSAGE WM_USER+1    int WINAPI WinMain( 	HINSTANCE hInstance,  // handle to current instance 	HINSTANCE hPrevInstance,  // handle to previous instance 	LPSTR lpCmdLine,      // pointer to command line 	int nCmdShow          // show state of window 	) {	 	//创建一个窗口类 	WNDCLASS wndcls; 	 	 	//额外参数 	wndcls.cbClsExtra=0; 	wndcls.cbWndExtra=0; 	//背景色 	wndcls.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); 	//光标 	wndcls.hCursor=LoadCursor(NULL,IDC_ARROW); 	//图标 	wndcls.hIcon=LoadIcon(NULL,IDI_SHIELD); 	//应用程序实例号 	wndcls.hInstance=hInstance; 	//窗口过程函数 	wndcls.lpfnWndProc=WinSunProc; 	//类名 	//#include <tchar.h>	更多信息： http://bbs.csdn.net/topics/390631479?page=1 	wndcls.lpszClassName="weixin"; 	//菜单名 	wndcls.lpszMenuName=NULL; 	//风格 	wndcls.style=CS_HREDRAW|CS_VREDRAW;//水平重画 或上 垂直重画  	//注册 	RegisterClass(&wndcls);  	//创建窗口 	/*参考信息： 	CreateWindow 	该函数创建一个重叠式窗口、弹出式窗口或子窗口。它指定窗口类 	，窗口标题，窗口风格，以及窗口的初始位置及大小（可选的）。 	函数也指该窗口的父窗口或所属窗口（如果存在的话），及窗口的 	菜单。若要使用除CreateWindow函数支持的风格外的扩展风格，则 	使用CreateWindowEx函数代替CreateWindow函数。*/ 	HWND hwnd; 	hwnd=CreateWindow("weixin","北京维新科学技术中心",WS_OVERLAPPEDWINDOW,100, 		100,600,400,NULL,NULL,hInstance,NULL);  	//显示窗口 	ShowWindow(hwnd,SW_NORMAL);  	//显示欢迎信息 	HDC hdc; 	hdc=GetDC(hwnd); 	TextOut(hdc,200,0,"欢迎使用本程序！",strlen("欢迎使用本程序！")); 	ReleaseDC(hwnd,hdc);  	//更新窗口 	UpdateWindow(hwnd);   	  	//消息循环 	MSG msg; 	while(GetMessage(&msg,NULL,0,0)) 	{ 		TranslateMessage(&msg); 		DispatchMessage(&msg); 	}  	return 0; }  LRESULT CALLBACK WinSunProc( 	HWND hwnd,      // handle to window 	UINT uMsg,      // message identifier 	WPARAM wParam,  // first message parameter 	LPARAM lParam   // second message parameter 	) {	 	HDC hdc; 	//char ch[30]; 	//LOGFONT lf={0}; 	//CHOOSEFONT cf={0}; 	//POINT pt[3]; 	//RECT r={23,56,34,89};//矩形区域 	 	 	 	char temp[30]=""; 	char str[30]=""; 	char key[][30]={ 		"WM_KEYDOWN", 		"WM_KEYUP", 		"WM_CHAR", 		"WM_DEADCHAR", 		"WM_SYSKEYDOWN", 		"WM_SYSKEYUP", 		"WM_SYSCHAR", 		"WM_SYSDEADCHAR", 	};  	switch(uMsg) 	{	 	case WM_CHAR: 		if(GetKeyState(VK_LCONTROL)<0)//判断左ctrl是否按下 		{	 			hdc=GetDC(hwnd); 			sprintf_s(temp,30,"LCONTROL+%c",wParam); 			TextOut(hdc,0,(i++)*20,temp,strlen(temp)); 			ReleaseDC(hwnd,hdc); 		} 		break; 		//与字符有关的消息 	//case WM_KEYDOWN: 	//	/*if(wParam==VK_LEFT) 	//	sprintf_s(temp,10,"left key"); 	//	else if(wParam==VK_RIGHT) 	//	sprintf_s(temp,10,"right key"); 	//	else if(wParam==VK_UP) 	//	sprintf_s(temp,10,"up key"); 	//	else if(wParam==VK_DOWN) 	//	sprintf_s(temp,10,"down key"); 	//	hdc=GetDC(hwnd); 	//	TextOut(hdc,0,0,temp,10); 	//	ReleaseDC(hwnd,hdc); 	//	break;*/ 	//case WM_KEYUP: 	//case WM_CHAR: 	//case WM_DEADCHAR: 	//case WM_SYSKEYDOWN: 	//case WM_SYSKEYUP: 	//case WM_SYSCHAR: 	//case WM_SYSDEADCHAR: 	//	GetKeyNameText(lParam,temp,10); 	//	sprintf_s(str,30,"%s********%d:%s", 	//		key[uMsg-WM_KEYFIRST],wParam,temp);  	//	hdc=GetDC(hwnd);  	//	TextOut(hdc,0,20*(i++),str,strlen(str));  	//	ReleaseDC(hwnd,hdc); 	//	break; 	//case WM_RBUTTONDOWN: 	//	//字体与颜色，windows api,参考：WINDOWS API 刘思成 in E盘 	//	cf.lStructSize=sizeof(CHOOSEFONT); 	//	cf.lpLogFont=&lf; 	//	cf.Flags=CF_SCREENFONTS|CF_EFFECTS;//|CF_INITTOLOGFONTSTRUCT;(用lf的信息初始化) 	//	ChooseFont(&cf); 	//	hdc=GetDC(hwnd); 	//	SelectObject(hdc,CreateFontIndirect(cf.lpLogFont)); 	//	TextOut(hdc,50,300,"北京维新科学技术中心",strlen("北京维新科学技术中心")); 	//	 	//	//从(50,50)划线到(30,30) 	//	MoveToEx(hdc,50,50,NULL);//省略此句从(0,0)到(30,30) 	//	LineTo(hdc,30,30); 	//	 	//	pt[0].x=40; 	//	pt[0].y=40; 	//	pt[1].x=90; 	//	pt[1].y=40; 	//	pt[2].x=130; 	//	pt[2].y=20; 	//	Polyline(hdc,pt,3);//polylineto()折线 	//	Arc(hdc,20,100,40,300,40,100,40,100);//弧 	//	Rectangle(hdc,20,100,40,300);//矩形 	//	Ellipse(hdc,20,100,40,150);//椭圆  	//	//使用系统画笔 	//	/*GetStockObject() 	//		SelectObject() 	//		DeleteObject()*/  	//	//创建画笔对象 	//	SelectObject(hdc,CreatePen(PS_DOT,3,RGB(255,255,0))); 	//	SelectObject(hdc,GetStockObject(BLACK_BRUSH));//使用系统画刷 	//	SelectObject(hdc,CreateSolidBrush(RGB(0,255,255)));//创建纯色画刷 	//	Rectangle(hdc,360,130,490,290); 	//	SelectObject(hdc,CreateHatchBrush(HS_DIAGCROSS,RGB(0,255,255)));//创建图案画刷 	//	RoundRect(hdc,30,30,60,60,25,25); 	//	FillRect(hdc,&r,CreateHatchBrush(HS_DIAGCROSS,RGB(0,255,255)));//填充矩形区域 	//	FrameRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH));//填充矩形区域边框 	//	InvertRect(hdc,&r);//将矩形区域所有像素（包括边框）翻转 	//	  	//	ReleaseDC(hwnd,hdc); 	//	break; 	/*case WM_MYMESSAGE:		 		sprintf_s(ch,30,"wParam is %d,lParam is %d",wParam,lParam); 		MessageBox(hwnd,ch,"weixin(MOVE的后序触发事件)",0); 		break;*/ 	//case WM_MOVE: 	//	MessageBox(hwnd,"MOVE","weixin",0); 	//	//PostMessage(hwnd,WM_MYMESSAGE,100,200); 	//	break; 		/*case WM_CREATE: 		MessageBox(hwnd,"CREATE","weixin",0); 		break;*/ 	//case WM_SIZE: 	//	 	//	//lParam低16位存放宽度，高16位存放高度，又可表示鼠标坐标 	//	sprintf_s(ch,30,"宽度：%d 高度：%d",LOWORD(lParam),HIWORD(lParam)); 	//	MessageBox(hwnd,ch,"weixin",0); 	//	break; 	/*case WM_CHAR: 		sprintf_s(ch,30,"Char is %d",wParam); 		MessageBox(hwnd,ch,"weixin",0); 		break;*/ 		/*case WM_LBUTTONDOWN: 		MessageBox(hwnd,"左键按下","weixin",0); 		hdc=GetDC(hwnd); 		TextOut(hdc,50,120,"维新培训！",strlen("维新培训！")); 		ReleaseDC(hwnd,hdc); 		break;*/ 	//case WM_PAINT: 	//	PAINTSTRUCT ps; 	//	hdc=BeginPaint(hwnd,&ps);  	//	SelectObject(hdc,GetStockObject(ANSI_VAR_FONT));//选择启用新字体 	//	TextOut(hdc,50,50,"北京维新科学技术中心",strlen("北京维新科学技术中心")); 	//	 	//	TEXTMETRIC tm;//与文字信息相关的一个结构体 	//	GetTextMetrics(hdc,&tm);  	//	//LOGFONT lf={0};写在这里的话初始化由case跳过，error 	//	lf.lfHeight=45; 	//	lf.lfUnderline=1; 	//	SelectObject(hdc,CreateFontIndirect(&lf));  	//	TextOut(hdc,50,50+tm.tmHeight,"北京维新科学技术中心",strlen("北京维新科学技术中心")); 	//	 	//	lf.lfHeight=10; 	//	lf.lfUnderline=1; 	//	SelectObject(hdc,CreateFontIndirect(&lf));  	//	TextOut(hdc,50,50+(-1)*tm.tmHeight,"北京维新科学技术中心",strlen("北京维新科学技术中心"));  	//	SelectObject(hdc,GetStockObject(ANSI_FIXED_FONT));//选择启用新字体 	//	for(int i=0;i<10;i++) 	//	{	 	//		sprintf_s(ch,30,"%d is %c",i+1,'A'+i); 	//		TextOut(hdc,300,150+i*tm.tmHeight/*字体高度*/,ch,strlen((ch))); 	//	} 	//	EndPaint(hwnd,&ps); 	//	break; 	case WM_CLOSE: 		if(IDYES==MessageBox(hwnd,"真的要退出吗？","weixin",MB_YESNO)) 		{ 			DestroyWindow(hwnd); 		} 		break; 	case WM_DESTROY: 		PostQuitMessage(0); 		break; 	default: 		return DefWindowProc(hwnd,uMsg,wParam,lParam); 	} 	return 0; }

你按下一个键"A"会产生三条消息：  WM_KEYDOWN wParam= VK_A 这是键盘虚拟码的a WM_CHAR  wParam = 'a' 这是ascii码的a WM_KEYUP  wParam= VK_A  这就是它们的参数为什么不一样。  在<windows程序设计>这本书里键盘的这一章有详细说明

额，好明显的错误……  谢谢 另外wParam参数表示什么意思喔，为什么这个参数对于keydown和char消息不一样？


Question: 求助。。大神在哪

lz不是找大神吧，找人做作业

引用 4 楼 lmrblue 的回复:[quote=引用 2 楼 yangyunzhao 的回复:] lz不是找大神吧，找人做作业 人艰不拆。。 = =大神你会做这道题吗？[/quote] 应该是你知道我的代码为什么出这个错嘛。。

引用 2 楼 yangyunzhao 的回复:lz不是找大神吧，找人做作业 人艰不拆。。 = =大神你会做这道题吗？

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


Question: 初学C，求分析

好的，谢谢指导！

如果要比较字符串是否相等，是要逐个字符比较的，而不是比较指针，标准库函数是strcmp函数，在string.h头文件中有声明，楼主感兴趣可以看看strcmp的实现源码，网上一堆。

首先，这个不是我自己写的程序，我是在看测试题目。 题目要求是写出返回值，我自己判定错了，所以来这儿求解。  其次，你们真的太牛的！分析得很透彻。  最后，感谢各位的知道。 看来这题目考查的内容蛮多的。有指针、数组、指针地址。  再次感谢！

"abc"这是一个常量字符串，这个字符串在编译后，是放在可执行程序的常量数据段里面的，你可以先理解为"abc"放在一段固定的4个字节空间里(还有后面的'\0'，所以是4个)，我们假设它的空间地址为0x1000。 而char str1[] = "abc"；这条语句的意思是，申请一个指针数组，空间大小和字符串"abc"的一样大(4个字节)，我们假设它的起始地址为0x2000，然后把字符串"abc"拷贝到该空间去，即从0x1000这个地址拷贝4个字节到0x2000这个地址去。 同样，char str2[] = "abc"；这条语句的意思是，申请一个指针数组，空间大小和字符串"abc"的一样大(4个字节)，我们假设它的起始地址为0x3000，然后把字符串"abc"拷贝到该空间去，即从0x1000这个地址拷贝4个字节到0x3000这个地址去。  那么，我们可以看到 char str1[] = "abc"; char str2[] = "abc"; 两条语句分别分配了两个不同的地址（0x2000和0x3000），但他们的地址里面都存放了相同的内容('a','b','c','\0'四个字母)。  我们再回到 int strcamp2(char* pStr1, char* pStr2) 首先你要知道，参数pStr1和pStr2都是指向字符的指针，而指针是什么呢，就是地址。int iVal = strcamp2(str1, str2);也就是将字符数组str1和str2的地址传进去（我们已经假设分别为0x2000和0x3000），而strcamp2()函数里面的pStr1和pStr2的比较，就是比较两个指针的值，我们这里传进去的是0x2000和0x3000，0x2000肯定不等于0x3000的，所以按照你的代码结果肯定返回1啊。

strcmp函数包含在头文件string.h中 #include <string.h>

楼主对字符串对比的认知还有很大误解 字符串比较和数值比较是不同的，字符串的比较要对字符进行逐个比较，所有字符相同才相同，你用“==”号来直接判断字符串是否相等是得不到结果的，在C语言中，字符串比较需要使用strcmp（）函数，字符串的一系列操作你可以去查查string.h头文件里面的一些函数用法，或者百度“C语言字符串操作”去了解

楼主创建了2个字符数组str1和str2 int strcamp2(char* pStr1, char* pStr2)//调用函数时传入str1数组首地址和str2数组首地址 { if(pStr1 == pStr2)//因为str1数组和str2数组的首地址不同 return 0; else return 1;//所以返回1 }  改法： if(strcmp(str1,str2)==0) return 0;

我自己看下来，应该是if语句里的判定，这儿是使用的“==”


Question: 如何声明线程私有全局变量

要不然就把内存分成多块，每个线程访问一个memory pool ；

vc 2013  C:\demo\test>type test.cpp #include <iostream> #include <thread> #include <mutex>  std::mutex m; void foo(int id) {   __declspec( thread ) static int i = 0;   for(; i < 29; ++i)   {     std::lock_guard<std::mutex> lock(m);     std::cout <<id << ":" << i << std::endl;   } }  int main() {   std::thread t1(foo, 256);   std::thread t2(foo, 237);   t1.join();   t2.join();   return 0; }  C:\demo\test>cl  /EHsc /MT /Ox /DNDEBUG test.cpp Microsoft (R) C/C++ Optimizing Compiler Version 18.00.30501 for x86 Copyright (C) Microsoft Corporation.  All rights reserved.  test.cpp Microsoft (R) Incremental Linker Version 12.00.30501.0 Copyright (C) Microsoft Corporation.  All rights reserved.  /out:test.exe test.obj  C:\demo\test>test 256:0 237:0 256:1 237:1 256:2 237:2 256:3 237:3 256:4 237:4 256:5 237:5 256:6 237:6 256:7 237:7 256:8 237:8 256:9 237:9 256:10 237:10 256:11 237:11 256:12 237:12 256:13 237:13 256:14 237:14 256:15 237:15 256:16 237:16 256:17 237:17 256:18 237:18 256:19 237:19 256:20 237:20 256:21 237:21 256:22 237:22 256:23 237:23 256:24 237:24 256:25 237:25 256:26 237:26 256:27 237:27 256:28 237:28  C:\demo\test>

最简单的就是用现成的， 比如boost

c++ 11: thread_local

引用 6 楼 bbs2241 的回复:[quote=引用 5 楼 jsh13417 的回复:] [quote=引用 2 楼 zhao4zhong1 的回复:] #define MAXTHREADS 2000 POOL pool[MAXTHREADS];  pool[GetCurrentThreadId()%MAXTHREADS]=...;  这个方法不错，非常感谢。。 还是有一个疑问，声明一个全局的pool， 初始化放在线程中，会不会这个pool就是线程的私有全局变量。 在实际开发中测试证明好像是不行的，[/quote] 赵老师逗你玩捏，你居然信了。[/quote]  引用 6 楼 bbs2241 的回复:[quote=引用 5 楼 jsh13417 的回复:] [quote=引用 2 楼 zhao4zhong1 的回复:] #define MAXTHREADS 2000 POOL pool[MAXTHREADS];  pool[GetCurrentThreadId()%MAXTHREADS]=...;  这个方法不错，非常感谢。。 还是有一个疑问，声明一个全局的pool， 初始化放在线程中，会不会这个pool就是线程的私有全局变量。 在实际开发中测试证明好像是不行的，[/quote] 赵老师逗你玩捏，你居然信了。[/quote]   我信什么 ？？？？ ？？？？

引用 5 楼 jsh13417 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] #define MAXTHREADS 2000 POOL pool[MAXTHREADS];  pool[GetCurrentThreadId()%MAXTHREADS]=...;  这个方法不错，非常感谢。。 还是有一个疑问，声明一个全局的pool， 初始化放在线程中，会不会这个pool就是线程的私有全局变量。 在实际开发中测试证明好像是不行的，[/quote] 赵老师逗你玩捏，你居然信了。

引用 2 楼 zhao4zhong1 的回复:#define MAXTHREADS 2000 POOL pool[MAXTHREADS];  pool[GetCurrentThreadId()%MAXTHREADS]=...;  这个方法不错，非常感谢。。 还是有一个疑问，声明一个全局的pool， 初始化放在线程中，会不会这个pool就是线程的私有全局变量。 在实际开发中测试证明好像是不行的，

TLS  线程本地存储

map<DWORD, POOL*> poolmap;  DWORD dwThreadId = 0; CreateThread(NULL, 0, ThreadRun,  NULL, 0, &dwThreadId); poolmap[dwThreadId] = new POOL();  全部初始化好之后，设一个信号量，通知各个线程开始ThreadRun  由于在这之后，这个poolmap没有写操作，可以不加锁。

引用 1 楼 ADF1230 的回复:TLS  线程本地存储  下面函数应该就是 TLS吧，LINUX下api 设置"线程相关的数据",使用  int pthread_setspecific(pthread_key_t key, const void *pointer);  读取"线程相关的数据",使用  void * pthread_getspecific(pthread_key_t key);