Question: gdb 结构体的查看

测试代码如下：  struct a {           char *s; }; struct b {           char *c;           struct  a *ap; }; int main(int argc, char* argv[]) { 	b v; 	v.c = NULL; 	return 0; }  依次执行以下命令： gdb a.exe break 13 //根据代码行数，设置断点 r p *v.ap

4.2.8  查看运行时数据 在调试程序时，当程序被停住时，可以使用print命令(简写命令为p)，或是同义命令inspect来查看当前程序的运行数据。print命令的格式是： print <expr> print /<f> <expr> <expr>是表达式，是所调试的程序的语言的表达式(gdb可以调试多种编程语言)；<f>是输出的格式。比如，如果要把表达式按16进制的格式输出，那么就是/x。  1. 表达式 print和许多gdb的命令一样，可以接受一个表达式，gdb会根据当前的程序运行的数据来计算这个表达式。既然是表达式，那么就可以是当前程序运行中的常量、变量、函数等内容。可惜的是gdb不能使用在程序中所定义的宏。 表达式的语法应该是当前所调试的语言的语法，由于C/C++是一种大众型的语言，所以，本文中的例子都是关于C/C++的。而关于用gdb调试其他语言的内容，将在后面介绍。 在表达式中，有几种gdb所支持的操作符，它们可以用在任何一种语言中。 @ 是一个和数组有关的操作符，在后面会有更详细的说明。 :: 指定一个在文件或是一个函数中的变量。 {<type>} <addr> 表示一个指向内存地址<addr>的类型为type的一个对象。 2. 程序变量 在gdb中，可以随时查看以下3种变量的值： ●       全局变量(所有文件可见的) ●       静态全局变量(当前文件可见的) ●       局部变量(当前Scope可见的) 如果局部变量和全局变量发生冲突(也就是重名)，一般情况下是局部变量会隐藏全局变量。也就是说，如果一个全局变量和一个函数中的局部变量同名时，如果当前停止点在函数中，用print显示出的变量的值会是函数中的局部变量的值。如果此时想查看全局变量的值，可以使用“::”操作符： file::variable function::variable 可以通过这种形式指定所要查看的变量，是哪个文件中的或是哪个函数中的。例如，查看文件f2.c中的全局变量x的值： (gdb) p 'f2.c'::x 当然，“::”操作符会和C++中的发生冲突，gdb能自动识别“::”是否C++的操作符，所以不必担心在调试C++程序时会出现异常。 另外，需要注意的是，如果程序编译时开启了优化选项，那么在用gdb调试被优化过的程序时，可能会发生某些变量不能访问，或是取值错误的情况。这个是很正常的，因为优化程序会删改程序，整理程序的语句顺序，剔除一些无意义的变量等。所以在gdb调试这种程序时，运行时的指令和所编写的指令就不一样，也就会出现想象不到的结果。对付这种情况，需要在编译程序时关闭编译优化。一般来说，几乎所有的编译器都支持编译优化的开关，例如，GNU的C/C++编译器GCC，可以使用-gstabs选项来解决这个问题。关于编译器的参数，请查看编译器的使用说明文档。 3. 数组 有时候需要查看一段连续的内存空间的值。比如数组的一段，或是动态分配的数据的大小。可以使用gdb的@操作符。@的左边是第一个内存地址的值，@的右边则是想查看的内存的长度。例如，程序中有这样的语句： int *array = (int *) malloc (len *sizeof (int)); 于是，在gdb调试过程中，可以用如下命令显示出这个动态数组的取值： p *array@len @的左边是数组的首地址的值，也就是变量array所指向的内容，右边则是数据的长度，其保存在变量len中。其输出结果，大约是下面这个样子的： (gdb) p *array@len         $1={2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40} 如果是静态数组的话，直接用print数组名就可以显示数组中所有数据的内容了。 4. 输出格式 一般来说，gdb会根据变量的类型输出变量的值。但也可以自定义gdb的输出格式。例如，想输出一个整数的十六进制或是二进制来查看这个整型变量中的位的情况。要做到这样，可以使用gdb的数据显示格式： ●       x  按十六进制格式显示变量。 ●       d  按十进制格式显示变量。 ●       u  按十六进制格式显示无符号整型。 ●       o  按八进制格式显示变量。 ●       t  按二进制格式显示变量。 ●       a  按十六进制格式显示变量。 ●       c  按字符格式显示变量。 ●       f  按浮点数格式显示变量。 (gdb) p i $21 = 101 (gdb) p/a i $22 = 0x65 (gdb) p/c i $23 = 101 'e' (gdb) p/f i $24 = 1.41531145e-43 (gdb) p/x i $25 = 0x65 (gdb) p/t i $26 = 1100101 5. 查看内存 可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示： x/<n/f/u> <addr> ●       n、f、u是可选的参数。 ●       n 是一个正整数，表示显示内存的长度，也就是说从当前地址向后显示几个地址的内容。 ●       f 表示显示的格式，参见上面。如果地址所指的是字符串，那么格式可以是s，如果是指令地址，那么格式可以是i。 ●       u 表示从当前地址往后请求的字节数，如果不指定的话，gdb默认是4个bytes。u参数可以用下面的字符来代替：b表示单字节，h表示双字节，w表示四字节，g表示八字节。当指定了字节长度后，gdb会从指定的内存地址开始，读写指定字节，并把其当作一个值取出来。 ●       <addr>表示一个内存地址。 n/f/u三个参数可以一起使用。例如： x/3uh 0x54320 表示从内存地址0x54320读取内容，h表示以双字节为1个单位，3表示3个单位，u表示按十六进制显示。 6. 自动显示 可以设置一些自动显示的变量，当程序停住时，或是在单步跟踪时，这些变量会自动显示。相关的gdb命令是display。 display <expr> display/<fmt> <expr> display/<fmt> <addr> expr是一个表达式，fmt表示显示的格式，addr表示内存地址。当用display设定好了一个或多个表达式后，只要程序停下来，gdb会自动显示所设置的这些表达式的值。 格式i和s同样被display支持，一个非常有用的命令是： display/i $pc $pc是gdb的环境变量，表示指令的地址，/i则表示输出格式为机器指令码，也就是汇编。于是当程序停下后，就会出现源代码和机器指令码相对应的情形，这是一个很有意思的功能。 下面是一些和display相关的gdb命令： undisplay <dnums...> delete display <dnums...> 删除自动显示，dnums意为设置好了的自动显示的编号。如果要同时删除几个编号，可以用空格分隔；如果要删除一个范围内的编号，可以用减号表示(如：2-5)。 disable display <dnums...> enable display <dnums...> disable和enalbe不删除自动显示的设置，而只是让其失效和恢复。 info display 查看display设置的自动显示的信息。gdb会显示出一张表格，报告调试中设置了多少个自动显示设置，其中包括设置的编号、表达式及是否enable。 7. 设置显示选项 gdb中关于显示的选项比较多，这里只列举大多数常用的选项。 set print address set print address on 打开地址输出，当程序显示函数信息时，gdb会显出函数的参数地址。系统默认为打开的，如： (gdb) f #0  set_quotes (lq=0x34c78 "<<", rq=0x34c88 ">>") at input.c:530 530         if (lquote != def_lquote) set print address off 关闭函数的参数地址显示，如： (gdb) set print addr off (gdb) f #0  set_quotes (lq="<<", rq=">>") at input.c:530 530         if (lquote != def_lquote) show print address 查看当前地址显示选项是否打开。 set print array set print array on 打开数组显示。打开后当数组显示时，每个元素占一行；如果不打开的话，每个元素以逗号分隔。这个选项默认是关闭的。 set print array off show print array set print elements <number-of-elements> 这个选项主要是设置数组的，如果数组太大了，就可以指定一个<number-of-elements>来指定数据显示的最大长度，当达到这个长度时，gdb就不再往下显示了。如果设置为0，则表示不限制。 show print elements 查看print elements的选项信息。 set print null-stop <on/off> 如果打开了这个选项，那么当显示字符串时，遇到结束符则停止显示。这个选项默认为off。 set print pretty on 如果打开printf pretty这个选项，那么当gdb显示结构体时会比较漂亮。如：             $1 = {                  next = 0x0,                  flags = {                     sweet = 1,                    our = 1                  },                  meat = 0x54 "Pork"               } set print pretty off 关闭printf pretty这个选项，gdb显示结构体时会如下显示： $1 = {next = 0x0, flags = {sweet = 1, sour = 1}, meat = 0x54 "Pork"} show print pretty 查看gdb是如何显示结构体的。 set print sevenbit-strings <on/off> 设置字符显示，是否按“/nnn”的格式显示。如果打开，则字符串或字符数据按/nnn显示，如“/065”。 show print sevenbit-strings 查看字符显示开关是否打开。 set print union <on/off> 设置显示结构体时，是否显示其内的联合体数据。例如有以下数据结构：       typedef enum {Tree, Bug} Species;           typedef enum {Big_tree, Acorn, Seedling} Tree_forms;           typedef enum {Caterpillar, Cocoon, Butterfly}                       Bug_forms;            struct thing {           Species it;           union {             Tree_forms tree;             Bug_forms bug;           } form;           }; struct thing foo = {Tree, {Acorn}}; 当打开这个开关时，执行 p foo 命令后，会如下显示： $1 = {it = Tree, form = {tree = Acorn, bug = Cocoon}} 当关闭这个开关时，执行 p foo 命令后，会如下显示： $1 = {it = Tree, form = {...}} show print union 查看联合体数据的显示方式。 set print object <on/off> 在C++中，当一个对象指针指向其派生类时，如果打开这个选项，gdb会自动按照虚方法调用的规则显示输出，如果关闭这个选项，gdb就不管虚函数表了。这个选项默认是off。 show print object 查看对象选项的设置。 set print static-members <on/off> 这个选项表示，当显示一个C++对象中的内容时，是否显示其中的静态数据成员。默认是on。 show print static-members 查看静态数据成员选项设置。 set print vtbl <on/off> 当此选项打开时，gdb将用比较规整的格式来显示虚函数表时。其默认是关闭的。 show print vtbl 查看虚函数显示格式的选项。 8. 历史记录 当用gdb的print查看程序运行时的数据时，每一个print都会被gdb记录下来。gdb会以$1, $2, $3 .....这样的方式为每一个print命令编上号。于是，可以使用这个编号访问以前的表达式，如$1。这个功能所带来的好处是，如果先前输入了一个比较长的表达式，并想查看这个表达式的值，可以使用历史记录来访问，省去了重复输入。 9. gdb环境变量 可以在gdb的调试环境中定义自己的变量，用来保存一些调试程序中的运行数据。 要定义一个gdb的变量很简单，只需使用gdb的set命令。gdb的环境变量和UNIX一样，也是以$起头。如： set $foo = *object_ptr 使用环境变量时，gdb会在第一次使用时创建这个变量，而在以后的使用中，则直接对其赋值。环境变量没有类型，可以给环境变量定义任意的类型，包括结构体和数组。 show convenience 该命令查看当前所设置的所有的环境变量。 这是一个比较强大的功能，环境变量和程序变量的交互使用将使得程序调试更为灵活便捷。例如： set $i = 0 print bar[$i++]->contents 输入这样的命令后，只用按回车键，重复执行上一条语句，环境变量会自动累加，从而完成逐个输出的功能。 10. 查看寄存器 要查看寄存器的值，很简单，可以使用如下命令： info registers 查看寄存器的情况(除了浮点寄存器)。 info all-registers 查看所有寄存器的情况(包括浮点寄存器)。 info registers <regname ...> 查看所指定的寄存器的情况。 寄存器中放置了程序运行时的数据，比如程序当前运行的指令地址(ip)，程序的当前堆栈地址(sp)等。同样可以使用print命令来访问寄存器的情况，只需要在寄存器名字前加一个$符号就可以了，如p。


Question: PAT考试1007. 素数对猜想 (20)

#include <stdio.h> #include <stdlib.h> #include <math.h>  int main() {     int limit = 0, *prime;     int i = 0, j = 0, k = 0, l = 0, digit = 0;      scanf("%d", &limit);      prime = (int *)malloc(limit * sizeof(int));     if (!prime)         return -1;     if(limit > pow(10, 5))         exit(0);      for(i = 2; i <= limit; i ++)     {         for(j = 2; j < i; j ++)         {             if(i % j == 0)             {                 break;             }         }         if(j == i)             prime[k++] = i;     }     for(l = 0; l < k; l ++) {    /*这个地方是不是应该从0开始？*/         if(prime[l] - prime[l-1] == 2)             digit ++;     }     printf("%d", digit);      return 0; }

边界条件 输入输出格式 ……

引用 1 楼 zhao4zhong1 的回复:int limit = 0, prime[1000] = {0}; 改为  int limit = 0,  static int prime[1000] = {0};  在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。 堆上是不是可以申请大于1M的空间呢？Linux下malloc是可以的，你说是？


Question: c语言中scanf函数的转换说明的格式问题

引用 2 楼 cfjtaishan 的回复:scanf是格式化输入，即你的输入格式要按照scanf的第一个参数的格式来输入 %lf输入double类型数据，不需要在第一个参数里加空格，输入时加上空格用于区分不同的输入即可。这个输入缓冲区会识别。 我知道了，是因为scanf函数读取到最后一个数的时候，要按照%lf_格式来匹配输入，而最后一个数后面只有空白符，而没有输入新的数字字符了，而且%lf_后面的空格可以匹配多个空白字符，所以造成了scanf函数在输入最后一个数据的时候阻塞了，导致最后一个数据输入不了。 谢谢大佬的指点

引用 4 楼 cfjtaishan 的回复:[quote=引用 3 楼 xiaowangzi666 的回复:] [quote=引用 2 楼 cfjtaishan 的回复:] scanf是格式化输入，即你的输入格式要按照scanf的第一个参数的格式来输入 %lf输入double类型数据，不需要在第一个参数里加空格，输入时加上空格用于区分不同的输入即可。这个输入缓冲区会识别。  就是弄不明白为什么lf%后面有空格的话num数组最后一个输入的数接收不到。 [/quote] 这是因为它要匹配最后一个输入后的空格吧（空格可以匹配tab，回车，不定个的空格）[/quote] 例如我输入 1.0   2.0    3.0  4.0  5.0  6.0  7.0  8.0  这八个数，按lf%_ 后面有个空格这种格式来输出， 每个数中间都隔了两个空格，8.0后面也有2个空格，可是输出的时候8.0 没能赋给数组，数组中只输入到 7.0 这里，如果匹配最后一个空格的话，应该8.0 也输入进去才对啊。。。

引用 3 楼 xiaowangzi666 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] scanf是格式化输入，即你的输入格式要按照scanf的第一个参数的格式来输入 %lf输入double类型数据，不需要在第一个参数里加空格，输入时加上空格用于区分不同的输入即可。这个输入缓冲区会识别。  就是弄不明白为什么lf%后面有空格的话num数组最后一个输入的数接收不到。 [/quote] 这是因为它要匹配最后一个输入后的空格吧（空格可以匹配tab，回车，不定个的空格）

引用 2 楼 cfjtaishan 的回复:scanf是格式化输入，即你的输入格式要按照scanf的第一个参数的格式来输入 %lf输入double类型数据，不需要在第一个参数里加空格，输入时加上空格用于区分不同的输入即可。这个输入缓冲区会识别。  就是弄不明白为什么lf%后面有空格的话num数组最后一个输入的数接收不到。

大神在哪里呀

请判断scanf函数的返回值。 仅供参考：#include <stdio.h> int main() {     int a,b,n,v,r,k;     char buf[80];     char *p;      k=0;     r=EOF;     while (1) {         if (EOF==r) {             fgets(buf,80,stdin);             p=buf;         }         while (1) {             r=sscanf(p,"%d%n",&v,&n);             if (1==r) {k++;break;}             if (EOF==r) break;             p++;         }         if (EOF==r) continue;         p+=n;         if (1==k) a=v;         if (2==k) {             b=v;             break;         }     }     printf("%d,%d\n",a,b);     return 0; }


Question: socket无法接收数据

接收到数据后，写入一个文档，看看写入的内容是否想要接收的内容。

用抓包工具看下数据包收发是不是正常 如果软件解决不了，得排查硬件是不是有问题

这个要看一下你的socket代码的处理逻辑了


Question: 又是C编译报错

