Question: 求解答关于链表的问题

引用 10 楼 ipresk 的回复:[quote=引用 3 楼 mortimer7866 的回复:] 的确是你理解有误，pHead是指向头结点的指针，pNew是每次用来添加结点的指针，pTail是指向最后一个结点的指针，你先申请了一个结点，pNew,pTrail始终指向最后一个结点，pTrail->next=pNew,意思是将新申请的结点链接到当前最后一个节点的后面，pNew->next=NULL，就是将你新申请的结点中的nextz 指针域置为NULL，然后pTrail=pNew是将pTrail指针重新指向改动过的链表的最后一个结点，这样形成循环，创建链表，最后说一句，你创建链表的这个方法很不好，pNew->next=NULL这一句应该是在空间申请结束下一句，个人见解这个代码写得很不好，需要改进  昨晚自己又琢磨了一下流程算是弄明白了，我没有充分考虑pTail在该函数的参数变化，归根结底还是因为粗心大意。还有一个问题，pTail事实上并没有生成内存，它是个局部变量吧。 至于您指出的这个代码写法我并不是很清楚，据教材说这是个最基础的非循环单链表，我只是贴出了它的代码。谢谢您提示，我会看看其他例子[/quote] 看看这个创建链表代码的写法，和你的对比一下 #define _CRT_SECURE_NO_DEPRECATE  #include <stdio.h> #include <stdlib.h>  typedef struct node { 	int data; 	struct node *next; }node; node *head = NULL, *p = NULL, *last = NULL;  void createlinklist() { 	int i,length; 	puts("please input the length of linklist:"); 	scanf("%d", &length); 	for (i = 0;i < length;i++) 	{ 		p = (node *)malloc(sizeof(node)); 		p->next = NULL; 		if (NULL == head) 			head = p; 		else 			last->next = p; 		last = p; 	} }  void traverselinklist() { 	for (p = head;p;p = p->next) 		printf("%d-", p->data); }  int main() { 	createlinklist(); 	traverselinklist(); }

引用 10 楼 ipresk 的回复:[quote=引用 3 楼 mortimer7866 的回复:] 的确是你理解有误，pHead是指向头结点的指针，pNew是每次用来添加结点的指针，pTail是指向最后一个结点的指针，你先申请了一个结点，pNew,pTrail始终指向最后一个结点，pTrail->next=pNew,意思是将新申请的结点链接到当前最后一个节点的后面，pNew->next=NULL，就是将你新申请的结点中的nextz 指针域置为NULL，然后pTrail=pNew是将pTrail指针重新指向改动过的链表的最后一个结点，这样形成循环，创建链表，最后说一句，你创建链表的这个方法很不好，pNew->next=NULL这一句应该是在空间申请结束下一句，个人见解这个代码写得很不好，需要改进  昨晚自己又琢磨了一下流程算是弄明白了，我没有充分考虑pTail在该函数的参数变化，归根结底还是因为粗心大意。还有一个问题，pTail事实上并没有生成内存，它是个局部变量吧。 至于您指出的这个代码写法我并不是很清楚，据教材说这是个最基础的非循环单链表，我只是贴出了它的代码。谢谢您提示，我会看看其他例子[/quote] 嗯，多看看例子，慢慢琢磨

引用 3 楼 mortimer7866 的回复:的确是你理解有误，pHead是指向头结点的指针，pNew是每次用来添加结点的指针，pTail是指向最后一个结点的指针，你先申请了一个结点，pNew,pTrail始终指向最后一个结点，pTrail->next=pNew,意思是将新申请的结点链接到当前最后一个节点的后面，pNew->next=NULL，就是将你新申请的结点中的nextz 指针域置为NULL，然后pTrail=pNew是将pTrail指针重新指向改动过的链表的最后一个结点，这样形成循环，创建链表，最后说一句，你创建链表的这个方法很不好，pNew->next=NULL这一句应该是在空间申请结束下一句，个人见解这个代码写得很不好，需要改进 引用 5 楼 kira_invoke 的回复:printf("%s %s", pTail->pNext,pNew->pNext); 这句我没看明白。。这能打印什么吗。。  很长时间没接触了，其实想用是%0x打印地址2333

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  仅供参考：//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*q1,*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;     }      //将整个链表逆序     if (head->next!=NULL && head->next->next!=NULL) {         p=head->next;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head->next=p;     }      //输出整个单链表     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; } //84->28->20->23->96->19->59->97->29->41-> //84->28->05->20->23->96->19->59->97->29->41-> //84->28->05->20->96->19->59->97->29->41-> //05->19->20->28->29->41->59->84->96->97-> //97->96->84->59->41->29->28->20->19->05-> //41->29->28->20->19->05->97->96->84->59-> //

再供参考：//不带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include <locale.h> struct NODE {     int          data;     struct NODE *next; } *head,*p,*q,*s,*p1,*p2,*q1,**ta; int i,k,n,t,m,v,N=10; int main() {     setlocale(LC_ALL,"chs");     srand(time(NULL));      head=NULL;      printf("创建%d个节点的单链表:",N);//创建N个节点的单链表     p=head;     for (i=0;i<N;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) exit(1);         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         if (NULL==p) {             head=q;             p=head;         } else {             p->next=q;             p=q;         }     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=3;     v=5;     printf("将值为%d的结点插入到单链表的第%d个结点前:",v,k);//将值为v的结点插入到单链表的第k个结点前     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) exit(1);             q->data=5;             q->next=head;             head=q;             break;         } else {             if (k-1==n) {                 q=(struct NODE *)malloc(sizeof(struct NODE));                 if (NULL==q) exit(1);                 q->data=5;                 q->next=p->next;                 p->next=q;                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=5;     printf("删除第%d个节点:",k);//删除第k个节点     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=head;             head=head->next;             free(q);             break;         } else {             if (k-1==n) {                 q=p->next;                 if (q) {                     p->next=q->next;                     free(q);                 }                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      printf("从小到大排序:");//从小到大排序     for (p=head,p1=NULL;p!=NULL;p1=p,p=p->next) {         for (q=p->next,q1=p;q!=NULL;q1=q,q=q->next) {             if (p->data > q->data) {                  //交换data //              printf("swap %02d %02d\n",p->data,q->data); //              t=p->data;p->data=q->data;q->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->data,q->data);                 if (p==head) {//p是头                     if (p->next==q) {//pq挨着                         head=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=head;                     } else {//pq不挨着                         head=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=head;                     }                 } else {//p不是头                     if (p->next==q) {//pq挨着                         p1->next=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=p1->next;                     } else {//pq不挨着                         p1->next=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=p1->next;                     }                 }                  //输出整个单链表 //              s=head; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表并计算链表长度n     n=0;     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         n++;         s=s->next;     }      printf("将整个链表逆序:");//将整个链表逆序     if (n>=2) {         p=head;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head=p;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      m=4;     n=6;     printf("将单链表中前%d个结点和后%d个结点进行互换:",m,n);//将单链表中前m个结点和后n个结点进行互换,m+n为链表总长     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m==k) {             q=p;         }         s=p;         p=p->next;     }     q1=head;     head=q->next;     s->next=q1;     q->next=NULL;      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //创建10个节点的单链表:08->74->07->23->03->99->31->56->88->16-> //将值为5的结点插入到单链表的第3个结点前:08->74->05->07->23->03->99->31->56->88->16-> //删除第5个节点:08->74->05->07->03->99->31->56->88->16-> //从小到大排序:03->05->07->08->16->31->56->74->88->99-> //将整个链表逆序:99->88->74->56->31->16->08->07->05->03-> //将单链表中前4个结点和后6个结点进行互换:31->16->08->07->05->03->99->88->74->56-> //

引用 8 楼 ipresk 的回复:[quote=引用 3 楼 mortimer7866 的回复:] 的确是你理解有误，pHead是指向头结点的指针，pNew是每次用来添加结点的指针，pTail是指向最后一个结点的指针，你先申请了一个结点，pNew,pTrail始终指向最后一个结点，pTrail->next=pNew,意思是将新申请的结点链接到当前最后一个节点的后面，pNew->next=NULL，就是将你新申请的结点中的nextz 指针域置为NULL，然后pTrail=pNew是将pTrail指针重新指向改动过的链表的最后一个结点，这样形成循环，创建链表，最后说一句，你创建链表的这个方法很不好，pNew->next=NULL这一句应该是在空间申请结束下一句，个人见解这个代码写得很不好，需要改进 引用 5 楼 kira_invoke 的回复:printf("%s %s", pTail->pNext,pNew->pNext); 这句我没看明白。。这能打印什么吗。。  很长时间没接触了，其实想用是%0x打印地址2333[/quote]  谢谢

引用 3 楼 mortimer7866 的回复:的确是你理解有误，pHead是指向头结点的指针，pNew是每次用来添加结点的指针，pTail是指向最后一个结点的指针，你先申请了一个结点，pNew,pTrail始终指向最后一个结点，pTrail->next=pNew,意思是将新申请的结点链接到当前最后一个节点的后面，pNew->next=NULL，就是将你新申请的结点中的nextz 指针域置为NULL，然后pTrail=pNew是将pTrail指针重新指向改动过的链表的最后一个结点，这样形成循环，创建链表，最后说一句，你创建链表的这个方法很不好，pNew->next=NULL这一句应该是在空间申请结束下一句，个人见解这个代码写得很不好，需要改进  昨晚自己又琢磨了一下流程算是弄明白了，我没有充分考虑pTail在该函数的参数变化，归根结底还是因为粗心大意。还有一个问题，pTail事实上并没有生成内存，它是个局部变量吧。 至于您指出的这个代码写法我并不是很清楚，据教材说这是个最基础的非循环单链表，我只是贴出了它的代码。谢谢您提示，我会看看其他例子

打印地址用%p  Run-Time Library Reference  printf Type Field Characters  See Also  Send Feedback     The type character is the only required format field; it appears after any optional format fields. The type character determines whether the associated argument is interpreted as a character, string, or number. The types C, n, p, and S, and the behavior of c and s with printf functions, are Microsoft extensions and are not ANSI compatible.   Character  Type  Output format   c  int or wint_t  When used with printf functions, specifies a single-byte character; when used with wprintf functions, specifies a wide character.   C  int or wint_t  When used with printf functions, specifies a wide character; when used with wprintf functions, specifies a single-byte character.   d  int  Signed decimal integer.   i  int  Signed decimal integer.   o  int  Unsigned octal integer.   u  int  Unsigned decimal integer.   x  int  Unsigned hexadecimal integer, using "abcdef."   X  int  Unsigned hexadecimal integer, using "ABCDEF."   e  double  Signed value having the form [ – ]d.dddd e [sign]dd[d] where d is a single decimal digit, dddd is one or more decimal digits, dd[d] is two or three decimal digits depending on the output format and size of the exponent, and sign is + or –.   E  double  Identical to the e format except that E rather than e introduces the exponent.   f  double  Signed value having the form [ – ]dddd.dddd, where dddd is one or more decimal digits. The number of digits before the decimal point depends on the magnitude of the number, and the number of digits after the decimal point depends on the requested precision.   g  double  Signed value printed in f or e format, whichever is more compact for the given value and precision. The e format is used only when the exponent of the value is less than –4 or greater than or equal to the precision argument. Trailing zeros are truncated, and the decimal point appears only if one or more digits follow it.   G  double  Identical to the g format, except that E, rather than e, introduces the exponent (where appropriate).   a  double  Signed hexadecimal double precision floating point value having the form [−]0xh.hhhh p±dd, where h.hhhh are the hex digits (using lower case letters) of the mantissa, and dd are one or more digits for the exponent. The precision specifies the number of digits after the point.   A  double  Signed hexadecimal double precision floating point value having the form [−]0Xh.hhhh P±dd, where h.hhhh are the hex digits (using capital letters) of the mantissa, and dd are one or more digits for the exponent. The precision specifies the number of digits after the point.   n  Pointer to integer   Number of characters successfully written so far to the stream or buffer; this value is stored in the integer whose address is given as the argument. See Security Note below.   p  Pointer to void  Prints the argument as an address in hexadecimal digits.   s  String   When used with printf functions, specifies a single-byte–character string; when used with wprintf functions, specifies a wide-character string. Characters are printed up to the first null character or until the precision value is reached.   S  String  When used with printf functions, specifies a wide-character string; when used with wprintf functions, specifies a single-byte–character string. Characters are printed up to the first null character or until the precision value is reached.    Note   If the argument corresponding to %s or %S is a null pointer, "(null)" will be printed.  Note   In all exponential formats, the default number of digits of exponent to display is three. Using the _set_output_format function, the number of digits displayed may be set to two, expanding to three if demanded by the size of exponent.  Security Note   The %n format is inherently insecure and is disabled by default; if %n is encountered in a format string, the invalid parameter handler is invoked as described in Parameter Validation. To enable %n support, see _set_printf_count_output.  See Also Concepts printf, _printf_l, wprintf, _wprintf_l Send feedback on this topic to Microsoft.

链表，顾名思义，就是一个连一个存    具体又分单链、双链

字打错了，是“支持”改为“指出”

刚开始看你的程序，首先支持既然写C程序就不要用C++语法或关键字，比如bool


Question: 这个是什么意思？为什么我编译的时候没有错误！

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。

