Question: 约瑟夫问题中一个很奇怪的问题！！！跪求看下我代码哪里错了！

引用 1 楼 paschen的回复:你直接看着代码想当然想不通了，为何不单步跟踪程序执行！ 单点调试，287要调到什么时候?？？我不是没试

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

你直接看着代码想当然想不通了，为何不单步跟踪程序执行！

引用 4 楼 醉花阴柳的回复:gdb输入b if L->val==287 我已经弄出来了，不要gdb什么的，每次打印出被删元素的前面和后面一个元素，就可以看出来哪里错了

gdb输入b if L->val==287


Question: C语言字符串长度

C++ Character Constants Character constants are one or more members of the “source character set,” the character set in which a program is written, surrounded by single quotation marks ('). They are used to represent characters in the “execution character set,” the character set on the machine where the program executes.  Microsoft Specific   For Microsoft C++, the source and execution character sets are both ASCII.  END Microsoft Specific  There are three kinds of character constants:   Normal character constants   Multicharacter constants   Wide-character constants  Note   Use wide-character constants in place of multicharacter constants to ensure portability.  Character constants are specified as one or more characters enclosed in single quotation marks. For example:  char ch = 'x';          // Specify normal character constant. int mbch = 'ab';        // Specify system-dependent                         //  multicharacter constant. wchar_t wcch = L'ab';   // Specify wide-character constant.  Note that mbch is of type int. If it were declared as type char, the second byte would not be retained. A multicharacter constant has four meaningful characters; specifying more than four generates an error message.  Syntax  character-constant :  'c-char-sequence' L'c-char-sequence'  c-char-sequence :  c-char c-char-sequence c-char  c-char :  any member of the source character set except the single quotation mark ('), backslash (\), or newline character escape-sequence  escape-sequence :  simple-escape-sequence octal-escape-sequence hexadecimal-escape-sequence  simple-escape-sequence : one of  \' \" \? \\ \a \b \f \n \r \t \v  octal-escape-sequence :  \octal-digit \octal-digit octal-digit \octal-digit octal-digit octal-digit  hexadecimal-escape-sequence :  \xhexadecimal-digit hexadecimal-escape-sequence hexadecimal-digit  Microsoft C++ supports normal, multicharacter, and wide-character constants. Use wide-character constants to specify members of the extended execution character set (for example, to support an international application). Normal character constants have type char, multicharacter constants have type int, and wide-character constants have type wchar_t. (The type wchar_t is defined in the standard include files STDDEF.H, STDLIB.H, and STRING.H. The wide-character functions, however, are prototyped only in STDLIB.H.)  The only difference in specification between normal and wide-character constants is that wide-character constants are preceded by the letter L. For example:  char schar = 'x';               // Normal character constant wchar_t wchar = L'\x81\x19';    // Wide-character constant  Table 1.2 shows reserved or nongraphic characters that are system dependent or not allowed within character constants. These characters should be represented with escape sequences.  Table 1.2   C++ Reserved or Nongraphic Characters  Character ASCII  Representation ASCII  Value Escape Sequence  Newline NL (LF) 10 or 0x0a \n  Horizontal tab HT 9 \t  Vertical tab VT 11 or 0x0b \v  Backspace BS 8 \b  Carriage return CR 13 or 0x0d \r  Formfeed FF 12 or 0x0c \f  Alert BEL 7 \a  Backslash \ 92 or 0x5c \\  Question mark ? 63 or 0x3f \?  Single quotation mark ' 39 or 0x27 \'  Double quotation mark " 34 or 0x22 \"  Octal number ooo — \ooo  Hexadecimal number hhh — \xhhh  Null character NUL 0 \0    If the character following the backslash does not specify a legal escape sequence, the result is implementation defined. In Microsoft C++, the character following the backslash is taken literally, as though the escape were not present, and a level 1 warning (“unrecognized character escape sequence”) is issued.  Octal escape sequences, specified in the form \ooo, consist of a backslash and one, two, or three octal characters. Hexadecimal escape sequences, specified in the form \xhhh, consist of the characters \x followed by a sequence of hexadecimal digits. Unlike octal escape constants, there is no limit on the number of hexadecimal digits in an escape sequence.  Octal escape sequences are terminated by the first character that is not an octal digit, or when three characters are seen. For example:  wchar_t och = L'\076a';  // Sequence terminates at a char    ch = '\233';     // Sequence terminates after 3 characters  Similarly, hexadecimal escape sequences terminate at the first character that is not a hexadecimal digit. Because hexadecimal digits include the letters a through f (and A through F), make sure the escape sequence terminates at the intended digit.  Because the single quotation mark (') encloses character constants, use the escape sequence \' to represent enclosed single quotation marks. The double quotation mark (") can be represented without an escape sequence. The backslash character (\) is a line-continuation character when placed at the end of a line. If you want a backslash character to appear within a character constant, you must type two backslashes in a row (\\). (SeePhases of Translation in the Preprocessor Reference for more information about line continuation.)

引用 7 楼 clarkchenhot 的回复:[quote=引用 5 楼 fefe82 的回复:] [quote=引用 楼主 clarkchenhot 的回复:]  #include<stdio.h> void main() {      int length;      char a[] = "\\\065a,\n";      length = strlen(a);      printf("%d\n",length); }  如上：a 的长度为啥是5？ 还有一个问题，C中是不是没有字符串这个类型。所谓的字符串末尾有个’\0‘是指的C++？ C 没有，C++ 也没有“字符串”这个类型。（但是 C++ 有 std::string，这个跟 "abcdef" 不是一回事）  “字符串末尾有个’\0‘” 同样适用与 C 与 C++ 。这个可以被称作“以零结尾的字符串” "abcdef" 在 C 与 C++ 里都称作 string literal ，类型都是 char[] (字符数组，长度由字符串长度决定，包括最后的 '\0'，"abcdef" 的类型是 char[7]），最后都会自动补充一个 '\0' 。  strxxx 系列的函数，会接受一个 (const) char * 输入，并已 '\0' 作为字符串的结束。  以零为结束的字符串内部，不能包含 '\0' 。  std::string 不是以零未结束的字符串。std::string 内部可以包含 '\0' 。[/quote] 您好，有几个问题 1、以0结尾的字符串，‘0’字符是字符0的ASCII码不是00000000，为何不能包括‘\0’。我理解的是字符数组在内存中存的末尾都有一个'\0‘作为结束。 2、我这个字符数组在内存中存储的时候最后是不是有个'\0'。但是strlen()函数不包括’\0‘所占的1B的空间？[/quote] 1. 因为遇到 '\0' 字符串就结束了，其后内容不会被认为是字符串的一部分。所以’\0' 不能出现在以零为止的字符串的内部。     同时 '\0' 本身也不是字符串的一部分（只是一个结束符号）。所以以零为止的字符串实际不能包含 '\0' 。 2. 最后会有一个 '\0'。但是由于它并不是以零为止的字符串的一部分，所以 strlen 得到的长度是不包括这个 '\0' 的。

引用 7 楼 clarkchenhot 的回复:[quote=引用 5 楼 fefe82 的回复:] [quote=引用 楼主 clarkchenhot 的回复:]  #include<stdio.h> void main() {      int length;      char a[] = "\\\065a,\n";      length = strlen(a);      printf("%d\n",length); }  如上：a 的长度为啥是5？ 还有一个问题，C中是不是没有字符串这个类型。所谓的字符串末尾有个’\0‘是指的C++？ C 没有，C++ 也没有“字符串”这个类型。（但是 C++ 有 std::string，这个跟 "abcdef" 不是一回事）  “字符串末尾有个’\0‘” 同样适用与 C 与 C++ 。这个可以被称作“以零结尾的字符串” "abcdef" 在 C 与 C++ 里都称作 string literal ，类型都是 char[] (字符数组，长度由字符串长度决定，包括最后的 '\0'，"abcdef" 的类型是 char[7]），最后都会自动补充一个 '\0' 。  strxxx 系列的函数，会接受一个 (const) char * 输入，并已 '\0' 作为字符串的结束。  以零为结束的字符串内部，不能包含 '\0' 。  std::string 不是以零未结束的字符串。std::string 内部可以包含 '\0' 。[/quote] 您好，有几个问题 1、以0结尾的字符串，‘0’字符是字符0的ASCII码不是00000000，为何不能包括‘\0’。我理解的是字符数组在内存中存的末尾都有一个'\0‘作为结束。 2、我这个字符数组在内存中存储的时候最后是不是有个'\0'。但是strlen()函数不包括’\0‘所占的1B的空间？[/quote]  1、‘\0’与'0'是两码事 2、是的，strlen的说明参看：http://en.cppreference.com/w/c/string/byte/strlen

引用 5 楼 fefe82 的回复:[quote=引用 楼主 clarkchenhot 的回复:]  #include<stdio.h> void main() {      int length;      char a[] = "\\\065a,\n";      length = strlen(a);      printf("%d\n",length); }  如上：a 的长度为啥是5？ 还有一个问题，C中是不是没有字符串这个类型。所谓的字符串末尾有个’\0‘是指的C++？ C 没有，C++ 也没有“字符串”这个类型。（但是 C++ 有 std::string，这个跟 "abcdef" 不是一回事）  “字符串末尾有个’\0‘” 同样适用与 C 与 C++ 。这个可以被称作“以零结尾的字符串” "abcdef" 在 C 与 C++ 里都称作 string literal ，类型都是 char[] (字符数组，长度由字符串长度决定，包括最后的 '\0'，"abcdef" 的类型是 char[7]），最后都会自动补充一个 '\0' 。  strxxx 系列的函数，会接受一个 (const) char * 输入，并已 '\0' 作为字符串的结束。  以零为结束的字符串内部，不能包含 '\0' 。  std::string 不是以零未结束的字符串。std::string 内部可以包含 '\0' 。[/quote] 您好，有几个问题 1、以0结尾的字符串，‘0’字符是字符0的ASCII码不是00000000，为何不能包括‘\0’。我理解的是字符数组在内存中存的末尾都有一个'\0‘作为结束。 2、我这个字符数组在内存中存储的时候最后是不是有个'\0'。但是strlen()函数不包括’\0‘所占的1B的空间？

黑底字符 \\ 实际只表示 \ ，只算一个字符，同理其他  字符串不能作为一种类型，他只是一个以0结尾的字符数组

引用 楼主 clarkchenhot 的回复: #include<stdio.h> void main() {      int length;      char a[] = "\\\065a,\n";      length = strlen(a);      printf("%d\n",length); }  如上：a 的长度为啥是5？ 还有一个问题，C中是不是没有字符串这个类型。所谓的字符串末尾有个’\0‘是指的C++？ C 没有，C++ 也没有“字符串”这个类型。（但是 C++ 有 std::string，这个跟 "abcdef" 不是一回事）  “字符串末尾有个’\0‘” 同样适用与 C 与 C++ 。这个可以被称作“以零结尾的字符串” "abcdef" 在 C 与 C++ 里都称作 string literal ，类型都是 char[] (字符数组，长度由字符串长度决定，包括最后的 '\0'，"abcdef" 的类型是 char[7]），最后都会自动补充一个 '\0' 。  strxxx 系列的函数，会接受一个 (const) char * 输入，并已 '\0' 作为字符串的结束。  以零为结束的字符串内部，不能包含 '\0' 。  std::string 不是以零未结束的字符串。std::string 内部可以包含 '\0' 。

引用 3 楼 clarkchenhot 的回复:[quote=引用 1 楼 qq423399099 的回复:] 分析下："\\\065a,\n" 第一个字符\\,第一个\表示转义，第二个\代表该字符 第二个字符\065,八进制表达（有点凑巧啊） 第三个字符a 第四个字符, 第五个字符\n 所以答案是5 如果LZ把"\\\065a,\n"改为"\\\0a65a,\n"使\065不能组成一个特殊转义字符，那么strlen结果将是1 哦，明白了，如果改为"\\\8065a,\n"其中的第三个\就无意义了吧，strlen结果是8，编译器是这么个意思吧？[/quote] 对的

引用 1 楼 qq423399099 的回复:分析下："\\\065a,\n" 第一个字符\\,第一个\表示转义，第二个\代表该字符 第二个字符\065,八进制表达（有点凑巧啊） 第三个字符a 第四个字符, 第五个字符\n 所以答案是5 如果LZ把"\\\065a,\n"改为"\\\0a65a,\n"使\065不能组成一个特殊转义字符，那么strlen结果将是1 哦，明白了，如果改为"\\\8065a,\n"其中的第三个\就无意义了吧，strlen结果是8，编译器是这么个意思吧？

C语言中所谓的字符串实际上是字符数组。C风格字符串通常是指以'\0'字符为结尾的字符数组，所以一边表示一个字符串可以给出首字符的地址（指针），然后以遇到结束符为止

printf(”%s”，a)就知道了


Question: 新手刚学C，对于指针有点问题求大神解答

*a就是b,字数补丁

情况1里，b赋值为0之后。即指针a所指向的内存区域的元素值为0了。即*a==0。所以，b=*a即b=0。

来人啊


Question: 头文件定义结构体，fatal error LNK1169: 找到一个或多个多重定义的符号

7# 就行了.

引用 8 楼 qq423399099 的回复:[quote=引用 6 楼 u012911202 的回复:] [quote=引用 1 楼 qq423399099 的回复:] LZ的这个错误是典型的链接错误，#ifndef 加在头文件重是为了保证类的头文件在一个.cpp文件中被多次引用后会不会出现重复定义的问题,注意,只是防止在一个.cpp文件中被多次引用 如果是C++，可以对头文件的函数定义加inline或者static表明函数是在线或者静态的，这样编译器就可以自行解决重复定义的问题。 如果是C，则只能通过头文件函数定义加static来表明函数为静态，这样连接器不会报错。 正确的做法应该是只在头文件中声明，而真正的定义放到源文件中，这样不管哪个源文件包含了头文件，都不会有问题，因为定义的地方只有一个，链接的时候会找到的。谢谢师兄回复，有问题想继续请教：  问题1，头文件中只声明不定义，学习过这点。师兄强调的：#ifndef只是防止在一个.cpp中被多次引用，不是很明白。拿main.cpp来说，我在里面不同位置写了两次#include "stuscore.h"，#ifndef的作用就显出来了？可以这理解不？  问题2，C++加inline或static，C加static，针对我这个具体工程，适用吗？需要的话，具体加在哪个位置？  [/quote] 第一个可以这么理解 第二个的话，感觉并不不太适用，全局静态的只能在一个文件里用，其他文件访问不到，就算名字相同也是不同的变量[/quote]