引用 5 楼 赵4老师的回复:请那些喜欢将数组作为函数参数传来传去或作为函数返回值的码农思考一下为什么不把整个互联网内容当作函数参数传来传去或作为函数返回值呢？ 那为何，结构也可以作为函数参数传递呢，虽然结构指针更快但是可能会改变原始数据，而传递结构虽然慢一些，但是函数处理的是结构的一个副本，就比直接处理原始数据安全，而相对于互联网，我更倾向于用指针

引用 7 楼 JILAU_WHO_AM_I_Q234 的回复:可是这个列数已经定死了 100，我想写的是对于任意大小的二维数组 一个解决方案应该是用二维指针吧

引用 3 楼 自信男孩的回复:#include <stdio.h> #include <stdlib.h>  #define ROW     100 #define COL     100  void copy_arr(int m,int n,const double (*arr)[COL],double (*arr1)[COL]); void arr_show(int m,int n,const double (*arr)[COL],const double (*arr1)[COL]); int main(void) {     int m,n;     printf("请输入两个整数：");     scanf("%d%d",&m,&n);     double array[ROW][COL];     for(int i=0;i<m;i++)         for(int j=0;j<n;j++)             array[i][j] = 0.0;     double array1[ROW][COL];     copy_arr(m,n,array,array1);     arr_show(m,n,array,array1);     system("pause");     return 0; } void copy_arr(int m,int n,const double (*arr)[COL],double (*arr1)[COL]) {     for(int i = 0;i<m;i++)     {         for(int j = 0;j<n;j++)         arr1[i][j] = arr[i][j];     } } void arr_show(int m,int n,const double (*arr)[COL],const double (*arr1)[COL]) {     printf("array[%d][%d]:    array1[%d][%d]:",m,n,m,n);     for(int i=0;i<m;i++)     {         for(int j=0;j<n;j++)         {             printf("%f    %f",arr[i][j],arr1[i][j]);         }     } } 二维数据作为形参时，至少列数需要告知，即是一个确定值。 以上的代码参考一下吧 可是这个列数已经定死了 100，我想写的是对于任意大小的二维数组

引用 2 楼 verphan的回复: int m,n;     printf("请输入两个整数：");     scanf("%d%d",&m,&n);     double array[m][n]; 我认为上面这一段都会出错，m,n是变量，用来创建数组应该通不过的，可是测试却可以，不懂。求解答。 void copy_arr(int m,int n,const double arr[m][n],double arr1[m][n]); 函数传入数组参数，使用变量作为维度应该不被允许，应该要用常量，但这方面我也不熟不知道怎么改 copy_arr(m,n,array[][],array1[][]); 调用函数时只要写数组名就行了，像下面这样： copy_arr(m,n,array,array1); c99已经支持变长数组了，所以可以用变量

引用 1 楼 hdt 的回复:我记得c多维数组做参数，必须给定最后一维大小 编译器提示除了第一维，其他维度大小都要给出

我记得c多维数组做参数，必须给定最后一维大小


Question: 请教一个问题，这种写法是什么意思

谢谢各位不吝赐教

宏定义要写在同一行，一定要分多行写的时候，每一行的最后用'\'表示连接在一起

#define ASSERT_HANGUP_FAIL(e) \     if (e != UAPP_OK)\     {\         Util_ErrorBeep(1);\         _Ums_Remove_Card();\         Ums_CommHangUp(UHANGUP_DELAY);\         return UAPP_FAIL;\     }   ///把它想成一个函数就行了 ASSERT_HANGUP_FAIL 是函数名 e 是参数

宏定义，分多行写的形式。\符号是说明宏定义是一个整体


Question: 下面这个程序为什么执行时按回车没有反应

.不是回车符，\r才是回车，

[code=c] #include <stdio.h> #define PERIOD '.'         //定义PERIOD表示. int main(void) {  int ch; int charcount = 0;  while ((ch = getchar()) != PERIOD)   //当输入点（.）这个符号时，循环才会结束，按回车是不会结束循环的 {  if (ch != '"' && ch != '\'')    //当输入既不是双引号(")，也不是斜杠（\）的时候，charcount加1 charcount++;  } printf("There are %d non-quote characters.\n", charcount); return 0; }[/code]

#include <stdio.h>  #define PERIOD '.'  int main(void) {      int ch;     int charcount = 0;      while ((ch = getchar()) != PERIOD)     {          if (ch != '\"' && ch != '\\')             charcount++;      }     printf("There are %d non-quote characters.\n", charcount);      return 0; } 程序是遇到'.'退出循环。不过"和\都需要转义一下。

if (ch != '"' && ch != '\'') //ch不是"也不是'


Question: C语言数组多次初始化问题

引用 3 楼 cfjtaishan 的回复:通过循环或者用memset对其赋值5.2, calloc函数只是在堆上申请空间，并对其初始化为0谢谢， 我也是刚刚查到， 非常感谢

仅供参考：#include <windows.h> //#include <intrin.h> #include <stdio.h> #define COUNT 8000 __declspec(align(16)) float data[COUNT]; int i; unsigned __int64 nCtr2,nCtr1; int main() { //  for (i=0;i<COUNT;i++) {data[i]=1.0f;printf("%g\n",data[i]);}      QueryPerformanceCounter((LARGE_INTEGER *) &nCtr1);     __asm {         push ecx         push edi         mov ecx,COUNT         mov eax,0xBF800000 //-1.0f         lea edi,data         rep stosd         pop edi         pop ecx     }     QueryPerformanceCounter((LARGE_INTEGER *) &nCtr2);     printf("%I64u\n",nCtr2-nCtr1);      QueryPerformanceCounter((LARGE_INTEGER *) &nCtr1);     __asm {         push ecx         mov eax,0xBF800000 //-1.0f         mov ecx,COUNT/80         movd xmm0,eax         lea eax,data         pshufd xmm0,xmm0,0     __loop:         movdqa [eax+64],xmm0         movdqa [eax+48],xmm0         movdqa [eax+32],xmm0         movdqa [eax+16],xmm0         movdqa [eax],xmm0         add eax,80         sub ecx,1         jnz __loop         pop ecx     }     QueryPerformanceCounter((LARGE_INTEGER *) &nCtr2);     printf("%I64u\n",nCtr2-nCtr1);      QueryPerformanceCounter((LARGE_INTEGER *) &nCtr1); //  data[0]=-1.0f; //  __m128 m128=_mm_load_ps1((float *)&data[0]); //  for (i=0;i<COUNT;i+=4) _mm_store_ps1(&data[i],m128);     __asm {         push ecx         mov eax,0xBF800000 //-1.0f         movd xmm0,eax         shufps xmm0,xmm0,0         lea eax,data         mov ecx,eax         add ecx,COUNT*4 //COUNT*sizeof(float)     loop1:         movaps oword ptr [eax],xmm0         add eax,16         cmp eax,ecx         jb loop1         pop ecx     }     QueryPerformanceCounter((LARGE_INTEGER *) &nCtr2);     printf("%I64u\n",nCtr2-nCtr1);  //  for (i=0;i<COUNT;i++) printf("%g\n",data[i]);      return 0; } //36679 //2228 //4806 //

比如说， fortran 语言中就可以直接  integer :: i, n real, dimension (:,:), allocatable :: a allocate (a(size1, size2)) n = 10000 do i = 1, n   a = 5.2 end do 就会循环一万次，每一次都会直接把二维数组a中的所有元素都赋值为5.2


Question: 帮忙修改指向指针数组的指针问题，解决我注释的疑问。

虽然不会报错，但是毫无意义 比如 int *a[3],i,j,k; a[0]=&i;a[1]=&j;a[2]=&k; //区别 a[0]=23;a[1]=54;a[2]=77;

/*这儿不要对一堆野指针直接赋值，（N个野指针)*/        arry[i] = (int *)malloc(sizeof(int));         if (!arry[i])             return -1;                                                指针不是指向数组了吗？没赋值给数组的话还算是野指针吗？在这里一定要申请内存吗？

#include<stdio.h> #include<stdlib.h>  #define N 5  void _sequence(int *pointer[],int n);  int main() {     int *arry[N];     int **p;     int i;     p = arry;     printf("enter numbers :\n");     for(i=0;i<N;i++) {   /*这儿不要对一堆野指针直接赋值，（N个野指针)*/         arry[i] = (int *)malloc(sizeof(int));         if (!arry[i])             return -1;         scanf("%d", *(p + i));     }     //p = arry;         //冗余代码     _sequence(arry, N);     //p = arry;         //冗余代码     for(i=0;i<N;i++)     {         printf("%d\n",*(*(p+i)));     }     return 0; }  void _sequence(int *pointer[],int n) {     int i,j,k;     int *temp;    /*这个地方可以初始化为NULL，但也可以不初始化，因为下面是先对其赋值 */      for(i=0;i<n-1;i++)               //选择排序法     {         k=i;         for(j=i+1; j<n;j++)             if(*(*(pointer+k)) < *(*(pointer+j)))   /*应该是比较值，而不是指针（地址）*/                 k = j;         if(k!=i)         {             temp = *(pointer+k);             *(pointer + k) = *(pointer+i);             *(pointer+i) = temp;         }     } }  指针是比较晦涩的知识点，建议楼主好好体会。先从一重指针开始，然后是二重指针。 另外，建议弄懂两个概念：指针数组和数组指针。

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素 http://edu.csdn.net/course/detail/2455 C语言指针与汇编内存地址-二.函数 http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组 http://edu.csdn.net/course/detail/2517 C语言指针与汇编内存地址-四.三维数组

一般是不是要初始化z指向为NULL?   那种特意声明一个数组让其指向的又是有什么区别呢

int *temp;    //为啥指针不指向变量却可以直接用？  if(k!=i)         {           temp=*(pointer+k);   *(pointer+k)=*(pointer+i);   *(pointer+i)=temp;	 } 根据你的代码，temp指针虽然没有初始化，但是你第一次使用前会先让它指向变量temp=*(pointer+k);就没问题了。如果没有指向变量就去访问指针就不允许。


Question: 关于C语言数组的问题

才看到，敲错了

1 数组的初始化 在函数体外定义的内置数组，其元素均初始化为0；在函数体内定义的内置数组，其元素无初始化。 数组arr1是在函数体内部定义的，所以没有初始化。我在VS2015 Windows64位下的输出是  数组arr1的地址是0x0x00effd60，从下图可以看到，arr1数组中所有元素的值都是0xCCCCCCCC，即-858993460  可以在你的程序中观察arr1的地址，之后查看该地址中的值，是否是0x00000004 2 数组下标 你程序的目的应该是输出arr1的所有元素，在调用aranpo()函数后，再次输出arr1的所有元素。需要注意的是，数组元素从0开始计数，对于一个包含5个元素的数组，正确的下标值是0到4，而不是1到5。所以，我觉得你的代码应该都是   for(int i =0;i<5;i++)     printf("%d  ",arr1[i]); 而不是  for(int i =0;i<5;i++)     printf("%d  ",arr1[5]); 此时的输出可以看到，在调用aranpo()函数后，arr1数组中的元素与arr数组中的元素相同了。但是第一次输出arr1的数组时仍然是-858993460，可以考虑在定义arr1数组时对其进行初始化  int arr1[5] = { 0 }; 此时的输出为

请那些喜欢将数组作为函数参数传来传去或作为函数返回值的码农思考一下为什么不把整个互联网内容当作函数参数传来传去或作为函数返回值呢？

其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。  判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

打印arr1[5]是一个越界行为，下标只能从0～4，对于越界行为结果是未定义的，也有可能是段错误出现。

引用 5 楼 JILAU_WHO_AM_I_Q234 的回复:传递数组作为参数实际上是指针对吧，也就是说可以在函数中修改原来的数据 是的，传递数组其实传的是地址

传递数组作为参数实际上是指针对吧，也就是说可以在函数中修改原来的数据

输出的都是一个值！

int arr[5]，实际上只有 arr1[0],arr1[1],arr1[2],arr1[3],arr1[4]五个元素，你用的arr1[5]已经超出了范围，显示的就不知道是什么了~~~  #include <stdio.h> void aranpo(const int array[],int array1[],int n); int main(void) {     int arr[5] = {4,6,2,3,9};     int arr1[5];     for(int i =0;i<5;i++)     printf("%d  ",arr1[i]);     putchar('\n');     aranpo(arr,arr1,5);      for(int i =0;i<5;i++)     printf("%d  ",arr1[i]);     putchar('\n');     return 0; }  void aranpo(const int array[],int array1[],int n)   {     for(int i = 0;i<n;i++)     {         array1[i] = array[i];      }        }

你打印的一直是 arr1[5]，所以输出的都是同一个值。而且 5 越界了，应该是 0-4，所以输出的值是什么应该是无法预测的。我的编译器结果就是输出 0.

循环变量没有用上呀  void aranpo(const int array[],int array1[],int n) { 	for(int i = 0;i<n;i++) 	{ 		array1[i] = array[i]; 	}  }  int _tmain(int argc, _TCHAR* argv[]) { 	int arr[5] = {4,6,2,3,9}; 	int arr1[5]; 	for(int i =0;i<5;i++) 		printf("%d  ",arr[i]); 	putchar('\n'); 	aranpo(arr,arr1,5); 	for(int i =0;i<5;i++) 		printf("%d  ",arr1[i]); 	putchar('\n'); 	return 0; }


Question: 怎样实现一个平面任意切割长方体的体积算法？

谢谢！我得思考一下

至少要分这么多情况分别讨论吧：

能不能稍微讲的细一点！

布尔操作。 编辑对象、物理属性、体积。

参考中文版3DS Max联机帮助。

体积难道会变化 ???


Question: C语言比较三个数字大小求助

引用 3 楼 cfjtaishan 的回复:代码是没问题，编辑程序建议切换至英文输入法，并且是半月状态。  谢谢，确实是输入法的原因，新手，见笑了

代码没有问题！

代码是没问题，编辑程序建议切换至英文输入法，并且是半月状态。

引用 1 楼 D1352612146 的回复:你好，代码没有出错，我用你的代码跑了，结果正确，你可能是跑的时候输入过程中没有切换成英文输入法的问题.  之前用的win10，没有默认英文输入法，用的搜狗，运行3个正数没问题，就运行第二个数是负数不行，切换之后结果都正确了，估计是搜狗输入法下负号的原因，谢谢

复制过来的代码运行，没毛病。。。

估计楼主输入了空格，导致了数字识别提前结束。。。

代码跑了一遍，没毛病！


Question: 关于“流stream”的问题

个人认为流是最伟大的抽象之一。  在真正理解这个概念之前，建议学学Linux的命令行操作，感受下“流”的实际应用。

引用 2 楼 赵4老师的回复:源码面前，了无秘密。  理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后，就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 谢谢。。。。。。。。

第三行的“世纪”改为“实际”！


Question: c语言怎么动态调用dll函数

http://blog.csdn.net/zhao4zhong1/article/details/53078924 老司机找bug的十年心路历程

引用 8 楼 ccssddnn218 的回复:支持 zhao4zhong1 的大多数观点，他更多的时候是在告诉新人为什么这样做，以及如何去做，在阐述一种通用方法；而不是一个简单的答案。我为什么支持？因为我就受益于他的很多回复，从新手到菜鸟，再到目前，一个稍微有点经验的菜鸟。 http://my.csdn.net/zhao4zhong1

引用 6 楼 zhao4zhong1 的回复:[quote=引用 5 楼 qq_35824650 的回复:] 2楼正解3楼的有点乱 2楼只是说说；3楼才是干货！[/quote] http://bbs.csdn.net/topics/390374955

其实DLL都是动态加载，你想问的是不是 如何显式调用dll

引用 5 楼 qq_35824650 的回复:2楼正解3楼的有点乱 2楼只是说说；3楼才是干货！

不是这样的吧，而是将动态库里的函数加载到内存，根据输入的数据，指定执行内存中函数的地址。

注：就像Python交互编程一样

2楼正解3楼的有点乱

LoadLibrary

先下载安装MSDN98 MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl  再参考： MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\TRACERES.H MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\TRACEAPI.H MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\DLLTRACE.DSP MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\DLLTRACE.DSW MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\DLLTRACE.MAK MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\DLLTRACE.RC MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\HELLO.ICO MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\MAKEFILE MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\RESOURCE.H MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\TRACE.CLW MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\TRACE.CPP MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\TRACE.DEF MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\TRACE.MAK MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\TRACE.RC MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\TRACE1.DSP MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\DLLTRACE.CLW MSDN98\SAMPLES\VC98\MFC\ADVANCED\DLLTRACE\DLLTRACE.CPP