NULL 指针的解析。

跟堆栈啊，朋友，ide什么都能告诉你

出错时定位通过调用堆栈定位出错位置，然后分析，从你出错的信息看，应该是访问了空指针


Question: 这代码编译时没错，但运行时出错了；我调试后，在第三次入队时出错了，但还是不知道原因，求解决！

LINE L;//在堆栈上分配一段内存用于存放L

原来这样就可以了，先感谢你的回答！但我还有个疑问，像我刚才那样为什么会出错，为什么不能给pL分配内存吗？意义有不同吗

#include <stdio.h> #include <malloc.h> typedef struct qnode{     int data;     struct qnode * next; }QNode,*PQNode;  typedef struct line{     PQNode front;     PQNode rear; }LINE,*PLINE; void init(PLINE pL); void enLine(PLINE pL,int val); void outLine(PLINE p); int main(void){     LINE L;     init(&L);     enLine(&L,3);     enLine(&L,1);     enLine(&L,44);     outLine(&L);     return 0; } //链队初始化 void init(PLINE pL){     pL->front=pL->rear=NULL; } //入队 void enLine(PLINE pL,int val){     PQNode p=(PQNode)malloc(sizeof(QNode));     p->data=val;     p->next=NULL;     if(pL->rear==NULL){         pL->front=pL->rear=p;     }     else{         pL->rear->next=p;         pL->rear=p;     } } //遍历输出队列 void outLine(PLINE p){     PQNode q;     while (p->front!=NULL) {         q=p->front;         printf("%d ",q->data);         p->front=q->next;         free(q);     } }


Question: 编了个十进制换算二进制的c程序，遇到了点小问题

一般局部变量也是放在栈上,i和bi[64]地址刚好相同,你在对bi[64]赋值的时候实际是对i赋值,把&i和bi+64打印出来看看就明白了

数组越界并不是编译器来保证，是程序员自己保证的，没出错只是运气好，如果后面跟着重要的数据，可能就被你覆盖了

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

纠结未定义行为没有意义


Question: 如何才算精通C语言？？？希望能得到答案；

C语言本身就是一种编程语言，就是一种语言。 类比下我们的汉语，可以怎么问：怎么样才算是精通汉语呢？ 答：。。。。此处省略，实在不知道怎么说。鄙人作文不合格。

感觉够用就可以了，毕竟所有的东西都是为了用的。

引用 15 楼 zhao4zhong1 的回复:如何才算精通XXX？？？希望能得到答案； 当lz不再问这个问题的时候，我认为lz就精通了。 当lz百年之后，lz不会再问这个问题。 综上所述，lz百年之后，就精通XXX了。  所谓的精通都是相对的~

你只要做到通过c语言这个引子，去了解其他东西，并经过时间的积累，才有资格谈精通，不然就是夜郎自大。

首先要做到《ISO/IEC 9899:1990》、《ISO/IEC 9899:1999》和《ISO/IEC 9899:2011》这三个文档倒背如流。

C 语言就是一个 unsigned long 时,你就入门了

引用 11 楼 ri_aje 的回复:[quote=引用 10 楼 dustpg 的回复:] 当lz不再问这个问题的时候, 我认为lz就精通了. ++[/quote] i++；

引用 10 楼 dustpg 的回复:当lz不再问这个问题的时候, 我认为lz就精通了. ++

当你能看懂01的时候就真的精通了

你想实现某个功能，可以很顺手的用C刷刷刷就写出来，在论坛上看到C的问题都知道是个什么回事

精通c语言(或任何语言)，都是指精通语言之外的东西，不是语言本身

当lz不再问这个问题的时候, 我认为lz就精通了.

任何编程语言，主要的是运用，会熟练用就行。。。

如果是单片机C，如果懂得汇编级调试差不多算精通了

会是一回事，精通是另一回事。至于SOCKET,MFC什么的，不属于“精通C”这个范畴。  引用 1 楼 user-19 的回复:还有 Socket 网络啊，还有 MFC 图形界面程序啊，标准 C 谁不会啊，你去街上随便找个小学生都会写，要学 MFC，没有人喜欢控制台程序  按我的理解，精通C，应该包含两方面内容： 1.底层：C语言代码的汇编实现。这一点主要体现在C代码的优化上，也就是说，你既要知道你的C代码，也要知晓C代码编译成汇编后，大致是个什么样子，如果再进一步，你需要对C编译器特别熟悉，知道它具体是如何工作的。  2.标准：需要对C语言标准有深入理解，能熟练使用标准库中的大部分内容。  至于算法，那是另一个范畴；MFC属于框架结构范畴；SOCKET属于网络编程范畴。

很显然是不会有标准的, 多看好的代码, 多写好的代码, 自然就精通了

如果什么都能做，什么都会写，什么岗位都胜任。。

个人意见：眼睛看到的是C语句，脑中响应的是该C语句对应的Debug和Release版汇编指令以及这些指令通过OS对内存、磁盘、网卡等存储或通讯设备上各字节的影响。


Question: 一些题连意思都没看懂。。求大神

3   取对数

再供参考：//地上一大块由长M米，宽N米共M×N个小块组成的高低不平的区域，地面高度为0，每小块内部是平的，其高度为0～9米不等. //一场大雨过后，这块区域的积水共多少立方米？ //假设水只会流到正东、正南、正西、正北相邻的且高度较低的小块里; //而不会流到东北、东南、西北、西南相邻的且高度较低的小块里。 #include <stdio.h> #include <time.h> #include <stdlib.h> #define M 10 #define N 10 int a[M+4][N+4];//地面高度 int w[M+4][N+4];//水面高度 int sp=0; int xs[(M+4)*(N+4)]; int ys[(M+4)*(N+4)]; int xx,yy; int x,y; int i,h; int tw; void push(int py,int px) { //  printf("%03d %d,%d\n",sp,py,px);     ys[sp]=py;     xs[sp]=px;     if (sp<(M+4)*(N+4)-1) {         sp=sp+1;     } else {         printf("stack overflow!\n");         exit(1);     } } void pop(void) {     sp=sp-1;     yy=ys[sp];     xx=xs[sp]; } int check(int cy,int cx,int ch) {     if (a[cy][cx]<=ch && w[cy][cx]>ch) return 1;     else return 0; } void floodfilling(int hh) {     push(1,1);     while (1) {         if (sp<=0) break;//         pop();         if (check(yy,xx,hh)) {             w[yy][xx]=hh;             if (check(yy-1,xx  ,hh)) push(yy-1,xx  );             if (check(yy  ,xx+1,hh)) push(yy  ,xx+1);             if (check(yy  ,xx-1,hh)) push(yy  ,xx-1);             if (check(yy+1,xx  ,hh)) push(yy+1,xx  );         }     }     for (y=0;y<=M+3;y++) {         for (x=0;x<=N+3;x++) {             printf("%d%d ",a[y][x],w[y][x]);         }         printf("\n");     }     for (x=0;x<=N+3;x++) printf("---");     printf("hh=%d\n",hh); } void main() {     //最外圈增加一圈高度9的小块     for (i=0;i<=M+3;i++) {a[i][0]=9;a[i][N+3]=9;}     for (i=0;i<=N+3;i++) {a[0][i]=9;a[M+3][i]=9;}      //次外圈增加一圈高度0的小块     for (i=1;i<=M+2;i++) {a[i][1]=0;a[i][N+2]=0;}     for (i=1;i<=N+2;i++) {a[1][i]=0;a[M+2][i]=0;}      srand(time(NULL));     for (y=2;y<=M+1;y++) {         for (x=2;x<=N+1;x++) {             a[y][x]=rand()%10;//初始地面高度         }     }      for (y=0;y<=M+3;y++) {         for (x=0;x<=N+3;x++) {             w[y][x]=9;//初始水面高度9         }     }      printf("当前每小块地面高度水面高度\n",tw);     for (y=0;y<=M+3;y++) {         for (x=0;x<=N+3;x++) {             printf("%d%d ",a[y][x],w[y][x]);         }         printf("\n");     }     for (x=0;x<=N+3;x++) printf("---");     printf("hh=9\n");      for (h=8;h>=0;h--) floodfilling(h);//检查水面高度8到0      tw=0;     for (y=2;y<=M+1;y++) {         for (x=2;x<=N+1;x++) {             tw+=(w[y][x]-a[y][x]>0)?w[y][x]-a[y][x]:0;         }     }     printf("共积水%d立方米\n",tw); } //当前每小块地面高度水面高度 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 09 09 09 09 09 09 09 09 09 09 09 09 99 //99 09 89 49 39 79 79 69 49 79 09 69 09 99 //99 09 19 29 59 39 39 99 09 59 49 79 09 99 //99 09 09 39 59 79 99 29 39 09 69 39 09 99 //99 09 79 59 89 59 09 39 09 49 79 49 09 99 //99 09 09 69 19 99 39 39 19 59 99 29 09 99 //99 09 29 19 39 99 79 29 39 89 79 99 09 99 //99 09 29 29 39 29 89 69 19 89 39 99 09 99 //99 09 99 99 89 79 49 79 89 69 39 09 09 99 //99 09 29 19 29 69 39 89 39 39 99 19 09 99 //99 09 79 39 19 39 19 29 19 89 69 79 09 99 //99 09 09 09 09 09 09 09 09 09 09 09 09 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=9 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 08 08 08 08 08 08 08 08 08 08 08 08 99 //99 08 88 48 38 78 78 68 48 78 08 68 08 99 //99 08 18 28 58 38 38 99 08 58 48 78 08 99 //99 08 08 38 58 78 99 28 38 08 68 38 08 99 //99 08 78 58 88 58 08 38 08 48 78 48 08 99 //99 08 08 68 18 99 38 38 18 58 99 28 08 99 //99 08 28 18 38 99 78 28 38 88 78 99 08 99 //99 08 28 28 38 28 88 68 18 88 38 99 08 99 //99 08 99 99 88 78 48 78 88 68 38 08 08 99 //99 08 28 18 28 68 38 88 38 38 99 18 08 99 //99 08 78 38 18 38 18 28 18 88 68 78 08 99 //99 08 08 08 08 08 08 08 08 08 08 08 08 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=8 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 07 07 07 07 07 07 07 07 07 07 07 07 99 //99 07 88 47 37 77 77 67 47 77 07 67 07 99 //99 07 17 27 57 37 37 99 07 57 47 77 07 99 //99 07 07 37 57 77 99 27 37 07 67 37 07 99 //99 07 77 57 88 57 07 37 07 47 77 47 07 99 //99 07 07 67 17 99 37 37 17 57 99 27 07 99 //99 07 27 17 37 99 77 27 37 88 77 99 07 99 //99 07 27 27 37 27 88 67 17 88 37 99 07 99 //99 07 99 99 88 77 47 77 88 67 37 07 07 99 //99 07 27 17 27 67 37 88 37 37 99 17 07 99 //99 07 77 37 17 37 17 27 17 88 67 77 07 99 //99 07 07 07 07 07 07 07 07 07 07 07 07 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=7 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 06 06 06 06 06 06 06 06 06 06 06 06 99 //99 06 88 46 36 77 77 66 46 77 06 66 06 99 //99 06 16 26 56 36 36 99 06 56 46 77 06 99 //99 06 06 36 56 77 99 26 36 06 66 36 06 99 //99 06 77 56 88 56 06 36 06 46 77 46 06 99 //99 06 06 66 16 99 36 36 16 56 99 26 06 99 //99 06 26 16 36 99 77 26 36 88 77 99 06 99 //99 06 26 26 36 26 88 66 16 88 36 99 06 99 //99 06 99 99 88 77 46 77 88 66 36 06 06 99 //99 06 26 16 26 66 36 88 36 36 99 16 06 99 //99 06 77 36 16 36 16 26 16 88 66 77 06 99 //99 06 06 06 06 06 06 06 06 06 06 06 06 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=6 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 05 05 05 05 05 05 05 05 05 05 05 05 99 //99 05 88 45 35 77 77 66 45 77 05 66 05 99 //99 05 15 25 55 35 35 99 05 55 45 77 05 99 //99 05 05 35 55 77 99 25 35 05 66 35 05 99 //99 05 77 55 88 55 05 35 05 45 77 45 05 99 //99 05 05 66 15 99 35 35 15 55 99 25 05 99 //99 05 25 15 35 99 77 25 35 88 77 99 05 99 //99 05 25 25 35 25 88 66 15 88 35 99 05 99 //99 05 99 99 88 77 45 77 88 66 35 05 05 99 //99 05 25 15 25 66 35 88 35 35 99 15 05 99 //99 05 77 35 15 35 15 25 15 88 66 77 05 99 //99 05 05 05 05 05 05 05 05 05 05 05 05 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=5 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 04 04 04 04 04 04 04 04 04 04 04 04 99 //99 04 88 44 34 77 77 66 44 77 04 66 04 99 //99 04 14 24 55 35 35 99 04 55 44 77 04 99 //99 04 04 34 55 77 99 24 34 04 66 34 04 99 //99 04 77 55 88 55 04 34 04 44 77 44 04 99 //99 04 04 66 14 99 34 34 14 55 99 24 04 99 //99 04 24 14 34 99 77 24 34 88 77 99 04 99 //99 04 24 24 34 24 88 66 14 88 34 99 04 99 //99 04 99 99 88 77 44 77 88 66 34 04 04 99 //99 04 24 14 24 66 34 88 34 34 99 14 04 99 //99 04 77 34 14 34 14 24 14 88 66 77 04 99 //99 04 04 04 04 04 04 04 04 04 04 04 04 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=4 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 03 03 03 03 03 03 03 03 03 03 03 03 99 //99 03 88 44 33 77 77 66 44 77 03 66 03 99 //99 03 13 23 55 35 35 99 04 55 44 77 03 99 //99 03 03 33 55 77 99 24 34 04 66 33 03 99 //99 03 77 55 88 55 04 34 04 44 77 44 03 99 //99 03 03 66 13 99 34 34 14 55 99 23 03 99 //99 03 23 13 33 99 77 24 34 88 77 99 03 99 //99 03 23 23 33 23 88 66 14 88 33 99 03 99 //99 03 99 99 88 77 44 77 88 66 33 03 03 99 //99 03 23 13 23 66 33 88 33 33 99 13 03 99 //99 03 77 33 13 33 13 23 13 88 66 77 03 99 //99 03 03 03 03 03 03 03 03 03 03 03 03 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=3 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 02 02 02 02 02 02 02 02 02 02 02 02 99 //99 02 88 44 33 77 77 66 44 77 02 66 02 99 //99 02 12 22 55 35 35 99 04 55 44 77 02 99 //99 02 02 33 55 77 99 24 34 04 66 33 02 99 //99 02 77 55 88 55 04 34 04 44 77 44 02 99 //99 02 02 66 13 99 34 34 14 55 99 22 02 99 //99 02 22 12 33 99 77 24 34 88 77 99 02 99 //99 02 22 22 33 23 88 66 14 88 33 99 02 99 //99 02 99 99 88 77 44 77 88 66 33 02 02 99 //99 02 22 12 22 66 33 88 33 33 99 12 02 99 //99 02 77 33 12 33 12 22 12 88 66 77 02 99 //99 02 02 02 02 02 02 02 02 02 02 02 02 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=2 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 01 01 01 01 01 01 01 01 01 01 01 01 99 //99 01 88 44 33 77 77 66 44 77 01 66 01 99 //99 01 11 22 55 35 35 99 04 55 44 77 01 99 //99 01 01 33 55 77 99 24 34 04 66 33 01 99 //99 01 77 55 88 55 04 34 04 44 77 44 01 99 //99 01 01 66 13 99 34 34 14 55 99 22 01 99 //99 01 22 12 33 99 77 24 34 88 77 99 01 99 //99 01 22 22 33 23 88 66 14 88 33 99 01 99 //99 01 99 99 88 77 44 77 88 66 33 01 01 99 //99 01 22 12 22 66 33 88 33 33 99 11 01 99 //99 01 77 33 11 33 11 22 11 88 66 77 01 99 //99 01 01 01 01 01 01 01 01 01 01 01 01 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=1 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //99 00 00 00 00 00 00 00 00 00 00 00 00 99 //99 00 88 44 33 77 77 66 44 77 00 66 00 99 //99 00 11 22 55 35 35 99 04 55 44 77 00 99 //99 00 00 33 55 77 99 24 34 04 66 33 00 99 //99 00 77 55 88 55 04 34 04 44 77 44 00 99 //99 00 00 66 13 99 34 34 14 55 99 22 00 99 //99 00 22 12 33 99 77 24 34 88 77 99 00 99 //99 00 22 22 33 23 88 66 14 88 33 99 00 99 //99 00 99 99 88 77 44 77 88 66 33 00 00 99 //99 00 22 12 22 66 33 88 33 33 99 11 00 99 //99 00 77 33 11 33 11 22 11 88 66 77 00 99 //99 00 00 00 00 00 00 00 00 00 00 00 00 99 //99 99 99 99 99 99 99 99 99 99 99 99 99 99 //------------------------------------------hh=0 //共积水40立方米