引用 5 楼 u012911202 的回复:[quote=引用 3 楼 github_27756899 的回复:] stuscore.h：  struct student_score {     char name[10];     int num;     int China;     int Math;     int English; }score[100]; //改为如下: struct student_score {     char name[10];     int num;     int China;     int Math;     int English; };  main.cpp：  #include "stuscore.h"   int main() {     int i,n;     char filename[50]; //添加 struct student_score score[100];  a1.cpp :  #include "stuscore.h"   void save(char*name,int n) {     FILE *fp;     int i; //添加 extern struct student_score score[100];  a2.cpp :  #include "stuscore.h"   void show(char*name,int n) {     int i;     FILE *fp; //添加 extern struct student_score score[100];   试试谢谢师兄的具体修改。改过后，出现新问题：  1>a1.obj : error LNK2001: 无法解析的外部符号 "struct student_score * score" (?score@@3PAUstudent_score@@A) 1>a2.obj : error LNK2019: 无法解析的外部符号 "struct student_score * score" (?score@@3PAUstudent_score@@A)，该符号在函数 "void __cdecl show(char *,int)" (?show@@YAXPADH@Z) 中被引用 1>G:\VS2010\mywork\example7\Debug\e170.exe : fatal error LNK1120: 1 个无法解析的外部命令  这个错误也常见，网上解答较多，只是自己不能对应上。。。[/quote]  #include "stuscore.h"    //添加 struct student_score score[100];  int main() {     int i,n;     char filename[50];  a1.cpp :  #include "stuscore.h"  //添加 extern struct student_score score[100]; void save(char*name,int n) {     FILE *fp;     int i;   a2.cpp :  #include "stuscore.h"  //添加 extern struct student_score score[100]; void show(char*name,int n) {     int i;     FILE *fp;

引用 7 楼 user-3 的回复:stuscore.h： #ifndef _STUDENTSCORE_H_ #define _STUDENTSCORE_H_  #include <stdio.h> #include <stdlib.h> #include <iostream>  struct student_score { 	char name[10]; 	int num; 	int China; 	int Math; 	int English; };  extern struct student_score score[100];  void save(char*name,int n); void show(char*name,int n);  #endif   main.cpp： #include "stuscore.h"  student_score score[100];  int main() { 	int i,n; 	char filename[50]; 	printf("how many students in your class?\n"); 	scanf("%d",&n); 	printf("please input filename:\n"); 	scanf("%s",filename); 	printf("please input name,number,China,math,English:\n"); 	for(i=0;i<n;i++) 	{ 		printf("NO%d",i+1); 		scanf("%s%d%d%d%d",score[i].name,&score[i].num,&score[i].China,&score[i].Math,&score[i].English); 		save(filename,n); 	} 	show(filename,n); 	system("pause"); }  a1.cpp: #include "stuscore.h"  void save(char*name,int n) { 	FILE *fp; 	int i; 	if ((fp=fopen(name,"wb"))==NULL) 	{ 		printf("cannot open file\n"); 		exit(0); 	} 	for(i=0;i<n;i++) 		if(fwrite(&score[i],sizeof(struct student_score),1,fp)!=1) 			printf("file write error\n"); 	fclose(fp); }   a2.cpp： #include "stuscore.h"  void show(char*name,int n) { 	int i; 	FILE *fp; 	if ((fp=fopen(name,"rb"))==NULL) 	{ 		printf("cannot open file\n"); 		exit(0); 	} 	for (i=0;i<n;i++) 	{ 		fread(&score[i],sizeof(struct student_score),1,fp); 		printf("%-10s%4d%4d%4d%4d\n",score[i].name,score[i].num,score[i].China,score[i].Math,score[i].English); 	} } 运行成功，谢谢师兄

引用 6 楼 u012911202 的回复:[quote=引用 1 楼 qq423399099 的回复:] LZ的这个错误是典型的链接错误，#ifndef 加在头文件重是为了保证类的头文件在一个.cpp文件中被多次引用后会不会出现重复定义的问题,注意,只是防止在一个.cpp文件中被多次引用 如果是C++，可以对头文件的函数定义加inline或者static表明函数是在线或者静态的，这样编译器就可以自行解决重复定义的问题。 如果是C，则只能通过头文件函数定义加static来表明函数为静态，这样连接器不会报错。 正确的做法应该是只在头文件中声明，而真正的定义放到源文件中，这样不管哪个源文件包含了头文件，都不会有问题，因为定义的地方只有一个，链接的时候会找到的。谢谢师兄回复，有问题想继续请教：  问题1，头文件中只声明不定义，学习过这点。师兄强调的：#ifndef只是防止在一个.cpp中被多次引用，不是很明白。拿main.cpp来说，我在里面不同位置写了两次#include "stuscore.h"，#ifndef的作用就显出来了？可以这理解不？  问题2，C++加inline或static，C加static，针对我这个具体工程，适用吗？需要的话，具体加在哪个位置？  [/quote] 第一个可以这么理解 第二个的话，感觉并不不太适用，全局静态的只能在一个文件里用，其他文件访问不到，就算名字相同也是不同的变量

引用 1 楼 qq423399099 的回复:LZ的这个错误是典型的链接错误，#ifndef 加在头文件重是为了保证类的头文件在一个.cpp文件中被多次引用后会不会出现重复定义的问题,注意,只是防止在一个.cpp文件中被多次引用 如果是C++，可以对头文件的函数定义加inline或者static表明函数是在线或者静态的，这样编译器就可以自行解决重复定义的问题。 如果是C，则只能通过头文件函数定义加static来表明函数为静态，这样连接器不会报错。 正确的做法应该是只在头文件中声明，而真正的定义放到源文件中，这样不管哪个源文件包含了头文件，都不会有问题，因为定义的地方只有一个，链接的时候会找到的。谢谢师兄回复，有问题想继续请教：  问题1，头文件中只声明不定义，学习过这点。师兄强调的：#ifndef只是防止在一个.cpp中被多次引用，不是很明白。拿main.cpp来说，我在里面不同位置写了两次#include "stuscore.h"，#ifndef的作用就显出来了？可以这理解不？  问题2，C++加inline或static，C加static，针对我这个具体工程，适用吗？需要的话，具体加在哪个位置？

引用 3 楼 github_27756899 的回复:stuscore.h：  struct student_score {     char name[10];     int num;     int China;     int Math;     int English; }score[100]; //改为如下: struct student_score {     char name[10];     int num;     int China;     int Math;     int English; };  main.cpp：  #include "stuscore.h"   int main() {     int i,n;     char filename[50]; //添加 struct student_score score[100];  a1.cpp :  #include "stuscore.h"   void save(char*name,int n) {     FILE *fp;     int i; //添加 extern struct student_score score[100];  a2.cpp :  #include "stuscore.h"   void show(char*name,int n) {     int i;     FILE *fp; //添加 extern struct student_score score[100];   试试谢谢师兄的具体修改。改过后，出现新问题：  1>a1.obj : error LNK2001: 无法解析的外部符号 "struct student_score * score" (?score@@3PAUstudent_score@@A) 1>a2.obj : error LNK2019: 无法解析的外部符号 "struct student_score * score" (?score@@3PAUstudent_score@@A)，该符号在函数 "void __cdecl show(char *,int)" (?show@@YAXPADH@Z) 中被引用 1>G:\VS2010\mywork\example7\Debug\e170.exe : fatal error LNK1120: 1 个无法解析的外部命令  这个错误也常见，网上解答较多，只是自己不能对应上。。。

3楼师兄，谢谢具体修改。改过后，出现新问题：  1>a1.obj : error LNK2001: 无法解析的外部符号 "struct student_score * score" (?score@@3PAUstudent_score@@A) 1>a2.obj : error LNK2019: 无法解析的外部符号 "struct student_score * score" (?score@@3PAUstudent_score@@A)，该符号在函数 "void __cdecl show(char *,int)" (?show@@YAXPADH@Z) 中被引用 1>G:\VS2010\mywork\example7\Debug\e170.exe : fatal error LNK1120: 1 个无法解析的外部命令  这个错误也常见，网上解答较多，只是自己不能对应上。。。

补充一下 哈哈，有几个错别字见谅 #ifndef 加在头文件中是为了保证类的头文件在一个.cpp文件中被多次引用后不会出现重复定义的问题,注意,只是防止在一个.cpp文件中被多次引用 楼主在头文件中最好不要定义变量(score[100])，变量的定义都放到.cpp文件中


Question: 求助

原理就是要把基础打扎实啊

*的优先级高于++,()的优先级高于*

引用 1 楼 qq423399099 的回复:这个一般用在字符串拷贝上，strcpy内部实现就是这样的 ++以后取*就是逐字节拷贝，先让2个指针都向后移一位，然后第二个字符串取出对应的字符赋给第一个字符串对应的字符 拷贝完一个字符就判断一下是否等于'\0'(如果是的话说明fov指针指向的字符串已经到结尾了) 楼上正解，你可以理解为 char a[100], b[100]; for(int i = 0; i < 100; i ++) {     a[i] = b[i];     if('\0' == b[i])     {         break;     } }


Question: 信任求解vs2015，无法打开源文件

我也遇到这样的问题，怎么解决的，我把“”换成<>也不行

谢谢各位，已解决，新人问一下只能每天发帖赚积分吗？

用""而不是<>

楼主用双引号 #include"SqStack.h"

换成 #include "SqStack.h"


Question: symbol "private: static unsigned long const * const CryptoPP::Blowfish::s_init"

错误问题解决了么？解决了给大家说说啊。

C++ 中 private 的类是私有变量，不能继承，只能在所属类中进行修改，在类外不能进行修改

private: static 删除。 并且确认定义在类外。


Question: fopen错误问题

应该是进程中某种资源耗尽了，LS的猜测(文件描述符耗尽)有可能

漏fclose，我猜。


Question: C语言中文件操作之fseek遇到问题，致使读取数据失败

引用 2 楼 user-4 的回复:这个是我邮箱1058375583@qq.com 感谢您的回复，问题已经解决，是因为结构体的对齐补全问题，下面这个网址中的文章给出了详细的解释，对于本程序，只要添加了#pragma pack（1）便可以解决问题。http://www.cnblogs.com/luxiaoxun/archive/2012/11/09/2762438.html

引用 5 楼 lgbxyz 的回复:因为还有结构体对齐产生的补齐字节，不是简单偏移就能得到正确值。 最好是整体读。 谢谢您的指导。忘了考虑结构体的补齐了确实。整体读觉得有点冗余，所以试试这个

引用 4 楼 liehu232 的回复:写的是一个结构体，你却想读出字符串，应该读出结构体 首先感谢指导。我是觉得如果读出结构体的话，有很多的内容是不需要的只要两项，所以想这样

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了

因为还有结构体对齐产生的补齐字节，不是简单偏移就能得到正确值。 最好是整体读。

写的是一个结构体，你却想读出字符串，应该读出结构体

为什么不用ftell呢？  When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed (the file is said to be open for “update”). However, when you switch between reading and writing, there must be an intervening fflush, fsetpos, fseek, or rewind operation. The current position can be specified for the fsetpos or fseek operation, if desired.

介不介意吧这个程序和存的员工信息的这个txt发给我，我看了看，觉得跟我用的scanf有些不一样


Question: 超级基础的c语言问题

引用 6 楼 qq_34274794的回复:[quote=引用 5 楼 finish_dream 的回复:] 函数缺少类型，要用return 0那就用int main(),要用空的void main()就把//return 0 不太懂[/quote] 这么说吧，函数的作用是把传入的参数(也可以没有参数)处理的到一个返回值，当没有返回值的时候函数的类型就可以定义为void

主函数类型 int main（）

引用 1 楼 Liu_Jack 的回复:是什么问题呢？编译出错？还是结果不符合预期？ 不符合预期

谢谢大家的建议  ，我的代码的确是可以运行，但是得到的结果与预期的结果差别很大 听说要在main（）前加int，void因为是初学者不是很懂，希望能详细一点

引用 5 楼 finish_dream 的回复:函数缺少类型，要用return 0那就用int main(),要用空的void main()就把//return 0 不太懂

你的代码均可以正常编译执行

main函数没有类型，后面有return0，应该是int型

是什么问题呢？编译出错？还是结果不符合预期？


Question: 求助！在C语言中这个程序输入ABCDEFG123456为什么运行不出结果？

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

不知道楼主所说的运行不出结果是指什么，楼主把程序的目的说明一下吧。按照代码的结果是有数的，就是1楼说的246

出错了点中断，通过调用堆栈、变量窗口等观察分析原因

有结果啊，下标位偶数，编码也是偶数的，246


Question: 求助，不知道为什么后面的字符不能覆盖前面的。

if (('A' <= *temp && *temp <= 'Z')  || ('a' <= *temp && *temp <= 'z'))

谢谢大神的指导，新手上路，还有很多地方会犯比较低级的错误，见谅见谅哈。

LZ有几个问题： 1.if(*temp>='A'||*temp<='Z'||*temp>='a'||*temp<='z')判断错误，这样所有的字符都会满足条件 2.else分支里应当将所有后续字符都向前移一位 3.字符串结尾判断应当用 '\0' 改正后代码如下  #include<stdio.h> #include<iostream> using namespace std;  void deleteother(char *p) { 	char *temp = p; 	int j = 0; 	for(;j<100;j++) 	{ 		if((*temp >= 'A' && *temp <= 'Z') || (*temp >= 'a' && *temp <= 'z')) 		{	 			temp++; 			continue; 		} 		else if(*temp == '\0') //已经到字符串尾部 			break; 		else  		{ 			int i; 			for(i = 0; i < 100; i++)//将当前字符后面的所有字符都向前移一位 			{ 				*(temp + i) = *(temp + i + 1); 				if (*(temp + i) == '\0') 					break; 			}	 		}	 	} }  int main() { 	char str[100]; 	printf("Please input the string : "); 	gets(str); 	deleteother(str); 	printf("\noutput: %s\n", str); 	system("pause"); 	return 0; }  运行结果：


