Question: 关于指针与数组的疑问

sizeof(a)是指针a的大小，不是a所在指向的存储空间的大小

引用 12 楼 ganpengjin1 的回复:[quote=引用 9 楼 seraphlyy 的回复:] [quote=引用 6 楼 zhuobattle 的回复:] [quote=引用 5 楼 seraphlyy 的回复:] [quote=引用 3 楼 zhuobattle 的回复:] a所在指向的存储空间比t的要大: 这句话压根不成立，你拿一个变量和一个指针有什么好比的呢？额，你没明白的意思，如果此时a就是单纯的指针变量，那我传递给t的地址给a的时候，a就该指向存储t变量的那个存储区域，但是现在是a指向的那块区域被扩大了[/quote] 就因为sizeof(a)=4，你就说是被扩大了？[/quote]不是，因为sizeof(a)=4，我贴图给你看吧[/quote] 最后再回复你一下，不想再多说了： 1，a是指向的b【2】这个数组，并不是扩大了，懂？？？？ 2，你在sizeof（a）用为4，不是什么内存扩大了。 3，该仔细看书，该多思考。[/quote]你误会我的意思了。我已经知道哪里误解了。

sizeof(a)是指针变量的大小，32位程序永远为4，和指针指向的数组大小没有任何关系。

引用 11 楼 zhuobattle 的回复:[quote=引用 9 楼 seraphlyy 的回复:] [quote=引用 6 楼 zhuobattle 的回复:] [quote=引用 5 楼 seraphlyy 的回复:] [quote=引用 3 楼 zhuobattle 的回复:] a所在指向的存储空间比t的要大: 这句话压根不成立，你拿一个变量和一个指针有什么好比的呢？额，你没明白的意思，如果此时a就是单纯的指针变量，那我传递给t的地址给a的时候，a就该指向存储t变量的那个存储区域，但是现在是a指向的那块区域被扩大了[/quote] 就因为sizeof(a)=4，你就说是被扩大了？[/quote]不是，因为sizeof(a)=4，我贴图给你看吧[/quote] 呵呵，这也能证明扩大了吗？那个地方，随便写个只要存在的地址它都能给你显示出结果了。 [/quote]测了下，果然如此。谢谢了

引用 9 楼 seraphlyy 的回复:[quote=引用 6 楼 zhuobattle 的回复:] [quote=引用 5 楼 seraphlyy 的回复:] [quote=引用 3 楼 zhuobattle 的回复:] a所在指向的存储空间比t的要大: 这句话压根不成立，你拿一个变量和一个指针有什么好比的呢？额，你没明白的意思，如果此时a就是单纯的指针变量，那我传递给t的地址给a的时候，a就该指向存储t变量的那个存储区域，但是现在是a指向的那块区域被扩大了[/quote] 就因为sizeof(a)=4，你就说是被扩大了？[/quote]不是，因为sizeof(a)=4，我贴图给你看吧[/quote] 少年，看来你的路还很长，要好好学习。

引用 9 楼 seraphlyy 的回复:[quote=引用 6 楼 zhuobattle 的回复:] [quote=引用 5 楼 seraphlyy 的回复:] [quote=引用 3 楼 zhuobattle 的回复:] a所在指向的存储空间比t的要大: 这句话压根不成立，你拿一个变量和一个指针有什么好比的呢？额，你没明白的意思，如果此时a就是单纯的指针变量，那我传递给t的地址给a的时候，a就该指向存储t变量的那个存储区域，但是现在是a指向的那块区域被扩大了[/quote] 就因为sizeof(a)=4，你就说是被扩大了？[/quote]不是，因为sizeof(a)=4，我贴图给你看吧[/quote] 最后再回复你一下，不想再多说了： 1，a是指向的b【2】这个数组，并不是扩大了，懂？？？？ 2，你在sizeof（a）用为4，不是什么内存扩大了。 3，该仔细看书，该多思考。

引用 9 楼 seraphlyy 的回复:[quote=引用 6 楼 zhuobattle 的回复:] [quote=引用 5 楼 seraphlyy 的回复:] [quote=引用 3 楼 zhuobattle 的回复:] a所在指向的存储空间比t的要大: 这句话压根不成立，你拿一个变量和一个指针有什么好比的呢？额，你没明白的意思，如果此时a就是单纯的指针变量，那我传递给t的地址给a的时候，a就该指向存储t变量的那个存储区域，但是现在是a指向的那块区域被扩大了[/quote] 就因为sizeof(a)=4，你就说是被扩大了？[/quote]不是，因为sizeof(a)=4，我贴图给你看吧[/quote] 呵呵，这也能证明扩大了吗？那个地方，随便写个只要存在的地址它都能给你显示出结果了。

引用 8 楼 abc814251901 的回复:a仅仅是一个指针，他指向的是变量t,这个跟t占多少空间没有关系的 这两个也没有啥可比性啊

引用 6 楼 zhuobattle 的回复:[quote=引用 5 楼 seraphlyy 的回复:] [quote=引用 3 楼 zhuobattle 的回复:] a所在指向的存储空间比t的要大: 这句话压根不成立，你拿一个变量和一个指针有什么好比的呢？额，你没明白的意思，如果此时a就是单纯的指针变量，那我传递给t的地址给a的时候，a就该指向存储t变量的那个存储区域，但是现在是a指向的那块区域被扩大了[/quote] 就因为sizeof(a)=4，你就说是被扩大了？[/quote]不是，因为sizeof(a)=4，我贴图给你看吧

引用 1 楼 ganpengjin1 的回复:注意，参数没有数组的说法，都是指针。我的描述有误，我的意思不是a本身，而是a指向的那块区域，

引用 5 楼 seraphlyy 的回复:[quote=引用 3 楼 zhuobattle 的回复:] a所在指向的存储空间比t的要大: 这句话压根不成立，你拿一个变量和一个指针有什么好比的呢？额，你没明白的意思，如果此时a就是单纯的指针变量，那我传递给t的地址给a的时候，a就该指向存储t变量的那个存储区域，但是现在是a指向的那块区域被扩大了[/quote] 就因为sizeof(a)=4，你就说是被扩大了？

引用 3 楼 zhuobattle 的回复:a所在指向的存储空间比t的要大: 这句话压根不成立，你拿一个变量和一个指针有什么好比的呢？额，你没明白的意思，如果此时a就是单纯的指针变量，那我传递给t的地址给a的时候，a就该指向存储t变量的那个存储区域，但是现在是a指向的那块区域被扩大了

引用 2 楼 seraphlyy 的回复:引用 1 楼 ganpengjin1 的回复:注意，参数没有数组的说法，都是指针。你的意思此时参数a就是个指针，那为何test(&t);时候a所在指向的存储空间比t的要大 注意是空间位置，与大小无关，内存位置由编译器随机分配。如果你sizeof参数a，那它就是sizeof（指针大小） = 4

注意，参数没有数组的说法，都是指针。


Question: char**和char[][]的问题

引用 22 楼 rongxiaojun 的回复:[quote=引用 17 楼 dcw0402 的回复:] 这里,二维数组其实是一个一维数组的加长版.... 改成这样也可以 void output(char *buffer){ 	printf("%s\n",buffer); } 我也不知道为啥,感觉7楼说有的些道理  这是因为char buffer[100][1024]中，buffer的值即char[0][0]的地址，（真不可思议，二维数组地址即第一个数组中第一个元素地址，而非第一个数组的地址），然后调用函数output(buffer)，此时buffer的值传进参数中，参数类型char*，则参数为char* 类型且指向了首字符'i',然后printf打印字符串直到'\0'出现，一切都解释通了。[/quote] 你的理解还是有问题，buffer是一个数组名，当你将buffer作为指针使用时，其被转化为一个指向数组首元素的指针。这里数组首元素是什么？是一个包含1024个char的数组（因为本质上所有数组都是一维数组），buffer[0]可以当做它的数组名！

void output（char **buffer）{    printf（“%s\n”,buffer[0]）;        // output::buffer == ((char**) (main::buffer);        // output::buffer[0] == ((char**) (&main::buffer ))[0];        //         // 这是把 main::buffer 当作储存指针的数组使用，        // output::buffer[0]是该指针数组的第一个元素        // 该指针其实是把         // main::buffer[0][0],main::buffer[0][1],main::buffer[0][2],main::buffer[0][3]。。。。        // 这4（指针长度）个字符,组成的一个整型数据，当作指针使用        // 这样 output::buffer[0] 其实是个野指针。        // 出错是正常，不错是巧合。        // 这里借用一下，C++的作用域限定符:: 表示作用域   }                                 void main(){    char buffer[100][1024] = {0};    int len = sprintf(buffer[0],"i am a bastard...");    buffer[0][len] = '\0';    output(buffer);//传递buffer 即 &buffer[0]，这里类型不对，应该报错，或者警告。  }  多级指针，需要指针数组做中转，或者动态分配数据 才能和多维数组匹配 //维持这种函数定义，需要传如指针地址，指针数组，和二级指针 void output（char **buffer）{    printf（“%s\n”,buffer[0]）;     }                                 void main(){    char buffer[100][1024] = {0};    int len = sprintf(buffer[0],"i am a bastard...");    buffer[0][len] = '\0';       /************* 1 ***************/    { char *p[100];      int i;      for(i=0;i<100;i++)p[i] = buffer[i];      output(p);    }     /************* 1 ***************/    { char *p[100];      char **pp = &p;      int i;      for(i=0;i<100;i++)p[i] = buffer[i];      output( pp );//    }    /*********** 3**********/    {      char **pp = malloc(sizeof(char *)*100);//c++ 替换为 char ** =new char*[100];      int i;      for(i=0;i<100;i++)pp[i] = buffer[i];      output( pp );//      free(pp);   //c++ 替换为 delete[]pp;    } }  多级指针，多维数组 数组维度，和指针的级别是不同的概念，虽然有对应关系。 指针级别，就是间接访问的次数， 数组维度，指的是数组层次，是一层套一层的概念，这个就是多维数组，递归定义的含义。 数组访问是逐层查找， 就像中央---省 ---县----镇----村--- 家-----个人 这样的查找的，不过是按照每一层次的大小（改维度的大小）数数而已。 数组每个维度，只是大块和小块的关系，整个数组是在一起的。  变量（所谓对象），和数据是直接对应的，所以是直接访问的。 指针，访问所指地址中的数据，是间接访问的。  多级指针，就是不断找到下级地址访问数据。每一级指针，只能找到下级指针。  指针分级，并不需要放在一起存储，除了一级一级找到地址，无法一次到位访问。 如果，某级指针未定义（初始化），就不能向下级访问了。 比如  int *p;// int **pp =& p;//  可以访问 *pp ;不可以访问 *p; 因为 p ；没有初始化----定义时候，没有初始化，也没有赋值，让他指向对象(变量)的地址。 数组，已经定义，各个维度都定义好了。 即  int a[M][N];//二维数组 a 已经定义。 a[0].........a[M-1] 都是定义好的一维子数组。 a[0][1].........a[M-1][N-1]; //都是定义好的数组元素（变量）。

参数类型的原因，你可以参考下我的这篇博文，希望能让你找到答案 http://blog.csdn.net/xuchao1229/article/details/8223518

无论一维，二维，三维，四维，五维...数组，本质上，它的首地址，都只是寻一次地址，大概可以说等价于一维指针。  但是一维，二维，三维...指针就不一样了。n维指针，要寻找n次地址。

引用 27 楼 rongxiaojun 的回复:[quote=引用 26 楼 lwouyang 的回复:] 说了，技术上相等，因为算出来的都是同一个地址，不让它们相等能怎么办？ 怎么算出来的？ &地址符不就是取变量地址吗？都取了地址了buffer又怎么能和&buffer相等呢？buffer[0]是值，&buffer[0]是它的地址，值和地址是一回事吗？ int a = 14; 你怎么不让a和&a相等？[/quote] 因为是同一个地址，只不过类型不一样，

这个只能弄成数组指针

//在堆中开辟一个4×5的二维int数组 #include <stdio.h> #include <malloc.h> int **p; int i,j; void main() {     p=(int **)malloc(4*sizeof(int *));     if (NULL==p) return;     for (i=0;i<4;i++) {         p[i]=(int *)malloc(5*sizeof(int));         if (NULL==p[i]) return;     }     for (i=0;i<4;i++) {         for (j=0;j<5;j++) {             p[i][j]=i*5+j;         }     }     for (i=0;i<4;i++) {         for (j=0;j<5;j++) {             printf(" %2d",p[i][j]);         }         printf("\n");     }     for (i=0;i<4;i++) {         free(p[i]);     }     free(p); } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19  //在堆中开辟一个3×4×5的3维int数组 #include <stdio.h> #include <malloc.h> int ***p; int i,j,k; void main() {     p=(int ***)malloc(3*sizeof(int **));     if (NULL==p) return;     for (i=0;i<3;i++) {         p[i]=(int **)malloc(4*sizeof(int *));         if (NULL==p[i]) return;         for (j=0;j<4;j++) {             p[i][j]=(int *)malloc(5*sizeof(int));             if (NULL==p[i][j]) return;         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 p[i][j][k]=i*20+j*5+k;             }         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 printf(" %2d",p[i][j][k]);             }             printf("\n");         }         printf("---------------\n");     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             free(p[i][j]);         }         free(p[i]);     }     free(p); } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //--------------- // 20 21 22 23 24 // 25 26 27 28 29 // 30 31 32 33 34 // 35 36 37 38 39 //--------------- // 40 41 42 43 44 // 45 46 47 48 49 // 50 51 52 53 54 // 55 56 57 58 59 //---------------

楼主来这里看看吧http://blog.csdn.net/code_crash/article/details/4855010 如果想了解的更清晰点，直接问supermegaboy本人

引用 26 楼 lwouyang 的回复:说了，技术上相等，因为算出来的都是同一个地址，不让它们相等能怎么办？ 怎么算出来的？ &地址符不就是取变量地址吗？都取了地址了buffer又怎么能和&buffer相等呢？buffer[0]是值，&buffer[0]是它的地址，值和地址是一回事吗？ int a = 14; 你怎么不让a和&a相等？

说了，技术上相等，因为算出来的都是同一个地址，不让它们相等能怎么办？

引用 23 楼 lwouyang 的回复:[quote=引用 22 楼 rongxiaojun 的回复:] [quote=引用 17 楼 dcw0402 的回复:] 这里,二维数组其实是一个一维数组的加长版.... 改成这样也可以 void output(char *buffer){ 	printf("%s\n",buffer); } 我也不知道为啥,感觉7楼说有的些道理  这是因为char buffer[100][1024]中，buffer的值即char[0][0]的地址，（真不可思议，二维数组地址即第一个数组中第一个元素地址，而非第一个数组的地址），然后调用函数output(buffer)，此时buffer的值传进参数中，参数类型char*，则参数为char* 类型且指向了首字符'i',然后printf打印字符串直到'\0'出现，一切都解释通了。[/quote] 错！准确的讲，二维数组名的值是指向第一个数组的指针值，buffer == &buffer[0]。 二维数组在概念上是数组的数组，第一个数组 buffer[0] 的值才是指向 buffer[0][0] 的指针值。这些概念是实在的，因此 buffer+1 和 buffer[0]+1 都有各自确切的意义。技术上，这几个地址值是相等的，buffer == &buffer[0] == buffer[0] == &buffer[0][0]。但是 buffer 和 buffer[0] 类型是不同的。二维数组名 buffer 和 char* buffer 之间必有一个强制类型转换，而 buffer[0] 与 char* buffer 则是兼容类型。[/quote] 真不可思议： buffer==&buffer==&buffer[0] == buffer[0] == &buffer[0][0]真的相等，为什么？buffer==&buffer 和 buffer[0]==&buffer[0]就明显不一样吧，明显取了地址的，为什么？

引用 22 楼 rongxiaojun 的回复:[quote=引用 17 楼 dcw0402 的回复:] 这里,二维数组其实是一个一维数组的加长版.... 改成这样也可以 void output(char *buffer){ 	printf("%s\n",buffer); } 我也不知道为啥,感觉7楼说有的些道理  这是因为char buffer[100][1024]中，buffer的值即char[0][0]的地址，（真不可思议，二维数组地址即第一个数组中第一个元素地址，而非第一个数组的地址），然后调用函数output(buffer)，此时buffer的值传进参数中，参数类型char*，则参数为char* 类型且指向了首字符'i',然后printf打印字符串直到'\0'出现，一切都解释通了。[/quote] 错！准确的讲，二维数组名的值是指向第一个数组的指针值，buffer == &buffer[0]。 二维数组在概念上是数组的数组，第一个数组 buffer[0] 的值才是指向 buffer[0][0] 的指针值。这些概念是实在的，因此 buffer+1 和 buffer[0]+1 都有各自确切的意义。技术上，这几个地址值是相等的，buffer == &buffer[0] == buffer[0] == &buffer[0][0]。但是 buffer 和 buffer[0] 类型是不同的。二维数组名 buffer 和 char* buffer 之间必有一个强制类型转换，而 buffer[0] 与 char* buffer 则是兼容类型。

引用 17 楼 dcw0402 的回复:这里,二维数组其实是一个一维数组的加长版.... 改成这样也可以 void output(char *buffer){ 	printf("%s\n",buffer); } 我也不知道为啥,感觉7楼说有的些道理  这是因为char buffer[100][1024]中，buffer的值即char[0][0]的地址，（真不可思议，二维数组地址即第一个数组中第一个元素地址，而非第一个数组的地址），然后调用函数output(buffer)，此时buffer的值传进参数中，参数类型char*，则参数为char* 类型且指向了首字符'i',然后printf打印字符串直到'\0'出现，一切都解释通了。

引用 11 楼 skyliuxu 的回复:[quote=引用 楼主 rongxiaojun 的回复:] 长话短说： void output（char **buffer）{    printf（“%s\n”,buffer[0]）; }  void main(){    char buffer[100][1024] = {0};    int len = sprintf(buffer[0],"i am a bastard...");    buffer[0][len] = '\0';    output(buffer); }  程序出现“段错误” 求解答！ 是linux下gcc编译系统吗？在vs下错误信息就是write access violation at address 0xblablabla(大概是这么个错误提示吧，记不清了)。 为什么会出现这样的错误呢？这就值得好好探讨了。 首先，指针和数组是根本不同的两个东西！尽管它们有着千丝万缕的联系！ 第二，要理解为什么出现上面这样的错误，需要理解两个最基本的东西： （1）数组名称出现在表达式中时（除用于sizeof外），会被看成一个指向该数组第一个元素的指针。注意，本质上讲，C中所有数组都是一维数组，所以第一个元素是什么是非常明确的。比如，int a[10]的第一个元素是一个整型数，而int a[10][10]的第一个元素是一个包含10个整型数的数组。 （2）指针可以与整型数进行加减法，结果是新的指针，而加减的单位是指针所指向元素的大小。比如，int *p, p = a;(注意体会（1）在这儿的作用)，则p + 1指向的是a[1],p+4指向的是a[4]. 下面可以看一下为什么出现上面的错误了。 char buffer[100][1024]表示buffer是一个二维数组，output(buffer)中的buffer会被看做指向该二维数组第一个元素的指针，即被看作指向一个包含1024个char的数组的指针，char (*)[1024]是这个指针的类型。而在output的定义中，其期望的参数类型是char **，所以编译结果会有warning。当然，你依然可以运行，因为存在强制类型转换。这也是为什么4楼做法没用的原因，你显式的进行类型转换除了消除了warning外（机器是很好糊弄的），基本没有什么意义。接着分析出现错误的原因，output函数的参数声明是char **，即二级指针（pointer to pointer）。注意，强制类型转换不会改变指针的值。这样，buffer的值与main中定义的buffer的值是一样，不过output里的buffer是二级指针。那么buffer[0]是什么，buffer是二级指针，buffer[0]当然就是一级指针！buffer[0]等于多少？buffer[0]实际上是*（buffer+0），前面说过，指针是可以与整数进行加减法的（这是array index的基础），而加减的单位是该指针指向的元素的大小，buffer指向的是什么元素？char*!所以*(buffer+0)的值是0x6d612069（i am所占的四个字节的值对应的地址，注意little endian），因此，出现write access violation就不足为奇了。 大概就是这么个意思，有一些地方的表述是不够准确的，欢迎进一步探讨。[/quote] 说的太好了，几乎完全消化了  我总结一下（我系统是64位）： GDB显示的结果如下： buffer=0x7ffffffe5180 buffer[0][0]=0x7ffffffe5180 output (buffer=0x7ffffffe5480) at b.c:22 如上三条说明了两个问题： 1.buffer其实是buffer[100][1024]中首元素buffer[0][0]的地址，即‘i’的地址 2.强制类型转换确实不会改变指针的值，尽管函数外buffer是char(*)[1024]类型、函数参数char**类型，外buffer还是将buffer[0][0]地址传给了参数char**。 此时问题来了，函数内buffer为二级指针，buffer[0]类型char*，为指针，64位系统指针8字节，则buffer[0]指针的值为buffer所指内存单元向下共8个内存单元内容组成的值。是不是很绕，这8个内存单元内容是什么呢，此时函数内buffer值就是函数外buffer[0][0]即字符'i'的地址，则从‘i’开始依次取八个字节得到的是'i am a b'，将其转化为数值即为0x6d612069，故buffer[0]的值为0x6d612069，printf（“%s\n”,buffer[0]）,故发生地址越界。

引用 19 楼 lwouyang 的回复:编译时编译器没抱怨吗？如果是，你可以把编译器扔了。 如果有报怨的话，你没看就轻易放过了？ 得饶人处且饶人，我看不是大错只是警告，想放它条生路

char**p是一个指向char*的指针，*p或p[0]必须是一个地址。你的实参不满足这要求。


Question: main函数如何调用其他文档的函数

main函数中调用t2fun不是这样：void t2fun();（看你贴的图是这样的），直接写t2fun()就可以了。 c++才允许函数原型参数为空，比如void main()，c要写上void，比如void main(void) 引用 10 楼 u013410394 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] t1.c: #include <stdio.h> #include "t.h" int main() {  t2fun();  return 0; } t.h: void t2fun();按您说的，结果不跳出来，只有main的printf会输出 t2.c void t2fun() {  printf("in t2fun()\n"); } [/quote]