引用 1 楼 fefe82 的回复:3   取对数 懂了，谢谢。这方法会记住的。。

引用 4 楼 user-3 的回复:1) 贪心, 排序后, 从头开始找相同数字, 比如样3 1 2 3 1 ==> 1 1 2 3 3 , 1找到1变成2, 再找2, 配对后变成3, 第一次去掉1123,  2) 面积比算一下 (a+d)/a =(b+c)/b *(a+b+c+d)/(a+b) ==> d=ac(ab+2b^2+bc)/(b^3-abc) 这两题搞定了，太厉害了！多谢！

4参考下面：#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <graphics.h> int xs[10000]; int ys[10000]; int i=0,xx,yy; int fc,bc; void push(int x,int y) {     xs[i]=x;     ys[i]=y;     if (i<10000-1) {         i=i+1;     } else {         printf("stack overflow!\n");         exit(1);     } } void pop(void) {     i=i-1;     xx=xs[i];     yy=ys[i]; } int check(int x,int y) {     int c;      c=getpixel(x,y); /* 获取当前点的颜色 */     return ((c!=bc)&&(c!=fc));/* 如果颜色为边界色或填充色则不填充 */ } void seedfilling(int x,int y,int fill_color,int boundary_color) {     fc=fill_color;     bc=boundary_color;     push(x,y);     while (1) {         if (i<=0) return;         pop();         if (check(xx,yy)) {             putpixel(xx, yy, 14);getch();  /* 加上这行显示当前填充状态 */              putpixel(xx, yy, fill_color); /* 画点 */              if (check(xx-1,yy  )) push(xx-1,yy  );             if (check(xx  ,yy+1)) push(xx  ,yy+1);             if (check(xx  ,yy-1)) push(xx  ,yy-1);             if (check(xx+1,yy  )) push(xx+1,yy  );             /* 去掉下面四句就是四连通 */             if (check(xx-1,yy-1)) push(xx-1,yy-1);             if (check(xx-1,yy+1)) push(xx-1,yy+1);             if (check(xx+1,yy-1)) push(xx+1,yy-1);             if (check(xx+1,yy+1)) push(xx+1,yy+1);         }     } } void main() {     int a,b,color;     int gdriver = DETECT, gmode, errorcode;     int poly[10];      initgraph(&gdriver, &gmode, "d:\\bc\\bgi");     a=150;     b=140;     color=4;     poly[0]=110;/* 第一个点的x坐标以及y坐标 */     poly[1]=110;     poly[2]=200;/* 第二点 */     poly[3]=105;     poly[4]=170;/* 第三点 */     poly[5]=120;     poly[6]=150;/* 第四点 */     poly[7]=170;     poly[8]=110;/* 多边形的起点与终点一样 */     poly[9]=110;     drawpoly(5,poly);/* 显示各点连接起来的多边形 */      /* 保证边界对八连通是封闭的 */     setviewport(0,1,600,300,0);     drawpoly(5,poly);/* 显示各点连接起来的多边形 */     setviewport(1,0,600,300,0);     drawpoly(5,poly);/* 显示各点连接起来的多边形 */     setviewport(1,1,600,300,0);     drawpoly(5,poly);/* 显示各点连接起来的多边形 */      /* 恢复默认viewport */     setviewport(0,0,600,300,0);      seedfilling(a,b,color,15);  /* 种子填充多边形 */      getch();     closegraph(); }

引用 1 楼 fefe82的回复:3   取对数 那这位大神请问具体该怎么解决？


Question: 求助 小白

好复杂

自己写了 感觉麻烦了

好好学习，勤快作业

#include <stdio.h> #define ABS(a) ((a)>=0?(a):-(a)) char s[]="DCBABCD"; int i; int main() {     for (i=-3;i<=3;i++) printf("%*s%.*s\n",ABS(i),"",(4-ABS(i))*2-1,s+ABS(i));     return 0; } //   A //  BAB // CBABC //DCBABCD // CBABC //  BAB //   A //

7*7的矩形，以3为中位。行改变是否显示，列改变字母。 两个For循环嵌套即可。。


Question: 急需一个代码...初接触C语言 求两段和素数有关的代码。谢谢！！！

百度呀，不是挺多的么

第一个问题：  //Eratosthenes筛法求素数 //把min和max之间所有整数放到一起， //保留2，把2的所有倍数从中去掉，再保留3，同时删去所有3的倍数，下一个数是5、7... //该函数实际是算出2到max之间的素数，再取出min到max的部分 int GetPrime(int*prime,unsigned min,unsigned max) { 	if(prime==NULL || max<min) 		exit(1); 	if(max<2) 		return 0; 	if(min<2) 		min=2; 	int num=0; //素数个数 	bool *sieve=new bool[max+1]; 	for(unsigned i=1;i<max+1;i++) 		sieve[i]=true; 	unsigned j=1; 	while(j<max) 	{ 		j++; 		if(sieve[j] && j>=min) 			prime[num++]=j; 		for(unsigned k=j;k<max+1;k+=j) 			sieve[k]=false; 	} 	delete[] sieve; 	return num; }    第二个问题，循环判断每个数就行  bool IsPrime(unsigned n) { 	if(n<2) 		return false; 	for(unsigned i=2;i*i<=n;i++) 		if(n%i==0) 			return false; 	return true; }   用的是用unsigned int 无符号整数

Finding prime numbers - Kenneth Haugland  Different schemas for finding prime numbers explained with code http://www.codeproject.com/Articles/429694/Finding-prime-numbers

找到一个好的算法，画好流程图，然后自己动手写，然后调试，这样能更好的学好c，等成高手在copy也不迟

1 直接筛 #define N 1000000 bool not_prime[N];  void sieve_init(){     for(int i=2,ii=sqrt(N)+1;i<=ii;i++) if(!not_prime[i]){         for(int j=i*i;j<N;j+=i) not_prime[j] =1;     } }  int main() {     int a,b;     sieve_init();     while(cin>>a>>b&&b){         if(b>=N) continue;         for(int i=max(a,2);i<=b;i++) if(!not_prime[i])             printf("%d ",i);         puts("");     }     return 0; }


Question: C语言的新手问题！

明白了！ 感谢2位大神！

double array[][5]={0};  第一维没有指定，需要使用初始化列表来推断。你的初始化列表只有一个元素，所以会推断为 double[1][5]。  所以从 array[1][0] 开始，就已经访问越界了。

1）double array[][5]={0};相当于 double array[1][5]={0};   要么初始化数据确定数组 大小，要么直接在数组声明部分确定数组大小   不要过于偷懒 2）array[1075576832][0]=8 这个数组没这么大？这是严重的越界。

array[1075576832][0]=8        //这样的时候 顺便输入一个数或则字符什么的 就自行结算了 按 <RETURN> 来关闭窗口...


Question: 求助 如何在有序加权任务图中寻找后继节点并找到最小值

是我表述不清楚么

楼主这个问题太高大上，不是矮穷矬的我辈所能理解和帮忙解决的。


Question: 关于SD卡判断最后存入的数据的位置

引用 3 楼 Saleayas 的回复:你需要在成功写入一个数据块的时候，在 SD 卡上写入标志。  我们的硬件工程师说，在掉电的时候，是有足够的时间向 SD 卡写入最后的数据的。 我的意思是我掉电之后再上电，怎么找到SD卡中我最后存入的数据的位置在哪里

引用 1 楼 user-2 的回复:不懂， 文件可以带时间吗？ 我也是刚开始用SD卡，还不清楚怎么带时间

不懂， 文件可以带时间吗？


Question: 代码

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

void squeeze(char s1[], char s2[]) { 	int i, j, k; 	k = 0; 	for (i = 0; s1[i] != '\0'; i++) 	{ 		for (j = 0; s2[j] != '\0'; j++) 			if (s1[i] == s2[j]) 				break; 		if(s2[j] == '\0') 			s1[k++] = s1[i]; 	} }

g刚没注意括号 void squeeze(char s1[], char s2[]) { int i, j, k; k = 0; for (i = 0; s1[i] != '\0'; i++) { for (j = 0; s2[j] != '\0'; j++) { if (s1[i] == s2[j]) break; } if(s2[j] == '\0') { s1[k] = s1[i]; k++; } } }

显然错了啊，没判断是否结束啊 void squeeze(char s1[], char s2[]) { int i, j, k; k = 0; for (i = 0; s1[i] != '\0'; i++) for (j = 0; s2[j] != '\0'; j++) { if (s1[i] == s2[j]) break; } if(s2[j] == '\0') { s1[k] = s1[i]; k++; }  }


Question: C++,错误:"const char *"类型的实参与"char *类型的形参不兼容"

if (ReadPgm ("im000.pgm", &I))  这个函数在visual stdio 2017中报了两个错，请教各位大神帮助  "const char *" 类型的实参与 "char *" 类型的形参不兼容  int ReadPgm(char*,imagestruct*)":无法将参数1从“”const char [10]“转换成“char” 请问各位大神以上两个问题应该怎么解决，谢谢

chartowchar 是个什么函数，他的参数类型是什么，是不是const char *

奇怪，为什么结帖后分数没有给出，我记得分配了分数的，谢谢大家，如果真的没有分数真不好意思

谢谢各位，最后解决了，用const_cast<char *>强制去除const属性，data.data(),data.c_str()我都试过不行的