Question: 第一个WINDOWS程序，怎么也编译不过。原因应该很简单，可惜我就是不知道。。求大神

1.Gdi32.lib有没有加到你的项目中？ 2.项目的编码格式是Unicode还是多字节？


Question: C语言初学者 求助帖

continue不是函数，continue就是从本行开始跳到循环开始（包括修改循环变量和判断循环条件），continue之后的循环体不再执行

continue的作用是如果ch大于9或者小于0（即字符ch不是数字字符的话），不执行下一句sum++,直接continue回到for当中，进行下一次for循环

continue语句导致最近的循环语句的当次迭代提前结束。对于while和do while语句，继续求解循环条件；对于for循环，程序流程接着求解for语句头中的express表达式。 for (i = 0; i < 30; i++) { ch = getchar(); if (ch < '0' || ch > '9') { continue; } sum++; } 如果ch小于’0’或者ch大于’9’，此时说明输入的不是数字字符，则执行continue语句。此时，程序不会向下执行sum++，而是执行for循环中的i++。即当输入的不是数字字符时，数字字符数量不变，而是继续获取下一个输入的字符。 continue语句只能出现在for、while或者do while循环中，包括嵌套在这些循环内部的块语句中。

学习

如果ch不是数字，if语句满足，就会执行continue，本次for循环体内continue之后的语句就不再执行。进入下一次if判断。

如果CH不是数字，就继续下一次循环了。 Continue语句作用就是直接跳至下一次循环，循环体内continue后面的语句不会执行（Sum++），这样就如果输入的是数字，就不会执行continue,而执行sum++

if (ch < '0' || ch > '9') { continue; } 如果小于1 大于9  也就是说如果不是数字 就重新循环 不执行下面的语句   这就是continue


Question: printf("%f ",3);输出的是0000？

因为float和int的存储结构在内存中完全不一样。所以会出现这么奇怪的问题。

谢谢，其实我想了解下，看什么书可以从计算机设计的层面理清这个现象的原因？

并不相同，由于%f适用于输入输出f'loat类型的，而3是整形的无法识别，才显示为0.0000，如你输出的是浮点型的就能正常识别了。 例：把3改为3.0

引用 7 楼 kakabulusi 的回复:[quote=引用 3 楼 lin5161678 的回复:] [quote=引用 2 楼 kakabulusi 的回复:] 楼上正解，使用强制转换操作，将数字转化一下格式就能正常显示了。 写成  3f   3.00   都可以实现转换， 除法运算中，也需要进行相应的处理  整数/整数  equal  整数，如果需要转换，写成  3.00/2 或者 3/2.00 或者强制转换后再进行乘除，系统在运算时候会自动对齐操作后再进行运算操作。 3f是语法错误[/quote] 3f 是高版本C++的隐式转换声明，也可能和编译器本身有关，[/quote]应该是你记错了  就算是 C++14  3f 也是一个语法错误

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

一般都是变量在printf里，直接3的话有问题吧。再者3是int型。%f是输出float型，不匹配啊。

引用 7 楼 kakabulusi 的回复:[quote=引用 3 楼 lin5161678 的回复:] [quote=引用 2 楼 kakabulusi 的回复:] 楼上正解，使用强制转换操作，将数字转化一下格式就能正常显示了。 写成  3f   3.00   都可以实现转换， 除法运算中，也需要进行相应的处理  整数/整数  equal  整数，如果需要转换，写成  3.00/2 或者 3/2.00 或者强制转换后再进行乘除，系统在运算时候会自动对齐操作后再进行运算操作。 3f是语法错误[/quote] 3f 是高版本C++的隐式转换声明，也可能和编译器本身有关，[/quote]哪个版本?

引用 3 楼 lin5161678 的回复:[quote=引用 2 楼 kakabulusi 的回复:] 楼上正解，使用强制转换操作，将数字转化一下格式就能正常显示了。 写成  3f   3.00   都可以实现转换， 除法运算中，也需要进行相应的处理  整数/整数  equal  整数，如果需要转换，写成  3.00/2 或者 3/2.00 或者强制转换后再进行乘除，系统在运算时候会自动对齐操作后再进行运算操作。 3f是语法错误[/quote] 3f 是高版本C++的隐式转换声明，也可能和编译器本身有关，

3/2  是int类型运算 3.0/2 是浮点类型运算 printf不存在隐式类型转换

输出前要进行类型转换，printf（）不会帮你转换的，如果格式不对就会这样。 	printf ("%f\n",(float)3);

浮点数格式 http://bbs.csdn.net/topics/390676437

建议了解一下float在内存中存储方式 http://blog.csdn.net/yezhubenyue/article/details/7436624 建议参考一下这个博主的博客～

引用 2 楼 kakabulusi 的回复:楼上正解，使用强制转换操作，将数字转化一下格式就能正常显示了。 写成  3f   3.00   都可以实现转换， 除法运算中，也需要进行相应的处理  整数/整数  equal  整数，如果需要转换，写成  3.00/2 或者 3/2.00 或者强制转换后再进行乘除，系统在运算时候会自动对齐操作后再进行运算操作。 3f是语法错误

Float 的存储结构和int 不同


Question: 如何把从文件读出的内容按以下格式存入的链表中

解析usr和password，然后创建节点，加入链表； 两个难点：解析出usr和password,然后是创建链表；创建链表可以从网上搜一下方法。

读取配置文件，使用节点方式


Question: C编译后弹出的命令提示符黑框中无法滚动翻页！也无法右键弹出菜单！

引用 4 楼 fight_in_dl 的回复:引用布局……  选择回答这道题，为什么不好好回答呢，这么语焉不详，典型的混分行为。 没看到截图中有“布局”二字吗？

谢谢各位的回答，我已经知道原因了，特此分享：  如果源代码中有“完成程序功能后循环输入"的语句时，则会出现这种情况，例如：  请输入：XXX XXX（实现功能） 输入N退出程序，否则继续输入：  有这样的代码，则会出现我所说的问题！如果源代码中没有循环输入语句，则一切正常！

布局……

引用 1 楼 fight_in_dl 的回复:引用不能右键弹出上图所示的菜单栏了  如图1，在cmd窗口标题栏上右键点击，打开属性设置对话框   如图2，不要勾选快速编辑模式   谢谢第一时间回答！我目前恰好就只能用你这个方法实现滚动翻页和复制、粘贴等命令！ 如果没有勾选“快速编辑模式”  反而会出现我现在遇到的问题（即是无法滚动翻页和弹出右键菜单）！


Question: 关于指针的使用问题