Question: 关于递归调用的指针参数问题

“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出

递归一直没得到退出，直到栈溢出

引用 2 楼 liehu232 的回复:递归函数没有出口，在if i==j 里面加上return退出函数  的确是没有出口的问题，但不是在if（i==j）里加return，条件应该单独写出来，  if (left>right) return ;  前面的判断条件也要改了，  while(p[i]<=temp&&j>i) 才对

引用 1 楼 zhangxiangDavaid 的回复:快速排序 http://blog.csdn.net/zhangxiangdavaid/article/details/25436609  内容很丰富，我好好看看。谢谢

递归函数没有出口，在if i==j 里面加上return退出函数


Question: 求一道随机置换算法的时间复杂度

仅供参考：#include <stdio.h> #include <stdlib.h> #include <time.h> int d[6]; int i,n,a,b,t; int c,j; void main() {     srand(time(NULL));     printf("shuffle 0..n-1 demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=0;i<n;i++) d[i]=i;/* 填写0～n-1 */             for (i=n;i>0;i--) {/* 打乱0～n-1 */                 a=i-1;b=rand()%i;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=0;i<n;i++) printf("%d",d[i]);             printf("\n");         }     }     printf("shuffle 1..n demo\n");     for (n=1;n<=5;n++) {/* 测试1～5个元素 */         printf("_____n=%d_____\n",n);         j=1;         for (c=1;c<=n;c++) j=j*c;/* j为n! */         j*=n*2;         for (c=1;c<=j;c++) {/* 测试n*2*n!次 */             for (i=1;i<=n;i++) d[i]=i;/* 填写1～n */             for (i=n;i>1;i--) {/* 打乱1～n */                 a=i;b=rand()%i+1;                 if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}             }             printf("%04d:",c);             for (i=1;i<=n;i++) printf("%d",d[i]);             printf("\n");         }     } }

可以花费 O(N)的空间复杂度，换来比较次数为 O(N) 的时间复杂度

假设随机数是均匀分布的，则随机数重复的概率是 1/N 已经生成的数据是某个数的概率各为1/N  最后一个数必为 所有数中从没有出现的数概率为1 这种比较方式的时间复杂度计算要用到概率论 很麻烦

随机置换算法，本身其实也是 O(N)的，不过不能比较，一比较就麻烦了

o (n2) 第n个数要和前面n-1个数比较总比较次数是n*(n-1)/2 次


Question: xml按指定语句拆分

使用Response节点来分是不对的，除非你真的能确定它是root，否则人家改个名字，你就抓瞎了。  从你目前的规则来看，要分的话，基于两点：  1.<?xml?>标志 2.根节点

#include <stdio.h> #include <string.h> char s[]= "<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<Response>" "<Item>   内容1略 </Item>" "</Response>" "<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<Response>" "<Item>   内容2略 </Item>" "</Response>" "<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<Response>" "<Item>   内容3略 </Item>" "</Response>"; char *p,*q,c,L; char gap[80]="</Response>"; int i; int main() {     L=strlen(gap);     q=s;     i=0;     while (1) {         p=strstr(q,gap);         if (p) {             c=p[L];             p[L]=0;             printf("%d [%s]\n",i,q);             i++;             p[L]=c;             q=p+L;         } else break;     }     return 0; } //0 [<?xml version="1.0" encoding="utf-8"?><Response><Item>   内容1略 </Item></Response>] //1 [<?xml version="1.0" encoding="utf-8"?><Response><Item>   内容2略 </Item></Response>] //2 [<?xml version="1.0" encoding="utf-8"?><Response><Item>   内容3略 </Item></Response>] //

大神能不能给个示例代码，小弟新手，非常感谢

数据不用保存，C++的库一般有两个参数，一个是begin, 一个是end。 如果你用的C++库只有一个字符串参数，辣鸡库，换一个(或者用std::string中转一下)。 遍历完一个xml, 送到解析器里面就行了。


Question: 新人求助！用codeblock写代码 碰到了关于int的问题。

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

n = getchar() - '0';  数值与数值的字符不是一回事

getchar()读取的是stdio的字符流，返回值是读取的第一个字符的ASCII值，如果你输入的是12，那它n就等于’1‘的ASCII值49（C语言里，char型可以有int型值）. 不过看图上你输入的是2，所以n等于‘2’的ASCII值50，这是getchar的用法问题，还有你的while不知道是干啥的。

getchar()得到的 '2'不是2; 应减去'0';  n = getchar()-'0';


Question: 关于windows驱动编程中RtlStringCchPrintfW函数求解


Question: 遇到这样一个面试题很无赖，可是怎么解释，请大虾指明下出处。

感谢两位及时解答，明白了

参考楼上意见：  #define OFFSET(type, field)    ((LONG)(LONG_PTR)&(((type *)0)->field))  结构体地址：0X12345678 - OFFSET(结构体变量， a)

去搜下offset的写法就差不多了。

重点不知这个a是在结构体中的第几个变量，而且标准好像也没有规定第一个变量一定要放在最前面


Question: 随机算法解非线性方程组

引用 1 楼 user-2的回复:楼主是不是在调用函数之前定义函数f的时候只写了一个参数，而实现写了两个参数？类似这样 double f(double *mp); int main() {  fx = f(mp, n); } double f(double *mp, int n); 使用函数前没申明，谢谢你的帮助

引用 2 楼 LubinLew的回复:函数没有声明返回值， 使用前应该先声明函数 呃呃，是的，弄了一上午终于弄好了，谢谢

函数没有声明返回值， 使用前应该先声明函数


Question: 请问栈的LIFO (Last in first out) 是什么意思？

详细解释看这里： http://blog.csdn.net/zhangxiangdavaid/article/details/26819603

原来是最后进来的最先出来的意思，谢谢。

就一个后进先出的方式。


Question: c内存中的数据对齐

引用 25 楼 u014517002 的回复:[quote=引用 23 楼 qq_29120981 的回复:] [quote=引用 19 楼 iGenius_的回复:][quote=引用 18 楼 qq_29120981 的回复:] 这和数据对齐好像没关系吧?还有楼主说的根据这三个地址算出a为1字节，这算不出来的，因为只输出了a的首地址，而内存中a又排在高地址，拿a的地址减b的地址只能得出b的大小 但是栈不是向下增长的吗？那用b的地址减a的地址不是得出了a的大小么？我不知道我理解得对不对[/quote] 根据abc的地址可以得出编译器是依次先后分配cba的内存的，而不是依次分配abc的内存，因为是前者，b的地址是内存首地址a的地址同理，ab地址之差就为b内存的大小。[/quote] 按cba的顺序分配内存？不是按abc吗？只不过是自上到下压栈的时候顺序刚好反过来了[/quote]  抱歉,不当的措辞让楼主误解了,我说的分配指的是内存从低位到高位的加载顺序. 这一张图应该能说明问题

引用 28 楼 qq_29120981 的回复:[quote=引用 25 楼 u014517002 的回复:] [quote=引用 23 楼 qq_29120981 的回复:] [quote=引用 19 楼 iGenius_的回复:][quote=引用 18 楼 qq_29120981 的回复:] 这和数据对齐好像没关系吧?还有楼主说的根据这三个地址算出a为1字节，这算不出来的，因为只输出了a的首地址，而内存中a又排在高地址，拿a的地址减b的地址只能得出b的大小 但是栈不是向下增长的吗？那用b的地址减a的地址不是得出了a的大小么？我不知道我理解得对不对[/quote] 根据abc的地址可以得出编译器是依次先后分配cba的内存的，而不是依次分配abc的内存，因为是前者，b的地址是内存首地址a的地址同理，ab地址之差就为b内存的大小。[/quote] 按cba的顺序分配内存？不是按abc吗？只不过是自上到下压栈的时候顺序刚好反过来了[/quote]  抱歉,不当的措辞让楼主误解了,我说的分配指的是内存从低位到高位的加载顺序. 这一张图应该能说明问题 [/quote] 恩，跟22楼说的一致。我理解了！谢谢你

大小端。。。

引用 22 楼 u012033027 的回复:另外，栈的增长方向向下，不代表保存a的四个字节的顺序是从大到小，反而是从小到大。 有用！我好像有点理解了！多谢

引用 23 楼 qq_29120981 的回复:[quote=引用 19 楼 iGenius_的回复:][quote=引用 18 楼 qq_29120981 的回复:] 这和数据对齐好像没关系吧?还有楼主说的根据这三个地址算出a为1字节，这算不出来的，因为只输出了a的首地址，而内存中a又排在高地址，拿a的地址减b的地址只能得出b的大小 但是栈不是向下增长的吗？那用b的地址减a的地址不是得出了a的大小么？我不知道我理解得对不对[/quote] 根据abc的地址可以得出编译器是依次先后分配cba的内存的，而不是依次分配abc的内存，因为是前者，b的地址是内存首地址a的地址同理，ab地址之差就为b内存的大小。[/quote] 按cba的顺序分配内存？不是按abc吗？只不过是自上到下压栈的时候顺序刚好反过来了

楼主如果想彻底弄明白这个问题，建议参考gcc源代码相关片断。

引用 23 楼 醉花阴柳的回复:[quote=引用 19 楼 iGenius_的回复:][quote=引用 18 楼 qq_29120981 的回复:] 这和数据对齐好像没关系吧?还有楼主说的根据这三个地址算出a为1字节，这算不出来的，因为只输出了a的首地址，而内存中a又排在高地址，拿a的地址减b的地址只能得出b的大小 但是栈不是向下增长的吗？那用b的地址减a的地址不是得出了a的大小么？我不知道我理解得对不对[/quote] 根据abc的地址可以得出编译器是依次先后分配cba的内存的，而不是依次分配abc的内存，因为是前者，b的地址是内存首地址a的地址同理，ab地址之差就为b内存的大小。[/quote] 你的想法是当编译器依次对abc分配内存时才成立的，(这样b-a的地址差为a的大小)而这又与输出地址不合

引用 19 楼 iGenius_的回复:[quote=引用 18 楼 qq_29120981 的回复:] 这和数据对齐好像没关系吧?还有楼主说的根据这三个地址算出a为1字节，这算不出来的，因为只输出了a的首地址，而内存中a又排在高地址，拿a的地址减b的地址只能得出b的大小 但是栈不是向下增长的吗？那用b的地址减a的地址不是得出了a的大小么？我不知道我理解得对不对[/quote] 根据abc的地址可以得出编译器是依次先后分配cba的内存的，而不是依次分配abc的内存，因为是前者，b的地址是内存首地址a的地址同理，ab地址之差就为b内存的大小。

引用 19 楼 u014517002 的回复:[quote=引用 18 楼 qq_29120981 的回复:] 这和数据对齐好像没关系吧?还有楼主说的根据这三个地址算出a为1字节，这算不出来的，因为只输出了a的首地址，而内存中a又排在高地址，拿a的地址减b的地址只能得出b的大小 但是栈不是向下增长的吗？那用b的地址减a的地址不是得出了a的大小么？我不知道我理解得对不对[/quote]  a, b c是一个函数之内的变量，它们在内存中的分配，跟编译器的策略有关，跟栈的增长方向反而没有多大关系。 0x22fe4c 0x22fe4b 0x22fe44 地址与对应的量之间的关系如下。 栈中间还有一些空白位置，比如a的上面和c的上面，这些地方写了写什么，要问编译器了，不过不必关心。

引用 17 楼 zhao4zhong1 的回复:楼主如果想彻底弄明白这个问题，建议参考gcc源代码相关片断。 理解和讨论之前请先学会如何观察！

引用 18 楼 qq_29120981 的回复:这和数据对齐好像没关系吧?还有楼主说的根据这三个地址算出a为1字节，这算不出来的，因为只输出了a的首地址，而内存中a又排在高地址，拿a的地址减b的地址只能得出b的大小 但是栈不是向下增长的吗？那用b的地址减a的地址不是得出了a的大小么？我不知道我理解得对不对

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  仅供参考：#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 // //A1.a 0 //A1.b 4 //A1.c 17 // //A2.a 0 //A2.b 4 //A2.c 18 // //A4.a 0 //A4.b 4 //A4.c 20 // //A8.a 0 //A8.b 4 //A8.c 24 // //A16.a 0 //A16.b 4 //A16.c 24 // //

引用 15 楼 u012033027 的回复:[quote=引用 13 楼 u014517002 的回复:] [quote=引用 12 楼 u012033027 的回复:] [quote=引用 9 楼 u014517002 的回复:] [quote=引用 7 楼 u012033027 的回复:] 你这个问题，只是说明了a, b, c三个变量的分配地址是a > b > c，因为是三个单独变量，怎么分配是编译器确定的，但还不能说明栈的增长问题。 要想看栈的增长方向，最好用函数栈来说明。如下程序 #include <stdio.h> void foo(){   int b;   printf("The address of b: %lx\n", &b); } int main(int argc, char **argv){   int a;   printf("The address of a: %lx\n", &a);   foo(); } main调用foo，所以栈中先有main,再有foo，然后程序的输出为： The address of a: 7fffac5f878c The address of b: 7fffac5f875c b的地址小于a的地址，所以栈是向下增长的。谢谢你的回答，我想问如果栈是向下增长的话，那a（int类型）只占1个byte？[/quote] int类型的a不是只占一个字节，应该是四个，具体要用sizeof(a)来看。 我的程序中输出的只是a的首字节的地址。[/quote] 我指按我最开始提出来的程序运行出来的结果：  #include <stdio.h> int main() {     int a;     char b;     int c;     printf("0x%x\n", &a);     printf("0x%x\n", &b);     printf("0x%x\n", &c); }  结果是： 0x22fe4c 0x22fe4b 0x22fe44 [/quote]  你的也是输出a的地址，跟我的一样的。 不过a的地址是个长整型，printf中应该用%lx，而不是%x。 一般的机器上，a应该占4个字节。[/quote] 我知道它在32位机上应该是4个字节...但是我不懂为什么dev c打印出来的地址那么奇怪，我按照地址的加减得出来的int a;的大小是1个字节啊！望您在您的机器上试试我上面的代码，看能不能理解为什么地址是那样。如果能，请告诉我为什么！谢谢您！