引用 1 楼 user-4 的回复:应该写data.c_str()吧 类型不兼容，强制转呗 写成 LPCTSTR macaddressvalue = chartowchar((char *)data.c_str()); 谢谢，这个待我试试


Question: 这个算法该怎么写?

就是遍历出这棵树就行了吧

应该一个简单的递归就可以吧  void OutputNode( Node *pNode )	{ 	if ( pNode->pLeft != NULL )	{ 		OutputNode ( pNode->pLeft ); 	} 	 	printf("%d", pNode->value ); 	 	if ( pNode->pRight != NULL )	{ 		OutputNode ( pNode->pRight ); 	} }  OutputNode ( root );	//Root is the root of 二叉排序树


Question: C语言的内存模式在DOS下和保护模式的区别??

VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！

平面内存模式 (flat memory model) 是一种组织 内存 寻址空间的方式。一个用本地32位Windows格式写成的程序是由所谓“平坦内存模型”创建的，它只有一个包含代码和数据的段。这个程序必须在386或更高的处理器上运行。早期的16位代码，由段和偏移地址混合达到寻址64k（段的限制）。与此不同的是，平坦内存模型只需要偏移量却有4G的寻址范围。这使得汇编更容易书写，而代码总得来说也将快一点。 在这种模式下，一个电脑的应用程序最多使用两个内存区段，一个是给程序码使用，另外一个是资料。此外，同样的区段也可以用量同时给程序码或是资料使用，但这是不必要的，因为只有对于自我更改程序码 的程序才有用处，但这种程序设计风格 现今被视为一种很不好的方法。  平面内存模型的优点 应用程序在存取他们的资料时候不需要切换不同的区段。然而，在 16 位元的 Intel 8086 和 80286 中，这种方式是不可行的，因为应用程序无法存取超过 64 KB 的资料。在 32 位元的芯片，应用程序可以存取最大到 4 GB 的资料。但这也变成现在大的数据库以及像是影片编辑应用程序的问题。  在这种平坦内存模型下，所有的段寄存器都被自动设为相同的值，而这意味着段/偏移寻址方式一定不能用于在32位Windows上运行的32位程序。 对于曾经在DOS下写程序的程序员来讲，一个32位的Windows PE可执行文件就像一个DOS下的COM文件，它们仅有一个包含程序代码和数据的段，而它们都直接用偏移地址，而不是段/偏移寻址方式。平坦模型程序是近（NEAR）代码寻址以及近数据寻址，都是在4G的范围之内。搜索 FS和GS段寄存器不在普通的程序中用到，但却被操作系统的某些程序实例所利用。

Win32 是仅有一种 （保护模式）flat 模式，有人翻译为 平坦模式。 不过汇编语言，还支持实模式 tiny,small 等5～6种模式

你问这些一下解释不清，要需要看这本书：杨季文《80x86汇编语言程序设计教程》的中后部分（从提高部分开始），该书讲解的相当不错，网上能下载到。

在WIN32下这个貌似不重要，都是虚拟存储管理、虚拟地址空间了，都是32位地址、指针。


Question: 求助大神阿！关于RGBA数据写BMP文件的问题！

4字节对齐数据，计算一下图像宽度吧，如果除4不是整数，就要多写余数个0补齐4字节。

引用 3 楼 u010297717 的回复:[quote=引用 2 楼 fly_dragon_fly 的回复:] RGBA, 这是32位的bmp吗 是的，图像的长宽像素都没有错误，但是打出来的图片都是错位的，而且错位的都很有规律[/quote]如果是32位图, 本身就对齐的暂时想不到什么原因, 这种规律倒像是24位图没对齐

提醒：每行像素数据是按4字节对齐的，如果没对齐，后面会有1、2、3个字节补齐。

1）是原图就是这样。 2）是读取数据出错。 用 画图程序看图，如果还是这样，就是原图错误，否则是读取有问题

引用 2 楼 fly_dragon_fly 的回复:RGBA, 这是32位的bmp吗 是的，图像的长宽像素都没有错误，但是打出来的图片都是错位的，而且错位的都很有规律

RGBA, 这是32位的bmp吗

估计是多线程读取，或者批量读取 开始位置计算错误，或者行宽算错了

文件宽度错误


Question: 调用声卡做同步放音