我之前搞错了，纠正为： t1.c: #include "t.h" int main() {  t2fun();  return 0; }  t2.c: #include <stdio.h> void t2fun() {  printf("in t2fun()\n"); }  t.h不变。

void t2fun(); -->t2fun();

引用 11 楼 u013410394 的回复:[quote=引用 8 楼 derekrose 的回复:] compile error 是什么 您看看十楼我发的图片，结果不跳出来，编译成功了。被调用函数不跳出结果[/quote]  debug 设断点

引用 8 楼 derekrose 的回复:compile error 是什么 您看看十楼我发的图片，结果不跳出来，编译成功了。被调用函数不跳出结果

引用 6 楼 zhao4zhong1 的回复:t1.c: #include <stdio.h> #include "t.h" int main() {  t2fun();  return 0; } t.h: void t2fun();按您说的，结果不跳出来，只有main的printf会输出 t2.c void t2fun() {  printf("in t2fun()\n"); }

引用 7 楼 u013410394 的回复:引用 5 楼 bijiaoben 的回复:你是编译连接不过还是运行不了？编译连接不过 把你自己写的简单代码和错误提示都贴上来

compile error 是什么

t1.c: #include <stdio.h> #include "t.h" int main() {  t2fun();  return 0; } t.h: void t2fun(); t2.c void t2fun() {  printf("in t2fun()\n"); }

你是编译连接不过还是运行不了？

引用 3 楼 derekrose 的回复:[quote=引用 2 楼 u013410394 的回复:] [quote=引用 1 楼 derekrose 的回复:] #include xxxxx 这个我知道，我是要更详细的[/quote]  include之后直接调用就可以了[/quote] 我试过，不行，一直跳错误，如果你真的懂的话，麻烦您直接给我两个列子，可以直接运行的。你可以直接写text1：.......... main文件：.......... 然后我直接运行main函数就成功运行，那我直接就给分了。

引用 2 楼 u013410394 的回复:[quote=引用 1 楼 derekrose 的回复:] #include xxxxx 这个我知道，我是要更详细的[/quote]  include之后直接调用就可以了

引用 1 楼 derekrose 的回复:#include xxxxx 这个我知道，我是要更详细的

#include xxxxx


Question: Labwindows/CVI中的fets()函数的疑问

谢谢高手的指点，我现在明白了C语言的前导空格这个概念了，后来百度了下还有尾随空格这一概念

void remove_front_space(char *sStr)//删除前导空格 {         int  i = 0, j = 0;         while ( sStr[i] && sStr[i] == ' ' )  i++;//第i个字符不是0且是空格，i逐字往后挪。其实可简写为while (sStr[i] == ' ' )  i++;         if ( i > 0 )//前i个字符都是空格         {                 while ( sStr[i] )//第i个字符不是0循环（即直到字符串末尾逐字循环）                 {                         sStr[j] = sStr[i];//将第i个字符赋值给第j个字符（）                         i++;                         j++;                 }                 sStr[j] = 0;//在前移的字符串的最后补0，作为去掉前导空格后新字符串的结束符         } }


Question: 联合体和结构体,为什么结果不对呢？

搞懂，

你这相当于union里有三个变量，int i;struct half;struct* ps; 当你给赋值时，相当于修改了ps的值，也就修改了half和i的值，你最后打印的是half的地址而不是half的值，不知道你懂了没？你可以查看下half的地值就是你最后输出的值。

正如1L所说，你这是个三个元素的union，一个是struct，一个是struct *，一个是int，所以你对其中任意一个赋值都会覆盖其他两个。而你的语句2对那个struct Unknow *ps赋了值，自然就覆盖掉了half的赋值，当然不可能出来a，b，c，d

更正：   number.ps = number.half;  -> number.ps = &number.half;

根本就通不过编译 类型不匹配

struct      {        char a;        char b;        char c;        char d;       }half,*ps; 和 struct      {        char a;        char b;        char c;        char d;       }half; struct      {        char a;        char b;        char c;        char d;       }*ps;  是一样的，联合体内有3个变量


Question: 这个程序那里错了

swap3 你给了两个指针给它，x和y记录的是2个地址，这个是不可能交换的

#include<stdio.h>  void swap1(int x, int y) { 	int tmp; 	tmp = x; 	x   = y; 	y   = tmp; }  void swap2(int *x, int *y) { 	int tmp; 	     tmp = *x; 	*x  = *y;   	*y  = tmp; }  void swap3(int *x, int *y) { 	int *tmp; 	     tmp = x;     x   = y;     y   = tmp; }  int main(void) { 	int a, b; 	int *pa, *pb; 	 	pa = &a; 	pb = &b;  	a = 10, b = 20; 	swap1(a, b); 	printf("a=%d,b=%d,*pa=%d,*pb=%d\n", a, b, *pa, *pb); 	 	a = 10, b = 20; 	swap2(pa, pb); 	printf("a=%d,b=%d,*pa=%d,*pb=%d\n", a, b, *pa, *pb); 	 	a = 10, b = 20; 	swap3(pa, pb); 	printf("a=%d,b=%d,*pa=%d,*pb=%d\n", a, b, *pa, *pb); 	 	return 0; }

#include<stdio.h>  void swap1(int x,int y) { 	int tmp; 	tmp = x; 	x   = y; 	y   = tmp; }  void swap2(int *x,int *y) { 	int tmp; 	     tmp = *x; 	*x  = *y;   	*y  = tmp; }  void swap3(int *x,int *y) { 	int *tmp; 	     tmp = x;     x   = y;     y   = tmp; }  int main(void) { 	int a, b; 	int *pa, *pb; 	 	pa = &a; 	pb = &b;  	a = 10, b = 20; 	swap1(a, b); 	printf("a=%d,b=%d,*pa=%d,*pb=%d\n", a, b, *pa, *pb); 	 	a = 10,b = 20; 	swap2(pa, pb); 	printf("a=%d,b=%d,*pa=%d,*pb=%d\n", a, b, *pa, *pb); 	 	a = 10, b = 20; 	swap3(pa, pb); 	printf("a=%d,b=%d,*pa=%d,*pb=%d\n", a, b, *pa, *pb); 	 	return 0; } 代码需要规范一下，并且代码中不要出现中文括号和分号！

引用 7 楼 zhao4zhong1 的回复:仅供参考#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 赵老师这编程风格，我怎么感觉我从来没学过C一样呢？

括号和分号变成全角的了

不知道你要问的是什么 只有swap2能交换成功  是不是你的void swap2（int *x,int *y）这个括号“（）”错了？改成英文的"()"  还有swap3的那个括号

swap1交换不了，swap2可以交换，swap3使用未初始化的指针错误

1、请把你的中文括号“（）”改为英文的“()” 2、swap2可以把实参内容交换；swap1 和swap3都是交换形参，对实参没影响，没什么用途。

错了？都能编译通过运行正常 lz要把疑问说出来 swap1交换的是整数副本 swap2交换的是指针指向的内存 swap3交换的是指针副本


Question: 编程题，求大神

cout<<

叼叼叼！

#include <stdio.h> int main() {  printf(   "123456789\n"   "987654321\n"   "123456789\n"  );  return 0; }

其实楼上说的都对呀！printf是万能的

LZ是来散分的吗？

楼上几位说的对

<< endl;

printf("123456789\r\n987654321\r\n123456789\r\n"); fflush(stdout);

一个就好，需要'\n'

3 printfs


Microsoft Visual Studio 2012的方法如下：  1）启动VS for Desktop 2）档案->新建专案->已安装的->Win32主控台应用程式 3）确定 4）应用程式设定->应用程式类型->DLL->完成  估计2013应该也差不多，没找到简体中文版的，暂时用的繁体中文版的，上面的步骤仅供参考

大哥，你解决了吗？

创建DLL项目就行了


Question: IP地址分类

这个分类可以说是一些规定，是规定一般也就只有去记住了

结束地址一定是255这样的数值，IP地址的分类只有死记。  引用 楼主 jiemo1123 的回复:IP地址分成5类，A类地址有的说是1.0.0.0到126.0.0.0，有的说是126.255.255.255，那个正确？具体的A到E类时如何划分的？linux中除了死记，还有什么方法可以查看某个IP是那类吗？


Question: 求C语言大神帮助，关于一道编程题

引用 5 楼 u013193033 的回复:我想问一下， 那个_getch()和getch有什么区别啊功能一样。不带下划线的是POSIX的，微软新的编译器已经废弃不用了，统一用带下划线的，如果你不用微软的编译器，那么建议用getch，移植性好点。如果用微软的编译器，就用带下划线的。

参考《编译原理》中的词法分析和有限状态自动机。

我想问一下， 那个_getch()和getch有什么区别啊

相邻两次按键间隔时间只要不超过宏定义的1000ms，就会当成连续按键记录次数，超时或者按了别的按键才会输出。 引用 2 楼 KenZhang1031 的回复:#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <time.h>  /* 超过1000ms认为超时输出 */ #define TIME_OVER		1000  /* key按下了count次，根据你自己的要求做按键解码,比如key='1'，count=2表示字母b，自己做处理 */ void translate_key(int key, int count) { 	printf("Pressed %c key %d count\r\n",(char)key, count); }   void main() { 	int iPrevKey, iCurKey; 	int iPressCount; 	time_t tPrevTime;  	iPressCount = 0; 	iCurKey = -1; 	while(1) 	{ 		if(_kbhit()) 		{ 			iCurKey = _getch(); 			tPrevTime = clock(); 			/* 如果新按键首次按下 */ 			if(iPressCount == 0) 			{ 				iPrevKey = iCurKey; 				iPressCount++; 			} 			else 			{ 				/* 如果该次按键和上次不一样，输出上次按键，并重新记录该次按键 */ 				if(iPrevKey != iCurKey) 				{ 					translate_key(iPrevKey, iPressCount); 					iPrevKey = iCurKey; 					iPressCount = 1; 				} 				/* 按键一样,记录次数 */ 				else 				{ 					iPressCount++; 				} 			} 		} 		/* 超时且有按键按下，输出 */ 		else if((iCurKey != (-1)) && ((clock() - tPrevTime) > TIME_OVER)) 		{ 			translate_key(iCurKey, iPressCount); 			iPressCount = 0; 			iCurKey = -1; 		} 	} }

谢谢2楼，太厉害了

记录毛时间啊，直接按几次回车就是几次了。


Question: Linux客户端和服务器，客户端和客户端通信

设置状态标志位，客户端连上后发账号密码，服务器把该用户的状态标志设为在线。这就还好多东西要去理了。用户登入后，如果你只是自己做着玩的话，用户少你可以把所有的用户都查询，然后通过心跳包把所有用户的状态传给每个用户。不然就是还有好友啊什么的，上线查询，心跳查询好友的状态

你的思路是可行的啊，以前用java做过类似的东西


Question: linux网络通信

引用 1 楼 jerry_dqh 的回复:需要锁的，两个线程会有冲突的。你一边写，那边读，会有问题。 中间遇到7E/7F,需要转义，具体转义成什么，各个协议不一样。读还有一个线程，共有三个，UI，读，写。转义的问题，明白了


FileTool.exe 替换打开和添加到项目中 Visual C++ 的新功能 http://support.microsoft.com/kb/241396/zh-cn

我运行以前成功过。 楼主可以baidu下， win7安装vc6， 安装后可以用。但不推荐。

有的就发下邮箱，要分的就发

有的，懂的人发下急用

根本就没有。为什么非要在win7上用vc6.看来微软真应该维护一下，估计能大赚一笔。

没有的，。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

已发，楼主查收。

话说VC6.0什么时候停止维护的？win7什么时候出的。怎么可能会有vc6.0支持win7呢。 话说win7不能兼用xp的vc6.0吗？  实在不行有个东西叫做虚拟机。

多少RMB?


Question: 关于CArray释放元素内存的问题

for(int i = 0, sz = pArray->GetSize(); i < sz; ++i) {   delete (*pArray)[i];  }  pArray->RemoveAll();

确实应该自己搞一个内存管理的东西。比如每一块连续的内存，存放1W个， 只要几十个这样的块就好。到时候直接把这个地方搞掉。中途变化只要标志为就好

引用 3 楼 buyong 的回复:CArray里不应该存这么多指针那应该怎么搞。。

引用 5 楼 derekrose 的回复:对象？还是指针？是指针~

引用 6 楼 hu19920520 的回复:引用 5 楼 derekrose 的回复:对象？还是指针？是指针~  那么你就必须一个一个delete 或者使用智能指针

对象？还是指针？

还有告诉LZ一个诀窍，你直接按debug，那delete确实很慢，可能要好几分钟，但若是按ctrl-F5，或者菜单里面找不调试运行，那么release版本，delete100万个对象估计不超过0.2秒

CArray里不应该存这么多指针

若LZ水平够的话，完全可以自己写个内存管理器，为所有对象的指针统一分配连续的内存，一次分配，一次释放~

你里面存放的是指针,就只能这样一个个的delete了......  或者,你可以用智能指针,或自己包装实现RAII


Question: memcpy的效率和for循环比起来如何？

先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\intel\memset.asm C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\intel\memcpy.asm

还是喜欢无码的

看源码吧, 最好是能看反汇编. memcpy复制小量数据, 可能会被优化成几次DWORD数据的赋值. 更大的数据会使用循环. 都是循环, 一考虑其它优化的情况下, 速度应该是半斤八两.

楼主不用在意这些细节，不要过早优化

引用 5 楼 angel_su 的回复:不用太担心，让编译器优化去，有可能你的for循环就变成调用memcpy，或者memcpy区域很小就转成简单代码，不去调用函数了...  ++ 根本用不着关注这种东西，怎么写方便就用哪个。

当然是memcpy快，memcpy的效率随设计者的不同而不同，但至少不会比for慢，而且由于设计者一般根据平台特性进行了优化，大多数情况下会比for快不少。

循环次数少时，赋值比较快，循环次数多时，memcpy一条语句块拷贝比for循环赋值快。

memcpy会按系统字长进行对齐优化。比如32bit系统上4字节4字节操作，64bit系统上8字节8字节操作。 如果你的循环中也是按对齐赋值的，就没有区别，如果你的赋值不是对齐，比如是char类型赋值，memcpy会快一些。

没区别，我特地测试过~ 当然是release版本，debug版本memXXX确实快不少，但比debug版本毫无意义不是吗？


Question: 输入顺序和结果的问题

c = 成功输入的数据个数。 第1个      键盘输入1.0        a = 1 输入成功，剩下.0 ;      b 没有输入成功，.0 没有用,所以 c = 1; 第2个     键盘输入 3 a = 3 输入成功;    接着键盘输入2,b = 2 输入成功所以 c = 2; 第3个    键盘输入3 2.0  a = 3 输入成功;    b = 2 输入成功，剩余 .0 没有用，所以 c = 2;

#include <stdio.h> int main() { 	int a, b, c; 	c = scanf("%d%d", &a, &b);   //c的结果为输入的参数个数 	printf("%d\n", c); 	return 0; }  c 的结果为输入的参数个数, 详细解释推荐你看下面文章： http://blog.sina.com.cn/s/blog_70ec9a6f010145ti.html

这是输入浮点数的结果


Question: 在windows平台上怎么编译LIBGD图形库

引用 3 楼 vipcxj 的回复:如果没有提供CMakeList.txt文件，那就想都别想，何况有了CMake，根本不需要mingw，直接编译成VS工程就是了。如果没CMake，下个msys，使用和linux平台相同的方式，使用mingw编译工程也可以。 http://eucaly61.blogspot.com/2009/03/msys-mingw-windows-gnu.html 随便搜了一下，虽然不是你这个库，但也是其他linux平台下的库用msys和mingw编译的  可以简单的说下怎么用CMAKE编译么??还有你给的地址打不开哦....

使用#pragma comment和在项目属性里设置效果是一样的，估计你项目设置有问题吧~

引用 10 楼 vipcxj 的回复:[quote=引用 9 楼 yxyy3604 的回复:] [quote=引用 7 楼 vipcxj 的回复:] 你zlib没搞好吧，zlib也可以生成dll的吧，windows平台上一般是.lib/.dll.a加上一个.dll文件，因为vs的工程貌似一般都是先包含了lib，由lib辅助链接dll文件的 现在已经搞定了,需要在libgd库的gd_gd2.c文件里面加一句#pragma comment(lib, "./zlib.lib")   这个用于指定zlib.lib的位置，这样在vs编译的时候才能连接成功。[/quote] ... 看来你不常用类库，我一般第一件事就是把项目的头文件保护路径，类库路径设置好，链接选项里记得好像是输入选项来着，这里第一行就能指定要链接的lib文件。当然很多类库lib文件实在太多了，我就先编译，如果出现链接错误，再需要包含哪个lib，然后再项目属性里包含。[/quote]我之前也向你说的那样试过，可是不好使，后来看了这个帖子才知道的。http://blog.csdn.net/htttw/article/details/7616124