引用 13 楼 u014517002 的回复:[quote=引用 12 楼 u012033027 的回复:] [quote=引用 9 楼 u014517002 的回复:] [quote=引用 7 楼 u012033027 的回复:] 你这个问题，只是说明了a, b, c三个变量的分配地址是a > b > c，因为是三个单独变量，怎么分配是编译器确定的，但还不能说明栈的增长问题。 要想看栈的增长方向，最好用函数栈来说明。如下程序 #include <stdio.h> void foo(){   int b;   printf("The address of b: %lx\n", &b); } int main(int argc, char **argv){   int a;   printf("The address of a: %lx\n", &a);   foo(); } main调用foo，所以栈中先有main,再有foo，然后程序的输出为： The address of a: 7fffac5f878c The address of b: 7fffac5f875c b的地址小于a的地址，所以栈是向下增长的。谢谢你的回答，我想问如果栈是向下增长的话，那a（int类型）只占1个byte？[/quote] int类型的a不是只占一个字节，应该是四个，具体要用sizeof(a)来看。 我的程序中输出的只是a的首字节的地址。[/quote] 我指按我最开始提出来的程序运行出来的结果：  #include <stdio.h> int main() {     int a;     char b;     int c;     printf("0x%x\n", &a);     printf("0x%x\n", &b);     printf("0x%x\n", &c); }  结果是： 0x22fe4c 0x22fe4b 0x22fe44 [/quote]  你的也是输出a的地址，跟我的一样的。 不过a的地址是个长整型，printf中应该用%lx，而不是%x。 一般的机器上，a应该占4个字节。

引用 11 楼 zhao4zhong1 的回复:#define field_offset(s,f)    /*将结构体s的成员f相对结构体开头的字节偏移量以int类型返回*/ \     (int) (                  /*强制转换为int类型                                      */ \         &(                   /*取地址                                                 */ \             (                                                                            \                 (struct s *)(/*强制转换为struct s *类型                               */ \                     0                                                                    \                 )                                                                        \             )->f             /*取前面结构体指针指向的成员f                            */ \         )                                                                                \     )  是将0强制转化为struct s*类型吗？为啥可以这样用？ 那个宏在64位机上要将(int)改成8位的(long)。

引用 12 楼 u012033027 的回复:[quote=引用 9 楼 u014517002 的回复:] [quote=引用 7 楼 u012033027 的回复:] 你这个问题，只是说明了a, b, c三个变量的分配地址是a > b > c，因为是三个单独变量，怎么分配是编译器确定的，但还不能说明栈的增长问题。 要想看栈的增长方向，最好用函数栈来说明。如下程序 #include <stdio.h> void foo(){   int b;   printf("The address of b: %lx\n", &b); } int main(int argc, char **argv){   int a;   printf("The address of a: %lx\n", &a);   foo(); } main调用foo，所以栈中先有main,再有foo，然后程序的输出为： The address of a: 7fffac5f878c The address of b: 7fffac5f875c b的地址小于a的地址，所以栈是向下增长的。谢谢你的回答，我想问如果栈是向下增长的话，那a（int类型）只占1个byte？[/quote] int类型的a不是只占一个字节，应该是四个，具体要用sizeof(a)来看。 我的程序中输出的只是a的首字节的地址。[/quote] 我指按我最开始提出来的程序运行出来的结果：  #include <stdio.h> int main() {     int a;     char b;     int c;     printf("0x%x\n", &a);     printf("0x%x\n", &b);     printf("0x%x\n", &c); }  结果是： 0x22fe4c 0x22fe4b 0x22fe44


Question: 问一个关于键盘钩子的问题