void CSoundOut::PlayTaskFun() { #ifdef _WIN32 	/* 	* set up the WAVEFORMATEX structure. 	*/ 	WAVEFORMATEX wfx; /* look this up in your documentation */ 	wfx.nSamplesPerSec = 16000; /* sample rate */ 	wfx.wBitsPerSample = 16; /* sample size */ 	wfx.nChannels= 1; /* channels*/ 	wfx.cbSize = 0; /* size of _extra_ info */ 	wfx.wFormatTag = WAVE_FORMAT_PCM; 	wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) >> 3; 	wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; 	/* 	* try to open the default wave device. WAVE_MAPPER is 	* a constant defined in mmsystem.h, it always points to the 	* default wave device on the system (some people have 2 or 	* more sound cards). 	*/ 	_lockWaveOut.Lock(); 	_hWaveOutEvent = CreateEventW(NULL, FALSE, FALSE, NULL); 	AIFASSERT(_hWaveOutEvent); 	if (_hWaveOutEvent) 	{ 		struct _WaveOutProc 		{ 			static void CALLBACK WaveOutProc(HWAVEOUT hWaveOut, UINT uMsg, HANDLE hEvent, DWORD dwParam1, DWORD dwParam2) 			{ 				if(uMsg == WOM_DONE) 				{ 					SetEvent(hEvent); 				} 			} 		};  		if(waveOutOpen(&_hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)_WaveOutProc::WaveOutProc, (DWORD_PTR)_hWaveOutEvent, CALLBACK_FUNCTION) == MMSYSERR_NOERROR) 		{ 			_lockWaveOut.Unlock(); 			WAVEHDR _whBlocks[2]; #else 	if (true) 	{ 		if (true) 		{ #endif 			while (_eventPlay.Wait(INFINITE) && _bActived) 			{ 				AIFASSERT(_pAsync); 				ISoundOutPlayAsync *pSoundOutPlayAsync = NULL; 				if (_pAsync) 				{ 					_pAsync->QueryInterface(&pSoundOutPlayAsync); 				} #ifdef _WIN32 				int nCurrent = 0; 				SetEvent(_hWaveOutEvent); 				for (int i = 0; (_bPlaying) && i < _nWaveID; ++i) 				{ 					int nWave = ((unsigned int *)_nWaveIDs[i])[-1]; 					char *pWave = (char *)_nWaveIDs[i]; 					//PlaySoundA(pWave, NULL, SND_MEMORY | SND_ASYNC); 					WAVEHDR *pWH = &_whBlocks[nCurrent]; 					if(pWH->dwFlags & WHDR_PREPARED) 					{ 						waveOutUnprepareHeader(_hWaveOut, pWH, sizeof (*pWH)); 					} 					ZeroMemory(pWH, sizeof (*pWH)); 					pWH->lpData = pWave; 					pWH->dwBufferLength = (DWORD)nWave; 					waveOutPrepareHeader(_hWaveOut, pWH, sizeof (*pWH)); 					waveOutWrite(_hWaveOut, pWH, sizeof (*pWH)); 					WaitForSingleObject(_hWaveOutEvent, INFINITE); 					nCurrent = nCurrent == 0 ? 1 : 0; 				} 				WaitForSingleObject(_hWaveOutEvent, INFINITE); #else 				PlayWave(_nWaveIDs, _nWaveID, _nChipSet, &_bPlaying, pSoundOutPlayAsync); #endif 				if (pSoundOutPlayAsync) 				{ 					pSoundOutPlayAsync->Release(); 				} 				if (!_bPlaying) 				{ // 如果是通过 Close 方法结束播放。 					// 那么设置等待事件，以便同时 Close 方法已经关闭完成。 					// 这里设置为空。 					// 因为整个播放线程是独立的， Close 方法可以立即返回。 				} 				else if (_pAsync) 				{ // 如果是正常播放完成。 					// 设置播放完成事件。 					_pAsync->SetEvent(); 				} 			} #ifdef _WIN32 			_lockWaveOut.Lock(); 			waveOutClose(_hWaveOut); 			_hWaveOut = NULL; 		} 		CloseHandle(_hWaveOutEvent); 		_hWaveOutEvent = NULL; 	} 	_lockWaveOut.Unlock(); #else 		} 	} #endif }

MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl 先下载安装MSDN98 然后参考：MSDN98\SAMPLES\VC98\SDK\GRAPHICS\AUDIO\REVERSE\*.*

引用 1 楼 zhao4zhong1 的回复:参考MSDN98里面的：Example of Writing Waveform Data The following example illustrates the steps required to allocate and set up a WAVEHDR structure and write a block of data to a waveform output device.   // Global variables.   HANDLE hData  = NULL;  // handle of waveform data memory  HPSTR  lpData = NULL;  // pointer to waveform data memory    void WriteWaveData(void)  {      HWAVEOUT    hWaveOut;      HGLOBAL     hWaveHdr;      LPWAVEHDR   lpWaveHdr;      HMMIO       hmmio;      UINT        wResult;      HANDLE      hFormat;      WAVEFORMAT  *pFormat;      DWORD       dwDataSize;       // Open a waveform device for output using window callback.       if (waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,                      (LPWAVEFORMAT)pFormat,                      (LONG)hwndApp, 0L, CALLBACK_WINDOW))      {          MessageBox(hwndApp,                     "Failed to open waveform output device.",                     NULL, MB_OK | MB_ICONEXCLAMATION);          LocalUnlock(hFormat);          LocalFree(hFormat);          mmioClose(hmmio, 0);          return;      }        // Allocate and lock memory for the waveform data.        hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, dwDataSize );      if (!hData)      {          MessageBox(hwndApp, "Out of memory.",                     NULL, MB_OK | MB_ICONEXCLAMATION);          mmioClose(hmmio, 0);          return;      }      if ((lpData = GlobalLock(hData)) == NULL)      {          MessageBox(hwndApp, "Failed to lock memory for data chunk.",                     NULL, MB_OK | MB_ICONEXCLAMATION);          GlobalFree(hData);          mmioClose(hmmio, 0);          return;      }        // Read the waveform data subchunk.        if(mmioRead(hmmio, (HPSTR) lpData, dwDataSize) != (LRESULT)dwDataSize)      {          MessageBox(hwndApp, "Failed to read data chunk.",                     NULL, MB_OK | MB_ICONEXCLAMATION);          GlobalUnlock(hData);          GlobalFree(hData);          mmioClose(hmmio, 0);          return;      }        // Allocate and lock memory for the header.       hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,          (DWORD) sizeof(WAVEHDR));      if (hWaveHdr == NULL)      {          GlobalUnlock(hData);          GlobalFree(hData);          MessageBox(hwndApp, "Not enough memory for header.",              NULL, MB_OK | MB_ICONEXCLAMATION);          return;      }        lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);      if (lpWaveHdr == NULL)      {          GlobalUnlock(hData);          GlobalFree(hData);          MessageBox(hwndApp,              "Failed to lock memory for header.",              NULL, MB_OK | MB_ICONEXCLAMATION);          return;      }        // After allocation, set up and prepare header.        lpWaveHdr->lpData = lpData;      lpWaveHdr->dwBufferLength = dwDataSize;      lpWaveHdr->dwFlags = 0L;      lpWaveHdr->dwLoops = 0L;      waveOutPrepareHeader(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));        // Now the data block can be sent to the output device. The      // waveOutWrite function returns immediately and waveform      // data is sent to the output device in the background.        wResult = waveOutWrite(hWaveOut, lpWaveHdr, sizeof(WAVEHDR));      if (wResult != 0)      {          waveOutUnprepareHeader(hWaveOut, lpWaveHdr,                                 sizeof(WAVEHDR));          GlobalUnlock( hData);          GlobalFree(hData);          MessageBox(hwndApp, "Failed to write block to device",                     NULL, MB_OK | MB_ICONEXCLAMATION);          return;      }  }      ？我是网口数据传输。应该用二进制读取wav格式，这个程序不能用啊

引用 楼主 zhanglusmile 的回复:in onreceivedData(STATTYPE *pStatparam,long* pByteSize,byte *byData) 这是我接受的数据byData,想调用底层声卡技术实现播放功能，大家有没有好的思路，我是先转化为wav,再播放，然而不是实时传输的，感觉不是很好，求好的思路我是网口数据传输。应该用二进制读取wav格式，这个程序不能用啊


Question: C语言的重定向和直接打开文件问题

用feof判断文件尾试试

你在编译器中调试时默认路径一般不是Debug文件夹路径，而是你CPP文件所在的那个文件夹，把txt放到那下面，或者用完整路径代替试下

楼主公布一下所有源码吧，我在我机器执行一下看看

用绝对路径, 或者在调试设置一下当前路径

Get the current working directory. char *_getcwd( char *buffer, int maxlen );  Change the current working directory. int _chdir( const char *dirname );  Create an absolute or full path name for the specified relative path name. char *_fullpath( char *absPath, const char *relPath, size_t maxLength );


Question: 谁有可以计算各种多项式crc值的网站


Question: C 语言下　读包含中文的unicode文件

In Visual C++ 2005, fopen supports Unicode file streams. A flag specifying the desired encoding may be passed to fopen when opening a new file or overwriting an existing file, like this:  fopen("newfile.txt", "rw, ccs=<encoding>");  Allowed values of the encoding include UNICODE, UTF-8, and UTF16-LE. If the file is already in existence and is opened for reading or appending, the Byte Order Mark (BOM) is used to determine the correct encoding. It is not necessary to specify the encoding with a flag. In fact, the flag will be ignored if it conflicts with the type of the file as indicated by the BOM. The flag is only used when no BOM is present or if the file is a new file. The following table summarizes the modes used in for various flags given to fopen and Byte Order Marks used in the file.  Encodings Used Based on Flag and BOM Flag  No BOM (or new file)  BOM: UTF-8  BOM: UTF-16   UNICODE  ANSI  UTF-8  UTF-16LE   UTF-8  UTF-8  UTF-8  UTF-16LE   UTF-16LE  UTF-16LE  UTF-8  UTF-16LE

把所有的char都转成 wchar

首先读取的是ascii码，然后转成unicode码  参考c/c++  http://blog.csdn.net/u010370871/article/details/48029071  代码如下 #include <iostream> #include <sstream> #include <fstream> #include <windows.h> using namespace std;  int main() {  	cout<<"input the strFilename:"<<endl; 	string strFilename; 	cin>>strFilename; 	ifstream infile(strFilename.c_str()); 	string strGetString; 	getline(infile,strGetString);  	int nGetStringSize=strGetString.length(); 	DWORD dwStringSize=MultiByteToWideChar(CP_ACP, 0, strGetString.c_str(), nGetStringSize, NULL, 0); 	wchar_t *wchGetString=new wchar_t[dwStringSize+1]; 	wmemset(wchGetString, L'\0', dwStringSize+1);  	//进行转换 	int nRet=MultiByteToWideChar(CP_ACP, 0, strGetString.c_str(), nGetStringSize, wchGetString, dwStringSize); 	if(nRet<=0) 	{ 		cout<<"转换失败"<<endl; 		DWORD dwErr=GetLastError(); 		switch(dwErr) 		{ 		case ERROR_INSUFFICIENT_BUFFER: 			printf("ERROR_INSUFFICIENT_BUFFER\n"); 			break; 		case ERROR_INVALID_FLAGS: 			printf("ERROR_INVALID_FLAGS\n"); 			break; 		case ERROR_INVALID_PARAMETER: 			printf("ERROR_INVALID_PARAMETER\n"); 			break; 		case ERROR_NO_UNICODE_TRANSLATION: 			printf("ERROR_NO_UNICODE_TRANSLATION\n"); 			break; 		} 	}  	wcout.imbue(locale("chs"));//中文输出 	cout<<strGetString<<endl; 	wcout<<wchGetString<<endl; 	wcout<<endl; 	  	return 0; }


Question: 二维数组用一维数组输出值为什么是地址？

其实C/C++中的二维数组就不是真正意义上的二维数组，而是一维数组的一维数组

其实C/C++中的二维数组就不是真正意义上的二维数组，而是一维数组的一维数组   假如 int arr[2][3][4]，则最左侕的int arr[2] 为第一层包内数据，下标2说明第一层包内有2个int[3][4]类型的小包；打开下一个小包，里面是int[4]，再打开下一个，里面是int  所以如果你只是写arr[0]那么得到的只是下一个包（是个数组），数组名可转换为指针，指向数组首地址，固输出的是地址

引用 2 楼 Drench_ed的回复:二维数组为什么要用一维数组去输出呢？ 只是想知道用一维数组输出后是什么结果

二维数组为什么要用一维数组去输出呢？


Question: 将一个浮点数转化为一个整数，不用强转，用位运算，怎么弄？

先看这个：http://www.cnblogs.com/dolphin0520/archive/2011/10/02/2198280.html  上面这个是浮点数在内存中的存储方式，是分成几部分存的，你用位取出各部分，再运算，得到对应的其他类型数  不建议楼主自己实现，麻烦且效率不高；如果直接转换，用的是硬件实现，使用CPU浮点寄存器

看是否IEEE浮点数， 不过一般如下方式处理就可以了： 首先，看是否特殊数，+0，-0，∞，Nan， 非数 设置一个策略，处理这些情况。 其次，是否非规格化小数，是 大约只能置为0 因为太小了。 对于规格化浮点数， 首先看指数，在不在整数表示范围。 不在，要么巨大，超过表示范围，置为最大整数（或者取最后若干位） 要么太小，不能化为整数，只能置为0了 其次看符号 设置+，-号 其次看尾数 ，和指数联合移位， 取出整数部分。 可能还需要 四舍五入，二进制其实是0 舍1入， 这个要根据你选取的策略，来决定是全部舍去，还是四舍五入 还是采用所谓的银行家算法（也是一种四舍五入， 不过5入不入看情况，分奇偶），

如果是 IEEE 754 的浮点数的话，可以参考 IEEE 754 标准浮点数的表示。  https://en.wikipedia.org/wiki/IEEE_floating_point


Question: 求助，C代码数组初化怎么优化

已完成优化，1亿执行时间0.83秒#include  <stdio.h> #include <Windows.h> #include <stdlib.h> #include <time.h> int creat_prime(int prime[], int sieve[], int n); int main(void) { 	clock_t start, finish; 	double  duration; 	int n=100000000;  	int *prime; 	prime = (int *)malloc((n + 7) * sizeof(int)); 	int *sieve; 	sieve = (int *)malloc((n / 15 + 2) * sizeof(int));  	start = clock(); 	printf("\n%d\n", creat_prime(prime, sieve, n)); 	finish = clock(); 	duration = (double)(finish - start) / CLOCKS_PER_SEC; 	printf("%f seconds\n", duration);  	system("pause"); 	return 0; } /* 初始化数组 prime{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20......n} sieve{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20......n} 第一次删除2倍数得到数组 prime{0,1,0,3,0,5,0,7,0,9,0,11,0,13,0,15,0,17,0,19,0......n} 2的倍数是{4，6，8，10......}/2---->{2,3,4,5......}---->取模---->sieve{3,5,7,11,13,17,19,......n} 下一次删除的就是sieve[0]的倍数，刚好它要删除的倍数都在sieve数组里。同样得到新的sieve数组 进行下一次计算。 算法是每个非质数只删除一次  下一步再做优化 prime数组{0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1....,0,0,0,1,0,1}   6n-1 6n+1 sieve数组{5,7,11,13,17,19},2424规则 从质数5开始 (sieve[j] % i)此段工作量少了2/3 */ int creat_prime(int prime[], int sieve[], int n) { 	register int i, j, k, l; 	//数组初始化 	for (i = 5; i <= n;)//6N+1,6N-1 	{ 		prime[i++] = 1; 		prime[i++] = 0; 		prime[i++] = 1; 		prime[i++] = 0; 		prime[i++] = 0; 		prime[i++] = 0; 	} 	prime[1] = 0, prime[2] = 1, prime[3] = 1, prime[4] = 0;  	int div = n / 15 + 1; 	sieve[0] = 5; 	for (i = 1; i <= div;)//2 4 2 4 	{ 		sieve[i] = sieve[i - 1] + 2; 		i++; 		sieve[i] = sieve[i - 1] + 4; 		i++; 	} 	//开始标记非质数 	l = 1; 	for (i = 5; l != 0; i = sieve[0])//sieve[0]  是质数 	{ 		l = j = 0; 		k = i * i;//从此数开始作标记  		while (k <= n) 		{ 			if (sieve[j] % i) sieve[l++] = sieve[j];//存储下一轮（FOR）循环的质数倍数，作%处理是防止下次（FOR）循环找到已标记过的数 			prime[k] = 0;//非质数标记为0 			k = i * sieve[++j];//下一个非质数，直接找到要标记的非质数 		} 	} 	//打印测试 	//for (i = 2; i <= n; i++)  if (prime[i]) printf("%d ", i); 	return 0; }   贴一个1亿扫执行时间为0.8秒的 #include <stdio.h>  #include <time.h>  #include <string.h>  #include <stdlib.h>  #define PRIME_LIM 10000000  #define N 100000000 int primes[PRIME_LIM] = {0};  int flags[N/96 + 1] = {0};  int get_prime()  { 	int nu = 5, to = 0;  	primes[0] = 2; 	primes[1] = 2, 	primes[2] = 3;  	for(int i = 0; nu <= N; i++) 	{  			if(!(flags[i>>5]&(1<<(i&31)))) 			primes[++primes[0]] = nu; 			for(int j = 3; j <= primes[0] && primes[j] * nu <= N; j++) 				{ 					to = (nu * primes[j] - 5) >> 1; 					to -= to/3; 					flags[to>>5] |= 1<<(to&31); 					if(!(nu % primes[j])) 						break; 				} 			nu += 2 + ((i&1) << 1); 	}  	return primes[0]; }  int main()  {  	clock_t t = clock(); 	printf("%d\n", get_prime()); 	printf("Time:%f\n", 1.0 * (clock() - t) / CLOCKS_PER_SEC); 	for(int i = 1; primes[i] < 100; i++) 	{  		printf("%d\n", primes[i]); 	}  	system("pause"); 	return 0; }  为什么下面的代码会更快？

引用 5 楼 paschen 的回复:[quote=引用 2 楼 uthman123444 的回复:] [quote=引用 1 楼 paschen 的回复:] 想怎样优化，用memcpy？  从质数5开始 (sieve[j] % i)此段工作量少了2/3 所以数组初始化方式要更改， 数组想用下面的方式 prime数组{0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1....,0,0,0,1,0,1}   6n-1 6n+1 sieve数组{5,7,11,13,17,19},2424规则 [/quote]  还是没明白，怎么prime中全是0和1， 6n-1 6n+1 怎么理解[/quote] n是自然数 所有大于6的数都可以表示为： 6n-2 6n-1 6n 6n+1 6n+2 6n+3 六种之一 6n 肯定能被6整除 6n+2 肯定能被2整除 6n+3 肯定能被3整除 6n-2 肯定能被2整除 prime初始：   0的话就是2或3的倍数，不是2或3的倍数为1

引用 2 楼 uthman123444 的回复:[quote=引用 1 楼 paschen 的回复:] 想怎样优化，用memcpy？  从质数5开始 (sieve[j] % i)此段工作量少了2/3 所以数组初始化方式要更改， 数组想用下面的方式 prime数组{0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1....,0,0,0,1,0,1}   6n-1 6n+1 sieve数组{5,7,11,13,17,19},2424规则 [/quote]  还是没明白，怎么prime中全是0和1， 6n-1 6n+1 怎么理解

引用 3 楼 zhao4zhong1 的回复:Finding prime numbers - Kenneth Haugland  Different schemas for finding prime numbers explained with code http://www.codeproject.com/Articles/429694/Finding-prime-numbers 我写的这种筛选可能是一种全新的， for (i = 2, j = 2; l != 0; i = sieve[0])//sieve[0]  是质数     {         l = 0;         k = i * i;//从此数开始作标记           while (k <= n)         {             if (sieve[j] % i) sieve[l++] = sieve[j];//存储下一轮（FOR）循环的质数倍数，作%处理是防止下次（FOR）循环找到已标记过的数             prime[k] = 0;//非质数标记为0             k = i * sieve[++j];//下一个合数，直接找到要标记的非质数         }         j = 0;     }

引用 1 楼 paschen 的回复:想怎样优化，用memcpy？  从质数5开始 (sieve[j] % i)此段工作量少了2/3 所以数组初始化方式要更改， 数组想用下面的方式 prime数组{0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1....,0,0,0,1,0,1}   6n-1 6n+1 sieve数组{5,7,11,13,17,19},2424规则

想怎样优化，用memcpy？

引用 22 楼 lm_whales 的回复:看到了  rep     stosd 应该还是 以这个为主，还是很快的啊，当然需要4字节对齐，这个条件，比较容易满足  [quote=引用 20 楼 paschen 的回复:]   最快的办法就是查表。。。把得到的所有质数做成一个表，之后要多少以内的素数就直接查了。。  那是当然，什么计算都是多余的[/quote] 你们讲的太深了，作为刚学会for while的我，压力很大

for(i=0;i<=n;)     {         prime[i++] =0;         prime[i++] =1;     }     prime[1]=0,prime[2]=1;     int div = n/3+1;     for(i=0; i<=div;)     {         sieve[i]=3+i;         i++;         sieve[i]=4+i;         i++;     } N=1亿时只要0.95秒了

看到了  rep     stosd 应该还是 以这个为主，还是很快的啊，当然需要4字节对齐，这个条件，比较容易满足  引用 20 楼 paschen 的回复:最快的办法就是查表。。。把得到的所有质数做成一个表，之后要多少以内的素数就直接查了。。  那是当然，什么计算都是多余的

引用 18 楼 u013550545 的回复:[quote=引用 16 楼 lm_whales 的回复:] 坚持这么做的化，可以这么初始化  ///1）Fill 0 ,memset(isprime,0,size);  这个效率通常很高的，没有停顿的循环，不带额外的比较操作，无跳转，核心指令只有一条stosb，带 rep 前缀的指令 rep stosb  X86 串操作指令，是高效的数据传输指令。  2）6n-1 6n+1 for(i=5;i<n;i+=6) {        isprime[i]=1;     isprime[i+2]=1; }        page    ,132         title   memset - set sections of memory all to one byte ;*** ;memset.asm - set a section of memory to all one byte ; ;       Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ;       contains the memset() routine ; ;*******************************************************************************          .xlist         include cruntime.inc         .list  page ;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ;       Sets the first "count" bytes of the memory starting ;       at "dst" to the character value "value". ; ;       Algorithm: ;       char * ;       memset (dst, value, count) ;               char *dst; ;               char value; ;               unsigned int count; ;               { ;               char *start = dst; ; ;               while (count--) ;                       *dst++ = value; ;               return(start); ;               } ; ;Entry: ;       char *dst - pointer to memory to fill with value ;       char value - value to put in dst bytes ;       int count - number of bytes of dst to fill ; ;Exit: ;       returns dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************          CODESEG      extrn   _VEC_memzero:near     extrn   __sse2_available:dword          public  memset memset proc \         dst:ptr byte, \         value:byte, \         count:dword          OPTION PROLOGUE:NONE, EPILOGUE:NONE          .FPO    ( 0, 3, 0, 0, 0, 0 )          mov     edx,[esp + 0ch] ; edx = "count"         mov     ecx,[esp + 4]   ; ecx points to "dst"          test    edx,edx         ; 0?         jz      short toend     ; if so, nothing to do          xor     eax,eax         mov     al,[esp + 8]    ; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support     test    al,al ; memset using zero initializer?     jne     dword_align     cmp     edx,080h ; block size exceeds size threshold?     jb      dword_align     cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?     je      dword_align      jmp     _VEC_memzero ; use fast zero SSE2 implementation     ; no return  ; Align address on dword boundary dword_align:          push    edi             ; preserve edi         mov     edi,ecx         ; edi = dest pointer          cmp     edx,4           ; if it's less then 4 bytes         jb      tail            ; tail needs edi and edx to be initialized          neg     ecx         and     ecx,3           ; ecx = # bytes before dword boundary         jz      short dwords    ; jump if address already aligned          sub     edx,ecx         ; edx = adjusted count (for later) adjust_loop:         mov     [edi],al         add     edi,1         sub     ecx,1         jnz     adjust_loop  dwords: ; set all 4 bytes of eax to [value]         mov     ecx,eax         ; ecx=0/0/0/value         shl     eax,8           ; eax=0/0/value/0          add     eax,ecx         ; eax=0/0val/val          mov     ecx,eax         ; ecx=0/0/val/val          shl     eax,10h         ; eax=val/val/0/0          add     eax,ecx         ; eax = all 4 bytes = [value]  ; Set dword-sized blocks         mov     ecx,edx         ; move original count to ecx         and     edx,3           ; prepare in edx byte count (for tail loop)         shr     ecx,2           ; adjust ecx to be dword count         jz      tail            ; jump if it was less then 4 bytes          rep     stosd main_loop_tail:         test    edx,edx         ; if there is no tail bytes,         jz      finish          ; we finish, and it's time to leave ; Set remaining bytes  tail:         mov     [edi],al        ; set remaining bytes         add     edi,1          sub     edx,1           ; if there is some more bytes         jnz     tail            ; continue to fill them  ; Done finish:         mov     eax,[esp + 8]   ; return dest pointer         pop     edi             ; restore edi          ret  toend:         mov     eax,[esp + 4]   ; return dest pointer          ret  memset  endp          end[/quote]#include <stdio.h> #include <windows.h>  __declspec(naked) __int64 __cdecl GetCycle(void)  { 	__asm  	{ 		rdtsc  		ret  	} }  __declspec(naked) void EmuRepStosd(void* d, size_t n)  { 	//	esp + 4 d  	//	esp + 8 n 	__asm  	{ 		push edi  		xor	 eax, eax   		mov	 edi, [esp+4+4] 		mov	 ecx, [esp+8+4] 		cld  		rep  stosd  		pop	 edi   		ret  	} }  int main(int argc, CHAR* argv[]) { #define LOOPSW 20 #define NUMSW 0x50000 	__declspec(align(16)) static char arrays[NUMSW]; 	__int64 tInit, tMemset, tRepSto; 	int i; 	for (i=0;i<LOOPSW;i++) 	{ // cache ready ... 	ZeroMemory(&arrays[0], sizeof(arrays)); 	ZeroMemory(&arrays[0], sizeof(arrays)); 	ZeroMemory(&arrays[0], sizeof(arrays)); 	ZeroMemory(&arrays[0], sizeof(arrays)); // get Memset Ticks head addr align 16 	tInit=GetCycle(); 	ZeroMemory(&arrays[0], sizeof(arrays)/2); 	tMemset=GetCycle()-tInit; // get Rep OPR Ticks head addr 0xNNNNNNN1 (unaligned)  	tInit=GetCycle(); 	EmuRepStosd(&arrays[1],sizeof(arrays)/2/4/*DWORD NUMS*/); 	tRepSto=GetCycle()-tInit; 	printf("REP TIME:%I64d CRT TIME:%I64d\n",tRepSto,tMemset); 	} }

引用 19 楼 lm_whales 的回复:[quote=引用 18 楼 u013550545 的回复:] [quote=引用 16 楼 lm_whales 的回复:] 坚持这么做的化，可以这么初始化  ///1）Fill 0 ,memset(isprime,0,size);  这个效率通常很高的，没有停顿的循环，不带额外的比较操作，无跳转，核心指令只有一条stosb，带 rep 前缀的指令 rep stosb  X86 串操作指令，是高效的数据传输指令。  2）6n-1 6n+1 for(i=5;i<n;i+=6) {        isprime[i]=1;     isprime[i+2]=1; }        page    ,132         title   memset - set sections of memory all to one byte ;*** ;memset.asm - set a section of memory to all one byte ; ;       Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ;       contains the memset() routine ; ;*******************************************************************************          .xlist         include cruntime.inc         .list  page ;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ;       Sets the first "count" bytes of the memory starting ;       at "dst" to the character value "value". ; ;       Algorithm: ;       char * ;       memset (dst, value, count) ;               char *dst; ;               char value; ;               unsigned int count; ;               { ;               char *start = dst; ; ;               while (count--) ;                       *dst++ = value; ;               return(start); ;               } ; ;Entry: ;       char *dst - pointer to memory to fill with value ;       char value - value to put in dst bytes ;       int count - number of bytes of dst to fill ; ;Exit: ;       returns dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************          CODESEG      extrn   _VEC_memzero:near     extrn   __sse2_available:dword          public  memset memset proc \         dst:ptr byte, \         value:byte, \         count:dword          OPTION PROLOGUE:NONE, EPILOGUE:NONE          .FPO    ( 0, 3, 0, 0, 0, 0 )          mov     edx,[esp + 0ch] ; edx = "count"         mov     ecx,[esp + 4]   ; ecx points to "dst"          test    edx,edx         ; 0?         jz      short toend     ; if so, nothing to do          xor     eax,eax         mov     al,[esp + 8]    ; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support     test    al,al ; memset using zero initializer?     jne     dword_align     cmp     edx,080h ; block size exceeds size threshold?     jb      dword_align     cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?     je      dword_align      jmp     _VEC_memzero ; use fast zero SSE2 implementation     ; no return  ; Align address on dword boundary dword_align:          push    edi             ; preserve edi         mov     edi,ecx         ; edi = dest pointer          cmp     edx,4           ; if it's less then 4 bytes         jb      tail            ; tail needs edi and edx to be initialized          neg     ecx         and     ecx,3           ; ecx = # bytes before dword boundary         jz      short dwords    ; jump if address already aligned          sub     edx,ecx         ; edx = adjusted count (for later) adjust_loop:         mov     [edi],al         add     edi,1         sub     ecx,1         jnz     adjust_loop  dwords: ; set all 4 bytes of eax to [value]         mov     ecx,eax         ; ecx=0/0/0/value         shl     eax,8           ; eax=0/0/value/0          add     eax,ecx         ; eax=0/0val/val          mov     ecx,eax         ; ecx=0/0/val/val          shl     eax,10h         ; eax=val/val/0/0          add     eax,ecx         ; eax = all 4 bytes = [value]  ; Set dword-sized blocks         mov     ecx,edx         ; move original count to ecx         and     edx,3           ; prepare in edx byte count (for tail loop)         shr     ecx,2           ; adjust ecx to be dword count         jz      tail            ; jump if it was less then 4 bytes          rep     stosd main_loop_tail:         test    edx,edx         ; if there is no tail bytes,         jz      finish          ; we finish, and it's time to leave ; Set remaining bytes  tail:         mov     [edi],al        ; set remaining bytes         add     edi,1          sub     edx,1           ; if there is some more bytes         jnz     tail            ; continue to fill them  ; Done finish:         mov     eax,[esp + 8]   ; return dest pointer         pop     edi             ; restore edi          ret  toend:         mov     eax,[esp + 4]   ; return dest pointer          ret  memset  endp          end[/quote]  引用 18 楼 u013550545 的回复:[quote=引用 16 楼 lm_whales 的回复:] 坚持这么做的化，可以这么初始化  ///1）Fill 0 ,memset(isprime,0,size);  这个效率通常很高的，没有停顿的循环，不带额外的比较操作，无跳转，核心指令只有一条stosb，带 rep 前缀的指令 rep stosb  X86 串操作指令，是高效的数据传输指令。  2）6n-1 6n+1 for(i=5;i<n;i+=6) {        isprime[i]=1;     isprime[i+2]=1; }        page    ,132         title   memset - set sections of memory all to one byte ;*** ;memset.asm - set a section of memory to all one byte ; ;       Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ;       contains the memset() routine ; ;*******************************************************************************          .xlist         include cruntime.inc         .list  page ;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ;       Sets the first "count" bytes of the memory starting ;       at "dst" to the character value "value". ; ;       Algorithm: ;       char * ;       memset (dst, value, count) ;               char *dst; ;               char value; ;               unsigned int count; ;               { ;               char *start = dst; ; ;               while (count--) ;                       *dst++ = value; ;               return(start); ;               } ; ;Entry: ;       char *dst - pointer to memory to fill with value ;       char value - value to put in dst bytes ;       int count - number of bytes of dst to fill ; ;Exit: ;       returns dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************          CODESEG      extrn   _VEC_memzero:near     extrn   __sse2_available:dword          public  memset memset proc \         dst:ptr byte, \         value:byte, \         count:dword          OPTION PROLOGUE:NONE, EPILOGUE:NONE          .FPO    ( 0, 3, 0, 0, 0, 0 )          mov     edx,[esp + 0ch] ; edx = "count"         mov     ecx,[esp + 4]   ; ecx points to "dst"          test    edx,edx         ; 0?         jz      short toend     ; if so, nothing to do          xor     eax,eax         mov     al,[esp + 8]    ; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support     test    al,al ; memset using zero initializer?     jne     dword_align     cmp     edx,080h ; block size exceeds size threshold?     jb      dword_align     cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?     je      dword_align      jmp     _VEC_memzero ; use fast zero SSE2 implementation     ; no return  ; Align address on dword boundary dword_align:          push    edi             ; preserve edi         mov     edi,ecx         ; edi = dest pointer          cmp     edx,4           ; if it's less then 4 bytes         jb      tail            ; tail needs edi and edx to be initialized          neg     ecx         and     ecx,3           ; ecx = # bytes before dword boundary         jz      short dwords    ; jump if address already aligned          sub     edx,ecx         ; edx = adjusted count (for later) adjust_loop:         mov     [edi],al         add     edi,1         sub     ecx,1         jnz     adjust_loop  dwords: ; set all 4 bytes of eax to [value]         mov     ecx,eax         ; ecx=0/0/0/value         shl     eax,8           ; eax=0/0/value/0          add     eax,ecx         ; eax=0/0val/val          mov     ecx,eax         ; ecx=0/0/val/val          shl     eax,10h         ; eax=val/val/0/0          add     eax,ecx         ; eax = all 4 bytes = [value]  ; Set dword-sized blocks         mov     ecx,edx         ; move original count to ecx         and     edx,3           ; prepare in edx byte count (for tail loop)         shr     ecx,2           ; adjust ecx to be dword count         jz      tail            ; jump if it was less then 4 bytes          rep     stosd main_loop_tail:         test    edx,edx         ; if there is no tail bytes,         jz      finish          ; we finish, and it's time to leave ; Set remaining bytes  tail:         mov     [edi],al        ; set remaining bytes         add     edi,1          sub     edx,1           ; if there is some more bytes         jnz     tail            ; continue to fill them  ; Done finish:         mov     eax,[esp + 8]   ; return dest pointer         pop     edi             ; restore edi          ret  toend:         mov     eax,[esp + 4]   ; return dest pointer          ret  memset  endp          end[/quote] 这个比一条指令的快？还是 code：： block 自带的编译器比较本分? memset,memcpy,理论上应该是比循环快的 那可以用 memcpy 并采用增量复制的办法，看看效果如何[/quote]  最快的办法就是查表。。。把得到的所有质数做成一个表，之后要多少以内的素数就直接查了。。

引用 18 楼 u013550545 的回复:[quote=引用 16 楼 lm_whales 的回复:] 坚持这么做的化，可以这么初始化  ///1）Fill 0 ,memset(isprime,0,size);  这个效率通常很高的，没有停顿的循环，不带额外的比较操作，无跳转，核心指令只有一条stosb，带 rep 前缀的指令 rep stosb  X86 串操作指令，是高效的数据传输指令。  2）6n-1 6n+1 for(i=5;i<n;i+=6) {        isprime[i]=1;     isprime[i+2]=1; }        page    ,132         title   memset - set sections of memory all to one byte ;*** ;memset.asm - set a section of memory to all one byte ; ;       Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ;       contains the memset() routine ; ;*******************************************************************************          .xlist         include cruntime.inc         .list  page ;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ;       Sets the first "count" bytes of the memory starting ;       at "dst" to the character value "value". ; ;       Algorithm: ;       char * ;       memset (dst, value, count) ;               char *dst; ;               char value; ;               unsigned int count; ;               { ;               char *start = dst; ; ;               while (count--) ;                       *dst++ = value; ;               return(start); ;               } ; ;Entry: ;       char *dst - pointer to memory to fill with value ;       char value - value to put in dst bytes ;       int count - number of bytes of dst to fill ; ;Exit: ;       returns dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************          CODESEG      extrn   _VEC_memzero:near     extrn   __sse2_available:dword          public  memset memset proc \         dst:ptr byte, \         value:byte, \         count:dword          OPTION PROLOGUE:NONE, EPILOGUE:NONE          .FPO    ( 0, 3, 0, 0, 0, 0 )          mov     edx,[esp + 0ch] ; edx = "count"         mov     ecx,[esp + 4]   ; ecx points to "dst"          test    edx,edx         ; 0?         jz      short toend     ; if so, nothing to do          xor     eax,eax         mov     al,[esp + 8]    ; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support     test    al,al ; memset using zero initializer?     jne     dword_align     cmp     edx,080h ; block size exceeds size threshold?     jb      dword_align     cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?     je      dword_align      jmp     _VEC_memzero ; use fast zero SSE2 implementation     ; no return  ; Align address on dword boundary dword_align:          push    edi             ; preserve edi         mov     edi,ecx         ; edi = dest pointer          cmp     edx,4           ; if it's less then 4 bytes         jb      tail            ; tail needs edi and edx to be initialized          neg     ecx         and     ecx,3           ; ecx = # bytes before dword boundary         jz      short dwords    ; jump if address already aligned          sub     edx,ecx         ; edx = adjusted count (for later) adjust_loop:         mov     [edi],al         add     edi,1         sub     ecx,1         jnz     adjust_loop  dwords: ; set all 4 bytes of eax to [value]         mov     ecx,eax         ; ecx=0/0/0/value         shl     eax,8           ; eax=0/0/value/0          add     eax,ecx         ; eax=0/0val/val          mov     ecx,eax         ; ecx=0/0/val/val          shl     eax,10h         ; eax=val/val/0/0          add     eax,ecx         ; eax = all 4 bytes = [value]  ; Set dword-sized blocks         mov     ecx,edx         ; move original count to ecx         and     edx,3           ; prepare in edx byte count (for tail loop)         shr     ecx,2           ; adjust ecx to be dword count         jz      tail            ; jump if it was less then 4 bytes          rep     stosd main_loop_tail:         test    edx,edx         ; if there is no tail bytes,         jz      finish          ; we finish, and it's time to leave ; Set remaining bytes  tail:         mov     [edi],al        ; set remaining bytes         add     edi,1          sub     edx,1           ; if there is some more bytes         jnz     tail            ; continue to fill them  ; Done finish:         mov     eax,[esp + 8]   ; return dest pointer         pop     edi             ; restore edi          ret  toend:         mov     eax,[esp + 4]   ; return dest pointer          ret  memset  endp          end[/quote]  引用 18 楼 u013550545 的回复:[quote=引用 16 楼 lm_whales 的回复:] 坚持这么做的化，可以这么初始化  ///1）Fill 0 ,memset(isprime,0,size);  这个效率通常很高的，没有停顿的循环，不带额外的比较操作，无跳转，核心指令只有一条stosb，带 rep 前缀的指令 rep stosb  X86 串操作指令，是高效的数据传输指令。  2）6n-1 6n+1 for(i=5;i<n;i+=6) {        isprime[i]=1;     isprime[i+2]=1; }        page    ,132         title   memset - set sections of memory all to one byte ;*** ;memset.asm - set a section of memory to all one byte ; ;       Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ;       contains the memset() routine ; ;*******************************************************************************          .xlist         include cruntime.inc         .list  page ;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ;       Sets the first "count" bytes of the memory starting ;       at "dst" to the character value "value". ; ;       Algorithm: ;       char * ;       memset (dst, value, count) ;               char *dst; ;               char value; ;               unsigned int count; ;               { ;               char *start = dst; ; ;               while (count--) ;                       *dst++ = value; ;               return(start); ;               } ; ;Entry: ;       char *dst - pointer to memory to fill with value ;       char value - value to put in dst bytes ;       int count - number of bytes of dst to fill ; ;Exit: ;       returns dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************          CODESEG      extrn   _VEC_memzero:near     extrn   __sse2_available:dword          public  memset memset proc \         dst:ptr byte, \         value:byte, \         count:dword          OPTION PROLOGUE:NONE, EPILOGUE:NONE          .FPO    ( 0, 3, 0, 0, 0, 0 )          mov     edx,[esp + 0ch] ; edx = "count"         mov     ecx,[esp + 4]   ; ecx points to "dst"          test    edx,edx         ; 0?         jz      short toend     ; if so, nothing to do          xor     eax,eax         mov     al,[esp + 8]    ; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support     test    al,al ; memset using zero initializer?     jne     dword_align     cmp     edx,080h ; block size exceeds size threshold?     jb      dword_align     cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?     je      dword_align      jmp     _VEC_memzero ; use fast zero SSE2 implementation     ; no return  ; Align address on dword boundary dword_align:          push    edi             ; preserve edi         mov     edi,ecx         ; edi = dest pointer          cmp     edx,4           ; if it's less then 4 bytes         jb      tail            ; tail needs edi and edx to be initialized          neg     ecx         and     ecx,3           ; ecx = # bytes before dword boundary         jz      short dwords    ; jump if address already aligned          sub     edx,ecx         ; edx = adjusted count (for later) adjust_loop:         mov     [edi],al         add     edi,1         sub     ecx,1         jnz     adjust_loop  dwords: ; set all 4 bytes of eax to [value]         mov     ecx,eax         ; ecx=0/0/0/value         shl     eax,8           ; eax=0/0/value/0          add     eax,ecx         ; eax=0/0val/val          mov     ecx,eax         ; ecx=0/0/val/val          shl     eax,10h         ; eax=val/val/0/0          add     eax,ecx         ; eax = all 4 bytes = [value]  ; Set dword-sized blocks         mov     ecx,edx         ; move original count to ecx         and     edx,3           ; prepare in edx byte count (for tail loop)         shr     ecx,2           ; adjust ecx to be dword count         jz      tail            ; jump if it was less then 4 bytes          rep     stosd main_loop_tail:         test    edx,edx         ; if there is no tail bytes,         jz      finish          ; we finish, and it's time to leave ; Set remaining bytes  tail:         mov     [edi],al        ; set remaining bytes         add     edi,1          sub     edx,1           ; if there is some more bytes         jnz     tail            ; continue to fill them  ; Done finish:         mov     eax,[esp + 8]   ; return dest pointer         pop     edi             ; restore edi          ret  toend:         mov     eax,[esp + 4]   ; return dest pointer          ret  memset  endp          end[/quote] 这个比一条指令的快？还是 code：： block 自带的编译器比较本分? memset,memcpy,理论上应该是比循环快的 那可以用 memcpy 并采用增量复制的办法，看看效果如何

引用 16 楼 lm_whales 的回复:坚持这么做的化，可以这么初始化  ///1）Fill 0 ,memset(isprime,0,size);  这个效率通常很高的，没有停顿的循环，不带额外的比较操作，无跳转，核心指令只有一条stosb，带 rep 前缀的指令 rep stosb  X86 串操作指令，是高效的数据传输指令。  2）6n-1 6n+1 for(i=5;i<n;i+=6) {        isprime[i]=1;     isprime[i+2]=1; }        page    ,132         title   memset - set sections of memory all to one byte ;*** ;memset.asm - set a section of memory to all one byte ; ;       Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ;       contains the memset() routine ; ;*******************************************************************************          .xlist         include cruntime.inc         .list  page ;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ;       Sets the first "count" bytes of the memory starting ;       at "dst" to the character value "value". ; ;       Algorithm: ;       char * ;       memset (dst, value, count) ;               char *dst; ;               char value; ;               unsigned int count; ;               { ;               char *start = dst; ; ;               while (count--) ;                       *dst++ = value; ;               return(start); ;               } ; ;Entry: ;       char *dst - pointer to memory to fill with value ;       char value - value to put in dst bytes ;       int count - number of bytes of dst to fill ; ;Exit: ;       returns dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************          CODESEG      extrn   _VEC_memzero:near     extrn   __sse2_available:dword          public  memset memset proc \         dst:ptr byte, \         value:byte, \         count:dword          OPTION PROLOGUE:NONE, EPILOGUE:NONE          .FPO    ( 0, 3, 0, 0, 0, 0 )          mov     edx,[esp + 0ch] ; edx = "count"         mov     ecx,[esp + 4]   ; ecx points to "dst"          test    edx,edx         ; 0?         jz      short toend     ; if so, nothing to do          xor     eax,eax         mov     al,[esp + 8]    ; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support     test    al,al ; memset using zero initializer?     jne     dword_align     cmp     edx,080h ; block size exceeds size threshold?     jb      dword_align     cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?     je      dword_align      jmp     _VEC_memzero ; use fast zero SSE2 implementation     ; no return  ; Align address on dword boundary dword_align:          push    edi             ; preserve edi         mov     edi,ecx         ; edi = dest pointer          cmp     edx,4           ; if it's less then 4 bytes         jb      tail            ; tail needs edi and edx to be initialized          neg     ecx         and     ecx,3           ; ecx = # bytes before dword boundary         jz      short dwords    ; jump if address already aligned          sub     edx,ecx         ; edx = adjusted count (for later) adjust_loop:         mov     [edi],al         add     edi,1         sub     ecx,1         jnz     adjust_loop  dwords: ; set all 4 bytes of eax to [value]         mov     ecx,eax         ; ecx=0/0/0/value         shl     eax,8           ; eax=0/0/value/0          add     eax,ecx         ; eax=0/0val/val          mov     ecx,eax         ; ecx=0/0/val/val          shl     eax,10h         ; eax=val/val/0/0          add     eax,ecx         ; eax = all 4 bytes = [value]  ; Set dword-sized blocks         mov     ecx,edx         ; move original count to ecx         and     edx,3           ; prepare in edx byte count (for tail loop)         shr     ecx,2           ; adjust ecx to be dword count         jz      tail            ; jump if it was less then 4 bytes          rep     stosd main_loop_tail:         test    edx,edx         ; if there is no tail bytes,         jz      finish          ; we finish, and it's time to leave ; Set remaining bytes  tail:         mov     [edi],al        ; set remaining bytes         add     edi,1          sub     edx,1           ; if there is some more bytes         jnz     tail            ; continue to fill them  ; Done finish:         mov     eax,[esp + 8]   ; return dest pointer         pop     edi             ; restore edi          ret  toend:         mov     eax,[esp + 4]   ; return dest pointer          ret  memset  endp          end

引用 16 楼 lm_whales 的回复:坚持这么做的化，可以这么初始化  ///1）Fill 0 ,memset(isprime,0,size);  这个效率通常很高的，没有停顿的循环，不带额外的比较操作，无跳转，核心指令只有一条stosb，带 rep 前缀的指令 rep stosb  X86 串操作指令，是高效的数据传输指令。  2）6n-1 6n+1 for(i=5;i<n;i+=6) {        isprime[i]=1;     isprime[i+2]=1; }串操作在数据不对其的情况下效率是成倍降得。对齐情况下是SIMD指令的速度，反之连mov都不如

引用 13 楼 lm_whales 的回复:筛法最重要的是不用除法，用了除法， 就没多少必要去筛了，除非算法非常高明 刚才代码有BUG 看看下面的int creat_prime(int prime[], int sieve[], int n) { 	register int i, j, k, l;  	for (i = 0; i < n + 1; i++) 	{ 		prime[i]=sieve[i] = i; 	}  	l = 1; 	for (i = 2, j = 2; l != 0; i = sieve[1]) 	{ 		l = 0; 		k = i * i;//从此数开始作标记  		while (k <= n) 		{ 			//if (sieve[j] % i) sieve[l++] = sieve[j];//存储下一轮（FOR）循环的质数倍数 			if  (prime[k]) sieve[l++] = sieve[j]; 			prime[k] = 0;//非质数标记为0 			k = i * sieve[++j];//下一个合数 		} 		j = 0; 	} 	//for (i = 2; i <= n; i++)  if (prime[i]) printf("%d ", i); 	return 0; } 这个是不用除法的，N=1亿时用时1.39秒，比原代码慢了一点。

引用 13 楼 lm_whales 的回复:筛法最重要的是不用除法，用了除法， 就没多少必要去筛了，除非算法非常高明 /* 初始化数组 prime{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20......n} sieve{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20......n} 第一次删除2倍数得到数组 prime{0,1,0,3,0,5,0,7,0,9,0,11,0,13,0,15,0,17,0,19,0......n} 2的倍数是{4，6，8，10......}/2---->{2,3,4,5......}---->取模---->sieve{3,5,7,11,13,17,19,......n} 下一次删除的就是sieve[0]的倍数，刚好它要删除的倍数都在sieve数组里。同样得到新的sieve数组 进行下一次计算。 算法是每个非质数只删除一次  下一步再做优化 prime数组{0,0,1,1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,1....,0,0,0,1,0,1}   6n-1 6n+1 sieve数组{5,7,11,13,17,19},2424规则 从质数5开始 (sieve[j] % i)此段工作量少了2/3 */ int creat_prime(int prime[], int sieve[], int n) { 	register int i, j, k, l;  	for (i = 0; i < n + 1; i++) 	{ 		prime[i]=sieve[i] = i; 	}  	l = 1; 	for (i = 2, j = 2; l != 0; i = sieve[0]) 	{ 		l = 0; 		k = i * i;//从此数开始作标记  		while (k <= n) 		{ 			//if (sieve[j] % i) sieve[l++] = sieve[j];//存储下一轮（FOR）循环的质数倍数 			if  (prime[k]) sieve[l++] = sieve[j]; 			prime[k] = 0;//非质数标记为0 			k = i * sieve[++j];//下一个合数 		} 		j = 0; 	} 	//for (i = 2; i <= n; i++)  if (prime[i]) printf("%d ", i); 	return 0; } 这个是不用除法的，N=1亿时用时0.774 用除法的，N=1亿时用时1.18 随然循环执行次数增加，但时间减少不少

筛法最重要的是不用除法，用了除法， 就没多少必要去筛了，除非算法非常高明

直接筛奇数就可以了，直接省去1/2 3的倍数不好指定，所以就不必处理了 多个1/3 没关系不然直接写到文件里，并且写成C语言数组形式好了 当然，你也可以把 N内的素数全部写成 数组 然后编译，直接搞定


Question: 学习日记四：现在忽然对链表的插入删除糊涂了，形参有没有真实改变实参

无头结点链表，删空的时候，就不好处理了，还是返回头结点比较实在

1)无额外头结点的链表， 当需要删除头结点的时候，必须更换头结点。 当插入在头结点前面时，也必须更换头结点。    一个变通方案是： 删除时候，把头结点的next节点数据交给头结点，并删除头结点的next，代替删除头结点 步骤如下： 1.1）把头结点的next 节点数据，复制到头节点， 1.2）然后next节点脱链，并保持链的完整。 1.3）删除头结点的 next节点 如此，可以不更换头结点。 插入类似，新插入的节点，初始化为头结点的数据， 头结点的数据改成新插入的数据，如此也可以不更换头结点。 不过，对于 每个数据都比较大的链表，效率就变差了  2}对于，有额外头结点的链表，插入删除，不会影响到头节点，可以不返回头结点，可以直接传递链表头结点。

插入或者删除头结点的时候就需要返回 head 了。

仅供参考：//不带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> #include <locale.h> struct NODE {     int          data;     struct NODE *next; } *head,*p,*q,*s,*p1,*p2,*q1,**ta; int i,k,n,t,m,v,N=10; int main() {     setlocale(LC_ALL,"chs");     srand(time(NULL));      head=NULL;      printf("创建%d个节点的单链表:",N);//创建N个节点的单链表     p=head;     for (i=0;i<N;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) exit(1);         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         if (NULL==p) {             head=q;             p=head;         } else {             p->next=q;             p=q;         }     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=3;     v=5;     printf("将值为%d的结点插入到单链表的第%d个结点前:",v,k);//将值为v的结点插入到单链表的第k个结点前     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) exit(1);             q->data=5;             q->next=head;             head=q;             break;         } else {             if (k-1==n) {                 q=(struct NODE *)malloc(sizeof(struct NODE));                 if (NULL==q) exit(1);                 q->data=5;                 q->next=p->next;                 p->next=q;                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      k=5;     printf("删除第%d个节点:",k);//删除第k个节点     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==1) {             q=head;             head=head->next;             free(q);             break;         } else {             if (k-1==n) {                 q=p->next;                 if (q) {                     p->next=q->next;                     free(q);                 }                 break;             }         }         p=p->next;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      printf("从小到大排序:");//从小到大排序     for (p=head,p1=NULL;p!=NULL;p1=p,p=p->next) {         for (q=p->next,q1=p;q!=NULL;q1=q,q=q->next) {             if (p->data > q->data) {                  //交换data //              printf("swap %02d %02d\n",p->data,q->data); //              t=p->data;p->data=q->data;q->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->data,q->data);                 if (p==head) {//p是头                     if (p->next==q) {//pq挨着                         head=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=head;                     } else {//pq不挨着                         head=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=head;                     }                 } else {//p不是头                     if (p->next==q) {//pq挨着                         p1->next=q;                         p->next=q->next;                         q->next=p;                         q=p;                         p=p1->next;                     } else {//pq不挨着                         p1->next=q;                         p2=p->next;                         p->next=q->next;                         q->next=p2;                         q1->next=p;                         q=p;                         p=p1->next;                     }                 }                  //输出整个单链表 //              s=head; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表并计算链表长度n     n=0;     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         n++;         s=s->next;     }      printf("将整个链表逆序:");//将整个链表逆序     if (n>=2) {         p=head;         q=p->next;         p->next=NULL;         while (1) {             q1=q->next;             q->next=p;             p=q;             q=q1;             if (NULL==q) break;         }         head=p;     }      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      m=4;     n=6;     printf("将单链表中前%d个结点和后%d个结点进行互换:",m,n);//将单链表中前m个结点和后n个结点进行互换,m+n为链表总长     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m==k) {             q=p;         }         s=p;         p=p->next;     }     q1=head;     head=q->next;     s->next=q1;     q->next=NULL;      //输出整个单链表     s=head;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //创建10个节点的单链表:08->74->07->23->03->99->31->56->88->16-> //将值为5的结点插入到单链表的第3个结点前:08->74->05->07->23->03->99->31->56->88->16-> //删除第5个节点:08->74->05->07->03->99->31->56->88->16-> //从小到大排序:03->05->07->08->16->31->56->74->88->99-> //将整个链表逆序:99->88->74->56->31->16->08->07->05->03-> //将单链表中前4个结点和后6个结点进行互换:31->16->08->07->05->03->99->88->74->56-> //


Question: 向大牛们求助，如何将openHEVC和libde这两个HEVC decoder的源程序文件编译成可运行的格式

有没有人来帮忙看看啊


Question: gcc 编译 utf16 编译不通过！跪求解决方法？？

引用 1 楼 user-1 的回复:1) u"" 的类型是 char16_t []   2) g++ 4.9.2 可以识别。  请给出你使用完整的程序，编译器及版本，完整的编译命令行及输出。   编译命令：   g++ -std=c++0x templ.cpp  已经通过。谢谢！

引用 1 楼 user-1 的回复:1) u"" 的类型是 char16_t []   2) g++ 4.9.2 可以识别。  请给出你使用完整的程序，编译器及版本，完整的编译命令行及输出。  请问g++ 如何升级？