不用pragma comment的好处是便于移植，因为linux平台下可没有等价的命令

引用 9 楼 yxyy3604 的回复:[quote=引用 7 楼 vipcxj 的回复:] 你zlib没搞好吧，zlib也可以生成dll的吧，windows平台上一般是.lib/.dll.a加上一个.dll文件，因为vs的工程貌似一般都是先包含了lib，由lib辅助链接dll文件的 现在已经搞定了,需要在libgd库的gd_gd2.c文件里面加一句#pragma comment(lib, "./zlib.lib")   这个用于指定zlib.lib的位置，这样在vs编译的时候才能连接成功。[/quote] ... 看来你不常用类库，我一般第一件事就是把项目的头文件保护路径，类库路径设置好，链接选项里记得好像是输入选项来着，这里第一行就能指定要链接的lib文件。当然很多类库lib文件实在太多了，我就先编译，如果出现链接错误，再需要包含哪个lib，然后再项目属性里包含。

引用 7 楼 vipcxj 的回复:你zlib没搞好吧，zlib也可以生成dll的吧，windows平台上一般是.lib/.dll.a加上一个.dll文件，因为vs的工程貌似一般都是先包含了lib，由lib辅助链接dll文件的 现在已经搞定了,需要在libgd库的gd_gd2.c文件里面加一句#pragma comment(lib, "./zlib.lib")   这个用于指定zlib.lib的位置，这样在vs编译的时候才能连接成功。

引用 6 楼 yxyy3604 的回复:[quote=引用 5 楼 jiandingzhe 的回复:] [quote=引用 2 楼 yxyy3604 的回复:] [quote=引用 1 楼 wangliangffaflgh 的回复:] http://download.csdn.net/detail/zxwangyun/4123767 我是说如何把libgd的源文件编译成库,不过还是谢谢你哦[/quote] 1：创建一个目录。 2：在目录里运行cmake XXXX/XXXX/XXX。后面那个是你源代码的根目录，目录里应当有CMakeLists.txt文件。默认情况下好像是生成makefile的。 或者用CMake-gui: 1：创建一个目录。 2：在目录里运行cmake-gui XXXX/XXXX/XXX。会弹出一个窗口，先问你toolchain是什么，然后列出所有的cmake配置变量让你修改。先点configure，再多点几次configure，再点生成。如果有错误，会有红色的显示。[/quote]  你说的这些我已经做过了,使用CMAKE 生成了VS2010的工程,然后编译工程,但是没有生成DLL文件,检查之后发现是没有ZLIB库.然后又下载zilb的1.2.8版本,照旧使用CMAKE产生工程,然后编译.将编译好的ZILB加进LIBGD的工程之后再次编译,结果还是没有产生DLL文件,错误信息如下: 2>     正在创建库 C:/Users/Administrator/Desktop/LibGD/libgd/Bin/Release/libgd.lib 和对象 C:/Users/Administrator/Desktop/LibGD/libgd/Bin/Release/libgd.exp 2>gd_gd2.obj : error LNK2019: 无法解析的外部符号 _uncompress，该符号在函数 __gd2ReadChunk 中被引用 2>gd_gd2.obj : error LNK2019: 无法解析的外部符号 _compress，该符号在函数 __gdImageGd2 中被引用 2>C:\Users\Administrator\Desktop\LibGD\libgd\Bin\Release\libgd.dll : fatal error LNK1120: 2 个无法解析的外部命令 这两个没有找的函数在zlib.h文件里面声明了，而且在zlib的源文件里面也有实现，但是不知道为什么就是链接不成功。[/quote] 你看看CMakeCache.txt，或者用cmake-gui看看配置，zlib的库是否被cmake包括进去了。 windows我不怎么熟。

引用 5 楼 jiandingzhe 的回复:[quote=引用 2 楼 yxyy3604 的回复:] [quote=引用 1 楼 wangliangffaflgh 的回复:] http://download.csdn.net/detail/zxwangyun/4123767 我是说如何把libgd的源文件编译成库,不过还是谢谢你哦[/quote] 1：创建一个目录。 2：在目录里运行cmake XXXX/XXXX/XXX。后面那个是你源代码的根目录，目录里应当有CMakeLists.txt文件。默认情况下好像是生成makefile的。 或者用CMake-gui: 1：创建一个目录。 2：在目录里运行cmake-gui XXXX/XXXX/XXX。会弹出一个窗口，先问你toolchain是什么，然后列出所有的cmake配置变量让你修改。先点configure，再多点几次configure，再点生成。如果有错误，会有红色的显示。[/quote]  你说的这些我已经做过了,使用CMAKE 生成了VS2010的工程,然后编译工程,但是没有生成DLL文件,检查之后发现是没有ZLIB库.然后又下载zilb的1.2.8版本,照旧使用CMAKE产生工程,然后编译.将编译好的ZILB加进LIBGD的工程之后再次编译,结果还是没有产生DLL文件,错误信息如下: 2>     正在创建库 C:/Users/Administrator/Desktop/LibGD/libgd/Bin/Release/libgd.lib 和对象 C:/Users/Administrator/Desktop/LibGD/libgd/Bin/Release/libgd.exp 2>gd_gd2.obj : error LNK2019: 无法解析的外部符号 _uncompress，该符号在函数 __gd2ReadChunk 中被引用 2>gd_gd2.obj : error LNK2019: 无法解析的外部符号 _compress，该符号在函数 __gdImageGd2 中被引用 2>C:\Users\Administrator\Desktop\LibGD\libgd\Bin\Release\libgd.dll : fatal error LNK1120: 2 个无法解析的外部命令 这两个没有找的函数在zlib.h文件里面声明了，而且在zlib的源文件里面也有实现，但是不知道为什么就是链接不成功。

引用 2 楼 yxyy3604 的回复:[quote=引用 1 楼 wangliangffaflgh 的回复:] http://download.csdn.net/detail/zxwangyun/4123767 我是说如何把libgd的源文件编译成库,不过还是谢谢你哦[/quote] 1：创建一个目录。 2：在目录里运行cmake XXXX/XXXX/XXX。后面那个是你源代码的根目录，目录里应当有CMakeLists.txt文件。默认情况下好像是生成makefile的。 或者用CMake-gui: 1：创建一个目录。 2：在目录里运行cmake-gui XXXX/XXXX/XXX。会弹出一个窗口，先问你toolchain是什么，然后列出所有的cmake配置变量让你修改。先点configure，再多点几次configure，再点生成。如果有错误，会有红色的显示。

引用 1 楼 wangliangffaflgh 的回复:http://download.csdn.net/detail/zxwangyun/4123767 我是说如何把libgd的源文件编译成库,不过还是谢谢你哦


Question: x86中 div汇编指令问题

;以下计算1到10000的和         xor ax, ax         xor dx, dx         mov cx, 10000      @f:         add ax, cx         adc dx, 0         loop @f           ;以下计算累加和的每个数位         xor cx, cx         mov ss, cx  ;设置堆栈段的段基址         mov sp, cx          mov bx, 10         xor cx, cx      @d:         inc cx         mov bp, ax         mov ax, dx         xor dx, dx         div bx         xchg bp, ax         div bx         or dl, 0x30         push dx         mov dx, bp         cmp dx, 0         jne @d         cmp ax, 0         jne @d

第一次， 商 qh （在AX中）余数是 rh' 第二次， 商 ql 余数是 remain  所以两次除法，足够了。 只是需要把  qh （在AX中）处理好---存放到商的高位 XL取到 AX中 rh'（在DX中不动），，接着用于第二次除法          qh ql      ------------ y  ) 0 xh  xl      第一次除法 DX=0，AX=xh        ..   --------------         rh' xl     第二次除法 DX=rh'，不动，AX=xl           ......         --------            remain  余数在DX中  就可以了，所以不是很复杂  就是第一次，DX初始化为0 然后，自高向低，依次取出X 的各16Bits，放入 AX寄存器中，开始除。 这就像10进制的多位数除1位数，实际上还是比较简单的。 这是除法指令，设计出来就是这样的效果。  如果是高级语言，就比较麻烦了； 汇编语言一次计算，可以得到商和余数。 所以，比较简单。 大概代码如下： Mov DX，0 Mov AX，x+2 mov BX ,y div BX       ；第1次除法  mov q+2,AX mov AX,x div BX        ；第2次除法 mov q,AX mov remain,DX

前面有人说两次除，其实没那么简单，首先要试商，试完了要乘，乘完要判断大小，然后调整。

引用 4 楼 CrazyCater 的回复:就是在8086的那种情况 只有16位的时候怎么办  看《计算机程序设计艺术》多精度算数

32 bit： edx, eax 64 bit: rdx, rax

引用 1 楼 lm_whales 的回复:扩展一下，接着除 比如： 改成 BX：DX：AX 左移8位再除 哦想起来了不用移位，就可以了  DX：AX   先用 DX --》0 AX高16 去除 再把余数放到DX，AX 低 16 通过两次除法，就可以算出32Bits的商了

假设被除数高16位B，低16位A，除数C  mov ax,B xor dx,dx div C mov cx,ax mov ax,A div C  商：CX:AX, 余数: DX

就是在8086的那种情况 只有16位的时候怎么办

64位除法用 RDX RAX

32位除法用 EDX EAX

扩展一下，接着除 比如： 改成 BX：DX：AX 左移8位再除


Question: gdb中怎样知道哪个线程拥有互斥体，代码编译时加了 -O2的，---在线等！！！

二楼的在-g模式编译是可以的，但是如果没有加-g编译，而是加了-O2编译，也就是没有用debug生成，而是build的时候，对代码进行了优化。不知道这个加了-O2的是否也可以呢，我的好像不行！

学习2楼

学习2楼

学习二楼。

查看进程对应的proc目录 ？

学习2楼！

例如： 查看哪个线程拥有互斥体（然后list代码，查看使用互斥变量的名称）  (gdb) print AccountA_mutex $1 = {__m_reserved = 2, __m_count = 0, __m_owner = 0x2527, __m_kind = 0, __m_lock = {__status = 1, __spinlock = 0}} (gdb) print 0x2527 $2 = 9511 (gdb) print AccountB_mutex $3 = {__m_reserved = 2, __m_count = 0, __m_owner = 0x2529, __m_kind = 0, __m_lock = {__status = 1, __spinlock = 0}} (gdb) print 0x2529 $4 = 9513 (gdb) 从上面的命令中，我们可以看出AccontA_mutex是被线程 5（LWP 9511）加锁（拥有）的，而AccontB_mutex是被线程 3（LWP 9513）加锁（拥有）的。


Question: 编写一个税收软件，要求最精简容易明白的代码

引用 3 楼 vipcxj 的回复: #include <iostream> #include <cstdlib> using namespace std;  //1.小于3500部分不收税。 //2.大于3500小于5000部分收0.3%的税。 //3.大于5000小于8000部分收0.5%的税。 //4.大于8000小于10000部分收0.7%的税。 //5.大于10000部分收1%的税。  //利用递归 double jisuanSui(double ShouRu) { 	if (ShouRu > 10000) 	{ 		return jisuanSui(10000) + (ShouRu - 10000)*0.01; //大于10000部分收1%的税。 	} 	else if (ShouRu > 8000) 	{ 		return jisuanSui(8000) + (ShouRu - 8000)*0.007; //大于8000小于10000部分收0.7%的税。 	} 	else if (ShouRu > 5000) 	{ 		return jisuanSui(5000) + (ShouRu - 5000)*0.005; //大于5000小于8000部分收0.5%的税。 	} 	else if (ShouRu > 3500) 	{ 		return jisuanSui(3500) + (ShouRu - 3500)*0.003; //小于3500部分不收税。 	} 	else 		return 0; }  不用递归的版本  tax = 0; if (income > 10000) { 	tax += (income - 10000)*0.01; //大于10000部分收1%的税。 	income = 10000; } if (income > 8000) { 	tax += (income - 8000)*0.007; //大于8000小于10000部分收0.7%的税。 	income = 8000; } if (income > 5000) { 	tax += (income - 5000)*0.005; //大于5000小于8000部分收0.5%的税。 	income = 5000; } if (income > 3500) { 	tax += (income - 3500)*0.003; //小于3500部分不收税。 	//income = 3500; } return tax;

#include <iostream> #include <cstdlib> using namespace std;  //1.小于3500部分不收税。 //2.大于3500小于5000部分收0.3%的税。 //3.大于5000小于8000部分收0.5%的税。 //4.大于8000小于10000部分收0.7%的税。 //5.大于10000部分收1%的税。  //利用递归 double jisuanSui(double ShouRu) { 	if (ShouRu > 10000) 	{ 		return jisuanSui(10000) + (ShouRu - 10000)*0.01; //大于10000部分收1%的税。 	} 	else if (ShouRu > 8000) 	{ 		return jisuanSui(8000) + (ShouRu - 8000)*0.007; //大于8000小于10000部分收0.7%的税。 	} 	else if (ShouRu > 5000) 	{ 		return jisuanSui(5000) + (ShouRu - 5000)*0.005; //大于5000小于8000部分收0.5%的税。 	} 	else if (ShouRu > 3500) 	{ 		return jisuanSui(3500) + (ShouRu - 3500)*0.003; //小于3500部分不收税。 	} 	else 		return 0; }   int main() { 	double ShouRu; 	cout << "请输入你的收入："; 	cin >> ShouRu; 	cout << "你所要缴纳的税收为：" << jisuanSui(ShouRu) << endl; 	system("pause"); 	return 0; }

其实也可以用最笨最简单的不断if判断的方式，不过我当时被要求是简洁的代码 看来都是学生啊

之前我也做过这道题。只要修改两个数组里面相应的税率和收税的点就可以了  #include<stdio.h> int main() { 	double a[4] = {12500,8000,5000,3500}; 	double b[4] = {0.25,0.2,0.1,0.03}; 	/*数组a作为每次判断的标准(点)，数组b作为每次判断之后的税收*/  	 	double earn,temp,shui,rest; 	int i; 	/*earn是用户输入赚了多少钱，temp是earn赋值过来用来计算的，shui是税收总额，rest是每次减去税收点的税收计算额*/ 	 	printf("请输入你这个月赚了多少钱："); 	scanf("%lf",&earn); 	 	/*计算主体*/ 	for(temp=earn,i=0,shui=0;i<4;i++) 	{ 		if(temp - a[i] <= 0) 		{ 			continue; 		} 		/*这里主要判断目前的钱是否大于a[i]的这个税收点，如果结果小于0，则表明不在该点，程序i++跳到下一个判断点*/ 		 		else 		{ 			rest = temp - a[i]; 			shui += rest * b[i]; 			temp -= rest; 		} 		/*税收计算主体，如果不是上面的条件了，就是表明符合了这个条件*/ 		/*首先将目前的钱减去这个点，剩下的就是这个点需要计算这个点的税收的钱*/ 		/*下一个需要判断的点其实是从这个点开始的，不过目前可以用temp -= rest来计算*/ 		 	} 	printf("收入为：%.2lf\t所需交税：%.2lf\t税后收入为：%.2lf\n\n",earn,shui,earn-shui);	 	main(); }


Question: 关于水仙花数的问题

for(a=100;a<=999;a++) l=a/100; 因为没有大括号的存在，l的赋值最终是l=999/100；在这之前l始终跳不出for循环。这才是正解！！！

引用 6 楼 u012571406 的回复:for没有大括号{}，有错误……个人觉得! 看错了，你那样也是可以的……

for没有大括号{}，有错误……个人觉得!

http://www.baike.com/wiki/%E6%B0%B4%E4%BB%99%E8%8A%B1%E6%95%B0  和这个列表比对下，如果相符，就对了。

引用 1 楼 user-4 的回复:LZ觉得有错就有错，LZ觉得没错就没错，我都听LZ的，所以LZ可以结贴给分了 大哥，一天24小时在线吗？每次都能看到...

还可以这么求 a=n/100;百位 c=n%10;个位 b=n%100/10;十位

可以的，如果有毛病估计是for循环没大括号的原因  #include "stdio.h" int main() {	 	int i,a,l,m,n; 	for(a=100;a<=999;a++) 	{//在这行对比下和你的程序有什么不同 		l=a/100; 		m=a/10-l*10; 		n=a-l*100-m*10; 		if(a==l*l*l+m*m*m+n*n*n) 			printf("%d\n",a); 	}//还有这里 	return 0; }

LZ觉得有错就有错，LZ觉得没错就没错，我都听LZ的，所以LZ可以结贴给分了


Question: 求一行代码的理解。

引用 7 楼 my_live_123 的回复:n2可能是个掩码，保留右边的部分位！ 这个回答有点靠谱了，问题的核心是求chr+2*(n2&chr)的逆运算。

引用 5 楼 zhao4zhong1 的回复:将0～255带进chr参数，输出函数对应的返回值。 额，大神能不能花点时间看问题。 这个问题的核心是求And运算的逆运算，还是比较新颖的。 明天结贴。

n2可能是个掩码，保留右边的部分位！

将0～255带进chr参数，输出函数对应的返回值。

我已经想出来答案了,n1是奇数，n2任意,加密函数暂时不贴出来。 用AND来加密这种方法还是比较新颖的，大家以后可以用上面的函数+内联汇编来对字符串进行加密，还是比较有效果的。

你还是到数学论坛上咨询比较好

有逻辑运算的应该是不能倒推的。

上面计算a的就是解密函数吧，你倒推一下就能推出加密函数


Question: c语言学习  求指导

#pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <stdio.h> #include <stdlib.h> #include <time.h> #include <windows.h> HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);      if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     int i,x,y;       srand(time(NULL));     system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hfont = CreateFont(48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");     SelectObject(hdc,hfont);     TextOut(hdc,10,10,"地球人都知道！",14);     MoveToEx(hdc,5,5,NULL);     LineTo(hdc,300,  5);     LineTo(hdc,300, 60);     LineTo(hdc,  5, 60);     LineTo(hdc,  5,  5);     for (i=0;i<100;i++) {         x=rand()%400;         y=rand()%300;         SetPixel(hdc,x,y,0);     }     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getchar();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }

c和指针，。

我觉得看视频太慢了，还是看一些书吧，主要把基础看完就好了，感觉你有delphi的基础，学C应该很快，只是要多实现，动手才好。

其实呢 像这种基础学习的我倒是有在看一本书C Primer plus ，The C Programming Language也是属于这种类型吧。我是想把这个当成参考书，再找一个高级一点的，能综合运用这些知识的教材，学起来不至于太无聊，这样可好

PDF的话 《The C Programming Language》   《c和指针》已经很好了，一个基础的，一个深入的，也不求别的书了。 看视频学习确实慢，所以呢我想要的视频是那种讲讲某小项目怎么做的，代码结构，设计思路这种，看完自已也可以尝试实现一下。而不是基础知识讲解的视频，这种的话确实是看书好。 如果有人看过的话，求推荐一套了

我觉得比较好的学习方法是看下基本语法等基础，然后找一些经典的例题，自己来实现，在这个过程中逐步解决各种遇到的问题，慢慢累积

The C Programming Language


Question: 请教指针函数的问题