char *test3() {     static char buf[120];     char tempbuf[100];      strncpy(tempbuf, "the be in the", strlen("the be in the") + 1);     //printf(tempbuf);     puts(tempbuf);     strcpy(buf,(char*)"Game's Over");      return buf; }

malloc/free     new/delete 是一对在堆上开辟内存区的函数，通常情况下是配对使用的。如果只进行前半部分操作，程序不停的开辟内存区而不释放，最终会导致内存资源耗尽直至死机。  另外，malloc  new开辟的内存区与应用程序本身的生命周期相同，而与函数无关，这一点尤其要注意

万分感谢大神指点

#include<stdio.h> #include <stdlib.h> #include<string.h>  void test2() {     int i;   /* 改成有符号类型*/      char *aa[] = {"11","22","33","44","55"};      for(i = 4; i>=0;i--)    /*去掉;*/     {         printf("\n");         printf("%s\n", aa[i]);    /* printf参数有问题 或用puts(aa[i]);*/     }     return; }  char *test3() {     char buf[120];     char *tempbuf;      tempbuf = (char*)malloc(100*sizeof(char));     strncpy(tempbuf, "the be in the", strlen("the be in the") + 1);     //printf(tempbuf);     puts(tempbuf);     strcpy(buf,(char*)"Game's Over");      return buf; } int main() {     char *p;     char buf[15]= "asdsfgdhfhgjk";     const int num2 = 2;      test2();     p = buf;      printf("%s\n",buf);      strcpy(buf,p); }  以上是修改后的代码，参考一下吧; 很疑惑，main函数里printf用对了，为什么test2和test3中的printf就用错了呢？ 另外， test3中return buf局部变量，是未定义行为。

引用 4 楼 XiaRiKuHan 的回复:是因为我返回的是局部变量的地址所以不能拷贝么？ 是的，test3里面的buf是局部变量，出了函数就没有了。 楼主可以像下面这句一样，先用malloc分配内存，就可以了。 tempbuf = (char*)malloc(100*sizeof(char));

是因为我返回的是局部变量的地址所以不能拷贝么？

/*我把main函数改成这个样子，如何使最后的buf有数据输出*/ int main() { 	char *p; 	char buf[15]= "asdsfgdhfhgjk"; 	const int num2 = 2;  	test2(); 	p= test3();  	printf("p=%s\n",p);  	memset(buf,0,sizeof(buf)); 	strcpy(buf,p);    //哪里不对 	printf("buf=%s\n",buf);    	return 0; }


Question: 新手求助！！！

引用 2楼kugeniha 的回复:#include <stdio.h>  int main()  {      int n = 4;      float x, y, z, s = 0;      printf( "请输入第1个数：");      scanf("%f", &x);      printf( "请输入第2个数：" );      scanf("%f", &y);      printf( "请输入第3个数：" );      scanf("%f", &z);      s = y+z;      while ( x || y || z)      {          s = s + x;         z=y;         y=x;         printf( "请输入%d个数:", n++ );          scanf("%f", &x);               }      printf( "\ns=%f", s);  }感谢

引用 1楼自信男孩 的回复:#include <stdio.h> int main() {     int n = 4, cnt = 0;     float x, y, z, s = 0;     printf( "请输入第1个数：");     scanf("%f", &x);     printf( "请输入第2个数：" );     scanf("%f", &y);     printf( "请输入第3个数：" );     scanf("%f", &z);     s = y;     while ( x || y || z)     {         s = s + x;         if (cnt == 1)             y = x;         if (cnt == 2)             z = x;         printf( "请输入%d个数:", n++ );         scanf("%f", &x);         if (x != 0)             cnt = 0;         else             cnt++;     }     printf( "\ns=%f", s); } 试一下这种情况。 这个程序有一个bug,即float类型数据，判断是否为0，不能直接与0比较，而是fabs(x) < 0.000001(1e-6);感谢


Question: 用关键字static声明全局const变量的问题

static 出现在函数内部时才具有让  变量是存储在整个程序的“全局数据区域“  的作用. 出现在全局变量和函数定义前面是只是让链接属性变为内部链接而已, 你可以打印变量的地址出来看, 不同的 .c 里面定义的同名的 static 全局变量地址是不一样的.

引用 3 楼 adlay 的回复:[quote=引用 2 楼 cfjtaishan 的回复:] include是在预编译阶段执行的，即将头文件里的内容放到.c文件里。既然const变量在头文件里，那么就是两个.c文件都有该变量的声明了。 加static就不一样了，static的变量（全局）其作用域只能是所在文件里。若在头文件里定义的static变量，只能在头文件里使用。.c文件不能使用。 加了 static, 头文件的内容一样会被插入到两个 .c 里面去的. static 是让两个 .c 出现相同的名字时链接的时候不会冲突 [/quote] 嗯，你说的很对。我的想法是有问题的～刚才简单写代码试了一下

引用 2 楼 cfjtaishan 的回复:include是在预编译阶段执行的，即将头文件里的内容放到.c文件里。既然const变量在头文件里，那么就是两个.c文件都有该变量的声明了。 加static就不一样了，static的变量（全局）其作用域只能是所在文件里。若在头文件里定义的static变量，只能在头文件里使用。.c文件不能使用。 加了 static, 头文件的内容一样会被插入到两个 .c 里面去的. static 是让两个 .c 出现相同的名字时链接的时候不会冲突

include 就是把文件的内容插入到当前位置 两个 .c 里面 include 那个头文件就在两个 .c 里面都插入了这个头文件的内容.

引用 5 楼 user-3的回复:还有一种解释： static变量是存储在整个程序的“全局数据区域“，因此即使这个变量被多次插入到.c文件里，实际上仍然是指向同一个变量。 我的理解是：如果没有static那么就相当于在两个c文件都定义式声明了自动变量，然而这两个文件里虽然名字相同，但是分配的内存不同。这样的？


Question: 新手求教哪里错，详细指出

引用 楼主 qq_39681830 的回复:#include<stdio.h> int main() { int i=0; int pass; printf("请输入密码"); scanf("%d",&pass);        while(i<3)        {             if(123!=pass)             {                   printf("密码输入错误，当前输入第%d次密码.\n",i+1);             }              i++        }         return 0;  //自己对比 }

少了个大括号｝

#include<stdio.h>  int main() {     int i=0;     int pass;      printf("请输入密码");     scanf("%d",&pass);     while(i<3)     {         if(123 != pass) {             printf("密码输入错误，当前输入第%d次密码.\n",i+1);         } else {             break;         }         i++;         printf("请输入密码");         scanf("%d",&pass);     }     return 0; } 逻辑应该是这样吧

非常感谢各位

引用 6 楼 zhao4zhong1 的回复:偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。  这个方法是我经常用的。。。。。调试程序，特别是别人的程序，速度很快的。

输入密码的printf和scanf应该放在循环里吧，判断密码是否正确的if应该加else并return密码正确 循环外再用一个return 返回密码错误 好像是这个意思

4楼是对的。另外编辑器应该会提示出错的原因，楼主还是根据报错，去自己找，或者百度下。

return 0拿到大括号外面去


引用 9 楼 ccssddnn218 的回复:[quote=引用 8 楼 qq_38080117 的回复:] [quote=引用 2 楼 zhao4zhong1 的回复:] #pragma warning(disable:4996) ...问下这个东西是什么意思？用了它VS就不会报错了吗？[/quote] 出现这样的警告，是因为VC2005之后的版本中认为CRT中的一组函数如果使用不当，可能会产生诸如内存泄露、缓冲区溢出、非法访问等安全问题。这些函数如：strcpy、strcat等。  对于这些问题，VC2005建议使用这些函数的更高级的安全版本，即在这些函数名后面加了一个_s的函数。这些安全版本函数使用起来更有效，也便于识别，如：strcpy_s,calloc_s等。  当然，如果执意使用老版本、非安全版本函数，可以使用_CRT_SECURE_NO_DEPRECATE标记来忽略这些警告问题。办法是在编译选项 C/C++ | Preprocessor | Preprocessor Definitions中，增加_CRT_SECURE_NO_DEPRECATE标记即可。  另外一种解决方法: #pragma warning(disable:4996) //全部关掉 选自：http://www.cnblogs.com/bpbp/archive/2011/07/12/2104775.html[/quote]谢谢大神指点！

引用 8 楼 qq_38080117 的回复:[quote=引用 2 楼 zhao4zhong1 的回复:] #pragma warning(disable:4996) ...问下这个东西是什么意思？用了它VS就不会报错了吗？[/quote] 出现这样的警告，是因为VC2005之后的版本中认为CRT中的一组函数如果使用不当，可能会产生诸如内存泄露、缓冲区溢出、非法访问等安全问题。这些函数如：strcpy、strcat等。  对于这些问题，VC2005建议使用这些函数的更高级的安全版本，即在这些函数名后面加了一个_s的函数。这些安全版本函数使用起来更有效，也便于识别，如：strcpy_s,calloc_s等。  当然，如果执意使用老版本、非安全版本函数，可以使用_CRT_SECURE_NO_DEPRECATE标记来忽略这些警告问题。办法是在编译选项 C/C++ | Preprocessor | Preprocessor Definitions中，增加_CRT_SECURE_NO_DEPRECATE标记即可。  另外一种解决方法: #pragma warning(disable:4996) //全部关掉 选自：http://www.cnblogs.com/bpbp/archive/2011/07/12/2104775.html

引用 2 楼 zhao4zhong1 的回复:#pragma warning(disable:4996) ...问下这个东西是什么意思？用了它VS就不会报错了吗？

引用 5 楼 hou09tian 的回复:这是strcpy()函数的格式  char *strcpy(      char *strDestination,      const char *strSource    );    这是strcpy_s()函数的格式  errno_t strcpy_s(      char *strDestination,      size_t numberOfElements,      const char *strSource    );   可以看出strcpy()函数是两个参数，而strcpy_s()函数的参数是三个；所以直接把strcpy()改为strcpy_s()就会提示strcpy_s缺少参数。strcpy()函数的第一个参数表示目的字符串，第二个参数表示源字符串；strcpy_s()的第一个参数表示目的字符串；第二个参数表示目的字符串中元素的个数；第三个参数表示源字符串；如果把strcpy()改为strcpy_s()，只需要再为strcpy_s()添加一个参数，该参数添加到strcpy_s()函数的第二个参数位置上，为目的字符串中元素的个数，如  char dest[100] = {0}; strcpy(dest, "12345");  改为  char dest[100] = {0}; strcpy_s(dest,100, "12345"); 明白了，万分感谢！

引用 2 楼 zhao4zhong1 的回复:#pragma warning(disable:4996) ...好的，谢谢

那就是说其他平台不能用了？

#pragma warning(disable:4996) ...

缺少必要的头文件，你查一下这两个函数在哪个头文件里面，然后包含进去就行了


Question: 字符串的操作求助

仅供参考 #define LEN 64 struct DATA { 	char name[LEN]; 	char password[LEN]; 	DATA *next; };  // 解析字符串，构建链表 void BuildList(const char * src ,DATA **pHead) { 	DATA *pTemp = *pHead; 	const char *pEnd = src + strlen(src); 	const char* pPos1 = src-1; 	const char* pPos2 = pPos1; 	const char* pPos3 = pPos1;  	while (pPos1 < pEnd && pPos2 && pPos3 ) 	{ 		pPos2 = strstr(pPos1, ":"); 		if (pPos2) 		{ 			pPos3 = strstr(pPos2, ";"); 		} 		if (!pPos2 || !pPos3) 		{ 			break; 		} 		DATA *p = (DATA*)malloc(sizeof(DATA)); 		memset(p->name, 0, LEN); 		memset(p->password, 0, LEN); 		p->next = NULL; 		strncpy(p->name, pPos1 + 1, pPos2 - pPos1 - 1); 		strncpy(p->password, pPos2 + 1, pPos3 - pPos2 - 1); 		if (*pHead) 		{ 			(*pHead)->next = p; 			*pHead = p; 		} 		else 		{ 			*pHead = p; 			pTemp = *pHead; 		} 		pPos1 = pPos3; 	} 	*pHead = pTemp; }  // 销毁链表 void DestroyList(DATA *pHead) { 	DATA *p = NULL; 	while (pHead) 	{ 		p = pHead->next; 		free( pHead); 		pHead = p;  	} }  int _tmain(int argc, _TCHAR* argv[]) { 	char str[] = "user1:dsfds;user2:vcfgfe767fd;user3:user3lfjdk87f;";  	// 构建链表 	DATA *pHead = NULL; 	BuildList(str, &pHead);  	// 浏览一下 	DATA *p = pHead; 	while (p) 	{ 		printf("[%s]:[%s]\n", p->name, p->password); 		p = p->next; 	}  	// 释放链表空间 	DestroyList(pHead);  	return 0; }

也可以使用sscanf来实现

自己写一个split ，先按照;分开，再按照：分开

仅供参考：#include <stdio.h> char s[]="123 ab 4"; char *p; int v,n,k; void main() {     p=s;     while (1) {         k=sscanf(p,"%d%n",&v,&n);         printf("k,v,n=%d,%d,%d\n",k,v,n);         if (1==k) {             p+=n;         } else if (0==k) {             printf("skip char[%c]\n",p[0]);             p++;         } else {//EOF==k             break;         }     }     printf("End.\n"); } //k,v,n=1,123,3 //k,v,n=0,123,3 //skip char[ ] //k,v,n=0,123,3 //skip char[a] //k,v,n=0,123,3 //skip char[b] //k,v,n=1,4,2 //k,v,n=-1,4,2 //End.

有相应的C的库函数，先按“；”分隔，然后再按“：”分隔，这样就能取到值了


Question: 链表删除问题，与常规删除节点不同

引用 2 楼 cfjtaishan 的回复:void delet(int disnum, n *head) {     n p, q;      p = q = *head;     while (p) {         if (p->data == disnum) {             if (p == *head) {                 *head = (*head)->next;                 free(p);                 p = q = *head;                 continue;             } else {                 q->next = p->next;                 free(p);                 p = q;                 p = p->next;                 continue;             }         }         q = p;         p = p->next;     } } 试一下这个版本。  以下是我的测试代码：  #include <stdio.h> #include <stdlib.h>  typedef struct node {     int data;     struct node *next; }*n;   n create_link(int num) {     int i;     n p, q, phead = NULL;      for (i = 0; i < num; i++) {         p = (n)malloc(sizeof (struct node));         if (!p) {             fprintf(stderr, "malloc error!\n");             exit(-1);         }         scanf("%d", &p->data);          if (!phead) {             phead = p;             q = p;         } else {             q->next = p;             q = p;         }     }     q->next = NULL;      return phead; }  void print_link(n phead) {     n p = phead;      while (p) {         printf("%d\t", p->data);         p = p->next;     }     putchar(10); }  void delet(int disnum, n *head) {     n p, q;      p = q = *head;     while (p) {         if (p->data == disnum) {             if (p == *head) {                 *head = (*head)->next;                 free(p);                 p = q = *head;                 continue;             } else {                 q->next = p->next;                 free(p);                 p = q;                 p = p->next;                 continue;             }         }         q = p;         p = p->next;     } }  int main(void) {     int num;     n head;      scanf("%d", &num);     head = create_link(num);     print_link(head);      scanf("%d", &num);     delet(num, &head);     print_link(head);     return 0; }  你好棒棒啊，我去思考下你代码了，

引用 2 楼 cfjtaishan 的回复:void delet(int disnum, n *head) {     n p, q;      p = q = *head;     while (p) {         if (p->data == disnum) {             if (p == *head) {                 *head = (*head)->next;                 free(p);                 p = q = *head;                 continue;             } else {                 q->next = p->next;                 free(p);                 p = q;                 p = p->next;                 continue;             }         }         q = p;         p = p->next;     } } 试一下这个版本。  以下是我的测试代码：  #include <stdio.h> #include <stdlib.h>  typedef struct node {     int data;     struct node *next; }*n;   n create_link(int num) {     int i;     n p, q, phead = NULL;      for (i = 0; i < num; i++) {         p = (n)malloc(sizeof (struct node));         if (!p) {             fprintf(stderr, "malloc error!\n");             exit(-1);         }         scanf("%d", &p->data);          if (!phead) {             phead = p;             q = p;         } else {             q->next = p;             q = p;         }     }     q->next = NULL;      return phead; }  void print_link(n phead) {     n p = phead;      while (p) {         printf("%d\t", p->data);         p = p->next;     }     putchar(10); }  void delet(int disnum, n *head) {     n p, q;      p = q = *head;     while (p) {         if (p->data == disnum) {             if (p == *head) {                 *head = (*head)->next;                 free(p);                 p = q = *head;                 continue;             } else {                 q->next = p->next;                 free(p);                 p = q;                 p = p->next;                 continue;             }         }         q = p;         p = p->next;     } }  int main(void) {     int num;     n head;      scanf("%d", &num);     head = create_link(num);     print_link(head);      scanf("%d", &num);     delet(num, &head);     print_link(head);     return 0; }  谢谢

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633


Question: c语言修改文本文件的特定行的特定元素

程序目前不能直接修改文件里指定行或指定行里的某列。只能现将数据加载（读）到内存，在内存里修改，然后再写到文件里。 根据你的文件数据格式，建议使用fscanf/fprintf来操作。自己先写写吧，有问题再提出来。

引用应该怎么办  照这个例子改吧：http://www.sanfoundry.com/c-program-update-employee-details-employee-files/ 说明： 1  重点看update_rec函数 2  题目中记录的关键列是 套餐编号，以它为索引进行查找并修改对应记录，注意 套餐编号 不能重复  能照着例子把题目完成，C语言这门课就可以毕业了^_^

所谓修改删除文件a某位置的内容，其实是读打开文件a，再将‘a中修改删除位置之前的内容＋修改删除的内容＋a中修改删除位置之后的内容’保存到文件b，关闭文件a，删除文件a，将文件b改名为与之前文件a相同的名字，仅此而已。http://bbs.csdn.net/topics/391975224


Question: fscanf函数可以把从文件中提取出的内容分割如下格式分别存入相应的变量中吗？

仅供参考：//NAME: essaie bla bla //DIMENSION: 8 //DATA //1  14  15 //2  11  10 //3  6   4 //4  7   13 //5  9   21 //6  19  3 //7  1   5 //8  8   8 //EOF // // 文本文件中可能还含有其他内容，但是需要用到的内容即以上  //比如data.txt: //NAME: essaie bla bla //其它内容 //DIMENSION: 8 //其它内容 //DATA //其它内容 //1  14  15 //其它内容 //2  11  10 //其它内容 //3  6   4 //其它内容 //4  7   13 //其它内容 //5  9   21 //其它内容 //6  19  3 //其它内容 //7  1   5 //其它内容 //8  8   8 //其它内容 //EOF  // 目标是要获取NAME后字串，DIMENSION后数值，以及DATA以下的数值 // 其中NAME就是随便个字句，DIMENSION是城市数量，DATA以下是城市编号，X坐标，Y坐标 // 所有的这些将赋值给一个事先定义好的结构 #include <stdio.h> #include <string.h> #define MAXCPL   80   //每行最大字符数 #define MAXCITY  100  //每组数据中DATA最多项数，DIMENSION的最大值 #define MAXNAMEL 32   //NAME最大长度 struct S {     char NAME[MAXNAMEL+1];     int  DIMENSION;     struct D {         int NO;         int X;         int Y;     } DATA[MAXCITY]; } s; FILE *f; int st,n,i; char ln[MAXCPL]; int main() {     f=fopen("data.txt","r");     if (NULL==f) {         printf("Can not open file data.txt!\n");         return 1;     }     st=0;     n=0;     while (1) {         if (NULL==fgets(ln,MAXCPL,f)) break;         if (st==0) {             if (1==sscanf(ln,"NAME: %31[^\n]",s.NAME)) st=1;         } else if (st==1) {             if (1==sscanf(ln,"DIMENSION: %d",&s.DIMENSION)) st=2;         } else if (st==2) {             if (0==strcmp(ln,"DATA\n")) st=3;         } else if (st==3) {             if (3==sscanf(ln,"%d%d%d",&s.DATA[n].NO,&s.DATA[n].X,&s.DATA[n].Y)) {                 n++;                 if (n>=MAXCITY || n>=s.DIMENSION) break;             }         }     }     fclose(f);     printf("s.NAME=[%s]\n",s.NAME);     printf("s.DIMENSION=%d\n",s.DIMENSION);     for (i=0;i<n;i++) {         printf("s.DATA[%d].NO,X,Y=%d,%d,%d\n",i,s.DATA[i].NO,s.DATA[i].X,s.DATA[i].Y);     }     return 0; } //s.NAME=[essaie bla bla] //s.DIMENSION=8 //s.DATA[0].NO,X,Y=1,14,15 //s.DATA[1].NO,X,Y=2,11,10 //s.DATA[2].NO,X,Y=3,6,4 //s.DATA[3].NO,X,Y=4,7,13 //s.DATA[4].NO,X,Y=5,9,21 //s.DATA[5].NO,X,Y=6,19,3 //s.DATA[6].NO,X,Y=7,1,5 //s.DATA[7].NO,X,Y=8,8,8

当不止一个user_list的时候，会把下一行的值输入到最后一个password[64]这怎么办 就像这样 0 user:[user1] password:[user1abcd] 1 user:[;user2] password:[user2abcd] 2 user:[;user3] password:[user3abcd] 3 user:[;user4] password:[user4abcd  user_list2=user5:user5abcd] 多读了后面的user_list2的值

作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。 //in.txt: //user_list1=user1:user1abcd;user2:user2abcd;user3:user3abcd; #include <stdio.h> struct UP {     char user[64];     char password[64]; } ups[10]; int n,i; FILE *f; int main() {     f=fopen("in.txt","r");     if (f==NULL) {         printf("Can not open file in.txt!\n");         return 1;     }     n=0;     if (2==fscanf(f,"%*[^=]=%63[^:]:%63[^;]",ups[n].user,ups[n].password)) {         n++;         while (1) {             if (2==fscanf(f,";%63[^:]:%63[^;]",ups[n].user,ups[n].password)) {                 n++;                 if (n>=10) break;             } else {                 break;             }         }     }     fclose(f);     for (i=0;i<n;i++) {         printf("%d user:[%s] password:[%s]\n",i,ups[i].user,ups[i].password);     }     return 0; } //0 user:[user1] password:[user1abcd] //1 user:[user2] password:[user2abcd] //2 user:[user3] password:[user3abcd] //

fscanf(fp, "%s:%s;", user, password); 试试这种形式；


Question: 指针的指针，可以的话顺便找位老师，有空能帮忙指出我写不好的错误代码就万分感谢啦！

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素 http://edu.csdn.net/course/detail/2455 C语言指针与汇编内存地址-二.函数 http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组 http://edu.csdn.net/course/detail/2517 C语言指针与汇编内存地址-四.三维数组

恩，谢谢两位，我在吸收呢，我现在疑惑，用指针对地址内容进行修改，不是也可以吗？

引用 2 楼 lgbxyz 的回复:字符串是存储在静态区,不是string数组中,不能通过strcpy等等任何方式修改  #include <stdio.h> #include <string.h>  int main(void) { 	char *string[] = {"english", "frans", "vcpuls", "understan", "forced"}; 	char **pointer = string; 	char a[10]; 	char *temp = a; 	int i, j, k; 	 	for(j = 0; j < 4; j++) { 		k = j; 		for(i = j; i < 5; i++) {    			if(strcmp(*(pointer+i), *(pointer+k)) > 0) { 				k=i;    			} 		}    		if(k != j) {  			temp = string[j]; 			string[j] = string[k];          	string[k] = temp; 		} 	} 	 	for(i = 0; i < 5; i++)     	printf("%s\n",*(pointer+i)); 	 	return 0; }     这种办法也不错哦～+++

开辟栈动态区我还没掌握···这道题出在指针数组那章的。为啥平常的数字可以交换更改数据呀，这里的指针数组却不行？指针指向的是*string的地址呀，为啥用temp = string[j];   呀。                                                 string[j] = string[k];                                                 string[k] = temp;

#include<stdio.h> #include<string.h>  int main() {     char string[][10] = {"english","frans","vcpuls","understan","forced"};     char (*pointer)[10];     char *temp;     char a[10];     temp = a;     int i,j,k;      pointer = string;     for(j=0;j<4;j++)     {         k = j;         for(i =j + 1; i < 5; i++)             if(strcmp(*(pointer+i),*(pointer+k)) > 0)                 k = i;         if(k != j)         {             strcpy(temp,*(pointer+k));             strcpy(*(pointer+k), *(pointer+j));             strcpy(*(pointer+j),temp);         }     }      for(i=0;i<5;i++)         printf("%s\n",*(pointer+i));     return 0; }  改一下即可； string是指针数组，里面的字符串都是字符串常量，因此是不可以修改的。但是选择排序里通过strcpy又是对这些字符串修改。因此是矛盾的，修改会导致段错误； 修改的办法是将字符串常量拷贝到栈上，即申请5 × 10的字符空间，每个字符串在栈上申请10个字符空间，将这些只读字符串拷贝到栈上，在栈上操作就没问题。


Question: 帮忙解决下? unpass调用完全无数据输出，这题是求平均数和第一门成绩均分等的题目，新生一个，如果用(*)[5]作形参，如何写函数呢？求解

u[i*4+j]，这个不对吧，已经溢出来了

没有耶，想上传个图的，却转圈圈····其它数据是有的，就是unpass那里没有

引用 3 楼 cfjtaishan 的回复:[quote=引用 2 楼 for_grasp 的回复:] 传地址后，还是有问题，可执行，没有数据输出， 我改过你的程序后，测试了，有数据呢；你有没有发现你的代码里，在for循环那行最后有一个分号，这个分号导致你没有数据输出[/quote] 抱歉，没有分号； 我的代码建议你运行一下，看看是否还会出现没有输出的问题。

引用 2 楼 for_grasp 的回复:传地址后，还是有问题，可执行，没有数据输出， 我改过你的程序后，测试了，有数据呢；你有没有发现你的代码里，在for循环那行最后有一个分号，这个分号导致你没有数据输出

传地址后，还是有问题，可执行，没有数据输出，

#include<stdio.h>      void all(float up[][5]);     void average(float *av);     void unpass(float *u,int *s);  int main() {     int stu[4];     float course[4][5];     float (*p)[5];     p = course;     int i,j;     printf("enter four student's number\n");     for(i=0;i<4;i++)                           //输入学号     {         scanf("%d", &stu[i]);     }     putchar('\n');     printf("enter for student's score \n");     for(i=0;i<4;i++)                     //输入4X5 成绩     {         for(j=0;j<5;j++)         {             scanf("%f",*(p+i)+j);         }     }     getchar();     all(course);                   //分别调用三个函数     average(course[0]);     unpass(&course[0][0],stu);     return 0; }  void unpass(float *u,int *s) {     putchar('\n');     float un=0;     int i,j;     printf("the student who is did not pass:\n");     for(i=0;i<4;i++,u++)     {         for(j=0;j<5;j++)         {             if((*u+j)<60)                 un++;         }         if(un>=2)         {             printf("%d %f %f %f %f %f \n", *(s+i), *u,*(u+1),*(u+2),*(u+3),*(u+4));             un=0;             continue;         }     } }   void average(float *av) {     float average,sum=0;     int i;     printf("average one is :\n");     for(i=0;i<4;i++)     {         sum=sum+(*av+i);     }     average=sum/4;     printf("%f",average); }  void all(float up[][5]) {     float av,all,sum=0,tip=0;     int i,j;     printf("two course are beyond 90 :\n");     for(i=0;i<4;i++)     {         for(j=0;j<5;j++)         {             sum=sum+up[i][j];         }         av=sum/5;         if(av>=90)printf(" %f %f %f %f %f \n",up[i][0],up[i][1],up[i][2],up[i][3],up[i][4]);         av=0;sum=0;     }     printf("all course are beyong 85:\n");     for(i=0;i<4;i++)     {         for(j=0;j<5;j++)         {             if(up[i][j]>=85)tip++;         }         if(tip==5)printf(" %f %f %f %f %f \n",up[i][0],up[i][1],up[i][2],up[i][3],up[i][4]);         tip=0;     } }


Question: while结构死循环的问题

加个fflush(stdin);

嗯嗯。热心大神。

引用缓冲区里的e跳不过去  我之前答案里写错了。你理解的是对的 我看已经结帖了就没再发出来^_^

是e留在缓冲区吧，scanf输入的是数字，回车像空格一样会被忽略

引用死循环 这是因为回车字符'\n'遗留在缓冲区造成的。  可以这样：  #include <stdio.h> #include <cctype>  int main(void) { 	int number; 	char c = '0'; 	if (scanf("%d", &number) == 0) { 		printf("You input a wrong integer,please input again:\n"); 		do { 			c = getchar(); 		} while (!isdigit(c)); 		ungetc(c, stdin); 	} }

啊，我知道了，输入e的话，缓冲区里的e跳不过去，下次读取sacnf时，遇到的还是e，所以无限循环。

能请教下为什么吗，我试了加 getchar（）；也行。


Question: 求助找游戏变化基址

过一遍Cheat Engine联机教程？

这种问题, 你在这里是问错地方的. 应该去看雪这类的更专业点的网站上问, 那上面基本上多是搞逆向的.


Question: 使用C语言的多线程显示动态时间问题

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

《Windows核心编程》

你这个不是多线程吧。。。。。我怎么都没有看出来。。。

如果楼主把4楼代码中的每一句都起什么作用都弄明白了，……

引用 1 楼 loneking2001 的回复:原因是多线程没有同步造成的，比如 gotoxy(2,51)之后，printf 之前，主线程有可能改动了光标位置。 一般的办法是加个锁，比如子线程在第一个 goto 之前先获取锁，在第二个 goto 之后释放锁。同样的，主线程在进行输入输出操作时也要先获取锁。 这个方案有一个小问题克服不了，就是等待用户输入期间时间不能更新。  这样确实......我的主线程就是各种输入和显示输出......加锁这个上学期操作系统有学相关知识，但是编程我就不会用了......

引用 2 楼 kakabulusi 的回复:你这个不是多线程吧。。。。。我怎么都没有看出来。。。  这是我子线程调用的显示动态时间的函数。。。


Question: 关于宏定义的问题

写了篇关于宏定义的小文章 http://blog.csdn.net/hou09tian/article/details/76566000 请多指教

仅供参考：#include <stdio.h> #define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0) char   *p1="1" ,*p2="2" ; char    c1=1   , c2=2   ; short   s1=1   , s2=2   ; int     i1=1   , i2=2   ; __int64 I1=1i64, I2=2i64; float   f1=1.0f, f2=2.0f; double  d1=1.0 , d2=2.0 ; void main() {     SWAP((int)p1,(int)p2);                printf("char *     %5s,   %5s\n",p1,p2);     SWAP(c1,c2);                          printf("char       %5d,   %5d\n",c1,c2);     SWAP(s1,s2);                          printf("short      %5d,   %5d\n",s1,s2);     SWAP(i1,i2);                          printf("int        %5d,   %5d\n",i1,i2);     SWAP(I1,I2);                          printf("__int64 %5I64d,%5I64d\n",I1,I2);     SWAP(*(int     *)&f1,*(int     *)&f2);printf("float      %5g,   %5g\n",f1,f2);     SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double    %5lg,  %5lg\n",d1,d2);      SWAP(c1,c1);     printf("%d\n",c1); } //char *         2,       1 //char           2,       1 //short          2,       1 //int            2,       1 //__int64     2,    1 //float          2,       1 //double        2,      1 //2

加上大括号，说明SWAP是一个语句体，即一起执行；若不加大括号，就是不是一个语句体。  宏定义就是在编译的预处理阶段等价替换，若等价替换，你可以模拟一下预处理，然后看一下结果是不是符合你的逻辑。

2楼的大神。。对不起啊，第一次用给分功能，你的分没给成

同意楼上的看法。 宏展开是在预处理阶段完成的，这个阶段把替换文本只是看作一个字符串，并不会有任何的计算发生，在展开时是在宏出现的地方 只是简单地使用串来代替，并不会增添任何的符号。  如果是自己编程使用宏替换，则在使用简单宏定义时，当字符串中不只一个符号时，加上括号表现出优先级，如果是带参数的宏定义，则要给宏体中的每个参数加上括号，并在整个宏体上再加一个括号。所以更安全的写法是 #define SWAP((a),(b),(t)) { t=a; a=b; b=t; }

引用区别  宏定义在预编译阶段 纯文本替换 以上两种定义是有区别的，举例： 第一种定义 if(true) SWAP(a, b, t) 展开为： if(true)  { t=a; a=b; b=t; }   第二种定义 if(true) SWAP(a, b, t) 展开为： if(true) t=a; a=b; b=t; //if判断条件只对t=a;有影响   这样你应该能看出两者的区别了吧^_^


Question: c语言 内存对其问题

也可以手动指定对齐方式， 请百度    “C++ 位域”

仅供参考：#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("AD sizeof %d\n", sizeof(AD));     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("A1 sizeof %d\n", sizeof(A1));     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("A2 sizeof %d\n", sizeof(A2));     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("A4 sizeof %d\n", sizeof(A4));     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("A8 sizeof %d\n", sizeof(A8));     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("A16 sizeof %d\n", sizeof(A16));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 //AD sizeof 32 // //A1.a 0 //A1.b 4 //A1.c 17 //A1 sizeof 25 // //A2.a 0 //A2.b 4 //A2.c 18 //A2 sizeof 26 // //A4.a 0 //A4.b 4 //A4.c 20 //A4 sizeof 28 // //A8.a 0 //A8.b 4 //A8.c 24 //A8 sizeof 32 // //A16.a 0 //A16.b 4 //A16.c 24 //A16 sizeof 32 // //

结构体对齐，按照结构体元素中占用字节最大的成员标准对齐。int，4字节，即按照4字节对齐

http://www.cppblog.com/snailcong/archive/2009/03/16/76705.html 这个贴子总结得比较好.

引用 1 楼 T20091 的回复:short是二字节对齐，int是四字节对齐  struct data1 {         char a;         short b;         char c;         int d; }; data1：a一字节|空一个字节|b两个字节|c一字节|空三个字节|d四字节  struct data2 {         char a;         char b;         short c;         int d; }; data2：a一字节|b一字节|c两字节|d四字节 引用 2 楼 user-8 的回复:每个变量相对于起始位置的偏移量必须是该变量类型大小的整数倍，不是整数倍空出内存，直到偏移量是整数倍为止。  最后整个结构体的大小必须是里面变量类型最大值的整数倍。  一楼分析的很全面，二楼总结到点上了

一楼说的很好，结构体data1，因为内存对齐，会自动补充，第二个是自动对齐，没有补充。   #include<stdio.h>  struct data1 { 	char a; 	char x1; 	short b; 	char c; 	char x2; 	char x3; 	char x4; 	int d; };  struct data2 { 	char a; 	char b; 	short c; 	int d; }; void main() { 	printf("%d\n",sizeof(data1)); 	printf("%d\n",sizeof(data2)); }


Question: c语言链表插入问题，

什么时候自己会改代码呢，，，，，，，，，，，，，正确代码献上，感觉和我想法有点点不一样，，，，，，， 但是我本来也不知道该是什么样子，，， void insert(int place,int innum,n head) { //输入一个数字表示位置，另一个数表示插入的数字，在每一个位置的前面插入数字， 	n t,x1,p,q; 	t=head; 	while(t->next!=NULL) { 		if(t->next->data==place) { 			x1=(n)malloc(sizeof(linklist)); 			x1->data=innum; 			x1->next=t->next;// 			t->next=x1; 			t=x1;  		}  		t=t->next; 	}   }

引用 11 楼 fight_in_dl 的回复:引用看看代码  检查下insert函数中q是什么?  时间关系，如果可能的话，我再找时间调一下这个程序。好吧，q 我想表示成t的前一个位置，就是当遍历找到要插入的位置的时候，位置的前一个，，，，，

引用 9 楼 fight_in_dl 的回复:引用看看代码  一个一个函数来，先读create函数。  注意第一个数要输入 -1 才结束循环。对啊，，，，这是创建链表，和我后面的插入函数有很大关系么

引用 7 楼 fight_in_dl 的回复:不过，建议取一个合适的名字表示某个类型，便于阅读和后期维护^_^谢谢提醒一般是为了好写方便，可以帮我看看代码么，或者给我点思路，，

不过，建议取一个合适的名字表示某个类型，便于阅读和后期维护^_^

#include<stdio.h> #include<stdlib.h> typedef struct linklist {     int data;     struct linklist *next; } linklist,*n; n create() {     n head,p,q;     int num;     head=NULL;     p=(n)malloc(sizeof(linklist));     scanf("%d",&num);     p->data=num;     p->next=NULL;     while(num!=-1)     {         if(head==NULL)         {             head=p;             q=p;         }         else         {             q->next=p;             q=p;         }         p=(n)malloc(sizeof(linklist));         scanf("%d",&num);         p->data=num;         p->next=NULL;     }        return head; } void print(n head) {     n t,t1;     int i,j,m;     int count;     count=0;     t=head;     t1=head;     while(t)     {         printf("%d ",t->data);         //	t=t->next;         t=t->next;     }   printf("--------------\n");  } void count(n head) {     n t,t1;     t=head;     int i,j,m;     int count;     count=0;     for(i=0; i<9; i++)     {         count=0;         t=head;         while(t)         {             if(t->data==i)             {                 count++;             }             t=t->next;         }         printf(" %d ",count);     } } void insert(int place,int innum,n head)//输入一个数字表示位置，另一个数表示插入的数字，在每一个位置的前面插入数字， { 	n t,x1,p,q; 	t=head; 	while(t) 	{ 		if(t->data==place) 		{ 			x1=(n)malloc(sizeof(linklist)); 			x1->data=innum; 			x1->next=NULL;// 			q->next=x1->next; 			x1->next=t; 			 		} 		q=t;// 		t=t->next; 	} 	 	 } int main() {     n head;     printf("请输入链表：\n");     head=create();     print(head);     //printf("--------------\n");     //count(head);     //insert(3,5,head);  }

引用 4 楼 fight_in_dl 的回复:引用n是这个结构体指针  嗯，代码不全，如果在别的地方有定义，是可以的。 只看题目的代码，看不出n的定义。  这个是误会了。不好意思啊，，，，，我应该发全的，，

引用 2 楼 zuoside__lord 的回复:[quote=引用 1 楼 fight_in_dl 的回复:]  n t,x1,p,q; x1=(n)malloc(sizeof(linklist));  类似的地方都有错误，建议先考虑把语法错误修改完。  链表的实现网上范例非常多，或者你可以找一个对照学习，更快捷些。 这是其中的一篇，也可以找找别的，大同小异。 http://www.cnblogs.com/scrat/archive/2012/08/17/2644086.html谢谢[/quote]，等等，，它哪里错了，n是这个结构体指针，linklist是结构体

引用 1 楼 fight_in_dl 的回复:n t,x1,p,q; x1=(n)malloc(sizeof(linklist));  类似的地方都有错误，建议先考虑把语法错误修改完。  链表的实现网上范例非常多，或者你可以找一个对照学习，更快捷些。 这是其中的一篇，也可以找找别的，大同小异。 http://www.cnblogs.com/scrat/archive/2012/08/17/2644086.html谢谢


Question: 链表问题，为什么输入得字符串保存不了？？

strcpy

如1L代码，最后输出的时候发现链表中保存的值全部丢失


Question: C语言函数返回的值与实际不符

引用 1 楼 user-1 的回复:你得在函数调用之前 做函数声明    谢谢。。原来C语言不能像java那么自由，声明必须要在main函数前面

谢谢。。原来C语言不能像java那么自由，声明必须要在main函数前面

你得在函数调用之前 做函数声明


Question: 这个题目要求精度在0.0005,但是通过调试，我发现它在大于0.0005时依旧没有退出do 循环

你的代码没什么问题while循环是可以退出循环的。但是fun函数，传进去的实参没有使用，不知道为什么？！ 建议楼主查看一下你的代码和你发出来的代码是不是同一个。

引用 1 楼 fight_in_dl 的回复:do {    statement(s); } while( condition );  //当conditon为真，继续循环。当condition为假，退出循环  如果想当t大于0.0005时，退出循环，需要改成：        do { 		t = A / B; 		s = s + t; 		A = A*(a + 1); 		a = a + 1; 		B = B*(b + 2); 		b = b + 2; 	} while (t < 0.000500);   这样改确实是退出循环了，但是循环体只执行了一次。


Question: C语言while循环中不能用true

引用为什么会有这个错误呢 和C++不一样，C语言并没有布尔类型，在C语言中认为 0为假，非0为真， 所以条件表达式的写法非常灵活。  例如： char a = 'Y'; if(a) //合法  int i = 3; int *j = &i; if(j) //合法 0为假，非0为真，在各种C语言考试中这几乎也是一个必考的知识点。 另外，如果你查一下文档，会发现C语言并没有true这个关键字，而C++有。 C关键字：https://msdn.microsoft.com/zh-cn/library/befeaky0.aspx C++关键字：https://msdn.microsoft.com/zh-cn/library/2e6a4at9.aspx

严格地说，c标准里没有true和false，需用1和0代替。


Question: 为什么建立单链表时会出现这种编译错误？

引用&，这个是C++的语法，如果是C语言不建议使用，因为C语言的编译器不识别这个符号。 建议定义成：LinkList *L,然后函数里使用到L的地方都用*L即可。

引用 4 楼 runningfatty 的回复:[quote=引用 2 楼 hkangj 的回复:] 可以给我看看我这个代码为什么会运行错误么，搞不明白  你在函数里面操作的只是一个拷贝的变量，对主函数里的L是没有影响的 如果你想对L修改的话，有两种方法，一个是用二级指针，也就是传入L的地址，另一个就是不用参数，返回值就是创建的链表[/quote了解了，谢谢大佬

引用 2 楼 hkangj 的回复:可以给我看看我这个代码为什么会运行错误么，搞不明白  你在函数里面操作的只是一个拷贝的变量，对主函数里的L是没有影响的 如果你想对L修改的话，有两种方法，一个是用二级指针，也就是传入L的地址，另一个就是不用参数，返回值就是创建的链表

引用 楼主 hkangj 的回复: 可以给我看看我这个代码有什么错误吗，搞不明白

可以给我看看我这个代码为什么会运行错误么，搞不明白

你这是c，函数的参数LinkList &L，&去掉。 c++可以这么写，引用类型


Question: vs2015调试显示读取访问权限冲突

f = (void*)5;  //这么写只是让f的值等于0x00000005，但并没有让 f 指向某个变量，                                   //也就是说f属于未初始化的指针,0x00000005这个地址的内存还无法访问  正确的写法如下：  void* f = NULL; 	int i = 5; 	f = (void*)&i; 	int* p = (int*)f; 	printf("%d\n", *p);


Question: 求大神指引精确度高一点的测试程序运行时间的方法

time_t精确度是秒，建议使用gettimeofday函数，这个可以精确到微妙；执行两次gettimeofday，然后求时间差就是程序的执行时间了。

引用有没有方法可以测试出比较简短的代码的运行时间  可以用 QueryPerformanceCounter 函数原型：https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396  使用时需要包含#include "Windows.h"，一个范例：  LARGE_INTEGER frequency;        // ticks per second LARGE_INTEGER t1, t2;           // ticks double elapsedTime;  // get ticks per second QueryPerformanceFrequency(&frequency);  // start timer QueryPerformanceCounter(&t1);  // do something ...  // stop timer QueryPerformanceCounter(&t2);  // compute and print the elapsed time in millisec elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;


Question: 写了一段代码，运行结果符合题目，但是我不知道是哪里不符合题的要求，希望可以帮我指出来

百度搜相关关键字。

#include<stdio.h> #include <stdlib.h> //#include<malloc.h>  typedef struct node {     int data;     struct node *next;     struct node *prev; } SLNode;   struct node *create_link(int n) {     int i;     struct node *pcur = NULL, *ptmp;     struct node *phead = NULL;       for (i = 0; i < n; i ++) {         pcur = (struct node *)malloc(sizeof(struct node));         if (!pcur) {             fprintf(stderr, "malloc error!\n");             exit(-1);         }         scanf("%d", &pcur->data);         if (!phead) {             phead = pcur;             pcur->prev = pcur;             pcur->next = pcur;             ptmp = pcur;         } else {             pcur->prev = ptmp;             ptmp->next = pcur;             ptmp = pcur;         }     }     ptmp->next = phead;     phead->prev = ptmp;      return phead; }   void print_data_list(struct node *phead) {     struct node *pcur = phead;      while (pcur->next != phead) {         printf("%d\t", pcur->data);         pcur = pcur->next;     }     printf("%d\n", pcur->data); }  /* return 1 is palindrome, or not palindrome*/ int check_palindrome(struct node *phead) {     struct node *pstart, *pend;      pstart = phead;     pend = phead->prev;      while (pend > pstart && pend->data == pstart->data) {         pstart = pstart->next;         pend = pend->prev;     }     if (pend <= pstart)         return 1;      return 0; }   int main(void) {     struct node *phead = NULL;     int n, is_palindrome;      printf("Please input a number: ");     scanf("%d", &n);      phead = create_link(n);     print_data_list(phead);      is_palindrome = check_palindrome(phead);     if (is_palindrome)         printf("Is palindrome!\n");     else         printf("Is not palindrome!\n");     return 0; }    这个问题，建议使用双向循环链表来解决。既然要求用链表，那么就只能用链表来判断回文


Question: 大哥为什么我的程序时好时坏啊？

引用不知道那错了  fp1=fopen("employee1.txt","w"); //用w方式打开，会清除之前的内容。应换成a+方式打开  详细可参考： https://msdn.microsoft.com/zh-cn/library/yeby3zcb.aspx

找找是不是文件不存在了

数组长度不够


Question: 输出是多少？为什么？谢谢解答

引用 2楼baidu_37097818 的回复:代码中的操作是: 将int指针转换为double指针了。然后将指针解引用并赋值。我们假定你这里的int是32位的，那么由于double是64位的，所以解引用并赋值，会导致a[0]和接下来的a[1]值发生改变，但double和int的编码格式不一样，所以它们两个的值实际上是double的5.0转化成int的数值，而a[2]则不会发生改变嗯嗯谢谢，我知道了

输出是不确定的，换句话说，输出是多少没有意义。  按照C++标准的规定，reinterpret_cast只保证当转换为其它类型后，再转换回原类型时值不变。 并不确定中间值是多少。举个例子：  int* a = new int();  double * b = reinterpret_cast<double *>(a); //b的值不确定 int* c = reinterpret_cast<int*>(b);  //c一定等于a  那这么说reinterpret_cast有什么用呢? 可以参考：http://www.cnblogs.com/ider/archive/2011/07/30/cpp_cast_operator_part3.html 有详细阐述。


Question: wav格式的分析

请问楼上有bass库的说明吗

引用 4 楼 weixin_39547089 的回复:请问楼上有bass库的说明吗 难道网上搜不到？

推荐使用bass库处理音频。

我问题是如何得到时域数据  我能读到的数据都是十六进制  采样率 采样点我都知道了  关键是如何把data段的大量数据变成时域

先确定该wav的采样率，采样大小和声道数，在提取数据进行转换。如此获取的数据可能会更好处理。


Question: 单链表问题----指针指向方面有些不懂！！！

引用 2 楼 qq_39209116 的回复:好像明白了，，是这样吗?   s -> next 读取的指针L的内容，而L的内容是每一次循环中新开辟的结构体空间的地址。这样的话新的结构体总是指向“旧”的结构体，形成链表。而最新的那个节点就是首节点，L指针是头指针。想当于就是每次都从链表的头部插入啊，L=s是为了下一次如果要插入时，能够将新的s的next指向L，如果没有插入，那为L就为头指针

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633

这是头插方法建立链表，比如输入的x是1， 2 ，3那么，链表中的头就是3，其次是2， 1；

L是个指针, 通过L的指向可以访问到这个链表.跟L的地址有没有变化没有关系.L指针值变化就可以了.


Question: pcap生成静态库

引用怎么写  需要加： --enable-static  一个例子：http://www.aichengxu.com/linux/2430379.htm

不知道你要 搞什么, 没理解你的意思

搜“跟我一起写makefile”？

不用， 都是centos系统

要交叉编译吗?


Question: 求大神帮忙，有关选择排序的问题，为什么要定义一个变量int key=array[low]；还要这样使用if(array[j]

引用 3 楼 cfjtaishan 的回复:这是因为通过遍历数组找到最小值，low代表的最小值，是我们假想的或者假定的最小值，通过遍历找到比假定的最小值之后就要将最小值赋值key，但是如果第一次找到的最小值还不是最小值，那么将继续替换key和下标，知道将数组元素遍历完。然后继续找次最小值，一次类推。  我明白了，key就相当于一个游标，去找出最小值，不能把每次找到的最小值赋值给数组本身的元素，如果最小值不是首位的话，那循环j次就前面的元素全部都成了最小值了

因为你用key和array[]里面的所有值去比较，当然要先给key赋一个初始值

因为array[low]是不变的，而key是变化的


Question: 数据结构线性链表

引用 2 楼 cfjtaishan 的回复:以上的代码是修改后，并且加了2个函数。 注意二重指针。  蟹蟹你

#include <stdio.h> #include <stdlib.h> #include <assert.h> #include <unistd.h> #include <stdbool.h>  #define OVERFLOW -2 #define OK 1 #define ERROR 0  typedef struct Node{     int data;     struct Node *next; }Node;  typedef struct Node* LinkList;  //创建链表(尾插法) int CreateList(LinkList *L, int n) {     LinkList p,r;     int i,e;     (*L) = (LinkList)malloc(sizeof(Node));     r = *L;     for(i = 0; i < n; i++)     {         p = (Node*)malloc(sizeof(Node));         scanf("%d",&e);         p->data = e;         r->next = p;         r = p;//p为中介节点     }     r->next = NULL;      return OK; }  //删除链表 int ClearList(LinkList *L){     LinkList p,q;     p = *L;//报错     while(p)     {         q = p->next;         free(p);         p = q;     }     (*L)->next = NULL;      return OK; }  int GetLinkLenght(LinkList L) {     assert(L);     int len = 0;     LinkList p = L->next;      while (p) {         len++;         p = p->next;     }      return len; }  //获得元素 int GetElem(LinkList *L, int i, int *e) {     //当第i个元素存在时，其值赋给e，并返回OK，否则ERROR     LinkList p;     int j = 1, max_len;     p = (*L)->next;     max_len = GetLinkLenght(*L);     if (i > max_len)         return ERROR;      while(p&&(j < i))     {         p = p->next;         j++;     }     if(!p)         return ERROR;     *e = p->data;      return OK; }  //插入链表元素 int InsertElem(LinkList *L,int i,int e) {     //第i个元素之前插入e     LinkList p,s;     int j=1;     p = *L;//报错     while(p&&(j<=i))     {         p = p->next;         j++;     }     if(!p||j>i) return ERROR;     s = (LinkList)malloc(sizeof(Node));     s->data = e;     s->next = p->next;     p->next = s;      return OK; }  //删除链表元素 int DeleteElem(LinkList *L,int i,int *e){     //删除第i个元素，并由e返回其值     LinkList p;     int j=1;     p = *L;//报错     while(p&&(j<=i))     {         p = p->next;         j++;     }     if(!p||j>i) return ERROR;     *e = p->next->data;     p->next = p->next->next;     return *e; }  static void print_all_elem(LinkList L) {     assert(L);     LinkList p = L->next;      while (p) {         printf("data = %d\n", p->data);         p = p->next;     } }   int main() {     int n, x, e;     LinkList La;     printf("请输入你要输入的元素个数：");     scanf("%d", &n);     CreateList(&La, n);     // x = ClearList(La);      print_all_elem(La);      x = GetElem(&La, 2, &e);      printf("x = %d, %d\n", x,  e);      // if(x)     //     printf("OK");     // else     //     printf("Error2");     ClearList(&La);     return 0;  }   以上的代码是修改后，并且加了2个函数。 注意二重指针。

。。。说错了，是错的是指针


Question: 杭电2000 求告知哪里错了

把while循环条件 改成while(scanf("%c%c%c",&a,&b,&c)!=EOF)

#include <stdio.h>  int main() {     char x,a,b,c;     while(scanf("%c %c %c",&a,&b,&c)!=0)    /*加空格用于区分相邻两个输入*/     {         getchar();    /*用于接收'\n'*/         if(a>b)         {             x=a;             a=b;             b=x;          }          if(a>c)         {x=a;             a=c;             c=x;         }         if(b>c)         {             x=b;             b=c;             c=x;         }         printf("%c %c %c",a,b,c);         printf("\n");     }     return 0; }


Question: （C语言题目） 新手求助大神

下一步移动方向应该是随机产生的。

仅供参考：#include <stdio.h> #include <time.h> #include <stdlib.h> #define MAXX 10 #define MAXY 10 void main() {     char MAP[MAXX][MAXY];     char str;     int x,y,z,f,n;      for (x=0;x<MAXX;x++) {         for (y=0;y<MAXY;y++) {             MAP[x][y]='.';         }     }      for (x=0;x<MAXX;x++) {         printf("\n");         for (y=0;y<MAXY;y++) {             printf("%c",MAP[x][y]);         }     }     printf("\n");      srand((unsigned) time(NULL)); RETRY:     x=0;y=0;str='A';MAP[x][y]=str;      for (str='B';str<='Z';str++) {         n=0;         f=1;         while (1) {             n++;             z=rand()%4;             switch (z) {                 case 0: if (y+1<MAXY && MAP[x  ][y+1]=='.') {y++;MAP[x][y]=str;f=0;} break;                 case 1: if (x+1<MAXX && MAP[x+1][y  ]=='.') {x++;MAP[x][y]=str;f=0;} break;                 case 2: if (y-1>0    && MAP[x  ][y-1]=='.') {y--;MAP[x][y]=str;f=0;} break;                 case 3: if (x-1>0    && MAP[x-1][y  ]=='.') {x--;MAP[x][y]=str;f=0;} break;             }             if (f==0) break;             if (n>200) {//钻入死胡同                 for (x=0;x<MAXX;x++) {                     for (y=0;y<MAXY;y++) {                         MAP[x][y]='.';                     }                 }                 goto RETRY;             }         }//while         if (x==MAXX-1 || y==MAXY-1) break;     }//for      for (x=0;x<MAXX;x++) {         printf("\n");         for (y=0;y<MAXY;y++) {             printf("%c",MAP[x][y]);         }     }     printf("\n"); }


Question: c 类型转换

引用 1 楼 cfjtaishan 的回复:你虽然转换为无符号数，但是你还是以%d输出的，即还是以有符号数的形式输出来。问题在%d, 建议用%u或者%lu形式输出试试问你一下，那既然%d是有符号形式输出，为什么printf("%d\n", 2147483648);输出的还是-2147483648呢？？难道还转换了不成？为什么会被转换呢？

引用 1 楼 cfjtaishan 的回复:你虽然转换为无符号数，但是你还是以%d输出的，即还是以有符号数的形式输出来。问题在%d, 建议用%u或者%lu形式输出试试额！糊涂我了，我试试，谢了

引用 13 楼 zhao4zhong1 的回复:注意，常量也有类型！ C++ Integer Constants  Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.  Grammar integer-constant:  decimal-constant integer-suffixopt  octal-constant integer-suffixopt  hexadecimal-constant integer-suffixopt  'c-char-sequence'  decimal-constant:  nonzero-digit   decimal-constant digit  octal-constant:  0  octal-constant octal-digit  hexadecimal-constant:  0xhexadecimal-digit  0Xhexadecimal-digit   hexadecimal-constant hexadecimal-digit  nonzero-digit: one of  1 2 3 4 5 6 7 8 9  octal-digit: one of  0 1 2 3 4 5 6 7  hexadecimal-digit: one of  0 1 2 3 4 5 6 7 8 9   a b c d e f   A B C D E F  integer-suffix:  unsigned-suffix long-suffixopt  long-suffix unsigned-suffixopt  unsigned-suffix: one of  u U  long-suffix: one of  l L  64-bit integer-suffix:  i64 LL ll  To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.  To specify a decimal constant, begin the specification with a nonzero digit. For example:    Copy Code  int i = 157;   // Decimal constant int j = 0198;  // Not a decimal number; erroneous octal constant int k = 0365;  // Leading zero specifies octal constant, not decimal    To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example:    Copy Code  int i = 0377;   // Octal constant int j = 0397;   // Error: 9 is not an octal digit    To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the "x" does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:    Copy Code  int i = 0x3fff;   // Hexadecimal constant int j = 0X3FFF;   // Equal to i    To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:    Copy Code  unsigned uVal = 328u;             // Unsigned value long lVal = 0x7FFFFFL;            // Long value specified                                    //  as hex constant unsigned long ulVal = 0776745ul;  // Unsigned long value    To specify a 64-bit integral type, use the LL, ll or i64 suffix. For example,    Copy Code  // 64bitsuffix.cpp #include <stdio.h> enum MyEnum {    IntType,    Int64Type };  MyEnum f1(int) {    printf("in f1(int)\n");    return IntType; }  MyEnum f1(__int64) {    printf_s("in f1(__int64)\n");    return Int64Type; }  int main() {    MyEnum t1 = f1(0x1234), t2 = f1(0x1234i64); }    Output    in f1(int) in f1(__int64)    See Also Concepts Literals (C++)额！我刚学，被搞晕乎了，谢谢赵4老师

引用 8 楼 zgw2014 的回复:[quote=引用 5 楼 cfjtaishan 的回复:] [quote=引用 3 楼 zgw2014 的回复:] [quote=引用 1 楼 cfjtaishan 的回复:] 你虽然转换为无符号数，但是你还是以%d输出的，即还是以有符号数的形式输出来。问题在%d, 建议用%u或者%lu形式输出试试问你一下，那既然%d是有符号形式输出，为什么printf("%d\n", 2147483648);输出的还是-2147483648呢？？难道还转换了不成？为什么会被转换呢？ [/quote] 注意一下，这个2147483648是不是已经超出int有符号数正整数表示的范围了。可以查阅一下int类型的表示的范围。[/quote]它没有超出正数表示范围，刚好等于2的31次方，根据无符号数转换成有符号数的规则，x >= 2的（w-1）次方，结果就是 x - 2的w次方，使用%d输出的结果就是-2147483648[/quote] 注意，最高位不是数值位，而是符号位。若为1则是负值。

问下各位兄弟姐妹，针对超出系统最大整数值得数该怎么转换？比如 (unsigned) -2147483648 < 21474836487 这个运算的结果是多少？有点疑惑，跪求各位分析一下

引用 6 楼 fight_in_dl 的回复:基本数据类型能表达的数字有限制，具体多少和编译器对C++标准的具体实现以及机器字长有关。 可以用： cout<<INT_MAX<<endl; 看看这个极值是多少，再检查题目中的数字是否已经超出。  printf格式字符串这个知识点的内容挺多的，详细可参考： https://msdn.microsoft.com/zh-cn/library/tcxf1dw6.aspx好的，感谢

因为打印的是%d,这个是有符号打印

引用 5 楼 cfjtaishan 的回复:[quote=引用 3 楼 zgw2014 的回复:] [quote=引用 1 楼 cfjtaishan 的回复:] 你虽然转换为无符号数，但是你还是以%d输出的，即还是以有符号数的形式输出来。问题在%d, 建议用%u或者%lu形式输出试试问你一下，那既然%d是有符号形式输出，为什么printf("%d\n", 2147483648);输出的还是-2147483648呢？？难道还转换了不成？为什么会被转换呢？ [/quote] 注意一下，这个2147483648是不是已经超出int有符号数正整数表示的范围了。可以查阅一下int类型的表示的范围。[/quote]它没有超出正数表示范围，刚好等于2的31次方，根据无符号数转换成有符号数的规则，x >= 2的（w-1）次方，结果就是 x - 2的w次方，使用%d输出的结果就是-2147483648

引用 4 楼 g62r83t27 的回复:很明显，这个数是心机boy写出来的，编译告警被你忽略了，请用%ld试试使用%ld输出确实是原值，2147483648这个值正好是2的31次方，转换一下是-2147483648

引用 3 楼 zgw2014 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] 你虽然转换为无符号数，但是你还是以%d输出的，即还是以有符号数的形式输出来。问题在%d, 建议用%u或者%lu形式输出试试问你一下，那既然%d是有符号形式输出，为什么printf("%d\n", 2147483648);输出的还是-2147483648呢？？难道还转换了不成？为什么会被转换呢？ [/quote] 注意一下，这个2147483648是不是已经超出int有符号数正整数表示的范围了。可以查阅一下int类型的表示的范围。

很明显，这个数是心机boy写出来的，编译告警被你忽略了，请用%ld试试


Question: 大哥帮查一下错，文件处理，本来是可以运行的没有错。

#include <stdio.h> #include <stdlib.h>  typedef struct staff{     int number; //号码     char name[8]; //姓名     char sex[4]; //性别     int age; //年龄     char abode[20]; //住宅     int wage; //工资     char health[8]; //健康     char culture[8]; //文化 }ff;  int main() {     FILE *fp,*fp1;     ff jg[5];     int i=0;     fp=fopen("employee.txt","r");     if (!fp) {         fprintf(stderr, "Open file error!\n");         return -1;     }     fp1=fopen("employee1.txt","w");     if (!fp1) {         fprintf(stderr, "Open error!");         return -1;     }     fscanf(fp,"%d %s %s %d %s %d %s %s\n",&jg[i].number,jg[i].name,jg[i].sex,&jg[i].age,jg[i].abode,&jg[i].wage,jg[i].health,jg[i].culture);     while(!feof(fp)){         fprintf(fp1,"%d %s %d\n",jg[i].number,jg[i].name,jg[i].wage);         i++;         fscanf(fp,"%d %s %s %d %s %d %s %s\n",&jg[i].number,jg[i].name,jg[i].sex,&jg[i].age,jg[i].abode,&jg[i].wage,jg[i].health,jg[i].culture);     }     fclose(fp);     fclose(fp1);     return 0; }

程序看着没什么问题，注意下确保打开的文件没有问题，即判断返回的文件描述符，另外，注意下feof

fp=fopen("employee.txt","r");只有这个文件存在才能成功，如果这个文件不存在就会报错。

引用就不行了 fp1=fopen("employee1.txt","w"); //打开方式为w，这种方式当文件再次打开时，会清除掉之前的内容，宜换成a+方式  具体文件打开方式的区别，可参考： http://no001.blog.51cto.com/1142339/526653

建议楼主先把结构中的数组长度加大，应该是越界引起的错误，表现在时好时坏

引用 楼主 yi19861209 的回复:#include"stdio.h" #include"stdlib.h" typedef struct staff{ 	int number;		//号码 	char name[8];		//姓名 	char sex[4];		//性别 	int age;		//年龄 	char abode[20];		//住宅 	int wage;		//工资 	char health[8];		//健康 	char culture[8];	//文化 }ff; int main(){ 	FILE *fp,*fp1; 	ff jg[5]; 	int i=0; 	fp=fopen("employee.txt","r");           //判断下         if(!fp)         {           printf("判断下文件是否打开");           return 0;        }  	fp1=fopen("employee1.txt","w"); 	while(!feof(fp)){ 		fscanf(fp,"%d %s %s %d %s %d %s %s\n",&jg[i].number,jg[i].name,jg[i].sex,&jg[i].age,jg[i].abode,&jg[i].wage,jg[i].health,jg[i].culture); 		fprintf(fp1,"%d %s %d\n",jg[i].number,jg[i].name,jg[i].wage); 		i++; 	} 	fclose(fp); 	fclose(fp1); 	return 0; } //本来是可以运行的我试了好几次都没有错，过了一下不知道怎么了就不行了。我都是用编辑器输入   报的什么错


Question: C语言数据结构

引用 2 楼 qq_34668913 的回复:[quote=引用 1 楼 cfjtaishan 的回复:]  参考一下上面的代码吧；  错误主要是在main中。遇到这样的问题，比如合并，那么合并之前先确保La, Lb里面的数据没问题，然后在查看是不是合并函数里出了问题。你的代码里主要是在对La. Lb赋值时出了问题，即数据没有插入到La和Lb中。 如还有可以继续提出来。  你这样改了运行没问题。 可是一定得把数组ab改成指针么？ 还有，我没加Lb的时候，数组a是可以对La正常赋值的，为什么加了合并函数和Lb之后就不可以了呢？ [/quote] 之所以用a,b指针，因为考虑从栈上申请空间，m,n定义是没有初始化，是一个随机值；再说C语言不支持可变长度。 La和Lb是两个独立的数据结构变量，赋值也是独立，建议你对比一下代码，然后查找问题。

好的，蟹蟹你们

引用不可以了呢 int n,m,i;   int a[n],b[m];  //定义数组时，需要知道确定的大小。  如果所需的内存空间大小取决于实际输入的数据，而无法预先确定，这种情况下就需要动态分配内存空间。 可以参考：http://www.prglab.com/cms/pages/c-tutorial/advanced-data/dynamic-memory.php

引用 1 楼 cfjtaishan 的回复:参考一下上面的代码吧；  错误主要是在main中。遇到这样的问题，比如合并，那么合并之前先确保La, Lb里面的数据没问题，然后在查看是不是合并函数里出了问题。你的代码里主要是在对La. Lb赋值时出了问题，即数据没有插入到La和Lb中。 如还有可以继续提出来。  你这样改了运行没问题。 可是一定得把数组ab改成指针么？ 还有，我没加Lb的时候，数组a是可以对La正常赋值的，为什么加了合并函数和Lb之后就不可以了呢？

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdbool.h>   #define OVERFLOW -2 #define LIST_INIT_SIZE 100 #define LISTINCREMENT 10 #define OK 1 #define ERROR 0  typedef struct{     int *elem;// 存储空间基址     int length;//当前元素个数     int listsize;//当前最多能存放的个数 }SqList;  int InitList(SqList *L) {     //构造一个空的线性表     L->elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int));     //判断动态内存是否成功分配，若成功再初始化变量     if(!L->elem)         exit(OVERFLOW);     L->length =0;     L->listsize = LIST_INIT_SIZE;     return OK; }  int DestoryList(SqList *L) {     if(!L->elem)         return ERROR;     free(L->elem);     return OK; }  int ListInsert(SqList *L,int i,int e) {     //在顺序线性表L中第i个位置之前插入新元素e     //i的合法值为1<=i<=listlength(L)     int j;     int *newbase;      if(i < 1 || i > (L->listsize))         return ERROR; //i值不合法      if((L->length)>=(L->listsize))            //当前空间已满，增加分配     {         newbase = (int*)realloc(L->elem,(L->listsize+LIST_INIT_SIZE)*sizeof(int));         if(!newbase)             exit(OVERFLOW);//存储分配失败         L->elem = newbase;//新基址         L->listsize += LISTINCREMENT;//增加存储容量     }     for(j = (L->length)-1; j >= i-1; --j) {         L->elem[j+1] = L->elem[j];//插入位置及之后的元素右移     }     L->elem[j+1] = e;//插入e     ++(L->length);     return OK; }  int ListDelete(SqList *L,int i,int e){     //在顺序线性表L中删除第i个元素，并用e返回其值     //i的合法值为1<=i<=listlength(L)     if(i<1||i>L->length) return ERROR; //i值不合法     int p,q;     e = L->elem[i-1];//p为被删除的元素     q = *(L->elem)+(L->length)-1;//表尾元素的位置     for(p=i-1;p<=q;p++)         L->elem[p] = L->elem[p+1];          //被删除的元素之后的元素左移     --L->length;     return OK; }  //找出元素的位序 int LocateElem(SqList L,int e,int (*compare)(int,int)) {     //在顺序线性表中L中查找第一个与e满足compare()的元素的位序     int i=1;     int *p;     p = L.elem;     while(i <= L.length && !(*compare)(*p++,e))         ++i;     if(i <= L.length)         return i;     else         return 0; }  int compare(int e1,int e2) {     if(e1==e2)         return true;     return false; }  //根据位序找元素 int GetElem(SqList *L,int i,int *e){     //用e返回L中第i个元素的值     int k;     for(k=0;k<(L->listsize);k++)     {         if(k==i-1)         {             *e=L->elem[k];         }     }     return *e; }  int ListLength(SqList *L) {     return L->length; }  void Union(SqList *La, SqList Lb) {     // 将所有在线性表Lb中但不在La中的数据元素插入到La中     int La_len,Lb_len,i,e;     La_len = ListLength(La);          // 求线性表的长度     Lb_len = ListLength(&Lb);     for (i=1; i<=Lb_len; i++) {         GetElem(&Lb, i, &e);              // 取Lb中第i个数据元素赋给e         if (!LocateElem(*La, e, (*compare)))  // La中不存在和e相同的数据元素             ListInsert(La, ++La_len, e);  // 插入     } }  int main() {     SqList La,Lb;     int n,m,i;     int *a, *b;      //列表初始化     InitList(&La);     InitList(&Lb);      //列表La输入元素     printf("\n请输入您要输入的元素的个数：");     scanf("%d",&n);     a = (int *)malloc(sizeof(int) * n);     printf("\n请输入这 %d 个元素：",n);     for(i=0;i<n;i++)     {         scanf("%d", &a[i]);     }      //列表Lb输入元素     printf("\n请输入您要输入的元素的个数：");     scanf("%d", &m);     b = (int *)malloc(sizeof(int) * m);     printf("\n请输入这 %d 个元素：",m);     for(i=0; i < m; i++)     {         scanf("%d", &b[i]);     }      //列表La赋值     printf("\n您输入的列表La为：");     for(i=0;i < n;i++)     {         La.elem[i] = a[i];         ++La.length;         //ListInsert(&La, i+1, a[i]);         printf("%d\t", La.elem[i]);     }     printf("\n您输入的列表Lb为：");     for(i = 0; i < m; i++)     {         Lb.elem[i] = b[i];         ++Lb.length;         //ListInsert(&Lb, i+1, b[i]);         printf("%d\t",Lb.elem[i]);     }     printf("\n");      //合并     Union(&La,Lb);     printf("La's length = %d\n", La.length);     printf("\n合并后的La为：");     for(i = 0; i < La.length;i++)     {         printf("%d\t",La.elem[i]);     }       DestoryList(&La);     DestoryList(&Lb);     printf("\nover."); } 参考一下上面的代码吧；  错误主要是在main中。遇到这样的问题，比如合并，那么合并之前先确保La, Lb里面的数据没问题，然后在查看是不是合并函数里出了问题。你的代码里主要是在对La. Lb赋值时出了问题，即数据没有插入到La和Lb中。 如还有可以继续提出来。


Question: 关于指针的小问题

引用 8 楼 hou09tian 的回复:  兄弟，你教会了我方法，膜拜

[/quote] 但是pp指向是NULL，即pp变量不能存放数据（不可以读写），*pp = p; **pp还不是要往pp里面写数据。         我的理解是，并不是指向NULL不可以存放数据，向指向NULL的指针赋值，这个指针就会指向要指向的地方，但是不能给没    有 初始化的指针赋值，因为不知道没有赋值的指针指的是什么地方，可能就指向不可读的地方，这样连打印都不可能，别说改了  }[/code] 指针这块理解比较晦涩，但是还是要好好学习一下，因为这是C语言的精髓所在嘛[/quote]  初学，理解有误的话多讨论

[/quote] 但是pp指向是NULL，即pp变量不能存放数据（不可以读写），*pp = p; **pp还不是要往pp里面写数据。但是如下是可以的： #include <stdio.h> #include <stdlib.h>  int main() {     int** pp = NULL;     int* p = NULL;      p = (int*)100;    //p也是指向NULL，这个赋值成功     printf("%p\n", p);     pp = (int **)malloc(sizeof(int *));     *pp = p;     printf("%#x\n",*pp);      return 0;  } 指针这块理解比较晦涩，但是还是要好好学习一下，因为这是C语言的精髓所在嘛[/quote]

引用 2 楼 LD_______ 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] #include <stdio.h>  int main() {     int** pp = NULL;    [color=#FF0000] int* p = NULL;   //p也是指向NULL,但是赋值成功了      p = (int*)100;     printf("%p\n", p);     *pp = p;         printf("%x\n",*pp);      return 0;  } 将100赋值给p是没问题的，即p指向内存单元里以100开头的地址； 但是将*pp = p;赋值就是有问题的，因为pp指向NULL，即不可读不可写的地址，*pp = p;就是对其写操作，自然是会出现段错误； 引用 1 楼 cfjtaishan 的回复:#include <stdio.h>  int main() {     int** pp = NULL;     int* p = NULL;          p = (int*)100;    //p也是指向NULL，这个赋值成功     printf("%p\n", p);     *pp = p;         printf("%x\n",*pp);      return 0;  } 将100赋值给p是没问题的，即p指向内存单元里以100开头的地址； 但是将*pp = p;赋值就是有问题的，因为pp指向NULL，即不可读不可写的地址，*pp = p;就是对其写操作，自然是会出现段错误；  我将本来指向0地址的指针指向100，那我也可以将本来指向0的pp指向100，这样好像也说的过去，*pp也就是（int*）类型，将它指向100，应该也是可以的吧，难道是因为*pp没有初始化？  [/quote] 但是pp指向是NULL，即pp变量不能存放数据（不可以读写），*pp = p; **pp还不是要往pp里面写数据。但是如下是可以的： #include <stdio.h> #include <stdlib.h>  int main() {     int** pp = NULL;     int* p = NULL;      p = (int*)100;    //p也是指向NULL，这个赋值成功     printf("%p\n", p);     pp = (int **)malloc(sizeof(int *));     *pp = p;     printf("%#x\n",*pp);      return 0;  } 指针这块理解比较晦涩，但是还是要好好学习一下，因为这是C语言的精髓所在嘛

引用 3 楼 fight_in_dl 的回复:引用指正 p = (int*)100; //为指针变量赋值，将int类型强制转换为int*类型，正确。 p = 100; //赋值运算符两侧类型不匹配，错误。  int** pp = NULL; // *pp是未初始化的空指针，对其进行操作会引发内存访问错误。  对的，我想明白了，就是*PP没初始化。就是想不通为么每次都给我指到无法访问的地方，郁闷 还有，谢谢

引用 1 楼 cfjtaishan 的回复:#include <stdio.h>  int main() {     int** pp = NULL;    [color=#FF0000] int* p = NULL;   //p也是指向NULL,但是赋值成功了      p = (int*)100;     printf("%p\n", p);     *pp = p;         printf("%x\n",*pp);      return 0;  } 将100赋值给p是没问题的，即p指向内存单元里以100开头的地址； 但是将*pp = p;赋值就是有问题的，因为pp指向NULL，即不可读不可写的地址，*pp = p;就是对其写操作，自然是会出现段错误； 引用 1 楼 cfjtaishan 的回复:#include <stdio.h>  int main() {     int** pp = NULL;     int* p = NULL;          p = (int*)100;    //p也是指向NULL，这个赋值成功     printf("%p\n", p);     *pp = p;         printf("%x\n",*pp);      return 0;  } 将100赋值给p是没问题的，即p指向内存单元里以100开头的地址； 但是将*pp = p;赋值就是有问题的，因为pp指向NULL，即不可读不可写的地址，*pp = p;就是对其写操作，自然是会出现段错误；  我将本来指向0地址的指针指向100，那我也可以将本来指向0的pp指向100，这样好像也说的过去，*pp也就是（int*）类型，将它指向100，应该也是可以的吧，难道是因为*pp没有初始化？

#include <stdio.h>  int main() {     int** pp = NULL;     int* p = NULL;      p = (int*)100;     printf("%p\n", p);     *pp = p;     // pp是不可读不可写的，因为指向NULL了      printf("%x\n",*pp);      return 0;  } 将100赋值给p是没问题的，即p指向内存单元里以100开头的地址； 但是将*pp = p;赋值就是有问题的，因为pp指向NULL，即不可读不可写的地址，*pp = p;就是对其写操作，自然是会出现段错误；


Question: 我定义一个结构体，然后初始化，之后取其地址，为什么指针不为空？

楼上的兄弟伙些  正解

引用为什么不指向空  在代码中有注释:  #include<stdio.h> #include<string.h>  void ifStruct(void *indata) { 	if (NULL == indata) //传入的地址为空，才会执行这个分支，那到底indata是空指针吗? 	{ 		printf("结构体指针指向空\n"); 		return; 	}  	printf("结构体指针不指向空\n"); 	return; }  int main() { 	typedef struct student 	{ 		int id; 		char name[10];  	}Student;   	Student std; //在栈上创建了Student类的实例对象，该对象占用内存空间，&std是有值的。 	memset(&std, 0, sizeof(std));   	ifStruct(&std); //实参&std有值，传递到函数中，形参indata也有值，不是空指针。                               //可以在这行设置断点，调试中止后看一下std的值就清楚了 	return 0; }

对结构体变量初始化，只是对结构体里的元素初始化了。

因为传递给形参的是一个有效地址，即main函数里变量std的地址。即形参indata指向了std的地址。除非这样调用ifStruct函数： ifStruct(NULL);

你只是将结构体里面的数据改变为0，就是将id的值改为0，和将数组改为空数组，并没有将结构体的指针指向为空，现在结构体的指针指向一堆0，结构体的指针一直都在，从没有变过。


Question: C语言 服务器转发文件给客户端，客户端开线程接收文件出错

你用的不是TCP协议的，用的的UDP协议，这种协议传输，不保证数据的可靠性，以及是否到达，用TCP协议吧

引用 7 楼 hzy_76 的回复:关TCP什么事？楼主显然是用UDP的方式！  UDP是无保证的协议，需要自己处理丢包、重复的问题，我估计你可能出现重复收包了。一般的处理方式是每个包用一个ID号标识，一来可以处理重复问题，二来用于确定顺序。另外加入收包确认机制，发送方在一定时间内如果收不到确认，要重发该ID的数据。 谢谢，交完作业已经好几天了，我也不是专业的，所以这个问题并不是很想要深究下去。但是怎么才能在发帖后得到及时的帮助，这点能教教我吗？

引用 10 楼 hzy_76 的回复:这我也没有好办法，尤其是在论坛上，你的帖子被真正能帮你的人注意到，是无法量化时间的。如果你大概知道谁懂，就直接问他，这样最好了。要不就只能等，我在CSDN问一个问题，也是好多天后才有人提供比较好的思路，最终还是我自己搞定的。  自己搞定能有所提高，

引用 7 楼 hzy_76 的回复:关TCP什么事？楼主显然是用UDP的方式！  UDP是无保证的协议，需要自己处理丢包、重复的问题，我估计你可能出现重复收包了。一般的处理方式是每个包用一个ID号标识，一来可以处理重复问题，二来用于确定顺序。另外加入收包确认机制，发送方在一定时间内如果收不到确认，要重发该ID的数据。 不知道有多少前人掉在UDP Socket sendto(人多)sendto(病少)sendto(财富) recvfrom(人多)recvfrom(财富) 陷阱里面啊！

引用 2 楼 WindwaterSide 的回复:[quote=引用 1 楼 kakabulusi 的回复:] 这就需要你了解一下TCP传输机制了。  TCP的三次握手、超时重传等机制。 三次握手保证了数据传输的可靠性，超时重传保证了数据的完整性。  但是，实际情况可能不尽如人意，超时重传可能会遇到实际发送成功，但是在指定时间内没有应答的情况，这种情况下会造成异常重传。【比如说，应答的响应时间如果超过500ms则重传该批次数据，由于网络情况，某段数据流传输时间开销可能超过了500ms才到达接收方，此时发送方不再响应该包正常收到的应答信息，而重新传递该批次数据。这一点也是TCP和UDP协议在本质上的区别】  TCP本身是流式套接字，解决完这个问题后，你还会遇到很多问题，比如说滑动窗口、粘包等，希望对你有帮助。  谢谢回复，但是明天就是ddl了，所以现在只是想知道我的程序出了什么问题，能帮我看看吗[/quote]   现在看可能来不及了，

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

引用 1 楼 kakabulusi 的回复:这就需要你了解一下TCP传输机制了。  TCP的三次握手、超时重传等机制。 三次握手保证了数据传输的可靠性，超时重传保证了数据的完整性。  但是，实际情况可能不尽如人意，超时重传可能会遇到实际发送成功，但是在指定时间内没有应答的情况，这种情况下会造成异常重传。【比如说，应答的响应时间如果超过500ms则重传该批次数据，由于网络情况，某段数据流传输时间开销可能超过了500ms才到达接收方，此时发送方不再响应该包正常收到的应答信息，而重新传递该批次数据。这一点也是TCP和UDP协议在本质上的区别】  TCP本身是流式套接字，解决完这个问题后，你还会遇到很多问题，比如说滑动窗口、粘包等，希望对你有帮助。  谢谢回复，但是明天就是ddl了，所以现在只是想知道我的程序出了什么问题，能帮我看看吗


Question: 一个关于C编译器的问题

for循环里定义变量不是C的语法规则，你用C编译器就是通不过。对于是用C98还是C99总归都是C的语法规则

c++支持在函数内部任意地方定义变量，而c的变量只能在函数的开始定义。

后缀明是.ca呀，而且我在编译器的参数设置里加了-std=c99这样不就支持c99了吗？为什么说这是c++

提示说命令行参数是用来编译C源代码的指令  而你的源代码文件是C++的  把后缀名改成 .c 就没事了

c99才支持for内部定义变量

for (int i = 0; i < 5; i++) 这句int定义在for循环里是C++才有的语法。所以，这个error可能是这个导致的。把i的定义放在外面看看还提示这个错误不

你源代码文件的扩展名是.c吗？


Question: c 有符号与无符号之间的转换

电脑内存或文件内容或传输内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容或传输内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

无对应汇编指令，不分析。 仅供参考：#include <stdio.h> unsigned short int ui;   signed short int si; int main() { 	ui=(unsigned short int)0x8000u; 	si=(  signed short int)0x8000; 	printf("ui=%u\n",ui); 	printf("si=%d\n",si); 	ui=ui>>1; 	si=si>>1; 	printf("ui=%u\n",ui); 	printf("si=%d\n",si);  	printf("--------------\n"); 	ui=(unsigned short int)0x8000u; 	si=(  signed short int)0x8000; 	printf("ui=%u\n",ui); 	printf("si=%d\n",si); 	ui=((  signed short	int)ui)>>1; 	si=((unsigned short	int)si)>>1; 	printf("ui=%u\n",ui); 	printf("si=%d\n",si);  	return 0; } //ui=32768 //si=-32768 //ui=16384 //si=-16384 //-------------- //ui=32768 //si=-32768 //ui=49152 //si=16384

各位能不能就上边我提问题的截图里边的比较运算随便拿一个出来分析讲解一下为什么会是那个结果？我现在满疑惑的

你写的所有代码在内存中都是0和1，编译器也不认识它是不是有无符号，只有你告诉编译器他是有符号的或者无符号的，否则都是0和1的运算 至于你不知道什么时候转换，那你操心这些有设么用，等你需要大小比较时，自己就会知道什么时候要转换了，就是说你认为它不转换就是错的，你就可以转换了

一个数值在内存的单元里存放都是二进制形式，二进制值都是一样的，只是要看你用什么形式输出。 打个比方，在内存里存放的是0x11，%d输出的可能是-1，  %u输出的可能是3（仅仅是打个比方）；

引用在什么情况下该转换类型，什么情况下不该转换类型  强制转换类型取决于程序员，你可以任意转换不同数据类型。 但不同数据类型能存放的数值有上下限，如果等号右侧的数值超过等号左侧类型能存放的界限。 转换时会有截断，不能保证转换成功。  long int i = 123456789997787878; int j = (int)i;  //j不会等于123456789997787878  加入符号表示后情况也是一样，到底这个数值是多少，要看本质上 二进制各位的值。

注意：常量也有类型！  C++ Integer Constants  See Also  Send Feedback     Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types.  Grammar integer-constant:  decimal-constant integer-suffixopt  octal-constant integer-suffixopt  hexadecimal-constant integer-suffixopt  'c-char-sequence'  decimal-constant:  nonzero-digit   decimal-constant digit  octal-constant:  0  octal-constant octal-digit  hexadecimal-constant:  0xhexadecimal-digit  0Xhexadecimal-digit   hexadecimal-constant hexadecimal-digit  nonzero-digit: one of  1 2 3 4 5 6 7 8 9  octal-digit: one of  0 1 2 3 4 5 6 7  hexadecimal-digit: one of  0 1 2 3 4 5 6 7 8 9   a b c d e f   A B C D E F  integer-suffix:  unsigned-suffix long-suffixopt  long-suffix unsigned-suffixopt  unsigned-suffix: one of  u U  long-suffix: one of  l L  64-bit integer-suffix:  i64 LL ll  To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type.  To specify a decimal constant, begin the specification with a nonzero digit. For example:    Copy Code  int i = 157;   // Decimal constant int j = 0198;  // Not a decimal number; erroneous octal constant int k = 0365;  // Leading zero specifies octal constant, not decimal    To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example:    Copy Code  int i = 0377;   // Octal constant int j = 0397;   // Error: 9 is not an octal digit    To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the "x" does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example:    Copy Code  int i = 0x3fff;   // Hexadecimal constant int j = 0X3FFF;   // Equal to i    To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example:    Copy Code  unsigned uVal = 328u;             // Unsigned value long lVal = 0x7FFFFFL;            // Long value specified                                    //  as hex constant unsigned long ulVal = 0776745ul;  // Unsigned long value    To specify a 64-bit integral type, use the LL, ll or i64 suffix. For example,    Copy Code  // 64bitsuffix.cpp #include <stdio.h> enum MyEnum {    IntType,    Int64Type };  MyEnum f1(int) {    printf("in f1(int)\n");    return IntType; }  MyEnum f1(__int64) {    printf_s("in f1(__int64)\n");    return Int64Type; }  int main() {    MyEnum t1 = f1(0x1234), t2 = f1(0x1234i64); }    Output    in f1(int) in f1(__int64)    See Also Concepts Literals (C++)

字面量数字默认是有符号的。 有符号与无符号数字进入运算时，默认是把有符号自动转为无符号。 什么时候该用强制转换，得看你的意图是什么。首先要搞明白负数是如何存储与表达的。 对于计算机而言，全是二进制，它不管你正还是负，得看你怎么去解析它。 以单字节为例，一个字节能表示的范围是0x00~0XFF共256个数字，如果你认为它是无符号的，它的范围就是0~255；如果你认为它是有符号的，它的范围就是-128~127。注：负数是用补码存储。  127的二进制：0111 1111 如果再加1就成了二进制：1000 0000   这个时候如果你认为它是有符号的，它就是-128，无符号的就是128。 也就是说，00000000~0111 1111对于有符号和无符号都是表示0~127，而1000 0000 ~11111111对于有符号而言是-128 ~ -1，对于无符号而言是128~255。 于是不难看出char类型的-1跟unsigned char的255相等。


Question: 各位帮我看一看这个表达式,我觉得没问题啊

注释描述有问题呢，若a等于1，说明输入正确。

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

楼上正解。。。。。

while的那行后面的分号去掉啊！哈哈


Question: 关于缓存内容读取

在文件大小相同的前提下：  读刚读过的文件比头次读没读过的文件快  读转速快的硬盘上的文件比读转速慢的硬盘上的文件快  读没有磁盘碎片的文件比读有磁盘碎片的文件快  读文件不处理比边读边处理快  单线程从头到尾一次读文件比多线程分别读文件各部分快（非固态硬盘上）  读固态硬盘上的文件比读普通硬盘上的文件快  您是否希望迅速对您频繁使用的文件进行碎片整理？使用 Contig 优化单个的文件，或者创建连续的新文件。http://technet.microsoft.com/zh-cn/sysinternals/bb897428

引用 6 楼 chenzheng1030 的回复:这种问题可以用共享内存，把文件直接映射到进程地址空间，效率不会比都read到缓冲区（内存）慢 有画蛇添足之嫌。

不要低估操作系统读写文件时使用内存缓冲区策略所用的智商！

引用 3 楼 a24027 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] [quote=引用 楼主 a24027 的回复:] 解析文件,需要先读取文件,老板说频繁读取降低效率,所以先把文件内容读取到缓存区,然后从缓存里读取,但是缓存里怎么读呢  unsigned char* pBuf; pBuf=(char*)malloc(1000);  指针为字符指针,然而实际的数据有整型,短整型和字符型,怎样通过字符指针直接读取4个字节连在一起的内容呢 可以考虑定义结构体，读取的内容放到pBuf缓存里（char类型）然后再强制类型转换。[/quote] 从文件读取,内容又不是单一格式,不能定义结构体[/quote] 看你文件的内容是不是有格式或者规律的，使用fscanf可以对有格式的内容读取。如果没有规律，考虑读到pBuf里，然后挨个解析了。

引用 1 楼 cfjtaishan 的回复:[quote=引用 楼主 a24027 的回复:] 解析文件,需要先读取文件,老板说频繁读取降低效率,所以先把文件内容读取到缓存区,然后从缓存里读取,但是缓存里怎么读呢  unsigned char* pBuf; pBuf=(char*)malloc(1000);  指针为字符指针,然而实际的数据有整型,短整型和字符型,怎样通过字符指针直接读取4个字节连在一起的内容呢 可以考虑定义结构体，读取的内容放到pBuf缓存里（char类型）然后再强制类型转换。[/quote] 从文件读取,内容又不是单一格式,不能定义结构体

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

引用 楼主 a24027 的回复:解析文件,需要先读取文件,老板说频繁读取降低效率,所以先把文件内容读取到缓存区,然后从缓存里读取,但是缓存里怎么读呢  unsigned char* pBuf; pBuf=(char*)malloc(1000);  指针为字符指针,然而实际的数据有整型,短整型和字符型,怎样通过字符指针直接读取4个字节连在一起的内容呢 可以考虑定义结构体，读取的内容放到pBuf缓存里（char类型）然后再强制类型转换。


Question: 关于视频解析

引用求它的总帧数  如果只是为了完成求总帧数这个任务，可以借助opencv或者其它第三方库。 如果老师的意思是让你自己写算法来解决，肯定得分析文件结构组成。 可以把视频裁短些，先用其它库得到总帧数，假设为5帧。 然后自己分析文件，看看文件规律，看怎么样也能得到5帧。  视频中有关键帧概念，视频是分块压缩存储，每一块有一个关键帧，其他帧只记录与关键帧不同的地方以节省存储空间。

按你导师的提示，找到这两帧，通过他们的时间戳计算得出总时长，然后根据帧率计算出总帧数！比如25FPS，总时长1小时，那总帧数为：25 *（1*60*60）

根据视频文件的结构组成分析视频文件即可。  还有一个粗略的办法，获取到视频文件的帧率和时间，推算出总帧数。

使用ffmpeg库？