引用 1 楼 user-1 的回复:1) u"" 的类型是 char16_t []   2) g++ 4.9.2 可以识别。  请给出你使用完整的程序，编译器及版本，完整的编译命令行及输出。  多谢，多谢。  代码：  #include <uchar.h> int main(void) {         const char16_t *s=u"abcdefg";         return 0; }   编译命令行   g++ templ.cpp   编译器输出  templ.cpp:1:19: fatal error: uchar.h: No such file or directory compilation terminated.   g++版本： #g++ --version g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 Copyright (C) 2011 Free Software Foundation, Inc. This is free software; see the source for copying conditions.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Question: 二维数组用一维数组表示输出的为什么是地址？

当成地址看就好了，本身也是地址而已

二维数组分为行和列；i[1]表示的就是指第二行的首地址，即也是第二行第一列的首地址；当然在内存里存放的都是线性的，第一行和第二行都是串行保存在内存里的；为了便于理解二维数组，你可以理解成行和列，平面存储的；

#include <stdio.h> void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             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]:'.');             }             printf("%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]:'.');         }         printf("%s\n",binstr);     } } int main() {     int i[2][2]={{1,2},{3,4}};     HexDump((char *)&(i[0][0]),4*sizeof(int),(int)&(i[0][0]));     return 0; } //0012ff60 - 01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00  ................ //