引用 4 楼 dwjjyq 的回复:[quote=引用 1 楼 Automation_dmu 的回复:] short DB_find_1st_match(unsigned short fs_num, void* data , //添加一个要传入到match_routine里的data参数 	short （* match_routine）（void * rec_buffer） ） { 	... 	match_routine(data);//传入data进行匹配 	... } 要有返回值的哦[/quote]  这个是我定义的  short	Table_Match(void *rec) { 	return (!strncmp( (char *)rec, (char *)m_name, 16)); }  我的数据库里面有 typedef struct {         //单号          unsigned char odd_number[8];         //物料编码  	unsigned char new_code[8]; 	//名称  	unsigned char new_name[8]; 	//价格          unsigned char new_money[8];         //数量          unsigned char new_num[30]; }TYP_New_Bill_INFO;  我现在有单号，我要查其他数据 retshort = DB_find_1st_match(0,Table_Match);         if(retshort>=0)	//Note:important!!!!! 	{  	p_rec = (char *)DB_jump_to_record(3,retshort,&rec_flag);

引用 4 楼 dwjjyq 的回复:[quote=引用 1 楼 Automation_dmu 的回复:] short DB_find_1st_match(unsigned short fs_num, void* data , //添加一个要传入到match_routine里的data参数 	short （* match_routine）（void * rec_buffer） ） { 	... 	match_routine(data);//传入data进行匹配 	... }   要有返回值的哦[/quote]  if (match_routine(data)) {     ... ... } else {     ... ... }

引用 1 楼 Automation_dmu 的回复:short DB_find_1st_match(unsigned short fs_num, void* data , //添加一个要传入到match_routine里的data参数 	short （* match_routine）（void * rec_buffer） ） { 	... 	match_routine(data);//传入data进行匹配 	... }   要有返回值的哦

就是 short my_match_routine(void *p) { }

short my_match_routine(void* rec_buffer) {     char* data = (char*)rec_buffer;     ... }  引用 楼主 dwjjyq 的回复:我有一个api 是这样写的 short DB_find_1st_match(unsigned short fs_num,                          short （* match_routine）（void * rec_buffer） ）    参数：  fs_num  要查寻的数据表的索引号  match_routine  一个用户自己定义的匹配函数，非用来检验存在 rec_buffer 中的数据记录是否是用  户所需要的记录。匹配时应该返回非 0 值。如果这个参数为空，那么任何一条未删除 的记录都将被看作是符合条件的被选中的记录。   现在，我有一个编号为4的数据表，查询条件为char *data; 我该怎样定义short （* match_routine）（void * rec_buffer）；  把我的数据char *data传进去，然后查询出数据。  大神们，帮帮忙呗！我刚学的C


Question: windows下删除非空文件目录

引用 2 楼 yang15225094594 的回复:应该是已经删除了，但是需要刷新一下，这样应该就不显示了！ 引用 2 楼 yang15225094594 的回复:应该是已经删除了，但是需要刷新一下，这样应该就不显示了！ 怎么刷新呀，求指导呀！

io sync下。

refresh

应该是已经删除了，但是需要刷新一下，这样应该就不显示了！

自己顶一下！！！


Question: [c语言书籍] 《C陷阱与缺陷》-分享一本c语言好书！

我也看过这本书，讲的很多东西都是理论书籍涉及不到的，很有现实意义，对编程思想也有帮助。同理，在理论方面的编程思想提高的书籍也很好

引用 21 楼 lwouyang 的回复:看过，当之无愧的C经典精品。 阅之能更深透的掌握 C 本质，领会 C 的思想内涵和精髓，也有助于理解 C 语言的各种稀奇古怪的特性、缺陷的来龙去脉，了解 C 语言的前世今生。 可以一看，书也不厚，很薄一本，短小精悍。但建议在基本掌握整个 C 枝干之后再看。另外，作者的身份为书中内容的权威性提供了很好的保证。  然而，建议不要过分深究，看清楚陷阱如何产生，少招惹那些有问题的特性应用就好，识别、选择并力求塑造更清晰健壮的代码表达方式，而不是钻牛角尖，让思路停留在“这么写会有什么问题”的漩涡里打转。毕竟现在已经不是以书写诡异的神代码为荣的时代了，领会思路并以易于操控的结构组织起来的，以最朴实自然的方式表达出来代码才是好代码。  PS: 都别引用4楼了行吗？没营养的东西。大家过来是围观分享神级大师作品的，他在这里贴牛皮藓狗皮膏药，还一次占2版面，严重煞风景。赞同

好书，准备再看一遍

这本书的确经典，来来回回我看了5遍。

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

买了一直没看，看不太明白，所以继续充电。 然后。。我发现赵老师说的有道理。

我自己一直想不明白，为什么自己会想要分，你这么一说，原来如此，还真是这样，楼主赶紧散分。 引用 13 楼 N_sev7 的回复:[quote=引用 9 楼 u011530143 的回复:] 不太明白，为啥发资源都要我给分的呢？ 分高了，有一种莫名的满足感！！！ 满足感这种东西，大家都想要的[/quote]

LZ的分就在那放着，难道不结贴的？

没细读，不过感觉不错

这个看过，的确好书，推荐。

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

引用 楼主 u011530143 的回复:内容提要  作者以自己1985年在Bell实验室时发表的一篇论文为基础，结合自己的工作经验扩展成为这本对C程序员具有珍贵价值的经典著作。写作本书的出发点不是要批判C语言，而是要帮助C程序员绕过编程过程中的陷阱和障碍。 全书分为8章，分别从词法分析、语法语义、连接、库函数、预处理器、可移植性缺陷等几个方面分析了C编程中可能遇到的问题。最后，作者用一章的篇幅给出了若干具有实用价值的建议。 本书适合有一定经验的C程序员阅读学习，即便你是C编程高手，本书也应该成为你的案头必备书籍。  目录 第0章导读  第1章词法“陷阱” 1.1=不同于== 1.2&和|不同于&&和|| 1.3词法分析中的“贪心法” 1.4整型常量 1.5字符与字符串 第2章语法“陷阱” 2.1理解函数声明 2.2运算符的优先级问题 2.3注意作为语句结束标志的分号 2.4switch语句 2.5函数调用 2.6“悬挂”else引发的问题 第3章语义“陷阱” 3.1指针与数组 3.2非数组的指针 3.3作为参数的数组声明 3.4避免“举隅法” 3.5空指针并非空字符串 3.6边界计算与不对称边界 3.7求值顺序 3.8运算符&&、||和！ 3.9整数溢出 3.10为函数main提供返回值 第4章连接 4.1什么是连接器 4.2声明与定义 4.3命名冲突与static修饰符 4.4形参、实参与返回值 4.5检查外部类型 4.6头文件 第5章库函数 5.1返回整数的getchar函数 5.2更新顺序文件 5.3缓冲输出与内存分配 5.4使用ernlo检测错误 5.5库函数signal 第6章预处理器 6.1不能忽视宏定义中的空格 6.2宏并不是函数 6.3宏并不是语句 6.4宏并不是类型定义 第7章可移植性缺陷 7.1应对C语言标准变更 7.2标识符名称的限制 7.3整数的大小 7.4字符是有符号整数还是无符号整数 7.5移位运算符 7.6内存位置0 7.7除法运算时发生的截断 7.8随机数的大小 7.9大小写转换 7.10首先释放，然后重新分配 7.11可移植性问题的一个例子 第8章建议与答案 8.1建议 8.2答案 附录A：PRINTF，VARARGS与STDARG 附录B：Koenig和Moo夫妇访谈 http://url.cn/PpzAr0 这本书就像样多了，谭大爷的书和他比连厕纸都不是，老子还嫌他刮屁股

引用 9 楼 u011530143 的回复:不太明白，为啥发资源都要我给分的呢？ 分高了，有一种莫名的满足感！！！ 满足感这种东西，大家都想要的

不太明白，为啥发资源都要我给分的呢？

LZ快结贴，分都给我吧~

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

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

的确是好书，对有C基础的人而言是锦上添花。


Question: C新手的一些疑惑

数据类型就过不去，以后怎么学？遇到难题不用怕，怕的是不去做。

不要把学习当做是一种义务，而是权利

多动手练练就明白了

你是厌学症 http://baike.baidu.com/view/551999.htm

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

学编程不写代码，看书看不进去很正常

你试试把你的想法运行出来，看到结果也许你就开心了

可能编程不适合你


Question: 值一样的数组，转化成同类型的整数打印出来不一样

unsigned char *buf unsigned char checksum_buf[5]={0}; DLOG("%d %d", *(buf+i), checksum_buf[i]);  你把DLOG定义贴出来

这是多线程程序吧，  ck=CHECKSUM;         memcpy(checksum_buf, (unsigned char*)&ck, 4);         for(i=0;i<4;i++) DLOG("%d %d", *(buf+i), checksum_buf[i]); buf 没变，所以 ============================================   handle_net_msg(): cli.c: 695: 120 120   handle_net_msg(): cli.c: 695: 86 86   handle_net_msg(): cli.c: 695: 33 33   handle_net_msg(): cli.c: 695: 67 67 ================================================  if(!strncmp(checksum_buf, buf, 4))          DLOG("get %x %x", *((unsigned int *)buf), *((unsigned int *)checksum_buf)); checksum=*((unsigned int *)buf);的时候，buf中的内容改变了。 285678 所以 handle_net_msg(): cli.c: 696: get 285678 43215678 handle_net_msg(): cli.c: 698: checksum:285678

最高位的符号位考虑了么？

感觉是 checksum=*((unsigned int *)buf);的时候，buf中的内容改变了。


Question: memcpy（）求解

599 void *memcpy(void *dest, const void *src, size_t count) 600 { 601         char *tmp = dest; 602         const char *s = src; 603  604         while (count--) 605                 *tmp++ = *s++; 606         return dest; 607 }  这个是常用的string.c中的源码，如果效率要求苛刻用kernel的  32 static __always_inline void *__memcpy(void *to, const void *from, size_t n)  33 {  34         int d0, d1, d2;  35         asm volatile("rep ; movsl\n\t"  36                      "movl %4,%%ecx\n\t"  37                      "andl $3,%%ecx\n\t"  38                      "jz 1f\n\t"  39                      "rep ; movsb\n\t"  40                      "1:"  41                      : "=&c" (d0), "=&D" (d1), "=&S" (d2)  42                      : "" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from)  43                      : "memory");  44         return to;  45 }

引用 5 楼 u013431701 的回复:[quote=引用 2 楼 derekrose 的回复:] 去看memcpy的函数头  没看明白求教， 不支持重叠，得出错误结果才对啊，现在得出正确的结果了，我就不明白了.[/quote]  真相是这样的，有些memcpy的实现，是不判断方向的，就不支持重叠区， 但是有些实现是判断方向的，支持重叠区，就如30楼的那样的实现， BSD 的实现也是支持重叠区的 http://svnweb.freebsd.org/base/release/9.2.0/lib/libc/string/bcopy.c?revision=255898&view=markup  但是标准里说的是  4.11.2.1 The memcpy function Synopsis  #include <string.h> void *memcpy(void *s1, const void *s2, size_t n); Description  The memcpy function copies n characters from the object pointed to by s2 into the object pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined. Returns  The memcpy function returns the value of s1.

旧源的内容都被改变了！谁说源和目标重叠时memcpy是对的我跟他急！！

char t[10] = {'A','B','C','D','E'}； 初始化没有结束符，不太妥吧

引用 36 楼 lm_whales 的回复:memcpy 是 ，复制一份，完全相同的数据，到另一块内存。 前置条件是两块内存无重叠。 至于重叠了，结果如何，实际上相当于未定义行为，任何结果都是对的。  这才是正解！ 参考msdn：http://msdn.microsoft.com/zh-cn/library/dswaw1wk%28v=vs.90%29.aspx   memcpy copies count bytes from src to dest; wmemcpy copies count wide characters (two bytes). If the source and destination overlap, the behavior of memcpy is undefined. Use memmove to handle overlapping regions.

@u012997273 看起来memmove.asm=memcpy.asm，但是内存重叠还是memmove吧，貌似release版时memcpy代码不按上面的会出问题...

用debugger跟踪

技术都是在进步的, 最简单直接的办法是调试查看它到底是怎么计算的, 程序执行到memcpy的时候按F11进入, 就可看到源码或者反汇编代码.

memcpy不支持内存重叠。

买了amd的cpu，amd说如果超频，是不保证不会烧掉cpu，amd没有对超频做特殊处理，但是我超频了，结果不是逾期的啊，求指教.

void * __cdecl memmove (         void * dst,         const void * src,         size_t count         ) {         void * ret = dst;  #if defined (_M_IA64) || defined (_M_AMD64)          {           __declspec(dllimport)           void RtlMoveMemory( void *, const void *, size_t count );          RtlMoveMemory( dst, src, count );          }  #else  /* defined (_M_IA64) || defined (_M_AMD64) */         if (dst <= src || (char *)dst >= ((char *)src + count)) {                 /*                  * Non-Overlapping Buffers                  * copy from lower addresses to higher addresses                  */                 while (count--) {                         *(char *)dst = *(char *)src;                         dst = (char *)dst + 1;                         src = (char *)src + 1;                 }         }         else {                 /*                  * Overlapping Buffers                  * copy from higher addresses to lower addresses                  */                 dst = (char *)dst + count - 1;                 src = (char *)src + count - 1;                  while (count--) {                         *(char *)dst = *(char *)src;                         dst = (char *)dst - 1;                         src = (char *)src - 1;                 }         } #endif  /* defined (_M_IA64) || defined (_M_AMD64) */          return(ret); }  void * __cdecl memcpy (         void * dst,         const void * src,         size_t count         ) {         void * ret = dst;  #if defined (_M_IA64)          {           __declspec(dllimport)           void RtlCopyMemory( void *, const void *, size_t count );          RtlCopyMemory( dst, src, count );          }  #else  /* defined (_M_IA64) */         /*          * copy from lower addresses to higher addresses          */         while (count--) {                 *(char *)dst = *(char *)src;                 dst = (char *)dst + 1;                 src = (char *)src + 1;         } #endif  /* defined (_M_IA64) */          return(ret); }

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src\intel\memcpy.asm C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src\intel\memmove.asm 你看看这两个文件的内容，我的是vc 2010，是这个目录

引用 10 楼 u013431701 的回复:[quote=引用 7 楼 u012997273 的回复:] [quote=引用 6 楼 u012997273 的回复:] d = （char *）memcpy（&t[0],&t[1]，2）； 就看的清楚了 错了，用int代替char试试[/quote]  d = （char *）memcpy（&t[0],&t[1]，2）； 返回的是数组t的首地址，和int型没有关系吧.[/quote] 不好意思，刚才我还以为是memcpy内部做了4字节优化了， 跟踪了下发现，其实memcpy最终调用的却是memmove函数， 环境:vc 2010

memcpy就是直接用你传递到里面的字符串参数进行拷贝，所以是没有处理内存重叠的，就会得到AAADE 而memmove是把地址参数拷贝了一份字符串，然后进行拷贝，这就是处理了内存重叠，就会得到AABDE 这样说应该可以理解了吧

引用 9 楼 xihu1364 的回复:如果没有处理内存重叠，   不是应该是  t[0] = 'A';  t[1] = 'A';  t[2] = 'A';  吗？  结果应该是AAADE吗?   求解   不知道楼主怎么想的，怎么会是这个结果呢 ABCDE     t[1]是B开始           1   ABCDE    t[0]是A开始            2  蓝色代替红色 不就是最终结果 引用 9 楼 xihu1364 的回复:如果没有处理内存重叠，   不是应该是  t[0] = 'A';  t[1] = 'A';  t[2] = 'A';  吗？  结果应该是AAADE吗?   求解   不知道楼主怎么想的，怎么会是这个结果呢 ABCDE     t[1]是B开始           1   ABCDE    t[0]是A开始            2  蓝色代替红色 不就是最终结果  （char *）memcpy（&t[1],&t[0]，2） 把t[0]的内容copy到t[1]中， 不应是t[0]的内容不变，A， t[1]的内容变为A， 再把t[1]的内容copy到t[2], t[2]变为A，就结束了，有问题吗？

引用 7 楼 u012997273 的回复:[quote=引用 6 楼 u012997273 的回复:] d = （char *）memcpy（&t[0],&t[1]，2）； 就看的清楚了 错了，用int代替char试试[/quote]  d = （char *）memcpy（&t[0],&t[1]，2）； 返回的是数组t的首地址，和int型没有关系吧.

引用 6 楼 u012997273 的回复:d = （char *）memcpy（&t[0],&t[1]，2）； 就看的清楚了  什么意思，没懂啊.

引用 6 楼 u012997273 的回复:d = （char *）memcpy（&t[0],&t[1]，2）； 就看的清楚了 错了，用int代替char试试


Question: 文件指针移动不了，每次输出都是全部输出，求指教！！！

你fseek的是fp文件, fscanf的是fn文件, 移动文件指针和读数据都不是针对同一个文件, 怎么会起作用?  btw: LZ是看谭浩强那厮的书学c的吧, 居然把代码都写在main()里

我想间隔输出，但是用了fseek(fp,2*n*sizeof(struct students),0);后，还是全部输出，没什么用处啊，不明白。

什么意思，你不就是要全部输出吗？


Question: 学王爽的汇编碰到的一个问题

我刚刚翻了下书，是73页的内容吗？ 你书上是在0B39：0100地址写代码的，， 而你是直接在2000:000这个地址写代码的，，并且这个代码是在2000:0000这个地址进行堆栈的（程序地址和堆栈的地址在一堆了）。。。能不出错吗。。

书上多少页？以前看了一半，，好久没有看了。。

我试了好几次每次执行完mov ss,ax之后都显示下一条待执行的指令是： 2000:0008 0000          ADD     [BX+SI],AL  恳请前辈高人指点一二，万分感激。


Question: C语言问题，求助！

谢谢你们的指点。问题已经解决了。

当除数和被除数都为整型时，结果是取商，而不是以实数形式出现，看这道题，你体会下： 假定x和y为double型，则表达式(x=2,y=x+5/2)的值是_C_____ 。    A、4.500000                     B、4      C、4.000000                     D、2.000000 当然，若是除数或被除数或者两者都是浮点型的，则商以浮点型为准。

类型不匹配，你的b是float格式存放的，a按照整数存放的,5/4也会当成整数1。%f会按照float去解释你存放的数据，得到当然就不对了。同理%d去取float也是一样的道理。


Question: 有会用Vtune的吗？

引用 2 楼 baipv008 的回复:[quote=引用 1 楼 user-3 的回复:] 没有！都优化掉了 函数名都优化掉了吗？[/quote] release版本编译生成pdb，就可以看到相应的函数名了，这类分析工具肯定要pdb文件的。

vs2010以后自带性能分析工具。

LZ还有手册，查啊。

引用 4 楼 ForestDB 的回复:可以修改release的配置，不要strip掉函数名。 在哪里修改？vs2008

可以修改release的配置，不要strip掉函数名。

函数就一地址，哪有名字？

引用 1 楼 user-3 的回复:没有！都优化掉了 函数名都优化掉了吗？

没有！都优化掉了


Question: 网上下载的G.729A源码怎么生成dll动态库？

链接发过来 我给你编一个

284941821  QQ空间 的日志 是我以前看孙鑫视频时候的笔记 感觉一步一步手把手教的 可能能帮到你吧   一直想挪到CSDN上来的 下班回去总是记不起来了...

顶顶，没有人知道么？


Question: 动态开辟内存空间的问题

char *ss;     int i;     ss=(char *)malloc(sizeof(char)*7);     for(i=0;i<6;i++)     {         ss[i]='a';     }     ss[6] = '\0';     printf("%s\n",ss);

其实电脑开机后物理内存的每个字节都是可读写的，区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

引用 12 楼 mghhz816210 的回复:引用 9 楼 u011569364 的回复:i==5不是i=5那是不是动态开辟字符数组都要在后面加‘\0’ 如果你觉得内存中的数据是字符串，那就加‘\0’

引用 12 楼 mghhz816210 的回复:引用 9 楼 u011569364 的回复:i==5不是i=5那是不是动态开辟字符数组都要在后面加‘\0’表示同意，你说的对。

可以了  引用 11 楼 u011569364 的回复:引用 10 楼 mghhz816210 的回复:引用 9 楼 u011569364 的回复:i==5不是i=5急躁了这下可以了吧？

引用 9 楼 u011569364 的回复:i==5不是i=5急躁了

写错了应该是i=5,不过运行出来差不多，就差了个问号

char *ss; 	int i; 	//ss=plus(s1,s2); 	int num[]={98,99,109,109,97,97}; 	ss=(char *)malloc(sizeof(char)*6); 	for(i=0;i<6;i++) 	{ 		ss[i]='a'; 		if(i=6) 			ss[i]='\0'; 	} 	printf("%s\n",ss);  引用 4 楼 u011569364 的回复:你没有结束符，大会自动往后读，就是简单的地址加1，已知到遇到‘\0’停止，越界不检查，这就是指针不安全的地方之一

加完‘\0’是这样的

引用 4 楼 u011569364 的回复:你没有结束符，大会自动往后读，就是简单的地址加1，已知到遇到‘\0’停止，越界不检查，这就是指针不安全的地方之一纠错：它会

引用 2 楼 u011569364 的回复:最后一位应该搞个字符串的结束符‘\0’,不然会一直读取知道遇到‘\0’可是内存不是只开辟了6个字节吗，其余的是从哪里读取的呢

最后一位应该搞个字符串的结束符‘\0’,不然会一直读取知道遇到‘\0’

沙发先抢下


Question: 打开一批文件问题请求各位大神帮帮忙

引用 10 楼 mk112255 的回复:[quote=引用 9 楼 zhaobangyu 的回复:] [quote=引用 7 楼 mk112255 的回复:] [quote=引用 5 楼 zhaobangyu 的回复:] 路径和权限的问题, 先要确认这个目录下是否需要管理员权限 再确认你的路径是否正确   如何确定路径和是否需要管理权限[/quote] 1.路径正确否就是你自己检查文件路径是否正确,权限问题就是在你操作的文件路径下新建一个文件，看是否需要管理员权限 2.确认路径没问题，你直接用管理员权限运行你的程序看读取是正确(编绎程序时也能将程序设为管理员方式启动，右击工程属性，链接器，清单文件，UAC执行级别，设置为requireAdministrator)。 3.fp的值为x00000000时，打印出GetLasterror()的值，得到相关的信息。[/quote]  不明白怎样才能使用管理权限，我的是WINDOWSXP的系统[/quote] 哪你就使用第二条就行，将工程的UAC执行级别设置为requireAdministrator,重新编绎就行。

引用 9 楼 zhaobangyu 的回复:[quote=引用 7 楼 mk112255 的回复:] [quote=引用 5 楼 zhaobangyu 的回复:] 路径和权限的问题, 先要确认这个目录下是否需要管理员权限 再确认你的路径是否正确   如何确定路径和是否需要管理权限[/quote] 1.路径正确否就是你自己检查文件路径是否正确,权限问题就是在你操作的文件路径下新建一个文件，看是否需要管理员权限 2.确认路径没问题，你直接用管理员权限运行你的程序看读取是正确(编绎程序时也能将程序设为管理员方式启动，右击工程属性，链接器，清单文件，UAC执行级别，设置为requireAdministrator)。 3.fp的值为x00000000时，打印出GetLasterror()的值，得到相关的信息。[/quote]  不明白怎样才能使用管理权限，我的是WINDOWSXP的系统

引用 5 楼 zhaobangyu 的回复:路径和权限的问题, 先要确认这个目录下是否需要管理员权限 再确认你的路径是否正确   如何确定路径和是否需要管理权限

引用 2 楼 max_min_ 的回复:1 路径是否正确 2 是否有对应权限对文件进行操作  把错误码打印出来看看，就知道了！  我输入路径为D:\file\file1.c  读定方式为：r   fp的值为x00000000

我只会用单步还不会用断点

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。

D:\file\file1.c 不等于 D:file\file1.c

引用 7 楼 mk112255 的回复:[quote=引用 5 楼 zhaobangyu 的回复:] 路径和权限的问题, 先要确认这个目录下是否需要管理员权限 再确认你的路径是否正确   如何确定路径和是否需要管理权限[/quote] 1.路径正确否就是你自己检查文件路径是否正确,权限问题就是在你操作的文件路径下新建一个文件，看是否需要管理员权限 2.确认路径没问题，你直接用管理员权限运行你的程序看读取是正确(编绎程序时也能将程序设为管理员方式启动，右击工程属性，链接器，清单文件，UAC执行级别，设置为requireAdministrator)。 3.fp的值为x00000000时，打印出GetLasterror()的值，得到相关的信息。

引用 2 楼 max_min_ 的回复:1 路径是否正确 2 是否有对应权限对文件进行操作  把错误码打印出来看看，就知道了！  我试过不知为何只能在这个文件才能运行C:\Documents and Settings\Administrator\file.c    r 才会得到想要的输出，以及新建出设定的文件


Question: 前后两个程序怎么算出来的数值不一样？那个是对的？

看精度喽，浮点运算本身和精度和一块讨论才有意义

把第7行的float换成double，第一个的结果就是3.141592，更好点。


Question: apache调用fastcgi报错：(104)Connection reset by peer，高手快来啊！

cgi启动时会有个进程，查看下php-cgi或者其它进程是否启动。

你那搞定没？我也遇到了同样的问题，apache的mod_fcgid，fastcgi官网下的toolkit（fcgi-2.4.1-SNAP-0311112127），我怀疑它俩能兼容么？？

自己顶起！！！

引用 3 楼 microlab2009 的回复:php-fcgi 是否安装正确 是否启动 不是php-fcgi，是FastCGI，

php-fcgi 是否安装正确 是否启动

引用 1 楼 user-4 的回复:发错区了吧 应该是php那边的吧 fcgi是用C写的，我就发到C这边了，不是php

发错区了吧 应该是php那边的吧


Question: 浮点乘法如何优化，希望能是位运算

用定点数运算代替浮点数运算。

80x87浮点协处理器的功能早八辈子就集成到CPU内部了！ ========== 浮点运算指令集 ====================================================== ---------- 一、控制指令(带9B的控制指令前缀F变为FN时浮点不检查，机器码去掉9B)---- FINIT                 初始化浮点部件                   机器码  9B DB E3 FCLEX                 清除异常                         机器码  9B DB E2 FDISI                 浮点检查禁止中断                 机器码  9B DB E1 FENI                  浮点检查禁止中断二               机器码  9B DB E0 WAIT                  同步CPU和FPU                     机器码  9B FWAIT                 同步CPU和FPU                     机器码  D9 D0 FNOP                  无操作                           机器码  DA E9 FXCH                  交换ST(0)和ST(1)                 机器码  D9 C9 FXCH ST(i)            交换ST(0)和ST(i)                 机器码  D9 C1iii FSTSW ax              状态字到ax                       机器码  9B DF E0 FSTSW   word ptr mem  状态字到mem                      机器码  9B DD mm111mmm FLDCW   word ptr mem  mem到状态字                      机器码  D9 mm101mmm FSTCW   word ptr mem  控制字到mem                      机器码  9B D9 mm111mmm  FLDENV  word ptr mem  mem到全环境                      机器码  D9 mm100mmm FSTENV  word ptr mem  全环境到mem                      机器码  9B D9 mm110mmm FRSTOR  word ptr mem  mem到FPU状态                     机器码  DD mm100mmm FSAVE   word ptr mem  FPU状态到mem                     机器码  9B DD mm110mmm  FFREE ST(i)           标志ST(i)未使用                  机器码  DD C0iii FDECSTP               减少栈指针1->0 2->1              机器码  D9 F6 FINCSTP               增加栈指针0->1 1->2              机器码  D9 F7 FSETPM                浮点设置保护                     机器码  DB E4 ---------- 二、数据传送指令 ---------------------------------------------------- FLDZ                  将0.0装入ST(0)                   机器码  D9 EE FLD1                  将1.0装入ST(0)                   机器码  D9 E8 FLDPI                 将π装入ST(0)                    机器码  D9 EB FLDL2T                将ln10/ln2装入ST(0)              机器码  D9 E9 FLDL2E                将1/ln2装入ST(0)                 机器码  D9 EA FLDLG2                将ln2/ln10装入ST(0)              机器码  D9 EC FLDLN2                将ln2装入ST(0)                   机器码  D9 ED  FLD    real4 ptr mem  装入mem的单精度浮点数            机器码  D9 mm000mmm FLD    real8 ptr mem  装入mem的双精度浮点数            机器码  DD mm000mmm FLD   real10 ptr mem  装入mem的十字节浮点数            机器码  DB mm101mmm  FILD    word ptr mem  装入mem的二字节整数              机器码  DF mm000mmm FILD   dword ptr mem  装入mem的四字节整数              机器码  DB mm000mmm FILD   qword ptr mem  装入mem的八字节整数              机器码  DF mm101mmm  FBLD   tbyte ptr mem  装入mem的十字节BCD数             机器码  DF mm100mmm  FST    real4 ptr mem  保存单精度浮点数到mem            机器码  D9 mm010mmm FST    real8 ptr mem  保存双精度浮点数到mem            机器码  DD mm010mmm  FIST    word ptr mem  保存二字节整数到mem              机器码  DF mm010mmm FIST   dword ptr mem  保存四字节整数到mem              机器码  DB mm010mmm  FSTP   real4 ptr mem  保存单精度浮点数到mem并出栈      机器码  D9 mm011mmm FSTP   real8 ptr mem  保存双精度浮点数到mem并出栈      机器码  DD mm011mmm FSTP  real10 ptr mem  保存十字节浮点数到mem并出栈      机器码  DB mm111mmm  FISTP   word ptr mem  保存二字节整数到mem并出栈        机器码  DF mm011mmm FISTP  dword ptr mem  保存四字节整数到mem并出栈        机器码  DB mm011mmm FISTP  qword ptr mem  保存八字节整数到mem并出栈        机器码  DF mm111mmm  FBSTP  tbyte ptr mem  保存十字节BCD数到mem并出栈       机器码  DF mm110mmm  FCMOVB                ST(0),ST(i) <时传送              机器码  DA C0iii FCMOVBE               ST(0),ST(i) <=时传送             机器码  DA D0iii FCMOVE                ST(0),ST(i) =时传送              机器码  DA C1iii FCMOVNB               ST(0),ST(i) >=时传送             机器码  DB C0iii FCMOVNBE              ST(0),ST(i) >时传送              机器码  DB D0iii FCMOVNE               ST(0),ST(i) !=时传送             机器码  DB C1iii FCMOVNU               ST(0),ST(i) 有序时传送           机器码  DB D1iii FCMOVU                ST(0),ST(i) 无序时传送           机器码  DA D1iii ---------- 三、比较指令 -------------------------------------------------------- FCOM                  ST(0)-ST(1)                      机器码  D8 D1 FCOMI                 ST(0),ST(i)  ST(0)-ST(1)         机器码  DB F0iii FCOMIP                ST(0),ST(i)  ST(0)-ST(1)并出栈   机器码  DF F0iii FCOM   real4 ptr mem  ST(0)-实数mem                    机器码  D8 mm010mmm FCOM   real8 ptr mem  ST(0)-实数mem                    机器码  DC mm010mmm  FICOM   word ptr mem  ST(0)-整数mem                    机器码  DE mm010mmm FICOM  dword ptr mem  ST(0)-整数mem                    机器码  DA mm010mmm FICOMP  word ptr mem  ST(0)-整数mem并出栈              机器码  DE mm011mmm FICOMP dword ptr mem  ST(0)-整数mem并出栈              机器码  DA mm011mmm  FTST                  ST(0)-0                          机器码  D9 E4 FUCOM  ST(i)          ST(0)-ST(i)                      机器码  DD E0iii FUCOMP ST(i)          ST(0)-ST(i)并出栈                机器码  DD E1iii FUCOMPP               ST(0)-ST(1)并二次出栈            机器码  DA E9 FXAM                  ST(0)规格类型                    机器码  D9 E5 ---------- 四、运算指令 -------------------------------------------------------- FADD                  把目的操作数 (直接接在指令后的变量或堆栈缓存器) 与来源操作数 (接在目的操作数后的变量或堆栈缓存器) 相加，并将结果存入目的操作数 FADDP  ST(i),ST       这个指令是使目的操作数加上 ST 缓存器，并弹出 ST 缓存器，而目的操作数必须是堆栈缓存器的其中之一，最后不管目的操作数为何，经弹出一次后，目的操作数会变成上一个堆栈缓存器了 FIADD                 FIADD 是把 ST 加上来源操作数，然后再存入 ST 缓存器，来源操作数必须是字组整数或短整数形态的变数  FSUB                  减 FSUBP FSUBR                 减数与被减数互换 FSUBRP FISUB FISUBR  FMUL                  乘 FMULP FIMUL  FDIV                  除 FDIVP FDIVR FDIVRP FIDIV FIDIVR  FCHS                  改变 ST 的正负值  FABS                  把 ST 之值取出，取其绝对值后再存回去。  FSQRT                 将 ST 之值取出，开根号后再存回去。  FSCALE                这个指令是计算 ST*2^ST(1)之值，再把结果存入 ST 里而 ST(1) 之值不变。ST(1) 必须是在 -32768 到 32768 (-215 到 215 )之间的整数，如果超过这个范围计算结果无法确定，如果不是整数 ST(1) 会先向零舍入成整数再计算。所以为安全起见，最好是由字组整数载入到 ST(1) 里。  FRNDINT               这个指令是把 ST 的数值舍入成整数，FPU 提供四种舍入方式，由 FPU 的控制字组(control word)中的 RC 两个位决定                           RC    舍入控制                           00    四舍五入                           01    向负无限大舍入                           10    向正无限大舍入                           11    向零舍去 ================================================================================

对于0.01不可能优化，因为就算是浮点也是以二进制的科学计数发存放的。但换句话说，对于XXX*(2^n)是可以优化的，这里的n可以是负数，比如XXX*0.5 具体怎么优化，LZ去查下浮点在内存里是怎么放的吧，我记得有符号位，尾数和幂，不过都是二进制的

如果又浮点库，直接使用 没有，定义定点数，表示浮点数， 或者自己定义浮点类型（进行简单的计算，根据需要够用就成）。

引用 2 楼 judwenwen2009 的回复:[quote=引用 1 楼 uuuououlcz 的回复:] 位运算是针对整数的吧，浮点数位运算还木有见过......话说单片机浮点数用double了，float经度已经不够用了吗？  源数据是double的，理论上对特定的浮点运算是优化的，毕竟所有运算本质都是通过二进制实现的啊，我见过用为位运算实现开方运算的，比库函数快好几倍。所以想找找乘法的优化[/quote]  好吧，去搜了一下移位的开方算法，虽然不懂，但还真是涨姿势了，关于你说的浮点除法，看看这个有木有些用处： http://wenku.baidu.com/view/2f0f70d180eb6294dd886c1a.html

引用 1 楼 uuuououlcz 的回复:位运算是针对整数的吧，浮点数位运算还木有见过......话说单片机浮点数用double了，float经度已经不够用了吗？  源数据是double的，理论上对特定的浮点运算是优化的，毕竟所有运算本质都是通过二进制实现的啊，我见过用为位运算实现开方运算的，比库函数快好几倍。所以想找找乘法的优化


Question: 简单c

mallocs是C语言里面的一个动态分配内存的函数，原型是这样的： void* malloc (size_t size); size为要分配的空间大小，单位是字节。 如果分配成功则返回一个void类型的指针指向该内存的首地址， 一般会转换成自己需要的指针类型，比如 int * number = (int *)malloc(sizeof(int)); 如果分配失败，则返回空。

C++不允许讲void* 赋值给任何非void* 指针，所以需要强制转换， 但是C则没有这种限制！   引用 3 楼 u013410394 的回复:[quote=引用 1 楼 user-4 的回复:]  int size = sizeof(int[10]) ;//返回40 void *p = malloc(size);//分配一个40个BYTE的指针； int *pn = (int*)p;//然后p指针转换成int* //其实也就是pn指向一个可以容纳10个int的buffer.   int *pn = (int*)p;//这一步我需要打括号吗？我觉得不需要啊？我看到的很多我发的那个程序，都有括号，请问是为什么呢，谢谢[/quote]

引用 1 楼 user-4 的回复: int size = sizeof(int[10]) ;//返回40 void *p = malloc(size);//分配一个40个BYTE的指针； int *pn = (int*)p;//然后p指针转换成int* //其实也就是pn指向一个可以容纳10个int的buffer.   int *pn = (int*)p;//这一步我需要打括号吗？我觉得不需要啊？我看到的很多我发的那个程序，都有括号，请问是为什么呢，谢谢

malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available


Question: 有什么方法能让A程序查看B程序中某一个变量的值

哪有那么好搞。

如果是两个独立的程序，就是两个进程，可以进行进程间通信，比如共享内存，socket，管道等

引用 3 楼 lm_whales 的回复:Windows 可以用Debug Api。 ++

Private Sub CommandButton2_Click()   'MsgBox "ﾄ耡ｪﾍﾋｳｿ", vbInformation     Unload Me   'VarPtr,ｱ菽ｿｵﾄﾄﾚｴ豬ﾘﾖｷ '  Dim hMine As Long  'ﾉｨﾀﾗｴｰﾌ蠏ﾄｾ莖 '  Dim lPos As Long ' '  hMine = FindWindow(vbNullString, "ﾉｨﾀﾗ")    'ﾕﾒ ﾉｨﾀﾗ ｴｰｿﾚ '  mP.X = 20 + 16 * 3    '68 '  mP.Y = 60 + 16 * 3    '108 '  'ﾕ篋ｻﾖﾃﾊﾇｵﾚ4ﾐﾐｵﾚ4ｸ '  'ﾕ篋ｻﾖﾃﾊﾇｵﾚ1ﾅﾅｵﾚ7ｸ '  lPos = mP.X + mP.Y * 65536    '7077956 ' '  Call SendMessage(hMine, WM_LBUTTONDOWN, 0, lPos) '  Call SendMessage(hMine, WM_LBUTTONUP, 0, lPos)  '  Call SendMessage(hMine, WM_LBUTTONDOWN, 0, MakeDWord(20 + 16 * 3, 60 + 16 * 3)) '  Call SendMessage(hMine, WM_LBUTTONUP, 0, MakeDWord(20 + 16 * 3, 60 + 16 * 3))     End Sub    Private Sub RunMine()   Dim Ret As Long   Ret = MsgBox("ﾏﾖﾔﾚﾒｪﾔﾋﾐﾐﾉｨﾀﾗｳﾌﾐｿ", vbExclamation + vbYesNo, "ﾊﾇｷﾖﾔﾚﾔﾋﾐﾐﾉｨﾀﾗ")   If Ret = vbYes Then     'ｻﾃWindowsﾋﾚｵﾄﾄｿﾂｼ｣ｬﾈｻｺ・鯔ｨﾀﾗｳﾌﾐﾇｷ贇ﾚ｣ｬｲ｢ｸ獗ｦﾌ睫ｾ     'Debug.Print GetSystemDir     If Dir$(GetSystemDir & "\winmine.exe") <> "" Then       Shell GetSystemDir & "\winmine.exe", vbNormalFocus       MsgBox "ﾇ・ﾙｴﾎｵ羹ｨﾃ隹ｴﾅ･｣｡", 64     Else       MsgBox "ﾃｻﾓﾐﾕﾒｵｽﾉｨﾀﾗｳﾌﾐ｡ｿﾉﾄﾜﾊﾇﾃｻﾓﾐｰｲﾗｰ｣ｬﾔﾚｿﾘﾖﾆﾃ豌蠏ﾄ｡ｰﾌ晴ﾓ/ﾉｾｳｳﾌﾐｱﾀ・｡ﾔｰﾌ晴ﾓ/ﾉｾｳWindowsﾗ鮠(&A)｡ｱﾖﾐｰﾑｸｽｼﾖﾐｵﾄﾓﾎﾏｷﾑ｡ﾉﾏ｣ｬﾈｷｶｨｾﾍｿﾉﾒﾔｰｲﾗｰｺﾃﾁﾋ｡｣", vbInformation     End If        Else      End If End Sub     Private Sub OptAuto_Click()   chkSleep.Value = 1    End Sub  Private Sub txtSleep_Change() '  Dim Ss As Integer, mTime As Long '  'ｼﾆﾋ翹ｨﾀﾗﾋ襍ﾄﾊｱｼ菘・,ﾈ｡ｵﾃｸﾟｶﾈｺﾍｿ昮ﾈ｣ｬｵﾃｵｽｹｲﾓﾐｶ猖ﾙｸｴﾅ･｣ｬﾈｻｺﾙｼ･ﾀﾗﾊ '  If txtSleep.Text = "" Then Exit Sub '  Ss = CInt(txtSleep.Text) '  mTime = (CLng(30 * 16) - 99) * Ss \ 1000 '  mTime = mTime + 1    'ﾎ鋗ﾅﾊﾇﾐ｡1 '  lblInfo.Caption = "ｴﾅ " & mTime & " ﾃ・ﾉﾒﾔﾍ・ﾉﾉｨﾀﾗﾈﾎﾎ｣" End Sub     Private Sub txtSleep_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)   'If KeyAscii < 48 Or KeyAscii > 57 Then KeyAscii = 0   If (KeyAscii < 48 Or KeyAscii > 57) And KeyAscii <> 8 Then KeyAscii = 0   'If KeyAscii = 8 Then KeyAscii = 8  End Sub  Private Sub UserForm_Initialize()   'ﾅﾐｶﾏｲﾙﾗｵﾍｳｰ豎ｾ     Dim OSInfo As OSVERSIONINFO, PId As String     Dim Ret As Long     Dim OS As String, OSVersion As Single     Dim Str1 As String     OSVersion = CSng(GetOSVersion.osvOSVerMajor & "." & GetOSVersion.osvOSVerMinor)          Select Case GetOSVersion.osvOSName     Case 0    'Windows 32s       OS = "Win32"     Case 1    'Windows 95/98       Select Case OSVersion       Case 4: OS = "Win 95"       Case 4.1: OS = "Win 98"       Case 4.9: OS = "Wim Me"       End Select      Case 2    'Windows NT       Select Case OSVersion       Case 4: OS = "Win NT"       Case 5#: OS = "Win 2000"       Case 5.1: OS = "Win XP"        End Select     End Select          If OS = "Win 2000" Then       Opt2000.Value = True     ElseIf OS = "Win XP" Then       OptXP.Value = True     Else    'ｷﾇ2000/XPﾏｵﾍｳ       MsgBox "ｶﾔｲｻﾆ｡ｱｾｳﾌﾐｻﾄﾜﾔﾋﾐﾐﾔﾚWindows 2000/XPﾏｵﾍｳﾉﾏﾃ譯｣", vbInformation, "I'm Sorry!"     End If     OptAuto.Value = True End Sub  Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) auto_close End Sub

'***********************Excelﾉｨﾀﾗﾍ篁ﾒ************************* '***********************EH-yuanhongly************************* '***********************2008ﾄ・1ﾔﾂ11ﾈﾕ************************  Option Explicit  Dim mP As POINTAPI    'ｴ豢｢ﾊ・ｻﾖﾃ '0..8ｱ桄ｾﾊﾗﾖ｣ｬ9ｱ桄ｾﾃｻﾓﾐｴｪ｣ｬ*ｱ桄ｾﾀﾗ｣ｬFｱ桄ｾｱ・ﾇ  Private Sub CommandButton1_Click()   Dim hMine As Long  'ﾉｨﾀﾗｴｰﾌ蠏ﾄｾ莖   Dim pMine As Long  'ﾉｨﾀﾗｴｰﾌ蠏ﾄｽﾌｱ   Dim MineID As Long  'ﾉｨﾀﾗｴｰﾌ蠏ﾄｽﾌID   Dim lpBuffer As Byte  'ﾓﾃﾓﾚｶﾁﾈ｡ﾄﾚｴ贍ﾐｵﾄﾄﾚﾈﾝ   Dim nSize As Long  'ｶﾁﾈ｡ｵﾄｴ｡   Dim lpNumberOfBytesRead As Long  'ﾒﾑｶﾁﾈ｡ｵﾄﾗﾖｽﾚﾊ   Dim S As String   Dim Row, Col As Integer   'ﾐﾐﾊ｡｢ﾁﾐﾊ   Dim mWidth, mHeight, mPlayType As Integer  'ﾀﾗｵﾄﾁﾐﾊ｡｢ﾐﾐﾊ｡｢ﾍ豬ﾄﾄ｣ﾊｽ   Dim MineNum As Integer, mTime As Long   'ﾀﾗﾊ   'ﾉｨﾀﾗｴｰﾌ衙ﾏｵﾚﾒｻﾐﾐｵﾚﾒｻﾁﾐﾏ犖ﾔﾓﾚﾕ篋ｰﾌ蠏ﾄﾆｫﾒﾆﾁｿ｣ｬﾓﾃﾓﾚﾒﾔｺﾄﾊ・ﾔｶｯｵ羹   Dim xOffset As Integer, yOffset As Integer   Dim miBegin As Long, miHeight As Long, miWidth As Long, miStart As Long, miPlayType As Long      '&H010052C0  ﾍ豬ﾄﾄ｣ﾊｽ   '&H010052C4  2Kﾏﾂﾊﾇﾀﾗﾊﾆｼｵﾘﾖｷ   '&H010052C8  2Kﾏﾂﾊﾇﾀﾗﾇﾟｶﾈﾆｼｵﾘﾖｷ   '&H010052CC  2Kﾏﾂﾊﾇﾀﾗﾇ昮ﾈﾆｼｵﾘﾖｷ   '&H01005721  2Kﾏﾂﾊﾇﾀﾗﾇﾚﾈﾝﾆｼｵﾘﾖｷ｣ｬﾒﾀｴﾎﾊﾇ&H01005721+ｸﾟ*32+ｿ   '&H01005A60  2Kﾏﾂﾊﾇﾀﾗﾊ｣ﾓ犧    '&H010056A0  ﾍ豬ﾄﾄ｣ﾊｽ   '&H01005330/56A4  XPﾏﾂﾊﾇﾀﾗﾊﾆｼｵﾘﾖｷ   '&H01005338/56A8  XPﾏﾂﾊﾇﾀﾗﾇﾟｶﾈﾆｼｵﾘﾖｷ   '&H01005334/56AC  XPﾏﾂﾊﾇﾀﾗﾇ昮ﾈﾆｼｵﾘﾖｷ   '&H01005361  XPﾏﾂﾊﾇﾀﾗﾇﾚﾈﾝﾆｼｵﾘﾖｷ｣ｬﾒﾀｴﾎﾊﾇ&H01005361+ｸﾟ*32+ｿ   '&H01005194  XPﾏﾂﾊﾇﾀﾗﾊ｣ﾓ犧    If Opt2000.Value Then     miBegin = &H10052C4     miHeight = &H10052C8     miWidth = &H10052CC     miStart = &H1005721     miPlayType = &H10052C0   Else     miBegin = &H1005330     miHeight = &H1005338     miWidth = &H1005334     miStart = &H1005361     miPlayType = &H10056A0      End If   hMine = FindWindow(vbNullString, "ﾉｨﾀﾗ")    'ﾕﾒ ﾉｨﾀﾗ ｴｰｿﾚ   Call GetWindowThreadProcessId(hMine, MineID)    'ｷｵｻﾘ ﾉｨﾀﾗ ｽﾌｵﾄID｣ｬﾎｪmineId   yOffset = 60   xOffset = 20   pMine = OpenProcess(PROCESS_VM_READ, True, MineID)             'ｴｪ ﾉｨﾀﾗ ｽﾌ   If pMine = 0 Then     Call MsgBox("ﾄ羹ｹﾃｻﾓﾐｴｪﾉｨﾀﾗｰﾉ｣ｺ｣ｩ", vbInformation, "ﾕﾒｲｻｵｽﾅｶ")     RunMine     Exit Sub   End If   nSize = 1   'ReDim lpBuffer(nSize - 1)      If ReadProcessMemory(pMine, miBegin, lpBuffer, nSize, lpNumberOfBytesRead) Then       'ｽﾌｾ莖・ﾄﾚｴ貮ｷ,ﾊｾﾝｻｺｳ衂・ﾒｪｶﾁｵﾄﾗﾖｽﾚﾊ,ﾒﾑｶﾁﾗﾖｽﾚﾊ     Me.Caption = "ｹｲﾓﾐﾀﾗﾊ " + CStr(lpBuffer) + " ｸ・"     MineNum = lpBuffer   End If   If ReadProcessMemory(pMine, miWidth, lpBuffer, nSize, lpNumberOfBytesRead) Then     mWidth = lpBuffer     'ﾀﾗﾇ昮ﾈ｣ｬｼｴ ﾉｨﾀﾗ ｵﾄﾁﾐﾊ   End If   If ReadProcessMemory(pMine, miHeight, lpBuffer, nSize, lpNumberOfBytesRead) Then     mHeight = lpBuffer     'ﾀﾗﾇﾟｶﾈ｣ｬｼｴ ﾉｨﾀﾗ ｵﾄﾐﾐﾊ   End If     If ReadProcessMemory(pMine, miPlayType, lpBuffer, nSize, lpNumberOfBytesRead) Then     mPlayType = lpBuffer      'ﾉｨﾀﾗﾄ｣ﾊｽ   End If        'ｼﾆﾋ聆ﾔｶｯﾉｨﾀﾗﾋﾃﾊｱｼ   mTime = (CLng(mWidth * mHeight) - MineNum) * CInt(txtSleep.Text) \ 1000 + 1   lblInfo.Caption = "ｴﾅ " & mTime & " ﾃ・ﾉﾒﾔﾍ・ﾉﾉｨﾀﾗﾈﾎﾎ｣"      'SendMessageｵﾄﾗ鋓ｻｸﾎﾊlParamﾔﾚｷ｢ﾋﾍWM_LBUTTONDOWNﾏ鋧｢ﾊｱｴ﨑櫤凜ｬﾈ郤ﾎｰﾑﾗ鷙,Yｺﾏｲ｢ｳﾉlParamﾄﾘ   'DelphiﾊﾇﾓﾃMakelParam(x,y)   'a = postmessage(hwand,WM_LBUTTONDOWN , 0, (x And &hFFFF)+(y And &HFFFF)*&H10000)    '  For Row = 0 To mHeight      'ｴﾓｵﾚﾒｻﾐﾐｿｪﾊｼ｣ｬﾓﾉﾗﾒ｣ｬｴﾓﾉﾏｶﾂ '    For Col = 0 To mWidth   'ﾗﾔｶｯﾉｨﾀﾗｵﾄﾎﾊﾌ筌ｬﾈ郢鋐ﾑｾｭﾊﾇｰｴｹｵﾄ｣ｬｾﾍﾊﾇｱｻﾗﾔｶｯｷｭｿｪｵﾄ｣ｬｶﾁﾈ｡ﾒｻﾏﾂﾄﾚｴ贍ｵ｣ｬｷ｢ﾏﾖﾒﾑｾｭﾊﾇｷｭｿｪﾗｴﾌｬｵﾄ｣ｬｾﾍｲｻﾒｪﾔﾙﾒﾆｶｯｵ羹ﾋ｣ｬﾄﾇﾑﾍﾏﾔｵﾃﾓﾐｵ羮ﾙ   'ﾕ簷ﾓｵﾄﾗﾔｶｯﾉｨﾀﾗ｣ｬﾊﾇﾒｻﾐﾐﾒｻﾐﾐｵﾄﾋｳﾐｨﾏﾂﾀｴ｣ｬﾒﾔｺｼﾂﾇﾊｹﾓﾃﾋ貊揵ｨﾀﾗ｣ｬﾕ簷ﾔｵﾃﾕ賁ｵﾒｻｵ   'ﾈ郢鉑ｨﾀﾗﾊﾇﾒﾑｾｭｿｪﾊｼﾓﾎﾏｷｵﾄﾗｴﾌｬ｣ｬｻﾟﾊﾇﾒﾑｾｭｽ睫・ﾉｵﾄﾗｴﾌｬ｣ｬｿｼﾂﾇﾈﾃﾊ・ﾔｶｯｵ羹ﾇｸｦﾁｳｵﾄﾍｼｱ凜ｬﾈﾃﾓﾎﾏｷﾖﾘﾐﾂｿｪﾊｼ   'ﾗﾔｶｯﾒﾆｶｯﾖｸﾕ・ｱ｣ｬｷ｢ﾏﾖﾓﾐﾊｱﾖｸﾕ・眷ﾜｵｽｱﾄｵﾘｷｽ｣ｬﾂﾒﾉﾁ(ｿﾉﾓﾃﾒｲﾘﾖｸﾕ・ｦﾄﾜ｣ｬﾃｻｵ羹ｱﾒｲﾘ｣ｬﾗﾔｶｯｵ羹ｱﾏﾔﾊｾ,ShowCursor)   'ﾒｻｸ貉ﾖｵﾄﾎﾊﾌ筌ｬｵｱﾉｨﾀﾗｵｽﾁﾋﾗ鋓ﾄﾊｱｺｬｹ箜・ｻｻ睿｣ﾔﾚﾗ鋓ｻｸｬｶ｣ﾔﾚｵｹﾊｵﾚｼｸｸ・ﾒｻｰ聆鋓睫ﾇﾀﾗ      'ﾗﾔｶｯｵ羹ｦﾁｳﾍｼｱ・ｴﾅ･｣ｬﾖﾘﾐﾂｿｪﾊｼﾒｻｾﾖ(255,75,ﾉｨﾀﾗﾖﾐﾐｦﾁｳｰｴﾅ･ﾋﾚｵﾄﾎｻﾖﾃ)ﾕ篋ﾟｶﾈｲｻﾋ羈・簑ｸｵﾄｸﾟｶﾈｺﾍｲﾋｵ･ｵﾄｸﾟｶﾈ｣ｬﾖｻﾋ譱ﾍｻｧﾇﾄｸﾟｶﾈ '  SetForegroundWindow hMine '  mP.x = 255 '  mP.y = 75 - 45 '  Call ClientToScreen(hMine, mP) '  SetCursorPos mP.x, mP.y    '  Call SendMessage(hMine, WM_LBUTTONDOWN, 0, MakelParam(255, 30)) '  Call SendMessage(hMine, WM_LBUTTONUP, 0, MakelParam(255, 30))  '  mouse_event MOUSEEVENTF_LEFTDOWN Or MOUSEEVENTF_LEFTUP, 0, 0, 0, 0    'ｷ｢ﾋﾍｼ・ﾌﾏ鋧｢F2ｼ・ｬﾒｲｿﾉﾒﾔﾖﾘﾐﾂｿｪﾊｼﾐﾂﾓﾎﾏｷ   'Call SendMessage(hMine, WM_KEYDOWN, VK_F2, 0&)   'Call SendMessage(hMine, WM_KEYUP, VK_F2, 0&)      'sendkeys ( )    '  SetForegroundWindow hMine '  keybd_event VK_F2, 0, 0, 0 '  keybd_event VK_F2, 0, KEYEVENTF_KEYUP, 0   ' release H '  DoEvents    'ﾋ菠ｻﾏﾂﾃ豬ﾄﾓ・萼ﾐﾐｧ｣ｬｵｫﾊﾇｺﾃﾏﾌﾐｴﾃｻﾓﾐｴﾓﾄﾚｴ贍ﾐﾇ蟲ｸﾉｾｻ,VBｵﾄｽ睫・ﾔﾈｻﾓﾐﾐｧ｣ｬｴｰﾌ袵ﾑｾｭｲｻｼ訒ｬﾒｪﾊﾖｶｯｽ睫ﾌﾐ '  Call SendMessage(Command2.hwnd, WM_KEYDOWN, VK_SPACE, 0&) '  Call SendMessage(Command2.hwnd, WM_KEYUP, VK_SPACE, 0&)    For Row = 0 To (mHeight - 1)    'ｴﾓｵﾚﾒｻﾐﾐｿｪﾊｼ｣ｬﾓﾉﾗﾒ｣ｬｴﾓﾉﾏｶﾂ     For Col = 0 To (mWidth - 1)       'ﾈ郢赶ｴﾏﾂESCｼ・ｬﾔ｣ﾖｹﾗﾔｶｯﾉｨﾀﾗ       If GetAsyncKeyState(VK_ESCAPE) <> 0 Then         Call CloseHandle(pMine)         Exit Sub       End If              If ReadProcessMemory(pMine, miStart + Row * 32 + Col, lpBuffer, nSize, lpNumberOfBytesRead) Then         'If lpBuffer <> 143 Or (lpBuffer > &H40 And lpBuffer <= &H48) Then 'ｼｴ$8Fﾎｪﾀﾗ,&H40ｵｽ&H48ｴ﨑・-8         'If lpBuffer <> 143 Or (lpBuffer < &H40 And lpBuffer > &H48) Then           mP.x = xOffset + 16 * Col           mP.y = yOffset + 16 * Row         If lpBuffer <> 143 Then 'ｼｴ$8Fﾎｪﾀﾗ,&H40ｵｽ&H48ｴ﨑・-8           If OptAuto.Value Then     'ﾗﾔｶｯﾉｨﾀﾗ             If chkSleep.Value Then   'ﾈ郢鋙｡ﾖﾐﾁﾋﾑﾓﾊｱ               'ShowWindow hMine, SW_SHOW     'ｼ､ｻ鐱ｨﾀﾗｴｰｿﾚ               'ﾔｭｴﾋｴｦｷﾅｼ､ｻ鋗ｰｿﾚｵﾄｴ惲               If IsIconic(hMine) <> 0 Then     'ﾈ郢鉑ｨﾀﾗｴｰｿﾚﾊﾇﾗ隯｡ｻｯ｣ｬﾔﾖｸｴﾆ莇ｰｿﾚ                 ShowWindow hMine, SW_RESTORE               End If               If GetForegroundWindow <> hMine Then  'ﾈ郢鉑ｨﾀﾗｴｰｿﾚｲｻﾊﾇﾇｰﾌｨｴｰｿﾚ｣ｬﾔ靹ﾃﾎｪﾇｰﾌｨｴｰｿﾚ                 SetForegroundWindow hMine               End If                              'If lpBuffer >= &H40 And lpBuffer <= &H48 Then     'ﾈ郢鈹ﾇ0-8ｵﾄﾊﾗﾖﾔﾋｳｻﾗﾔｶｯｵ羹               'If lpBuffer < &H40 And lpBuffer > &H48 Then               If lpBuffer = &HF Then    'ﾈ郢軏ｻﾊﾇﾀﾗ｣ｬｶﾒﾃｻﾓﾐｷｭｿｪｹ,&H0F                 'Sleep 50      'ﾑﾓﾊｱ                 Sleep CInt(txtSleep.Text)                 DoEvents      'ﾗｪﾒﾆｿﾘﾖﾆﾈｨ                 'ﾒﾆｶｯﾊ・ｸﾕ・ｬｸﾐｾﾍﾏ豬ﾄﾔﾚﾗﾔｶｯﾉｨﾀﾗﾒｻﾑ                 Call ClientToScreen(hMine, mP)                 Call SetCursorPos(mP.x, mP.y)                                  'ﾄ｣ﾄ簔ﾋﾊ・・ﾄｵ羹ﾂｼ                 'ﾏ・ﾉｨﾀﾗ ｴｰﾌ蠏ﾄ ｣ｨxOffset+16*col,yOffset+16*row｣ｩｴｦ ｷ｢ﾋﾍﾊ・・ｴﾏﾂｵﾄﾏ鋧｢                 Call SendMessage(hMine, WM_LBUTTONDOWN, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))                 'ﾏ・ﾉｨﾀﾗ ｴｰﾌ蠏ﾄ ｣ｨxOffset+16*col,yOffset+16*row｣ｩｴｦ ｷ｢ﾋﾍﾊ・・ｧﾆﾄﾏ鋧｢                 Call SendMessage(hMine, WM_LBUTTONUP, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))                              End If             End If                        ElseIf OptNotMine.Value Then             'ﾔﾚｷﾇﾀﾗﾇ・｢ﾎﾊｺﾅ             'ﾄ｣ﾄ簔ﾋﾊ・ﾒｼ・ﾄｵ羹ﾂｼ             'ﾏ・ﾉｨﾀﾗ ｴｰﾌ蠏ﾄ ｣ｨxOffset+16*col,yOffset+16*row｣ｩｴｦ ｷ｢ﾋﾍﾊ・ﾒｼ・ｴﾏﾂｵﾄﾏ鋧｢             Call SendMessage(hMine, WM_RBUTTONDOWN, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))             Call SendMessage(hMine, WM_RBUTTONUP, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))             'ﾄ｣ﾄ簔ﾋﾊ・ﾒｼ・ﾄｵ羹ﾂｼｼｴｱ・｢ﾀﾗ             'ﾏ・ﾉｨﾀﾗ ｴｰﾌ蠏ﾄ ｣ｨxOffset+16*col,yOffset+16*row｣ｩｴｦ ｷ｢ﾋﾍﾊ・ﾒｼ・ｴﾏﾂｵﾄﾏ鋧｢             Call SendMessage(hMine, WM_RBUTTONDOWN, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))             'ﾏ・ﾉｨﾀﾗ ｴｰﾌ蠏ﾄ ｣ｨxOffset+16*col,yOffset+16*row｣ｩｴｦ ｷ｢ﾋﾍﾊ・ﾒｼ・ｧﾆﾄﾏ鋧｢             Call SendMessage(hMine, WM_RBUTTONUP, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))           End If          Else    '=&H8F(143),ﾓﾐﾀﾗ           'If OptMine.Value Or OptAuto.Value Then      'ｱ・ﾇﾀﾗﾇﾔｶｯﾉｨﾀﾗｶｼﾒｪﾓﾃﾓﾒｼ・ﾗﾇ衵｡ｺ・           If OptMine.Value Then             'ﾄ｣ﾄ簔ﾋﾊ・ﾒｼ・ﾄｵ羹ﾂｼ             'ﾏ・ﾉｨﾀﾗ ｴｰﾌ蠏ﾄ ｣ｨxOffset+16*col,yOffset+16*row｣ｩｴｦ ｷ｢ﾋﾍﾊ・ﾒｼ・ｴﾏﾂｵﾄﾏ鋧｢             Call SendMessage(hMine, WM_RBUTTONDOWN, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))             'ﾏ・ﾉｨﾀﾗ ｴｰﾌ蠏ﾄ ｣ｨxOffset+16*col,yOffset+16*row｣ｩｴｦ ｷ｢ﾋﾍﾊ・ﾒｼ・ｧﾆﾄﾏ鋧｢             Call SendMessage(hMine, WM_RBUTTONUP, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))           ElseIf OptAuto.Value Then             'Debug.Print Row; ","; Col              Sleep CInt(txtSleep.Text)             DoEvents      'ﾗｪﾒﾆｿﾘﾖﾆﾈｨ              'ﾒﾆｶｯﾊ・ｸﾕ・ｬｸﾐｾﾍﾏ豬ﾄﾔﾚﾗﾔｶｯﾉｨﾀﾗﾒｻﾑ             'ﾊ・ﾒﾒﾆｵﾄｴ﨔ﾖﾔﾚﾏﾂﾃ豬ﾄﾁｽｾ茱ｬﾒｪmPﾖﾐｴ豬ﾄｹ箜・ｻﾖﾃﾒﾑｾｭｱｻｻｻｹﾁﾋ｣ｬｴﾋﾊｱﾔﾙｻｻｾﾍｲｻｶﾔﾁﾋ             Call ClientToScreen(hMine, mP)             Call SetCursorPos(mP.x, mP.y)                          Call SendMessage(hMine, WM_RBUTTONDOWN, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))             Call SendMessage(hMine, WM_RBUTTONUP, 0, MakelParam(xOffset + 16 * Col, yOffset + 16 * Row))                      End If         End If       End If     Next   Next      Call CloseHandle(pMine)     End Sub       我这日文的操作系统对vba是硬伤,将就参考吧