GetCurrentDirectory The GetCurrentDirectory function retrieves the current directory for the current process.   DWORD GetCurrentDirectory(   DWORD nBufferLength,  // size, in characters, of directory buffer   LPTSTR lpBuffer       // pointer to buffer for current directory );   Parameters nBufferLength  Specifies the length, in characters, of the buffer for the current directory string. The buffer length must include room for a terminating null character.  lpBuffer  Pointer to the buffer for the current directory string. This null-terminated string specifies the absolute path to the current directory.  Return Values If the function succeeds, the return value specifies the number of characters written to the buffer, not including the terminating null character.   If the function fails, the return value is zero. To get extended error information, call GetLastError.   If the buffer pointed to by lpBuffer is not large enough, the return value specifies the required size of the buffer, including the number of bytes necessary for a terminating null character.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Unsupported.   Header: Declared in winbase.h.   Import Library: Use kernel32.lib.   Unicode: Implemented as Unicode and ANSI versions on Windows NT.  See Also File I/O Overview, File Functions, CreateDirectory,GetSystemDirectory,GetWindowsDirectory, RemoveDirectory, SetCurrentDirectory


Question: 请教各位，有几道题一直理解不了。。

引用 4 楼 qq423399099 的回复:[quote=引用 3 楼 yq_forever 的回复:] [quote=引用 2 楼 qq423399099 的回复:] 一个个说，先说第一个，一维数组名+1，其实就是指针移到下一个数组元素之前，而在内存中移动的字节数会隐式 转换成str + 1 * sizeof( char)会在内存中移动1个字节，所以str+1移动到了数组的第二个字符之前，指向了第二个字符'B' //这里以LZ给的数组为例啊，如果是int的数组，就要sizeof(int) ，一次+1移动4个字节 第二个问题，LZ要看清啊第一个if中是a=0而不是a==0,所以不会进第一个if判断，也不满足第二个if判断，所以执行了else中的y+=y 得到了y=20,所以选A 第三个问题，#define P(a,b)  strcpy(a,b)可以这样用的，但感觉并没有什么用   谢谢解答~ 第一个问题中，str+1也就是p指向了B,那么*（p+1）不就向后再移一位，指向'\0'了？ 第三个问题，刚写了个程序验证了一下，好像不合法[/quote] 我脑残了，原来“AB”前面有一个空格，那么str+1也就是p指向了第二个字符也就是A，所以*（p+1）就向后再移一位指向B 那个宏定义我这里可以的，LZ要么贴一下自己的代码和错误 [/quote]  原来有个空格！！我擦这什么题啊。。 是有一道选择题，这个宏是错误选项，可能是题目不严谨吧。。又试了一下，我程序刚忘了加<string.h>头文件了哈哈，总犯这种低级错误。。  非常感谢你的回答，谢谢啦

引用 3 楼 yq_forever 的回复:[quote=引用 2 楼 qq423399099 的回复:] 一个个说，先说第一个，一维数组名+1，其实就是指针移到下一个数组元素之前，而在内存中移动的字节数会隐式 转换成str + 1 * sizeof( char)会在内存中移动1个字节，所以str+1移动到了数组的第二个字符之前，指向了第二个字符'B' //这里以LZ给的数组为例啊，如果是int的数组，就要sizeof(int) ，一次+1移动4个字节 第二个问题，LZ要看清啊第一个if中是a=0而不是a==0,所以不会进第一个if判断，也不满足第二个if判断，所以执行了else中的y+=y 得到了y=20,所以选A 第三个问题，#define P(a,b)  strcpy(a,b)可以这样用的，但感觉并没有什么用   谢谢解答~ 第一个问题中，str+1也就是p指向了B,那么*（p+1）不就向后再移一位，指向'\0'了？ 第三个问题，刚写了个程序验证了一下，好像不合法[/quote] 我脑残了，原来“AB”前面有一个空格，那么str+1也就是p指向了第二个字符也就是A，所以*（p+1）就向后再移一位指向B 那个宏定义我这里可以的，LZ要么贴一下自己的代码和错误

引用 2 楼 qq423399099 的回复:一个个说，先说第一个，一维数组名+1，其实就是指针移到下一个数组元素之前，而在内存中移动的字节数会隐式 转换成str + 1 * sizeof( char)会在内存中移动1个字节，所以str+1移动到了数组的第二个字符之前，指向了第二个字符'B' //这里以LZ给的数组为例啊，如果是int的数组，就要sizeof(int) ，一次+1移动4个字节 第二个问题，LZ要看清啊第一个if中是a=0而不是a==0,所以不会进第一个if判断，也不满足第二个if判断，所以执行了else中的y+=y 得到了y=20,所以选A 第三个问题，#define P(a,b)  strcpy(a,b)可以这样用的，但感觉并没有什么用   谢谢解答~ 第一个问题中，str+1也就是p指向了B,那么*（p+1）不就向后再移一位，指向'\0'了？ 第三个问题，刚写了个程序验证了一下，好像不合法

呃 图片变态了一点，请别介意。。


Question: ，高手求助，定义int len = length_list(pHead)；下面的语句不执行，下面不能输出链表的长度，以及进行其他函数

int length_list(PNODE pHead)  {  PNODE p = pHead->pNext;  int len = 0;   while (NULL != p);  //dead loop  {  ++len;  p = p->pNext;  }  return len;  }

length_list 函数中while循环后面加了；所以成死循环了


Question: CPU：400MHZ , 256MB内存，需要十秒加载完， 请教从哪字符串转换为数值处理250万条数据能再帮忙优化下么？

引用 3 楼 mysticboy 的回复:int i3 = (BlackProCard_recordTable[i2].CardID[0] - '0') * 1000 + (BlackProCard_recordTable[i2].CardID[1] - '0') * 100 + (BlackProCard_recordTable[i2].CardID[2] - '0') * 10 + (BlackProCard_recordTable[i2].CardID[3] - '0');   改了下， 2秒内， 原来 十秒 分享下哈

多线程处理？

字符串数值是否有大小范围？如果有，可以直接查表映射，不用调用字符串函数


Question: 关于c语言数组

专门写一个函数用于申请和释放用户的数据空间   #include <stdlib.h> #include <stdio.h>  int *test(int *a, int src, int des) {     int i = 0;     int *b = (int *)malloc(sizeof(int) * des);     for(i = 0; i < des; i ++)     {         b[i] = i;     }     free(a);     return b; }  int main(int argc, char *argv[]) {     int *a;     int i;     int *b = (int *)malloc(sizeof(int) * 4);     int src = 4, des = 5;     a = test(b, src, des);     for(i = 0; i < des; i ++)     {         printf("%d ", a[i]);     }     return 0; }  仅供楼主参考

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

C99好像是有变长数组VLA  不然在需要改变大小时重新分配内存，然后复制数据到新内存，释放旧内存  或者自己实现一个类似C++STL中的vector、list之类的容器，然后之后使用这个容器

int a[];//


Question: 求解不对啊，哪里的问题呢？

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

引用 2 楼 lgbxyz 的回复:d = 0 的判断写错了  #include<stdio.h> #include<math.h>  double a,b,c,d;  void big  (double m,double n,double l); void small(double m,double n,double l); void equal(double m,double n);   int main(void) { 	printf("please input three number:\n"); 	scanf("%lf %lf %lf",&a, &b, &c); 	 	d = b * b - 4.0 * a * c; //b*b -4ac  	printf("%7.2lf\n", d);  	 	if (d < 0) 	{ 		small(a, b, d); 	} 	else  	{ 		if(0 == d) 	 		equal(a,b); 		else 			big(a,b,d);  	} 	 	return 0; }   void big(double m,double n,double l) { 	double x1,x2; 	x1=(-n+sqrt(l))/(2.0*m); 	x2=(-n-sqrt(l))/(2.0*m); 	printf("X1=%5.2f,X2=%5.2f\n",x1,x2); } void small(double m,double n,double l) { 	printf("wujie\n"); }  void equal(double m,double n) { 	double x; 	x=(-n)/(2.0*m); 	printf("X=%5.2f\n",x);  }   scanf("%f%f%f",&a, &b, &c);改成scanf("%lf %lf %lf",&a, &b, &c);即可成功，为什么？

编译没有问题，是代码逻辑问题吧，自己单步调试来跟踪


Question: 求高手翻译qsort函数，每一步作用都要

自己搜如何单步调试的博文或教学视频会吗？

引用 7楼赵4老师 的回复:VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）不行啊，

引用 3楼赵4老师 的回复:“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出这代码里有指针吗 哪个

引用 3楼赵4老师 的回复:“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出什么意思？咋跟踪？

引用 2楼paschen 的回复:你要先懂得快速排序的原理，网上很多这方面的博客讲解，也可以自己看书我懂啊 但是这代码不太正常

你要先懂得快速排序的原理，网上很多这方面的博客讲解，也可以自己看书

快速排序 网上资料一堆，自己查。 实在不会就直接用qsort函数   #include <stdlib.h>  void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));


Question: 请问这个用C语言写的堆排序算法错在哪里

堆排序 http://blog.csdn.net/zhangxiangdavaid/article/details/30069623

[code=c#include<stdio.h> #include<math.h>  int left(int i) {	return (i*2); }    int right(int i) {	return (i*2+1); }  void exchange(int A[],int i,int j) {	int temp;  	temp=A[i-1]; A[i-1]=A[j-1]; A[j-1]=temp; }  void MAX_HEAPIFY(int A[10],int i,int length,int heapsize) {	int l,r,largest;   	l=left(i); r=right(i);  	if(l<=heapsize && A[l-1]>A[i-1]) 		largest=l; 	else 		largest=i; 	if(r<=heapsize && A[r-1]>A[i-1]) 		largest=r;  	if(i!=largest)  	{	exchange(A,i,largest); 		MAX_HEAPIFY(A,largest,length,heapsize); 	}   }  void BUILD_HEAP(int A[10],int length,int heapsize) {	for(int i=floor(length/2);i>=1;i--) 	MAX_HEAPIFY(A,i,length,heapsize); }  void HEAPSORT(int A[10],int length,int heapsize) {	BUILD_HEAP(A,length,heapsize); 	for(int i=length;i>1;i--) 	{	exchange(A,1,heapsize--);  		MAX_HEAPIFY(A,1,length,heapsize); 	} }  int main() {	int A[10]={12,1,5,2,3,8,6,7,19,15},length=10,heapsize=10;    	HEAPSORT(A,length,heapsize);  	for(int i=0;i<10;i++) 	printf("%d ",A[i]); }][/code]


Question: fopen打开文件失败

楼主可以贴个代码么？就说fopen打开文件失败这个让人猜原因么。

检查什么原因导致的，可能的情况这里有详细说明：http://en.cppreference.com/w/c/io/fopen

如果是E盘下a.txt文件，LZ不妨写上完整路径fopen("E:\\a.txt", "r");

文件路径错了


Question: 新人求解

1、１、l、ｌ、I、Ｉ、|、│、

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

谢谢各位的帮助  我是看教材上的%lf    我以为是If   结果是Lf      谢谢大家

贴代码上来。

应该是 小写L    lf

楼主上面第一个程序scanf中输入的是1f么？第二个是lf？

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

可能是编译器的问题   double类型一般是用%lf 输出读入（楼楼前边的scanf就是用%lf） 但是下面的printf（)输出函数用%f  可能一个编译器可以调节这种错误 编译器“帮助”你调正，而其中一个编译器没有这种功能。我觉得是这样。

检查第一个程序你r的值是多少


Question: 关于顺序表的基本运算

引用 1 楼 qq423399099 的回复:LZ有几个问题，现在说一下： 1.第88行scanf("%d",&n);改为scanf("%d%*c",&n); //%*c是匹配掉输入缓冲区里遗留的回车符， 否则a[0]将读到回车符，LZ不信可以打印一下a[0] 2.第90行scanf("%c",&a[i]);改为scanf("%c%*c",&a[i]); //同样的道理%*c是匹配掉输入缓冲区里每个字符相隔的空格以及最后的一个回车符，LZ不信的话也可以自己打印验证 PS：按照LZ原来的写法输入5回车符，输入缓冲区读走了5，还剩\n,又输入a b c d e\n,输入缓冲区变成了\na b c d e\n 然后开始字符数组赋值，a[0]='\n',a[1]='a',a[2]=' ',a[3]='b',a[4]=' '，所以LZ打印出来这样的结果 3.ListInsert函数也有问题，改为如下这样：  bool ListInsert(SqList *L,int i,ElemType e) { 	int j; 	if(i<1||i>L->length+1) 		return false; 	i--; 	for(j=L->length;j>i;j--) 		L->data[j]=L->data[j-1]; 	L->data[i]=e; 	L->length++; 	return true; }  说明：LZ必须将插入位置之后的元素都向后移一个位置以后，再插入新的元素 三处改正后结果：    非常感谢！！！


Question: 数据结构顺序栈的基本操作，小白第一步卡主 了

原来的代码中的第二个函数的参数改为引用也是可以的，主要是为了能传递地址

struct test *s;  	InitStack(s);   没分配内存

#include<stdio.h> struct test { 	int *top, *base; 	int stacksize; }; void InitStack(struct test *s) { 	(*s).base = (int *)malloc(100 * sizeof(int));  	(*s).top = (*s).base; 	(*s).stacksize = 100; } int main() { 	struct test s; 	InitStack(&s); } 这样就可以了，不知道原因啊， #include<stdio.h> struct test { 	int *top, *base; 	int stacksize; }; void InitStack(struct test *s) { 	(*s).base = (int *)malloc(100 * sizeof(int));  	(*s).top = (*s).base; 	(*s).stacksize = 100; } int main() { 	struct test *s; 	InitStack(s); } 然而这样就不不可以了，求解释

InitStack(struct test s)  改成指针，


Question: 整数划分算法


Question: 在Visual studio 里有个关于C的编译问题，，应该很简单，但就是不知道哪里出错了

prinft拼错了，你少了一个f

我这里把print("%.0f", b);改成printf("%.0f", b);就能编译了

个人建议除了上面的f外，定义变量的时候记得初始，随便给个数字都可以，不初始化的话有时候会出现一些奇怪的错误，

倒数第三行。。。。。。。。

为什么要添第三行啊，大神

#include<stdio.h>  #include<math.h>  int main()  {  float a, b;  do  {  printf("Please input a number between 0 and 1000");  scanf("%f", &a);  } while (a <= 0 || a >= 1000);  b = sqrt(a);  print("%.0f", b);  return 0;  }


Question: 判断下列程序是否正确(纯C语言)

static 是程序生存期，自动变量是函数生存期。

试试 static char a[]="GOOD";

或者试试：const char* a="GOOD";

[root@localhost fu]# gcc -o const const.c  const.c: 在函数‘gen’中: const.c:6: 警告：函数返回局部变量的地址

编译是没有问题，不过你返回的是一个局部数组变量的地址，函数执行完就销毁了，之后再使用将是不确定行为，可能导致之后得到你不想要的结果或者程序崩溃

不正确啊，返回的是一个局部变量的地址，就算加了const也没用啊，只是在gen函数范围内不可修改而已，gen函数结束以后，a指向的地址的内容已经不确定了，我这里VS跑出来的结果是乱码


Question: 输入时，直接换行

引用 13 楼 super_admi 的回复:不要用scanf，自己去扫描键盘。 怎么理解？

不要用scanf，自己去扫描键盘。

引用 10 楼 zhao4zhong1 的回复:在scanf眼里，空格、Tab、换行是一回事。 Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

int i = 0; for(i = 0; i < 4; i ++) { printf("输入第%d行数据\n", i); scanf("%d%d%d%d", &a[0], &a[1], &a[2], &a[3]); } 楼主可以安按照这种方式输入，自己实现换行。

谢谢大家的支持

在scanf眼里，空格、Tab、换行是一回事。

实现不了，除非用户遵守约定，否则 必须另外想办法实现，输入合法性检验，以及按需输入

用户输入的时候直接点回车是会换行的，如果你想在用户输入空格来分割时也换行的，可以在后台用一个线程监视，在需要的时候执行换行

引用 3 楼 paschen 的回复:[quote=引用 2 楼 qq_25295961 的回复:] 有什么办法可以实现嗯？  先解释下你什么叫做自动换行 [/quote] 就是我想给一个二维数组输入数据比如说a【3】【4】，输入的时候，输入4个数，换行再进行输入。

scanf不负责这些

就是用循环输入，输入之后后用语句输出换行

输入之后，跟句printf("\n");啊！！！！！

引用 2 楼 qq_25295961 的回复:有什么办法可以实现嗯？  先解释下你什么叫做自动换行

有什么办法可以实现嗯？


Question: PE加壳软件源码  对‘额外数据’的处理好像有错误

引用 4 楼 u013315260 的回复:此贴结束啦。我也来自问自答吧。 书上源码 和 网上资料 对于“额外数据” 的概念，都是限于 在最后一个段的后面 的数据，就是 末段 地址PointerOfRawData + 末段大小RawDataSize ！= 文件大小。 然而我提出的理论 是 在没一个段后 都存在额外数据。那就是 某段地址PointerOfRawData + 某段大小RawDataSize ！= 下一段地址PointerOfRawData。 我瞎咧咧一句：这样可能会导致无法定位下一段的开始地址。

引用 2 楼 user-2 的回复:// 问题就在ReadFile这里，在上面一个循环中，文件指针指向了 最后一个段的 首地址 在上面一个循环中 文件指针不是指向了最后一段的末尾了 如果文件大小大于最后一个段的末地址，读取的正好是额外的数据 不太懂  您的意思呀。  额外数据 是存在于  各个段之间的吧？ 而不是 只存在于 文件末尾的吧！ 如果这样的话  就应该 搜索每个段的大小 多的部分 复制下来，最后再放到 文件末尾吧？

去看雪论坛逛逛。


Question: 在tcp/ip模型中，服务器端如何检测客户端是否保持连接？

引用 3 楼 truexf 的回复:tcp协议本身支持一个keepalive检测的。你去看下setsockopt里面的相关相关选项。  keep-alive  遇到不支持keep-alvie 的proxy ，反而会造成连接断开。

常见的长连接服务端，对一个tcp连接的处理是，记录上一次读写时间，超过一定时间就主动关闭。  所谓的探测连接是否存在的方法很多，关键是看你要解决什么问题。所以这里只给出业界服务框架常用的处理方法，细节你自己揣摩。

服务端发送心跳包给客户端，  客户端回应心跳包  服务端连续3次接收不到，就认为断开


Question: 求C语言大神帮忙！！！！在下菜鸟求教

应该跟楼主的编译器有关吧，估计VC6.0做了什么处理。我在Centos上打印的也是奇怪的字符。

相由心生

gei dian分

引用 4 楼 sinat_33492610 的回复:[quote=引用 2 楼 paschen的回复:]不可打印字符打印出来的形状不确定的 一楼的图显示的不是出现对应的字符了吗？而且如果是不确定的字符，为什么我试了几遍编译输出的结果都是一样的？不好意思请帮我解答一下。[/quote]  不同情况下可能不同

引用 5 楼 ooolinux的回复:你的本义是打印回车换行符吗？ 不是，我的本义是想看看输出\xhh这样格式的怎么使用，回车符的ascii码值应该不是16吧

不可打印字符打印出来的形状不确定的

你的本义是打印回车换行符吗？

引用 2 楼 paschen的回复:不可打印字符打印出来的形状不确定的 一楼的图显示的不是出现对应的字符了吗？而且如果是不确定的字符，为什么我试了几遍编译输出的结果都是一样的？不好意思请帮我解答一下。

引用 1 楼 小灸舞的回复:我这里打印出来都是三角，不管是在一个程序里分三条语句打印还是像LZ一样分3次每次打印一句都是这样的结果  \x10是表示16进制的10也就是10进制的16，相当于\16 这里打出的三角是asscii码  哦哦我懂了，但是我想也想知道为什么在我的编译器上会出现这样的字符？


Question: tcp的发送窗口大小谁决定的？

引用 24 楼 u012879787 的回复:[quote=引用 23 楼 DelphiGuy 的回复:] “接收端不断的回应win=0的报文给发送方”这应该是发送方使用持续定时器防止出现死锁（接收方窗口为0之后又恢复接收，但新的修改窗口大小的报文丢失，结果双方陷入互相等待的状态）的情况导致的，是接收方对发送方的探测数据的响应。可以参考tanenbaum的《computer networks》6.4.7 TCP定时器管理 部分。  他回复我邮件，他说的情况不是“死锁”！！！  而是： 假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了。  所以就就出现了连续回应win=0给发送端的情况。  他是著名公司EMC的网络工程师，包是他抓的。可信性是非常高！！！！！！   ———————————————————分割线—————————————————  TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   怎么会不应答呢？　明显就会应答嘛。　   我刚才举得例子是EMC工程师在实战中遇到的问题。 [/quote]  假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了。 所以就就出现了连续回应win=0给发送端的情况.这种情况不可能发生，上面楼说的死锁是对的。你这个工程师朋友貌似不靠谱啊

如果老是出现接收端发送win=0的响应报文，那就要看接收端的问题了，首先接收端的缓存是否足够大，这个会影响接收端的窗口，另外接收端的硬件设备是不是不能及时处理这些数据，还有就是接收端是否有其他非常耗cpu的其他程序，当然还得检查接收端本身的程序是否做了阻塞数据接收处理的操作了。

重新生命->重新声明

引用 24 楼 u012879787 的回复:[quote=引用 23 楼 DelphiGuy 的回复:] “接收端不断的回应win=0的报文给发送方”这应该是发送方使用持续定时器防止出现死锁（接收方窗口为0之后又恢复接收，但新的修改窗口大小的报文丢失，结果双方陷入互相等待的状态）的情况导致的，是接收方对发送方的探测数据的响应。可以参考tanenbaum的《computer networks》6.4.7 TCP定时器管理 部分。  他回复我邮件，他说的情况不是“死锁”！！！  而是： 假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了。  所以就就出现了连续回应win=0给发送端的情况。  他是著名公司EMC的网络工程师，包是他抓的。可信性是非常高！！！！！！   ———————————————————分割线—————————————————  TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   怎么会不应答呢？　明显就会应答嘛。　   我刚才举得例子是EMC工程师在实战中遇到的问题。 [/quote]  TCP连接建立之后，发送窗口的大小是发送方的拥塞窗口和接收方承认的窗口大小之中较小的那个，所以不会出现所谓的“假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了”这种事情。 tanenbaum的书中 6.4.5 TCP传输策略 中明确说了： 当滑动窗口为0时，发送方一般不能再发送数据段，但有两种情况除外。一种情况是可以发送紧急数据，例如，允许拥护终止（kill）在远端机上的运行进程。另一种情况是发送方可以发送一个1字节的数据段通知接收放重新生命它希望接收的下一字节及窗口大小。TCP标准明确地提供了该选项以防止窗口声明丢失时出现死锁情况。 发送方不需要从应用程序一到来数据便发送出去。接收方也不需要尽早发送确认。

引用 23 楼 DelphiGuy 的回复:“接收端不断的回应win=0的报文给发送方”这应该是发送方使用持续定时器防止出现死锁（接收方窗口为0之后又恢复接收，但新的修改窗口大小的报文丢失，结果双方陷入互相等待的状态）的情况导致的，是接收方对发送方的探测数据的响应。可以参考tanenbaum的《computer networks》6.4.7 TCP定时器管理 部分。  他回复我邮件，他说的情况不是“死锁”！！！  而是： 假设发送端狂发100个包个接收方，接收方收到50个包后，就满了，于是win=0， 但是另外50个包已到路上了。  所以就就出现了连续回应win=0给发送端的情况。  他是著名公司EMC的网络工程师，包是他抓的。可信性是非常高！！！！！！   ———————————————————分割线—————————————————  TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   怎么会不应答呢？　明显就会应答嘛。　   我刚才举得例子是EMC工程师在实战中遇到的问题。

up起来，等高手，

引用 16 楼 DelphiGuy 的回复:TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。   建议修改答案，看我用颜色标示的话。   我见过一个网络工程师分析报文，接收端不断的回应win=0的报文给发送方，  至于为什么不断的回应win=0.，肯定是接收方不断发送数据所致，连续收到win=0的报文，  发送方不会立即停止发送，很可能还会继续发送几次，最终停止发送。  我在联系“那个网络工程师”，希望从他那得到报文为什么是那样的原因，如果有消息，我会继续回复此贴。

引用 19 楼 u012879787 的回复:[quote=引用 16 楼 DelphiGuy 的回复:] TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。 注意是“最多”，发送方也有自己拥塞控制   １.　是说“拥塞窗口”这个概念，只是发送方控制这个意思吗？  ２.　　拥塞控制————只是由发送方决定吗？ 还是发送方、接受方两者来决定？  ３.　另外发送方的拥塞控制是指什么？   ３个问题，谢谢。      [/quote]  你不是已经知道了么。  引用 楼主 u012879787 的回复:发送窗口的大小因素有2部分： 拥塞、和接收方的接受窗口。  假设网络很好，没有出现拥塞。 那么发送方的发送窗口大小就由接收方的接受窗口大小决定。  可以参考tanenbaum的《计算机网络》一书6.4.6 TCP拥塞控制 那部分。

引用 14 楼 scy2510 的回复:翻书看了理论的说法，不知道与实际相差有多大  也正好在看TCP协议详解1，当中20.4提到，接受方提供的窗口大小可以由接收进程控制，这将影响TCP性能。 从接下来文字中可看出接受方提供的窗口大小其实就是接收端缓存大小。 这个大小可以是默认，也可以用API配置  比如WIN SOCKET，setsockopt 对单独SOCKET设置 从20.7.1中可看出，窗口大小的设置应该考虑通道的时延带宽乘积（作为协议去优化或者人为优化的依据）。  请有实战经验的来说说 比如协议出处 接收的缓存要比窗口大小大得多，一般的窗口大小是MSS的几倍，10几倍。

这是协议规定的，你去研究研究RFC文档。 我记得是有上限，通过数次的交互最终确定一个比较可靠的窗口大小。

引用 11 楼 bsnry 的回复:没看清，劳累再解释一下，这个概念我很模糊你说的发送窗口大小的相关因素都没错，只是楼主想知道接收端的窗口大小是怎么一回事

引用 14 楼 scy2510 的回复:翻书看了理论的说法，不知道与实际相差有多大  也正好在看TCP协议详解1，当中20.4提到，接受方提供的窗口大小可以由接收进程控制，这将影响TCP性能。 从接下来文字中可看出接受方提供的窗口大小其实就是接收端缓存大小。 这个大小可以是默认，也可以用API配置  比如WIN SOCKET，setsockopt 对单独SOCKET设置 从20.7.1中可看出，窗口大小的设置应该考虑通道的时延带宽乘积（作为协议去优化或者人为优化的依据）。  请有实战经验的来说说 比如协议出处 ，当中20.4提到，接受方提供的窗口大小可以由接收进程控制，这将影响TCP性能。   接受进程控制？内核不控制？我已经说过，即使应用层不从内核缓存中拷贝走数据，内核也会回应ack给发送方。 可见接受窗口的大小，不应该是完全是由接受进程控制！  接受进程如果拷贝走数据，接受窗口会增大，这也说明，接受窗口大小有可能是由接受进程控制！     从接下来文字中可看出接受方提供的窗口大小其实就是接收端缓存大小。  你这里的缓存是指什么缓存？

引用 16 楼 DelphiGuy 的回复:TCP报文头部有一个窗口域，16位整数，所以最大65535，代表的含义是“在你接收到下一次应答之前最多还可以发送这么多字节的数据”（注意是“最多”，发送方也有自己拥塞控制），这个窗口值是动态变化的，接收端会根据缓冲情况在应答报文中修改这个窗口值，如果缓冲已满仍然接收到报文，报文会被丢弃，同时不应答，直到缓冲区有空闲为止。至于初始值，当然直接设置成65535或者当前空闲缓冲区的大小二者中的较小值。 注意是“最多”，发送方也有自己拥塞控制   １.　是说“拥塞窗口”这个概念，只是发送方控制这个意思吗？  ２.　　拥塞控制————只是由发送方决定吗？ 还是发送方、接受方两者来决定？  ３.　另外发送方的拥塞控制是指什么？   ３个问题，谢谢。

不是setsockopt设置的吗？  setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &window_size, sizeof(window_size));

引用 2 楼 pengzhixi 的回复:发送窗口大小看已发送出去的数据包是否收到响应来决定，比如 你发了5个数据包出去，只收到头两个数据包得响应那么剩余的三个已经发送出去的数据包还必须留在发送窗口里面，也就是说这3个数据包在窗口里面要占空间，这个时候发送窗口大小自然变小了。  可是我问的是，接受窗口大小如何计算？  前提————没有拥塞的情况下，发送窗口由接受窗口大小决定，  接受窗口如何计算？  内核不管应用层有没有从内核缓存里拷贝走数据，就会回应应答报文。既然回应了，那么内核根据什么计算接受窗口大小。


Question: 已停止工作是什么鬼？

按照楼主的程序敲了一遍（楼主好省事，也不说贴哥源码看看），没遇到楼主说的问题，只不过结果不正确而已。 #include <stdlib.h> #include <stdio.h> #include <conio.h>  #define DENSITY 62.4  int main(int argc, char *argv[]) { 	double weight, volume; 	int size, letters; 	char name[40];  	printf("Hi!what's your first name?\n"); 	scanf_s("%s", name, 40); 	printf("$s, what's your weight in pounds?\n", name); 	scanf_s("%f", &weight); 	size = sizeof(name); 	letters = strlen(name); 	volume = weight / DENSITY; 	printf("Well, %s, your volume is %2.2f cubic feet.\n", name, volume); 	printf("Also, your first name has %d letters.\n", letters); 	printf("and we have %d bytes to store it in.\n", size); 	getchar(); 	return 0; }

一行一行的打印  看哪部份出问题，编译器不同，有时结果也不一样  这样问也没什么意义

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。 #include <stdlib.h> #include <stdio.h>  #define DENSITY 62.4  int main(int argc, char *argv[]) {     double weight, volume;     int size, letters;     char name[40];      printf("Hi!what's your first name?\n");     scanf_s("%s", name, 40);     printf("%s, what's your weight in pounds?\n", name);     scanf_s("%lf", &weight);     size = sizeof(name);     letters = strlen(name);     volume = weight / DENSITY;     printf("Well, %s, your volume is %2.2lf cubic feet.\n", name, volume);     printf("Also, your first name has %d letters.\n", letters);     printf("and we have %d bytes to store it in.\n", size);     getchar();     return 0; }

LZ将scanf_s("%s", name);改为scanf_s("%s", name, 40);试试 scanf_s多的那个参数用以指定字符串参数的长度，用以避免一些安全隐患。 不加40那个参数的话，你的name是读不到正确的输入进来的字符串的

改过以后还是这个样子，本质问题到底在哪？

一个 %s 打成了 $s 一个scanf对double应该用 %lf 但用了 %f

补充：运行后就是这个情况


Question: 代码求解

首先 if(t<1||t>20)         return 0; 这句，异常退出不要返回0，0是正常退出的标志，用-1，1什么的都可以； 其次你的数组分配得太大了，差不多100k，有些服务器会有限制，运行时间和空间的限制，在这种 不知道需要多少内存的情况下用动态内存，这是最好的做法。 算法应该没什么问题。贴代码的时候最好把题目也贴出来，不然别人看半天看不懂你的代码会很痛苦。

我大致瞄了一眼，发现你把int i=XXX这样的东西写进了FOR循环里，一定会报错的，我遇到过，


Question: malloc

分配失败返回NULL （On failure, returns a null pointer.）  http://en.cppreference.com/w/c/memory/malloc

找到原因了，进程内存分配空间小了。


Question: 删除链表的问题

链表当然要一个节点一个节点的释放了。

为了防止内存泄漏，如果链表不为空的时候，说明其内部有若干个元素，需要将每个元素释放，需要循环找到每一个元素的位置将每个元素释放。因此用的while

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

如果直接free(pNode)就存在一个内存泄漏的问题，因为只free了头结点，while循环正是释放整个链表的结点；其实if语句不要也可以，它只是判断是否只有头结点的情况，这种情况并不需要特殊处理，这样写还显得代码臃肿了。

节点是一个一个释放的，这就是while的作用


Question: 指针 求二维数组的最大值

引用 2 楼 lz20120808 的回复:[quote=引用 1 楼 qq423399099 的回复:] 代码如下，6个位置我做了标注  # include <stdio.h>  int main() { 	int a[5][5]; 	int *pa, i, n, m; 	int max, c, row, col; 	pa = &a[0][0]; //@#1 	scanf("%d%d", &n, &m); 	for(i = 0; i < n * m; pa = (i % m == m -1 ? &a[(i + 1) / m][0] : pa + 1), i++) //@#2 		scanf("%d", pa); 	pa = &a[0][0]; //@#3 	max = a[0][0]; //@#4 	c = 0; 	for(i = 0; i < n * m; i++) 	{ 		if(max < *(pa + i + (i / m) * (5 - m))) //@#5 		{ 			max =  *(pa + i + (i / m) * (5 - m)); //@#6 			c = i; 		} 	} 	printf("%d\n",  max); 	printf("%d %d\n", c/m, c%m); 	return 0; }  下面是运行结果：   2处，直接pa=pa+1 5处和6处 max < *(pa+i) 这样不更简单吗？ [/quote] 不能直接+1，如果你输入n=2,m=3,输入3个元素以后他要从a[0][2]变到a[1][0],你直接+1会从a[0][2]变到a[0][3], 这种没有初始化过的数组你使用这种元素的值结果是不确定的

引用 4 楼 lz20120808 的回复:[quote=引用 3 楼 qq423399099 的回复:] [quote=引用 2 楼 lz20120808 的回复:] [quote=引用 1 楼 qq423399099 的回复:] 代码如下，6个位置我做了标注  # include <stdio.h>  int main() { 	int a[5][5]; 	int *pa, i, n, m; 	int max, c, row, col; 	pa = &a[0][0]; //@#1 	scanf("%d%d", &n, &m); 	for(i = 0; i < n * m; pa = (i % m == m -1 ? &a[(i + 1) / m][0] : pa + 1), i++) //@#2 		scanf("%d", pa); 	pa = &a[0][0]; //@#3 	max = a[0][0]; //@#4 	c = 0; 	for(i = 0; i < n * m; i++) 	{ 		if(max < *(pa + i + (i / m) * (5 - m))) //@#5 		{ 			max =  *(pa + i + (i / m) * (5 - m)); //@#6 			c = i; 		} 	} 	printf("%d\n",  max); 	printf("%d %d\n", c/m, c%m); 	return 0; }  下面是运行结果：   2处，直接pa=pa+1 5处和6处 max < *(pa+i) 这样不更简单吗？ [/quote] 不能直接+1，如果你输入n=2,m=3,输入3个元素以后他要从a[0][2]变到a[1][0],你直接+1会从a[0][2]变到a[0][3], 这种没有初始化过的数组你使用这种元素的值结果是不确定的[/quote] 2行三列，不会有a[0][3]啊，其实我认为*p把二维数组变成了一位数组，只是地址在加1，不是值[/quote] 它不管你输入的n,m是多少，它直接就是int a[5][5];不是根据你输入的n和m来动态创建数组大小的

引用 3 楼 qq423399099 的回复:[quote=引用 2 楼 lz20120808 的回复:] [quote=引用 1 楼 qq423399099 的回复:] 代码如下，6个位置我做了标注  # include <stdio.h>  int main() { 	int a[5][5]; 	int *pa, i, n, m; 	int max, c, row, col; 	pa = &a[0][0]; //@#1 	scanf("%d%d", &n, &m); 	for(i = 0; i < n * m; pa = (i % m == m -1 ? &a[(i + 1) / m][0] : pa + 1), i++) //@#2 		scanf("%d", pa); 	pa = &a[0][0]; //@#3 	max = a[0][0]; //@#4 	c = 0; 	for(i = 0; i < n * m; i++) 	{ 		if(max < *(pa + i + (i / m) * (5 - m))) //@#5 		{ 			max =  *(pa + i + (i / m) * (5 - m)); //@#6 			c = i; 		} 	} 	printf("%d\n",  max); 	printf("%d %d\n", c/m, c%m); 	return 0; }  下面是运行结果：   2处，直接pa=pa+1 5处和6处 max < *(pa+i) 这样不更简单吗？ [/quote] 不能直接+1，如果你输入n=2,m=3,输入3个元素以后他要从a[0][2]变到a[1][0],你直接+1会从a[0][2]变到a[0][3], 这种没有初始化过的数组你使用这种元素的值结果是不确定的[/quote] 2行三列，不会有a[0][3]啊，其实我认为*p把二维数组变成了一位数组，只是地址在加1，不是值

引用 1 楼 qq423399099 的回复:代码如下，6个位置我做了标注  # include <stdio.h>  int main() { 	int a[5][5]; 	int *pa, i, n, m; 	int max, c, row, col; 	pa = &a[0][0]; //@#1 	scanf("%d%d", &n, &m); 	for(i = 0; i < n * m; pa = (i % m == m -1 ? &a[(i + 1) / m][0] : pa + 1), i++) //@#2 		scanf("%d", pa); 	pa = &a[0][0]; //@#3 	max = a[0][0]; //@#4 	c = 0; 	for(i = 0; i < n * m; i++) 	{ 		if(max < *(pa + i + (i / m) * (5 - m))) //@#5 		{ 			max =  *(pa + i + (i / m) * (5 - m)); //@#6 			c = i; 		} 	} 	printf("%d\n",  max); 	printf("%d %d\n", c/m, c%m); 	return 0; }  下面是运行结果：   2处，直接pa=pa+1 5处和6处 max < *(pa+i) 这样不更简单吗？


Question: 某公司的任职考试编程题，有兴趣的可以来挑战下

单独题目是不行的，还必须提供测试数据， 如果测试数据，自己搜集的话 四个小时估计够呛，除非做过，或者是高手

没办法搞PPT出来，只能自己描述，没有图看起来比较恼火，原谅下！其实PPT理解题目都要花1小时。


Question: C语言字符串分隔问题

strtok不好吗

代码如下：  #include <stdio.h> #include <string.h> int split(char strs[][50],char *p); void print(char strs[][50],int n);   int main() {    	int n; 	char strs[50][50]; 	char ch[3000]; 	scanf("%s",ch);  	n=split(strs,ch);  	//将ch按照#进行分割，将分隔后的多个字符串，保存到strs中,并且返回字符串个数,传给n   	printf("%d\n",n); 	print(strs,n); }  int split(char strs[][50],char *p)  {    	int i=0,j;         //分隔出第i个字符串,保存到strs[i]中，一开始i=0  	int len=strlen(p); //被分隔的字符串p(即ch)的长度  	int k=0;               //strs[i]中，下一个可放入字符的位置。  	for(j=0;j<len;j++)  //利用j扫描字符串p(即ch)  	{   		if(p[j]!='#') //如果不是# 		{ 			strs[i][k++] = p[j];//将p中的字符逐个复制给strs[i] 		}  		else 		{ 			strs[i][k] = '\0'; //给strs[i]添加字符串结束符0 			k = 0; //准备将分隔出的字符串，复制给下一个strs[i] 			i++; //让k指向新的strs[i]的起始位置  		} 	} 	return i; } void print(char strs[][50],int n) { 	int i;   	//输出n个字符串 	for(i=0;i<n;i++) 		printf("%s\n",strs[i]); //输出第i个字串并换行  }  运行结果：

所谓复制就是 a=b ;

需要填空的代码 #include <stdio.h> #include <string.h> int split(char strs[][50],char *p); void print(char strs[][50],int n);   int main() {   int n;     char strs[50][50];     char ch[3000];     scanf("%s",ch);          n=split(strs,ch);     //将ch按照#进行分割，将分隔后的多个字符串，保存到strs中,并且返回字符串个数,传给n          printf("%d\n",n);     print(strs,n); }     int split(char strs[][50],char *p)  {   int i=0,j;         //分隔出第i个字符串,保存到strs[i]中，一开始i=0      int len=strlen(p); //被分隔的字符串p(即ch)的长度      int k=0;               //strs[i]中，下一个可放入字符的位置。  	for(j=0;j<len;j++)  //利用j扫描字符串p(即ch)      {  if(p[j]!='#') //如果不是# 	{@@1          将p中的字符逐个复制给strs[i]          @@1 	 }  	   else 	 {@@2           给strs[i]添加字符串结束符0           准备将分隔出的字符串，复制给下一个strs[i]           让k指向新的strs[i]的起始位置           @@2  		     	 }          }     return i; } void print(char strs[][50],int n) {     int i;       //输出n个字符串     for(i=0;i<n;i++)     printf("%s\n",strs[i]); //输出第i个字串并换行         }

引用 4楼user-3 的回复:所谓复制就是 a=b ;能否劳烦写下代码，填下空呢

我比较笨哎，能直接填下空，把代码写一下吗？这样更好理解一点哎

引用 1楼user-3 的回复:方法一 两遍搜索 第一遍搜索#个数 n 如果第一个字符不是#，最后也不是# 那么 串数目  n+1 个 二者只有一个是#输出 n个 两个都是#n-1个 遇到 # 或者 结束符，输出一行字符串，空串不输出 方法一2 用一个字符数组储存字符串 其他同上我比较笨哎，能直接填下空，把代码写一下吗？这样更好理解一点哎￼


Question: C语言Windows程序

目测楼主缺少头文件，如wingdi.h;windows.h;等

没有包含相关头文件

-L库文件所在目录 -l库文件

GetStockObject，头文件：wingdi.h；库：gdi32.lib。 使用PlaySound函数时需要在#include<windows.h>后面加上（注意：不能加在前面）： #include <mmsystem.h> #pragma comment(lib, "WINMM.LIB")  不知道LZ是不是少了头文件

没有链接库文件吧


Question: getop函数中的细节

这本书叫什么

引用 3楼galiniur0u 的回复:s[i] = '\0';这种做法主要的目的是为字符串封尾，就是告诉编译器，这个字符数组到这个字符就结束了。 如果不用s[i] = '\0'这种做法，如果使用到s时，程序就会一直读到s的最后一个字符。就例如 #include <stdlib.h> #include <stdio.h>  int main(int argc, char *argv[]) { 	char s[] = {'a', 'b', 'c', 'd'}; 	printf("%s\n", s); 	s[2] = '\0'; 	printf("%s\n", s); 	return 0; }  如果操作字符数组能够明确的给出要操作到第几个，可以不写s[i] = '\0';但是这个程序里，使用到s时是用while循环判断的，如果不是空格会结束循环，还有必要用s[1]='\0'吗？

while循环判断不是空格或者不是tab键才结束，判断的是s[0]，而不是s[1]。书上这么写只是让人知道，字符串结尾字符是'\0'。 前面也说了，如果在操作字符数组的时候，你能够明确的从第几个字符结束扫描，是否加'\0'无所谓。

引用 1楼user-3 的回复:就是判断是不是空字符或制表符 是就以\0字符串结束符赋值给数组s 就是不保存判断条件里面的东西这一步可以省略吗，书中之前都没有这种用法，第一次遇到，所以是否是必须的？


Question: 急，求高手帮忙，程序设计要上交给老师

引用 9 楼 galiniur0u 的回复:windows下2013编译并运行，不过按照楼主这种方式的输出到文件的内容，因为内存对齐以及内存值的原因，基本上没法看。 这跟内存对齐可没有关系，这是因为fwrite是写二进制的，不是写文本的。

#include <stdlib.h> #include <stdio.h> #include <conio.h>  typedef struct information    //定义一个结构体，包含家庭成员的姓名，日期，收入及支出 { 	char name[7]; 	int date = 0; 	float income = 0.0f; 	float payout = 0.0f; }   xinxi; #define  sizexin sizeof(xinxi) int main() { 	xinxi x[1000];                //定义一个结构体数组 	 	FILE *fp;                     //定义一个文件指针 	int i = 0; 	char ch; 	char other[100]; 	printf("请按照示例输入今天家人们的收支情况:\n"); 	printf("姓名\t日期\t\t收入\t支出\n"); 	printf("张三\t20150120\t120\t40\n"); 	printf("\n"); 	do 	{ 		memset(x[i].name, '\0', 7); 		scanf("%s%d%f%f", x[i].name, &x[i].date, &x[i].income, &x[i].payout); 		gets(other);//这里接收多余字符 		printf("继续输入？(y / n)\n"); 		ch = getchar(); 		i++; 	} while ('y' == ch);//这里= 	fp = fopen("D:\\family financy.dat", "ab+"); 	while (i >= 0) 	{ 		fwrite(&x[i], sizexin, 1, fp); 		i--; 	} 	fclose(fp); 	printf("成功添加纪录!\n"); 	return 0; } windows下2013编译并运行，不过按照楼主这种方式的输出到文件的内容，因为内存对齐以及内存值的原因，基本上没法看。

可是好像还是有问题，有大神在电脑上运行过这段代码吗？为什么输入信息之后回车还是没出现 继续输入 ？

5楼真是厉害  只看出了第一处

楼上说的对，就是把\n读给了ch，不过我用的是gets()读走多余的。

LZ有两个问题： 1.while(ch='y');要改成while(ch=='y');   //楼上的已经说了 2.LZ需要读取掉输入缓冲区中遗留的\n,不然ch=getchar();会使得ch='\n',然后判断while循环ch=='y',结果是不相等， 循环结束，所有LZ看起来是直接就结束了程序 这里提供两种解决方法: 1.scanf("%s%d%f%f",x[i].name,&x[i].date,&x[i].income,&x[i].payout);改为scanf("%s%d%f%f%*c",x[i].name,&x[i].date,&x[i].income,&x[i].payout); //用%*c匹配掉最后的回车符 2.ch=getchar();这句前面加上一句getchar(); //先用一个getchar();读取掉回车符

运行的时候， 继续输入        没显示出来

检查文件是否打开成功

还是运行不出来

while(ch='y'); 改成 while(ch=='y');


Question: 大家好，新手问个问题，安卓的应用层语言是java，内核是基于Linux的，是C/C++编写。那请问那么和系统内核有关的软件，到底是用C/C++写的，还是用

防沉补丁安装中...

引用 3 楼 Saleayas 的回复:基于开发的需求。 如果 java 不能满足的时候，可以就需要使用 NDK 来开发。 如果是 Android 的底层服务是使用 Linux 开发，然后使用 NDK 或者 Binder 来暴露 java 接口的。  如果是纯粹的服务，就是 Linux 开发。   也就是说C/C++编写的Linux服务，可以在安卓系统中运行，即使不使用Java?

很多大型的应用都是有 C/C++ 代码的， 这就是为什么 Intel 心痛的原因，因为这些 C/C++ 代码，很多引用里面只有 arm 版本的。 导致同样运行在 Android 的虚拟机上，Android 应用依旧不能跨平台的原因。

引用 1 楼 user-2 的回复:安卓 有 NDK 开发 这个东西。 不一定涉及 内核开发， 游戏开发里面计算量大的，也是用C++开发打包成动态库的。   直接用C或C++写的程序可以在安卓系统上运行吗?


Question: 内存管理算法

memcached或redis有类似的源码

可以参考stl的allocator的实现。或者你直接看linux下的malloc不就好了。 windows下使用heapalloc 创建无分页内存。完成大内存实现。然后再通过链表时间内存插入。 不过你想别人帮你实现不太现实。应用不同实现都不一样。好的内存池专用算法 也不便宜。


引用 11 楼 FrankHB1989 的回复:为什么这里的人问这种智障题目会这么熟练啊……我倒觉得 这里的人 回答这种问题 这么熟练 也是挺赏心悦目的 哈哈哈

为什么这里的人问这种智障题目会这么熟练啊……

未定义行为，请不要使用

这条语句是未定义的语句，c++标准中没有这样的语句，简单的说这是个错误的语句。

又有人问这种问题....前几天刚有个人问完。完全没有结果的事总经常有人喜欢讨论。

介个东西吧！IDE不同 操作系统不同都能算出不一样的结果

关于C,C++表达式求值顺序 http://blog.csdn.net/fefe82/article/details/37833767，http://bbs.csdn.net/topics/370153775

好像C/C++对这个没有明确规定，结果应该不确定，与编译器有关

这是未定义行为，结果完全取决于编绎器。别人也问过了。要么把三个操作数都算出来，再计算和；要么先计算前两个操作数，计算其和，再计算第三个操作数。

这种行为不确定  关于C,C++表达式求值顺序  http://bbs.csdn.net/topics/370153775

这种题目没啥意思，各个编译器实现不一样，可能结果不一样。 具体看下面这个帖子， 写的很好 http://bbs.csdn.net/topics/370153775  我的编译器vs2012 结果是18 他生成的汇编代码  	mov	eax, DWORD PTR _a$[ebp] 	add	eax, 1 	mov	DWORD PTR _a$[ebp], eax 	mov	ecx, DWORD PTR _a$[ebp] 	add	ecx, 1 	mov	DWORD PTR _a$[ebp], ecx 	mov	edx, DWORD PTR _a$[ebp] 	add	edx, 1 	mov	DWORD PTR _a$[ebp], edx ----------------------------------------------------------------》 这里一口气 进行了3次 ++a 	mov	eax, DWORD PTR _a$[ebp] 	add	eax, DWORD PTR _a$[ebp] 	add	eax, DWORD PTR _a$[ebp] 	mov	DWORD PTR _b$[ebp], eax


Question: socket编程，为什么recv函数一直都只能接收到一个字节

不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。

int k=recv(s2,buffer,sizeof(buffer),0)>0 注意到优先级了没 > 和=

while( int k=recv(s2,buffer,sizeof(buffer),0)>0) {     printf("客户端：%d字节\n",k);     for (int i=0;i<k;i++) printf(" %02x",(unsigned char)buffer[i]);     printf("\n");     memset(buffer,100,0);     Sleep(100); }

int k=recv(s2,buffer,sizeof(buffer),0) while(k) {}


Question: 计算学生，课程的平均成绩的C程序，找了好久的Bug！没找到

除了上面说的问题外，还有一个数组越界的问题，程序运行后会崩溃。 打印课程平均分用的 stu[i] ，在上面for循环完事后，i就越界了。 另外，结构体中的平均分一个就够了，课程的平均分不应该在学生的结构体中， 因为与学生的属性无关，建议申请一个课程平均分的变量，这样也避免了数组越界的问题。   #include <stdio.h> #include <stdlib.h>  typedef struct student { 	char name[10]; 	int score[3];//三门考试成绩 	float average[2];//两个平均成绩 }STU;  int main(void) { 	STU stu[5]; 	int i,j; 	float sum; //	memset(&stu, 0x00, sizeof(stu)); 	printf("please input the students' score:\n"); 	printf("姓名	A	B	C\n"); 	//输入学生的数据 	for(i=0;i<5;i++) 	{ 		scanf("%s",stu[i].name); 		for(j=0;j<3;j++) 		{ 			scanf("%d", &stu[i].score[j]); 		} 	} 	//计算学生的平均成绩 	printf("\n学生的平均成绩\n"); 	for(i=0;i<5;i++) 	{ 		sum=0; 		for(j=0;j<3;j++) 		{ 			sum+=stu[i].score[j]; 		} 		stu[i].average[0]=sum/3; 		printf("%s的平均成分:%.2f\n",stu[i].name,stu[i].average[0]); 	}  	//计算课程的平均成绩 	printf("\n课程的平均成绩\n"); 	for(j=0;j<3;j++) 	{ 		sum=0; 		for(i=0;i<5;i++) 		{ 			sum+=stu[i].score[j]; 		} 		stu[i-1].average[1]=sum/5; //数组越界 		printf("%c课程的平均分%.2f\n",j+65,stu[i-1].average[1]); 	}  	system("pause"); 	return 0; }

scanf("%s",stu[i].name);这个后面的参数，如果是整形的需要加&，取地址的。

你确定是输入一组？还是只是一个(姓名)？

输入学生数据下面的for 循环的第二个scanf，就是输入分数，少了个&

运行之后的刚输入一组学生的数据 结果就 中断了！！！ 不知道有什么地方错了！自己也找了好久吗，绝对不是伸手党，实在是无可奈何了！ 才来向大家求助的。


Question: 关于link 2019的错误

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

main...

main函数的main拼写错了，其实链接错误提示也说的很明白了，找不到main的实现

......... 楼上已说

mian main拼写错误

请问为什么要改成这样呢？

主函数改成 int main()  { 。。。。 return 0; }

int mian(void)


Question: 谁知道 用C语言写excel文件，要求多个sheet(工作表)

我直接用写数据的方式写进去过，不过我只会写一个工作表，多个工作表不会写

可以二进制写进去，不过可能是乱码

可参考一些网上资源：http://download.csdn.net/detail/ql306800470/4344172#comment


Question: Linux socket  服务端发送心跳包

引用 2 楼 waitlessness 的回复:[quote=引用 1 楼 user-1的回复:]服务器开个线程扫描客户端列表，每个客户端关联一个计数器。  每隔几秒扫描一次，对计数器计数之前，查看是否 >= 你的次数， 如果>=， 就closesocket 你的意思是用alarm来产生信号，然后记数？[/quote]  直接sleep即可，  难度你觉得时间精度不够？

引用 1 楼 user-1的回复:服务器开个线程扫描客户端列表，每个客户端关联一个计数器。  每隔几秒扫描一次，对计数器计数之前，查看是否 >= 你的次数， 如果>=， 就closesocket 你的意思是用alarm来产生信号，然后记数？


Question: 【关于C语言动态内存分配的问题】

引用 2 楼 github_27756899 的回复:malloc(sizeof(tech));处理后 pName ,padress , pdate 本身已经有空间了,但是值未定.(空间存放值)。  psteach[i].pName=(char *)malloc(30);(char *)malloc(30); 申请空间存放值(pName），使指针指向申请的空间。  typedef struct date{   //日期结构体类型 	int day; 	int month; 	int year; }setDate;  typedef struct teacher{  //教师结构体类型 	char *name; 	char *address; 	setDate *birthday; }setTeacher;  void main(){ 	setTeacher *staff; 	int i; 	staff=(setTeacher *)malloc(sizeof(setTeacher)*3); 	for(i=0;i<3;i++) 	{ 		/* 		先进行动态内存分配 		*/  		staff[i].name=(char *)malloc(20); 		staff[i].address=(char *)malloc(20); 		staff[i].birthday=(setDate *)malloc(sizeof(setDate));    	} 	//通过strcpy把名字和地址赋值给指针字符串数组  	strcpy(staff[0].name,"Lu Shan"); 	strcpy(staff[1].name,"Zhi Feng"); 	strcpy(staff[2].name,"Chun Guo"); 	strcpy(staff[0].address,"BeiJing"); 	strcpy(staff[1].address,"ShangHai"); 	strcpy(staff[2].address,"ShenZhen"); 	//通过指针数组.birthday指向year  或者  month  或者   day  	staff[0].birthday->year=1996; 	staff[0].birthday->month=07; 	staff[0].birthday->day=14; 	staff[1].birthday->year=1995; 	staff[1].birthday->month=3; 	staff[1].birthday->day=10; 	staff[2].birthday->year=1970; 	staff[2].birthday->month=9; 	staff[2].birthday->day=25;  大大，可以最后一个问题吗~就是我的   "."和"->"使用得正确吗？因为我觉得,和->我比较模糊。可以解释一下吗 拜托了QAQ

引用 2 楼 github_27756899 的回复:malloc(sizeof(tech));处理后 pName ,padress , pdate 本身已经有空间了,但是值未定.(空间存放值)。  psteach[i].pName=(char *)malloc(30);(char *)malloc(30); 申请空间存放值(pName），使指针指向申请的空间。  所以就是动态分配都是需要需要定值的对吧   如果是通过sizeof()定义的都是需要后面定义具体数值是嘛

代码里的psteach变量后边都要有中括号下标才可以

指针的大小是确定的。


Question: for循环为什么没有执行

哈哈，LZ大于小于搞混了么

哦，楼主自己找到原因了，直接结贴吧，不然回答越来越多，都是无用的

循环条件设置错误 应该是对 for 循环的条件，理解有误，或者对要做的事情理解有误。 其实 C,C++ 循环 ，都是当型循环。 条件合适（非0）才执行，到不合适终止循环执行， 如果一开始就不合适 for,while 一次循环也不执行 其中for(e1;e2;e3){s;} 如果条件不合适， 仅仅执行 初始化表达式 e1一次， 执行条件表达式e2一次， 并作出判断是否执行循环体的判断一次。  while(e)s;  仅仅执行一次 e; 并作出判断是否执行循环体的判断一次。 do{s;}while(e);  仅仅执行循环体s一次,e 一次，并作出是否继续循环的判断一次。 C,C++ 没有直到型循环， 如果需要，可以自行把当型，转换成直到型（循环条件取非即可实现） 直到型循环，对于C,C++是一种语法冗余，所以C,C++没有实现直到型循环。

我来看看。。。。

打断点进行调试吧。

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

遇到这种问题学会利用单步调试，一步步看程序怎么执行，看哪一步和你预期的不一致

断点调试就能找到原因了


Question: 指针强制类型转换导致死机

STM32F030   使用MDK自带的编译器,遇到了同样的问题

在ARM上才可能出现对齐问题，但我打赌楼主用的不是ARM

在AMD CPU上也没问题。 好吧，在x86 CPU上都没问题。 也许，在复杂指令集CPU上都没问题。

引用 7 楼 zhao4zhong1 的回复:我敢打赌，楼主的问题是越界访问造成而非什么对齐造成。  赵老湿先是看出楼主用的INTEL CPU，然后断言楼主问题在于越界。这就好有一比：赵老湿穿的红内裤，所以认为大家都在穿红内裤，进而认为他的红内裤掉色，大家的秋裤都必须跟着染上红色素。

引用 6 楼 zhao4zhong1 的回复:在Intel CPU上，对齐不是问题。  赵老湿从哪里看出楼主是INTEL CPU

在Intel CPU上，对齐不是问题。

我敢打赌，楼主的问题是越界访问造成而非什么对齐造成。

引用 4 楼 zhao4zhong1 的回复:char Tab[5] = {0x01,0x02,0x03,0x04,0x05}; short *p; p = (short *)(&Tab[1]); printf("Dat = %d",*p);  赵老湿有点进步，知道*p可能越界（只是可能，因为short int和int的宽度可能相同）。但是不管你怎么改，对齐始终是个问题。我们认为程序的行为是未定义的。

试试 t[2] 呢？可能奇数地址上弄不出来 short，现在 cpu 一般情况下都是对齐的，正常情况下 short 不会放在寄地址上。

引用 2 楼 zhao4zhong1 的回复:char Tab[4] = {0x01,0x02,0x03,0x04}; short *p; p = (short *)(&Tab[1]); printf("Dat = %hd",*p);  printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  赵老师是欺负我们不懂C语言吗？ 1，%d要求一个int类型的参数，表达式* p的类型是short int，但这个表达式的值会在提升为int类型之后传递给printf函数，%d有错？？  2，好，就算是%hd，那也只不过是将* p的值从提升后的int再次转换为short int罢了，有意义？  3，表达式  (short *)(&Tab[1]); 唯一的问题就是转换后的指针可能不是正确对齐的。对于X86来说，这不是问题，大不了迂回一些，但对其它处理器来说问题就不是这么简单了。


Question: c语言fopen函数怎么打开指定路径文件？

引用 1 楼 qq423399099 的回复:LZ你的fnasb函数有问题，你不能返回一个局部变量的地址，这个值很有可能是个垃圾值 不信你可以打印一下fnasb(filename)的值 应该改成用new或者malloc char *fnasb(char *fn) { 	char *path_name =  (char *)malloc(300); 	strcpy(path_name, "E:\\cj\\"); 	strcat(path_name, fn); 	return path_name; } 注：别忘记要free,tnasb同理 都有正确答案了，我就来打个酱油吧，楼上正解。

@小灸舞 大牛！！编译器有对这个问题提出警告的！被我无视了！我一会改下试试，谢谢你啦！


Question: 关于指针数组解引用（*）问题

char *name[]={"Follow me","Good job","My GOd","Hello world"}; 这样的写法， []的优先级比*的优先级高,代表name是一个指针数组, 此时name相当于是一个二级指针 p也是一个二级指针，name+1代表一个地址数值，不能取地址,&只能对变量使用  你要么p=name+1,要么就是 char **p=NULL;	 char **p1 = name +1; // 中间转换一下  char ***p2 = &p1; cout << *p1 <<  "  " <<**p2 << endl;

楼上正解，数组的名字是常量，数组名字类似指针但是和指针不同，指针存地址，数组名字就是个地址，而地址是个常量！

&用于取变量的地址，name+1不是变量。

#include <stdlib.h> #include <stdio.h>  int main(int argc, char *argv[]) {     char *name[] = {"aaaa", "bbbb", "cccc"};     char **p = NULL;     p = name + 1;     printf("%s\n", *p);     return 0; }


Question: 马踏棋盘问题运行不出来

有空的话再帮你研究一下。。。。。。

“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出

出错时点中断，定位到相应代码，然后观察分析原因


Question: 在字符串中找出连续最长的数字串 总是显示运行错误，求原因

引用 3 楼 lgbxyz 的回复: #include <stdlib.h> #include <string.h> #include <stdio.h>  unsigned int Continumax(char** pOutputstr, char* intputstr) { 	int sum = 0,tempsum = 0; 	char *res = NULL, *temp = NULL;  	if ((intputstr == NULL) || (intputstr[0]=='\0'))  	{ //   **pOutputstr='\0';  //Ê¹ÓÃ·Ç·¨µØÖ·  	   return 0; 	}  //	*pOutputstr = (char *)malloc(100 * sizeof(char)); 	 	while (*intputstr != '\0')// 	{ 		if ((*intputstr > 47) && (*intputstr< 58)) 		{ 			tempsum++; 			if (1 == tempsum) 			{//first nubmer 				temp = intputstr; 			} 		} 		else  		{ 			if(tempsum >= sum) 			{ 				sum = tempsum; 				res = temp; 			} 			 			tempsum = 0; 			temp = NULL; 		} 		intputstr++; 	} 	 	if (tempsum >= sum) 	{ 		sum = tempsum; 		res = temp; 	} 	*pOutputstr = (char*)malloc(sum * sizeof(char) + 1); 	memcpy(*pOutputstr, res, sum); 	*(*pOutputstr + 1 + sum) = '\0';  	return sum;  }   int main(void) { 	int count = 0; 	char* res = NULL; 	char str[] = "1sdkf2jlsjflsj3fl22sj32flsk423fjsljf11lsjfl1234567sjf"; 	 	count = Continumax(&res, str); 	 	printf("%s:%d\n", res, count); 	free(res);  	return 0; }    忘了说了，我改了改终于运行成功了，谢谢

引用 3 楼 lgbxyz 的回复: #include <stdlib.h> #include <string.h> #include <stdio.h>  unsigned int Continumax(char** pOutputstr, char* intputstr) { 	int sum = 0,tempsum = 0; 	char *res = NULL, *temp = NULL;  	if ((intputstr == NULL) || (intputstr[0]=='\0'))  	{ //   **pOutputstr='\0';  //Ê¹ÓÃ·Ç·¨µØÖ·  	   return 0; 	}  //	*pOutputstr = (char *)malloc(100 * sizeof(char)); 	 	while (*intputstr != '\0')// 	{ 		if ((*intputstr > 47) && (*intputstr< 58)) 		{ 			tempsum++; 			if (1 == tempsum) 			{//first nubmer 				temp = intputstr; 			} 		} 		else  		{ 			if(tempsum >= sum) 			{ 				sum = tempsum; 				res = temp; 			} 			 			tempsum = 0; 			temp = NULL; 		} 		intputstr++; 	} 	 	if (tempsum >= sum) 	{ 		sum = tempsum; 		res = temp; 	} 	*pOutputstr = (char*)malloc(sum * sizeof(char) + 1); 	memcpy(*pOutputstr, res, sum); 	*(*pOutputstr + 1 + sum) = '\0';  	return sum;  }   int main(void) { 	int count = 0; 	char* res = NULL; 	char str[] = "1sdkf2jlsjflsj3fl22sj32flsk423fjsljf11lsjfl1234567sjf"; 	 	count = Continumax(&res, str); 	 	printf("%s:%d\n", res, count); 	free(res);  	return 0; }    用了您的代码，虽然不再报运行错误的问题，但是报答案错误了，我试了下，有的字符串确实会有奇怪的结果，另外也没有符合题目所述，若字符串数组为0，返回空字符串的要求。但是只有您是在我的代码基础上改的，很感谢

小小函数，有何难哉！大清早无事，见大家都写，朕也来卖弄一番。如果找不到则返回空字符串，故找不到也将调用malloc函数分配1个字节。 #include <stdlib.h>  unsigned int Continumax (char * * pOutputstr, char * intputstr) {     unsigned int n = 0, cnt = 0;      for (unsigned c, x = 0, y = 0; ; x ++)         if ((c = intputstr [x]) > '0' && c <= '9') y ++;         else         {             if (y > cnt) cnt = y, n = x - cnt;             if (c == '\0') break;             y = 0;         }      * pOutputstr = malloc (cnt + 1);     (* pOutputstr) [cnt] = '\0';      if (cnt)         for (unsigned x = 0; x < cnt; x ++)             (* pOutputstr) [x] = intputstr [n ++];      return cnt; }

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

首先你的动态空间固定死了是100，这就有问题。 仅供参考 unsigned int Continumax(char** pOutputstr,  char* inputstr) { 	if (NULL == inputstr || strlen(inputstr) == 0) 	{ 		return 0; 	} 	unsigned int uResult = 0;	  // 结果长度 	char *pBegin = inputstr;      // 记录数字串的首字符位置 	char *pMaxBegin = inputstr;   // 记录最长数字串的首字符位置 	unsigned int nMaxLength = 0;  // 记录最长数字串的长度 	bool bFlag = false;			  // 是否数字串状态 	while (*inputstr != '\0') 	{ 		if (*inputstr >= '0' && *inputstr <= '9')    // 是数字 		{ 			if (!bFlag)                           // 新开始的 			{ 				pBegin = inputstr; 				nMaxLength = 1; 				bFlag = true; 			} 			else 			{ 				nMaxLength++; 			} 		} 		else 		{ 			if (nMaxLength > uResult)         // 如果比之前的长，更新长度和首字符位置 			{ 				uResult = nMaxLength; 				pMaxBegin = pBegin; 			} 			nMaxLength = 0; 			bFlag = false; 		} 		inputstr++; 	} 	if (bFlag && nMaxLength > uResult)        // 处理以数字结尾的情况 	{ 		uResult = nMaxLength; 		pMaxBegin = pBegin; 	} 	if (uResult > 0) 	{ 		size_t nSize = uResult*sizeof(char) +1; 		*pOutputstr = (char *)malloc(nSize); 		memset( *pOutputstr ,0 ,nSize); 		strncpy_s(*pOutputstr, nSize,pMaxBegin ,uResult); 	} 	return uResult; }


Question: 将控制台程序隐藏后，cpu占用率增加

你这个隐藏方法不对。 应该用 nircmd win hide title "你要隐藏窗口的标题" 这种方法隐藏。 http://www.nirsoft.net/utils/nircmd.html