其实C/C++中的二维数组就不是真正意义上的二维数组，而是一维数组的一维数组   假如 int arr[2][3][4]，则最左侕的int arr[2] 为第一层包内数据，下标2说明第一层包内有2个int[3][4]类型的小包；打开下一个小包，里面是int[4]，再打开下一个，里面是int  所以如果你只是写arr[0]那么得到的只是下一个包（是个数组），数组名可转换为指针，指向数组首地址，固输出的是地址

int i[2][2]; i    数组的数组 i[1] 数组 printf("...", i[1]);  数组，自动转化为指向数组第一个元素的指针 &i[1]  指向数组（i[1] ）的指针。  数组与数组的第一个元素拥有相同的地址。

书上应该会告诉你，二维数组第一维是指针吧 http://blog.csdn.net/u010518261/article/details/43016765 博客上看看，


Question: 整理笔记心得1

写得多，错得多 错得多，学得多


Question: 简易的关机小程序

怎么不能运行呀

//以上版本在vs中不能运行，原因是vs中很多带“_s”后缀的函数是为了让原版函数更安全，传入一个和参数有关的大小值，避免引用到不存在的元素,防止越界。 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include <conio.h> using namespace std; void output() { 	printf("   ********************************\n"); 	printf("   *           关机小程序         *\n"); 	printf("   *                              *\n"); 	printf("   *   1.定时关机    2.取消关机   *\n"); 	printf("   *                              *\n"); 	printf("   *   3.立即关机    4.重启本机   *\n"); 	printf("   *                              *\n"); 	printf("   *   5.注销用户    0.退出程序   *\n"); 	printf("   *                         ydw  *\n"); 	printf("   ********************************\n"); } int main() { 	system("title 关机小程序");//设置cmd窗口标题 	system("mode con cols=38 lines=17");//窗口宽度高度 	system("color 0E");//设置颜色 	system("date /T");//时间 	system("TIME /T"); 	char cmd[20]= "shutdown -s -t "; 	char  t[10] = ""; 	output(); 	char c; 	int s; 	printf("请选择输入："); 	c = _getche(); 	//scanf("%d",&c); 	//getchar(); 	switch (c) 	{ 	case '1': 		printf("\n多少分钟后自动关机(输入后按回车):"); 		scanf_s("%d", &s); 		s = s * 60; 		sprintf_s(t, "%d", s);//将int 型的s 转为字符串型的 t 		strcat_s(cmd, 20, t);//拼接两个个字符串 		system(cmd); 		break; 	case '2':system("shutdown -a"); break; 	case '3':system("shutdown -s -t 0"); break;//system("shutdown -p"); 	case '4':system("shutdown -r"); break; 	case '5':system("shutdown -l"); break; 	case '0':break; 	default:printf("Error!\n"); 	} 	//system("pause"); 	//exit(0); 	return 0; }