不可能 内存中的数据运行时没有名称，连续内存也不分哪些字节是一起的

以前看到过一个用Excel VBA做的扫雷外挂,应该和这个问题的解决思想类似.感兴趣可以去excelhome搜下

推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

bool AdjustPrivileges() {     HANDLE hToken;     TOKEN_PRIVILEGES tp;     TOKEN_PRIVILEGES oldtp;     DWORD dwSize=sizeof(TOKEN_PRIVILEGES);     LUID luid;      if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {         if (GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) return true;         else return false;     }     if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {         CloseHandle(hToken);         return false;     }     ZeroMemory(&tp, sizeof(tp));     tp.PrivilegeCount=1;     tp.Privileges[0].Luid=luid;     tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;     /* Adjust Token Privileges */     if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &oldtp, &dwSize)) {         CloseHandle(hToken);         return false;     }     // close handles     CloseHandle(hToken);     return true; }  ReadProcessMemory The ReadProcessMemory function reads memory in a specified process. The entire area to be read must be accessible, or the operation fails.   BOOL ReadProcessMemory(   HANDLE hProcess,  // handle to the process whose memory is read   LPCVOID lpBaseAddress,                     // address to start reading   LPVOID lpBuffer,  // address of buffer to place read data   DWORD nSize,      // number of bytes to read   LPDWORD lpNumberOfBytesRead                      // address of number of bytes read );   Parameters hProcess  Handle to the process whose memory is being read. The handle must have PROCESS_VM_READ access to the process.  lpBaseAddress  Pointer to the base address in the specified process to be read. Before any data transfer occurs, the system verifies that all data in the base address and memory of the specified size is accessible for read access. If this is the case, the function proceeds; otherwise, the function fails.  lpBuffer  Pointer to a buffer that receives the contents from the address space of the specified process.  nSize  Specifies the requested number of bytes to read from the specified process.  lpNumberOfBytesRead  Pointer to the actual number of bytes transferred into the specified buffer. If lpNumberOfBytesRead is NULL, the parameter is ignored.  Return Values If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, call GetLastError.  The function fails if the requested read operation crosses into an area of the process that is inaccessible.   Remarks ReadProcessMemory copies the data in the specified address range from the address space of the specified process into the specified buffer of the current process. Any process that has a handle with PROCESS_VM_READ access can call the function. The process whose address space is read is typically, but not necessarily, being debugged.   The entire area to be read must be accessible. If it is not, the function fails as noted previously.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Unsupported.   Header: Declared in winbase.h.   Import Library: Use kernel32.lib.  See Also Debugging Overview, Debugging Functions, WriteProcessMemory, ReadProcessMemoryVlm

多少RMB？

VS，可以动态挂上被调试程序，既然如此，你也可以， 在程序运行过程中，可以暂时挂起B中的线程，然后搜内存，什么的。 你这是在做破解？还是准备做外挂？

共享内存、共享段、导出变量跨进程读取变量

引用 10 楼 h70614959 的回复:可以放到缓存组件cBase、memcatch 。实在不想用中间件。放到一个文件里面也是可以的。只要两个程序都可以访问即可。  哦，明白你的意思了，，， 可是你说的情况，需要对已经存在的B程序做修改，让B程序定期的把数据dump到某个容器内，，， 我想要的是，随便一个什么程序，只要在运行中，我就能读取到它当前所有活着的变量，并且查看变量值，前提是我不修改B程序

写硬盘文件或者得到B的窗口句柄

引用 3 楼 lm_whales 的回复:Windows 可以用Debug Api。 大概看了一下，3楼的像是靠谱的。。。。。。。看看再说。。

共享内存吧～～

引用 5 楼 h70614959 的回复:定义个全局变量，让A、B都可以看到这个变量，防止并发休息可以用 volatile 修饰 B是一个已经存在，并且一直运行着的程序，我现在想再写一个程序，来得到B中变量的值，如何定义一个变量让A，B同时看到？


Question: 读取txt文件里的数据，有没有通用程序啊？