不错不错，学习了，谢谢楼主

直接批处理更直接

用批处理更直接

可以自己做个界面，不用控制台语句而是使用API 另外重启应该改为system("shutdown -r -t 0");

其实就是个控制台语句………

不错不错~~！


Question: 怎么计算出各segment的虚拟地址

引用 4 楼 lm_whales 的回复:为什么要等于？  段与段之间不是应该相邻吗？我测试的时候相差0x1209，计算式算上连接处的两次映射和地址对齐也不应该相差这么多。 那段之间的部分应该是什么内容呢？

为什么要等于？

引用 6 楼 zhao4zhong1 的回复:Linux下ELF的装载和Windows下PE的装载没有本质区别，我觉得。  PE的装载不怎么熟悉，请问是怎么得到各segment的地址的呢？

Linux下ELF的装载和Windows下PE的装载没有本质区别，我觉得。

追加： 为什么segment table中第一行中的segment的地址加上segment大小不等于第二条segment的初始地址？

引用 1 楼 zhao4zhong1 的回复:参考《Windows PE权威指南》？ 现在主要是学习ELF的装载，没怎么注意PE的部分

参考《Windows PE权威指南》？


Question: 求一个实验的C语言

照着汇编用C语言改啊

主程序花点时间倒是可以转出来,但 引用EXTRN	CODE(PCF8563_INIT,Write,Read,Read_Sequence,Time_Write,Time_Read,Alarm_Read,Alarm_Stop,Sec_Read) EXTRN	CODE(LCD_INIT, Disp_LineR)这些外部函数怎么办?  还有,把单片机的问题发到这个版块合适吗?

这个网上应该有类似的资源的，你给100分估计没也没人愿意给你写的，这可不是一时半会能写好的，我建议你自己在网上搜一下吧

= =大学时也做过这种题目。略怀念。。