谢谢所有楼上的~原来读写个txt也不是那么容易。。。学到了很多东西~~~

引用 26 楼 skyliuxu 的回复:引用 25 楼 darksworld 的回复:[quote=引用 19 楼 skyliuxu 的回复:] [quote=引用 10 楼 darksworld 的回复:] [quote=引用 6 楼 luciferisnotsatan 的回复:] [quote=引用 4 楼 darksworld 的回复:] [quote=引用 3 楼 turingo 的回复:] 用fscanf函数。  [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的）   如果txt文件里有字符之类的呢？我试了一下，如果txt里面有字符的话用fscanf好像运行不下去。或者说我读的时候想跳过第i行，或者只读int型的数据其他类型的数据跳过不读，又该怎么办呢？[/quote] 你每行的格式要一样。比如： abc bcd 123 asd sfsd 1 那你可以用 %s %s %d.  如果你是 c plus plus zero x eleven 2011 c++98 1998  这样的两行两列，那你就只能自己分析了。 [/quote]  1.有没有那种函数：先判断当前要读的是不是某个类型，如果是就读完存到数组，如果不是就跳过。这样的函数？ 2.fgetc这个函数 我看网上介绍是把文件指针向后移动一位，但是我用的时候，它好像可以跳过空格和回车直接到下一个有值的位置啊。。。难道空格和回车在txt文本里面算空值吗？[/quote] 1.这种函数可以有，自己写呗。为什么标准库函数里没有？因为这种需求不必要！没有无谓的分析（除非谁闲的蛋疼），既然你要从一个txt文件里读取内容并用于某种计算或分析，那txt里存储的数据就必然满足一定模式（当然有可能存在无效数据），如果你能确保所有数据都是有效的，读取过程不是很easy么？ 2.空格和回车属于“blank character”, fgetc会跳过它们[/quote] 太对了~话说我小看fscanf了。。它可以直接跳过空格和回车[/quote] 抱歉，上面说错了，貌似fgetc是不会跳过blank character的。fscanf肯定是跳过blank字符的[/quote]  嗯~貌似用一次fgetc(); 文件指针后移一位 正好可以解决空格和回车的问题~~

引用 25 楼 darksworld 的回复:引用 19 楼 skyliuxu 的回复:[quote=引用 10 楼 darksworld 的回复:] [quote=引用 6 楼 luciferisnotsatan 的回复:] [quote=引用 4 楼 darksworld 的回复:] [quote=引用 3 楼 turingo 的回复:] 用fscanf函数。  [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的）   如果txt文件里有字符之类的呢？我试了一下，如果txt里面有字符的话用fscanf好像运行不下去。或者说我读的时候想跳过第i行，或者只读int型的数据其他类型的数据跳过不读，又该怎么办呢？[/quote] 你每行的格式要一样。比如： abc bcd 123 asd sfsd 1 那你可以用 %s %s %d.  如果你是 c plus plus zero x eleven 2011 c++98 1998  这样的两行两列，那你就只能自己分析了。 [/quote]  1.有没有那种函数：先判断当前要读的是不是某个类型，如果是就读完存到数组，如果不是就跳过。这样的函数？ 2.fgetc这个函数 我看网上介绍是把文件指针向后移动一位，但是我用的时候，它好像可以跳过空格和回车直接到下一个有值的位置啊。。。难道空格和回车在txt文本里面算空值吗？[/quote] 1.这种函数可以有，自己写呗。为什么标准库函数里没有？因为这种需求不必要！没有无谓的分析（除非谁闲的蛋疼），既然你要从一个txt文件里读取内容并用于某种计算或分析，那txt里存储的数据就必然满足一定模式（当然有可能存在无效数据），如果你能确保所有数据都是有效的，读取过程不是很easy么？ 2.空格和回车属于“blank character”, fgetc会跳过它们[/quote] 太对了~话说我小看fscanf了。。它可以直接跳过空格和回车[/quote] 抱歉，上面说错了，貌似fgetc是不会跳过blank character的。fscanf肯定是跳过blank字符的

引用 19 楼 skyliuxu 的回复:引用 10 楼 darksworld 的回复:[quote=引用 6 楼 luciferisnotsatan 的回复:] [quote=引用 4 楼 darksworld 的回复:] [quote=引用 3 楼 turingo 的回复:] 用fscanf函数。  [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的）   如果txt文件里有字符之类的呢？我试了一下，如果txt里面有字符的话用fscanf好像运行不下去。或者说我读的时候想跳过第i行，或者只读int型的数据其他类型的数据跳过不读，又该怎么办呢？[/quote] 你每行的格式要一样。比如： abc bcd 123 asd sfsd 1 那你可以用 %s %s %d.  如果你是 c plus plus zero x eleven 2011 c++98 1998  这样的两行两列，那你就只能自己分析了。 [/quote]  1.有没有那种函数：先判断当前要读的是不是某个类型，如果是就读完存到数组，如果不是就跳过。这样的函数？ 2.fgetc这个函数 我看网上介绍是把文件指针向后移动一位，但是我用的时候，它好像可以跳过空格和回车直接到下一个有值的位置啊。。。难道空格和回车在txt文本里面算空值吗？[/quote] 1.这种函数可以有，自己写呗。为什么标准库函数里没有？因为这种需求不必要！没有无谓的分析（除非谁闲的蛋疼），既然你要从一个txt文件里读取内容并用于某种计算或分析，那txt里存储的数据就必然满足一定模式（当然有可能存在无效数据），如果你能确保所有数据都是有效的，读取过程不是很easy么？ 2.空格和回车属于“blank character”, fgetc会跳过它们[/quote] 太对了~话说我小看fscanf了。。它可以直接跳过空格和回车

引用 21 楼 vipcxj 的回复:     //打开文件     ifstream fin("E:\\test.txt");     ofstream fout("E:\\result.txt");       //读取数据到数组Data     int data[10000] = {0};     int i = 0;    while(!fin)    {       fin >> data[i];       fout << data[i++];    }    这个就是LZ所要的？ 	FILE *fp1;  	fp1 = fopen("E:\\test.txt","r"); //读取  	//读取数据到数组Data 	int data[15000]; 	memset(data,0,sizeof(data)); 	int flag=0; 	while(flag<15000)// 	{ 		fscanf(fp1,"%d",&data[flag]); 		flag++; 	}    好像就是这样的。。如果用循环读的话fscanf可以自动跳过空格和回车 如果不用循环，那就只能用fgetc把文件指针指向下一个位置了,fgetc一次只能跳一个空格或者一个回车 是不是这样？

引用 18 楼 zhao4zhong1 的回复:[quote=引用 14 楼 zhao4zhong1 的回复:] Excel 自顶！[/quote]  我只要拿C写的。。。考试要用总得挑个保险的方法。。。

一般按业务逻辑，应该知道这一堆数据应有的格式，文字处理或许全当字串，科学计算全当浮点数未必不可，不大可能是依照文件里的面值去区分...

引用 21 楼 vipcxj 的回复:     //打开文件     ifstream fin("E:\\test.txt");     ofstream fout("E:\\result.txt");       //读取数据到数组Data     int data[10000] = {0};     int i = 0;    while(!fin)    {       fin >> data[i];       fout << data[i++];    }    这个就是LZ所要的？ 哎呀，看错了，原来这是C版

getc万能,自己调整

引用 10 楼 darksworld 的回复:引用 6 楼 luciferisnotsatan 的回复:[quote=引用 4 楼 darksworld 的回复:] [quote=引用 3 楼 turingo 的回复:] 用fscanf函数。  [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的）   如果txt文件里有字符之类的呢？我试了一下，如果txt里面有字符的话用fscanf好像运行不下去。或者说我读的时候想跳过第i行，或者只读int型的数据其他类型的数据跳过不读，又该怎么办呢？[/quote] 你每行的格式要一样。比如： abc bcd 123 asd sfsd 1 那你可以用 %s %s %d.  如果你是 c plus plus zero x eleven 2011 c++98 1998  这样的两行两列，那你就只能自己分析了。 [/quote]  1.有没有那种函数：先判断当前要读的是不是某个类型，如果是就读完存到数组，如果不是就跳过。这样的函数？ 2.fgetc这个函数 我看网上介绍是把文件指针向后移动一位，但是我用的时候，它好像可以跳过空格和回车直接到下一个有值的位置啊。。。难道空格和回车在txt文本里面算空值吗？[/quote] 1.这种函数可以有，自己写呗。为什么标准库函数里没有？因为这种需求不必要！没有无谓的分析（除非谁闲的蛋疼），既然你要从一个txt文件里读取内容并用于某种计算或分析，那txt里存储的数据就必然满足一定模式（当然有可能存在无效数据），如果你能确保所有数据都是有效的，读取过程不是很easy么？ 2.空格和回车属于“blank character”, fgetc会跳过它们

引用 14 楼 zhao4zhong1 的回复:Excel 自顶！

m行n列的数据 -->POCO Clang--> struct{...}<---Deserialization <-------- stream

打开文件，复制粘贴到excel中，另存csv格式。

引用 6 楼 luciferisnotsatan 的回复:引用 4 楼 darksworld 的回复:[quote=引用 3 楼 turingo 的回复:] 用fscanf函数。  [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的）   如果txt文件里有字符之类的呢？我试了一下，如果txt里面有字符的话用fscanf好像运行不下去。或者说我读的时候想跳过第i行，或者只读int型的数据其他类型的数据跳过不读，又该怎么办呢？[/quote] 你每行的格式要一样。比如： abc bcd 123 asd sfsd 1 那你可以用 %s %s %d.  如果你是 c plus plus zero x eleven 2011 c++98 1998  这样的两行两列，那你就只能自己分析了。 [/quote]  1.有没有那种函数：先判断当前要读的是不是某个类型，如果是就读完存到数组，如果不是就跳过。这样的函数？ 2.fgetc这个函数 我看网上介绍是把文件指针向后移动一位，但是我用的时候，它好像可以跳过空格和回车直接到下一个有值的位置啊。。。难道空格和回车在txt文本里面算空值吗？

取决于自己解析文本的方式。  引用 8 楼 darksworld 的回复:引用 5 楼 turingo 的回复:那是用法不对，fscanf/fgetc都是可以全部读完的。  [quote=引用 4 楼 darksworld 的回复:] [quote=引用 3 楼 turingo 的回复:] 用fscanf函数。  [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的）   如果txt文件里有字符之类的呢？我试了一下，如果txt里面有字符的话用fscanf好像运行不下去。或者说我读的时候想跳过第i行，或者只读int型的数据其他类型的数据跳过不读，又该怎么办呢？[/quote][/quote]  可是fscanf里面有读取数据类型的参数啊，如果在int数据里面 string类型的数据是随机出现的，那就没办法了吧？[/quote]  引用 8 楼 darksworld 的回复:引用 5 楼 turingo 的回复:那是用法不对，fscanf/fgetc都是可以全部读完的。  [quote=引用 4 楼 darksworld 的回复:] [quote=引用 3 楼 turingo 的回复:] 用fscanf函数。  [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的）   如果txt文件里有字符之类的呢？我试了一下，如果txt里面有字符的话用fscanf好像运行不下去。或者说我读的时候想跳过第i行，或者只读int型的数据其他类型的数据跳过不读，又该怎么办呢？[/quote][/quote]  可是fscanf里面有读取数据类型的参数啊，如果在int数据里面 string类型的数据是随机出现的，那就没办法了吧？[/quote]

引用 5 楼 turingo 的回复:那是用法不对，fscanf/fgetc都是可以全部读完的。  引用 4 楼 darksworld 的回复:[quote=引用 3 楼 turingo 的回复:] 用fscanf函数。  [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的）   如果txt文件里有字符之类的呢？我试了一下，如果txt里面有字符的话用fscanf好像运行不下去。或者说我读的时候想跳过第i行，或者只读int型的数据其他类型的数据跳过不读，又该怎么办呢？[/quote][/quote]  可是fscanf里面有读取数据类型的参数啊，如果在int数据里面 string类型的数据是随机出现的，那就没办法了吧？

如果你在linux下，那么这种case正好是awk的用武之地： http://blog.csdn.net/anzhsoft/article/details/17784019

引用 4 楼 darksworld 的回复:引用 3 楼 turingo 的回复:用fscanf函数。  [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的）   如果txt文件里有字符之类的呢？我试了一下，如果txt里面有字符的话用fscanf好像运行不下去。或者说我读的时候想跳过第i行，或者只读int型的数据其他类型的数据跳过不读，又该怎么办呢？[/quote] 你每行的格式要一样。比如： abc bcd 123 asd sfsd 1 那你可以用 %s %s %d.  如果你是 c plus plus zero x eleven 2011 c++98 1998  这样的两行两列，那你就只能自己分析了。

引用 13 楼 darksworld 的回复:[quote=引用 12 楼 lelieven 的回复:] [quote=引用 楼主 darksworld 的回复:] 一行数据比较好办。如果是m行n列的数据呢？（每n个数据换行一次）数据之间还有k个空格。我就不知道啊该怎么办了。。。求思路。。。（数据是int或者double类型的） http://blog.csdn.net/lelieven/article/details/18038495，看看满不满足你的要求？[/quote]  你这个是char啊。。。。不能读int吧？ 你看下我写的这个 能不能把10000个数（每个数之间有空格，21个数一行）读到数组里。。。。 	//打开文件 	FILE *fp1,*fp2; 	fp1 = fopen("E:\\test.txt","r"); //读取 	fp2 = fopen("E:\\result.txt","w"); //写回  	//读取数据到数组Data 	int data[10000]; 	memset(data,0,sizeof(data));    //声明结果数组    int* Data_result = (int*)malloc(sizeof(int)*10000);    memset(Data_result,0,sizeof(Data_result));  	int flag=0; 	while(flag<10000)//!feof(fp1) 	{ //		if(data[flag]!=' ') //		{ 		fscanf(fp1,"%d",&data[flag]); 		flag++;  //		} 	}  好像fscanf可以跳过空格和换行直接读数据？是这样吗？我试过10个数的情况没有问题，10000个数没发检查了。。。。[/quote]我也不太清楚，对C的文件操作还不是太熟，只写过读取char类型的！


Question: 关于return的返回终止函数问题

感觉你问的不是return，而是break

返回至调用fun处，和for还是if无关

引用 2 楼 u013410394 的回复:[quote=引用 1 楼 baichi4141 的回复:] 函数不分级。 嵌套函数，for函数里面带有if（）然后再for（return），这样子终止的是哪个，第一个for？？？[/quote] for不是函数，if也不是函数 函数是这样的  void fun() {       for()       {          if()            return ;//返回值调用fun处，和for还是if无关        } }

引用 2 楼 u013410394 的回复:[quote=引用 1 楼 baichi4141 的回复:] 函数不分级。 嵌套函数，for函数里面带有if（）然后再for（return），这样子终止的是哪个，第一个for？？？[/quote] 循环不是函数，return终止函数

引用 1 楼 baichi4141 的回复:函数不分级。 嵌套函数，for函数里面带有if（）然后再for（return），这样子终止的是哪个，第一个for？？？

函数不分级。

return后，函数就返回了。所谓return。


Question: 0xC0000005: 读取位置 0x00000030 时发生访问冲突，双向链表中插入将节点插入尾部这样写有错吗？

void insertclosed(Node *closed,Node *node)//将节点插入到双向链表closed的尾部 { 	if((closed->next==NULL)&&(closed->pre==NULL)) 	{ 		closed->next=closed->pre=node; 		node->pre=node->next=closed; 	} 	else 	{ 		Node *q=(Node *)malloc(sizeof(Node)); 		q=closed; 		while(q->next!=closed) 		{ 			q=q->next; 		} 		node->pre=q; 		node->next=closed; 		q->next=node; 		closed->pre=node; 		 	} } 现在还是不行啊

是执行到这句时出错while(q->next!=closed)，弹出弹窗信息！

如果closed参数是空的 不就悲剧了？

双链表，需要找到尾节点 链表closed 不为NULL，node是单一节点 ，有数据，或者为NULL void insertclosed(Node *closed,Node *node)//将节点插入到双向链表closed的尾部 {       ASSERT(closed && node);       if(!closed)return; //由于头节点，不可改变，所以空的链表，无法插入数据。       if(!node)return;   //插入空节点，不用做任何事情。       Node *rear = closed;       while( rear->next ){//尾节点的next必为NULL          rear = rear->next;       }       rear->next = node;  //尾节点rear的next ，置为新的尾节点 node       node->pre  = rear;  //新的尾节点 node的pre,置为原尾节点 rear       node->next = NULL;  //新的尾节点node的next， 置为 NULL；         }  双链表closed 不为NULL，node是是另一个双链表 ，有数据,或者为空的链表 //void insertclosed(Node *closed,Node *node)//将节点插入到双向链表closed的尾部 有鉴于，这个函数的实际意义，是合并两个链表，改名为合并 void mergeclosed(Node *closed,Node *node) {       Node* p,*q;//closed尾节点p,node尾节点q       ASSERT(closed && node);       if(!closed)return; //由于头节点，不可改变，所以空的链表，无法插入数据。       if(!node)return;       p = closed; //closed尾节点       while( p->next ){//尾节点的next必为NULL          p = p->next;       }       q= node;//node尾节点       while( q->next ){//尾节点的next必为NULL            q = q->next;       }       node->pre   = p;     // node的头节点的pre ,指向closed尾节点p       p->next     = node;  // closed尾节点 p的 next ，指向node 的头节点node        }  双向循环链表closed 不为NULL，node是单一节点 ，有数据，或者为NULL void insertclosed(Node *closed,Node *node)//将节点插入到双向链表closed的尾部 {       ASSERT(closed && node);       if(!closed)return; //由于头节点，不可改变，所以空的链表，无法插入数据。       if(!node)return;        node->pre  = closed->pre;  // 新的尾节点的pre ,指向原尾节点       node->next = closed;       // 新的尾节点的next，指向头节点       closed->pre->next = node;  // 尾节点的 next ，指向新的尾节点 node       closed->pre = node;        // 头节点的pre，指向新的尾节点的node }  双向循环链表closed 不为NULL，node是是另一个双向循环链表 ，有数据,或者为空的链表 //void insertclosed(Node *closed,Node *node)//将节点插入到双向链表closed的尾部 有鉴于，这个函数的实际意义，是合并两个链表，改名为合并 void mergeclosed(Node *closed,Node *node) {       Node* p,*q;       ASSERT(closed && node);       if(!closed)return; //由于头节点，不可改变，所以空的链表，无法插入数据。       if(!node)return;         p = closed->pre; //closed尾节点       q = node ->pre;  //node尾节点           node->pre   = p;      // 新的尾节点的pre ,指向closed尾节点p       p->next     = node;   // closed尾节点的 next ，指向node 的头节点node        q->next     = closed; // node 的的尾节点q的next，指向closed的头节点closed       closed->pre = q;      // closed头节点的pre，指向node的尾节点的q }

缓冲区指针为空， 访问出错

双向循环链表closed 不为NULL，node是单一节点 ，有数据，或者为NULL void insertclosed(Node *closed,Node *node)//将节点插入到双向链表closed的尾部 {       ASSERT(closed && node);       if(!closed)return; //由于头节点，不可改变，所以空的链表，无法插入数据。       if(!node)return;        node->pre  = closed->pre;  // 新的尾节点的pre ,指向原尾节点       node->next = closed;       // 新的尾节点的next，指向头节点       closed->pre->next = node;  // 尾节节点的 next ，指向新的尾节点 node       closed->pre = node;        // 头节点的pre，指向新的尾节点的node }  双向循环链表closed 不为NULL，node是是另一个双向循环链表 ，有数据,或者为空的链表 //void insertclosed(Node *closed,Node *node)//将节点插入到双向链表closed的尾部 有见于这个函数的实际意义是合并两个链表，改名为合并 void mergeclosed(Node *closed,Node *node) {       Node* p,*q;       ASSERT(closed && node);       if(!closed)return; //由于头节点，不可改变，所以空的链表，无法插入数据。       if(!node)return;         p = closed->pre; //closed尾节点       q = node ->pre;  //node尾节点           node->pre   = p;     // 新的尾节点的pre ,指向closed尾节点p       p->next     = node;     // closed尾节点的 next ，指向node 的头节点node        q->next     = closed;   // node 的的尾节点q的next，指向closed的头节点closed       closed->pre = q; // closed头节点的pre，指向node的尾节点的q }

1）你到底是双向链表，还是双向循环链表。 2）需不需要处理指针为 NULL 的情况。

if((closed->next==closed)&&(closed->pre==closed))  这句啥意思，没明白，怎么前后都指向自身？

(1) Node *q=(Node *)malloc(sizeof(Node));         q=closed; 这里内存泄漏了，你个q分了内存，又把它直接变成closed.  (2) while(q->next!=closed)         {             q=q->next;         } 就相当于你的closed是个循环链表。如果传入的不是，就crash


Question: free函数如何正确使用，求大神解答。。

终于知道第一个free那边为什么会错了。。原来是去free了一个常量字符串，我以为malloc之后就能调free,中间指向常量0后那个malloc（2）完全就没用到了  ALNG的思路真的不错，针对题目给出了特定的省时省内存的解法，收获不少，感谢。。其实我原先写了个通用点的大数加乘法看这题有用到就拷过来用了，好了结贴了

free函数只能释放通过malloc、realloc、calloc函数开辟的内存，你的代码里sum开始是malloc的，但是你紧接着就把sum指向了“0”（这里实际上已经造成了内存泄漏），后面tp又指向了sum指向的地址即“0”，这样的地址不是通过上述三个函数分配的，所以会报错。

闲的无聊，我实现了一遍，你先自己做在用我的对照吧。  好久不写C了，尽量按照记忆中的C写的，难保没有露马脚的地方 :)  /* It was said that when testing the first computer designed by von Neumann, people gave the  following problem to both the legendary professor and the new computer: If the 4th digit  of 2^n is 7, what is the smallest n? The machine and von Neumann began computing at the  same moment, and von Neumann gave the answer first.  Now you are challenged with a similar but more complicated problem: If the K-th digit of  M^n is 7, what is the smallest n?  Input  Each case is given in a line with 2 numbers: K and M (< 1,000).  Output  For each test case, please output in a line the smallest n.  You can assume:  The answer always exist. The answer is no more than 100. Sample Input  3 2 4 2 4 3 Sample Output  15 21 11 */  #include<stdio.h> #include<string.h> #include<stdlib.h>     int find_n(int k, int m);   int main() { 	int k,m;     while (scanf("%d %d", &k, &m) == 2)         printf("%d\n", find_n(m,k));     return 0; }  /* test if the digit'th(starting from 0) digit of num's decimal representation is 7  * return 1 when test true, false otherwise.  *  * eg. test7(157434,2) is true, while test7(157432,3) is false  *   * note: num should be between 0 and 10^9-1  *        and digit should be 0 to 8  */ int test7(long num, int digit) { 	char _[10]; 	sprintf(_,"%ld", num); 	return _[digit]=='7'; }  /* for debug only.  * I leave it behind because it sheds some light on how the large number  * should be interpreted  *  */ void dump(long * p, int cnt) { 	printf("%d", p[cnt-1]); 	for(int i=cnt-2; i>=0; --i) 		printf("%09d",p[i]); 	printf("\n"); }   void multiply(long* p, int* cnt_element, int m);  /* given integer k and m, find the smallest integer n such that  * the k'th digit of m^n (decimal representation) is 7  *  */ int find_n(int k, int m) { 	// sizeof(long) is guaranteed to be 4 	long array[34]; 	int cnt=1, // number of elements currently filled 		n=1; // the value that we are looking for 	array[0]=m; // we will put least significant int(s) in element 0  	--k; // so that first digit is the 0th digit  	while( cnt< k/9 || !test7(array[k/9], k%9) ) 	{ 		++n; 		multiply(array, &cnt, m); 	} 	return n; 	 }  /* our ad hoc large number multiplication function  * param: p: points to array of long's which represent a large number. note the least  *          significant element is the 0th element and each element should be between  *          0 and 10^9-1;  *        pcnt: points to number of elements actually used in the above array  *        m: number to multiply into the large number(no more than 100 according to problem description)     *  *  */ void multiply(long* p, int* pcnt, int m) { 	long long v=0; 	long carry=0; 	for(int i=0; i<*pcnt; ++i) 	{ 		v=carry+(long long)p[i]*m; 		p[i]=(long)(v%1000000000); 		carry=(long)(v/1000000000); 	} 	if(carry) 		p[(*pcnt)++]=carry; }

讨厌的CSDN不许连续回复超过3次！  回到这题，如果没有聪明的方法(估计有), 就用你的暴力法，那你的乘法实现还是太低效率了，即使写对了也10有8、9会timeout. 其实根本不需要那么多次动态分配内存，  已知M<1000, n<100, 所以M^n不大于10^300， 你直接在堆上开一个300的数组，就对它操作，这样一次malloc和free都不用，会大大提高你的程序的效率。  还可以再提高，你用一个字符来表示一个十进制的数位，这当然可以得到正确的结果，但效率还可以提高。 可以相信目标机器不会低于32位处理器，更准确的说法应该是目标机器上的c编译器的sizeof(int)不会低于4. 你完全可以用size_t或者int数组(instead of char[]), 在int间用10^9进位，每个int降级到10^9进位，即如果一个整数存的是10^9-1， 对它increment后，它会归0，而高位整数进一......希望你听懂了我的意思。这样的好处是计算更紧凑而保留了快速检查第k位是否为7的能力......   如果你能看懂我上面的意思，建议你用那个思路再实现一遍，甚至对比实现一遍，比较两者的效率，假定可以通过ACM的机器检测。  哦，你没必要定义乘法(*)，定义自乘(*=)就好了。形如:  void multiply_by(int self[], int num);  其中的self是一个足够装下10^300次方，成员间10^9进位的整型数组（啰嗦一下，每个成员装10^9, 10^300需要34个这样的int, 可以想一下你原来用成员用char，成员间10进位的方案要用300个元素, 哪一个会更快？)  你先试试，搞不定再问吧。

第一次进循环的时候，sum="0",tp=sum，这时候tp指向了常量字符串“0”，这种怎么能free呢？

引用 1 楼 ALNG 的回复:     char *sum = malloc(2);     char *tp;     sum = "0";     for (i = 0; i < l2; i++)     {         tp = sum;         t = multiplyHelper(s1, *(s2 + l2 - 1 - i) - '0');         zt = appendTailZero(t, i);         sum = add(tp, zt);         free(t);         free(zt);         free(tp);//假设在这free     }     return sum; }  tp就是sum, 循环体第二次再进入时那个指针就已经free掉了， tp和sum都指向未定义的内存位置了。不可以在循环体内free. 又因为你把返回值放在那里，如果你在本函数结束前free掉tp(亦即sum），调用函数使用返回值的时候又会发生访问错误，所以应该由调用者free. 谢谢你的解答，下面两个回复我能理解，这里还不是很清楚，以我的理解，在第一次进入循环开始，tp和sum都指向0字符串，而经过加和以后，sum指向add函数返回的新的内存区域，而我没有再tp=sum,这时候tp应该还是指向0字符串啊？难道这时tp和sum都是指向add后的新的内存区域，我free(tp)把加和的结果free掉了？

说一说你的multiply的设计，每一个函数原型都是一份合同，你的mutiply函数这份合同是这样的: s1指向乘数1字符数组的指针，s2指向乘数2字符数组的指针； 返回指向存放两者相乘的运算结果的字符数组的指针，这个字符数组是动态用malloc从堆中分配的，在使用完毕后free之是调用者的责任.  再看你的代码          while (strlen(r) < k)         {             r = multiply(r, m);             count++;         }  第一遍的时候r就是m, 等于计算m的平方，这个确实不需要free, 第二遍的时候那个r已经是动态分配的了，你如果不free掉它就直接把multiply的运算结果(一个新的动态分配的内存指针)赋给r, 那么前一次分配的内存就泄露了，如此反复，除了最后一个有用，之前的都泄露了......

int main() {     int k;     char m[5];     while (scanf("%d %s", &k, m) != EOF)     {         char *r = m;         int count = 1;         while (strlen(r) < k)         {             char * tmp=multiply(r, m);             if(r!=m)                 free(r);             r = tmp;             count++;         }         r += strlen(r) - k;         while (*r != '7')         {             char *tmp=multiply(r, m);             if(r!=m) // you should be able to skip this line!!                 free(r);             r=tmp;             r += strlen(r) - k;             count++;         }         printf("%d\n", count);     }     return 0; }  对应的， main应该做如上修改。没有查你的程序的逻辑和其他问题，不保证能通过。

char *sum = malloc(2);     char *tp;     sum = "0";     for (i = 0; i < l2; i++)     {         tp = sum;         t = multiplyHelper(s1, *(s2 + l2 - 1 - i) - '0');         zt = appendTailZero(t, i);         sum = add(tp, zt);         free(t);         free(zt);     }     return sum; }  tp就是sum, 循环体第二次再进入时那个指针就已经free掉了， tp和sum都指向未定义的内存位置了。不可以在循环体内free. 又因为你把返回值放在那里，如果你在本函数结束前free掉tp(亦即sum），调用函数使用返回值的时候又会发生访问错误，所以应该由调用者free.