Question: 最近自己在学数据结构，有个bug实在无法解决，求大家帮我看看，

我研究过这段代码，看懂了

又自己好了，过了一会运行，又可以了，为什么啊？

具体问题是这样的，你们把131行的    QElemType e放到   int durtime,intertime,i,t;下面就可以正常运行，但是放在上面就像我发的代码这样就无法运行。为什么呢？有人知道吗


Question: strcpy和memcpy内存覆盖还敢用吗？

在你要看Release版对应汇编指令的那句C函数前临时加DebugBreak();，重新编译链接，成功后按F5开始调试，当程序停在DebugBreak();这句时，按Alt+8打开汇编窗口，查看其后的汇编指令。 一般人我不告诉他！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！

引用 10 楼 zhao4zhong1 的回复:因为 copy的语义是操作后新目标和旧源内容相同且旧源的内容保持不变。 move的语义是操作后新目标和旧源内容相同且旧源的内容不一定保持不变。  所以 在源和目标内存覆盖的情况下，根本不可能实现copy！只能实现move    如果连这两者的语义都分不清的码农非要在不可能实现copy的情况下使用copy，那只能后果自负了！

引用 9 楼 layershow 的回复:我想楼主的问题不是越界应该是 char * p = malloc(1024); memcpy(p + 2, p, 500); strcpy(p + 2, p);  对于重叠，开发人员应该非常清楚，所谓的“随机性"就是你无法确定 dst 的值 比如 "abcdefg" 按字节处理 memcpy(p + 2, p, 8) 可能会变成 "abababab" 但是某些优化的 memcpy 可能按 4 字节拷贝，你就很难想象最终结果是什么 库函数的实现不是唯一的，所以结果是一个不可定义的 开发人员理解库函数能更好的使用，但是不要惧怕使用 不然还要考虑敢不敢用指针了。

引用 7 楼 zjq9931 的回复:[quote=引用 6 楼 kaiandshan 的回复:] 不好意思，都是“随机性”这个词惹的祸，如果des和src指向不同的空间，这些函数都可以使用；如果指向同一段内存，就会存在空间覆盖的问题，这种情况在函数使用者看来也是可以预见的。 动态分配的内存在堆中，比较难预见。 如果是编写的时候定义好的，在栈区的内存，一般会影响这个数组后面的变量的值。如果覆盖的更多。那就是黑客攻击的范畴了。[/quote] 是的，这些问题如果在定义或者申请的时候保证空间足够大，就不会产生覆盖的问题。

引用 9 楼 layershow 的回复:我想楼主的问题不是越界应该是 char * p = malloc(1024); memcpy(p + 2, p, 500); strcpy(p + 2, p);  对于重叠，开发人员应该非常清楚，所谓的“随机性"就是你无法确定 dst 的值 比如 "abcdefg" 按字节处理 memcpy(p + 2, p, 8) 可能会变成 "abababab" 但是某些优化的 memcpy 可能按 4 字节拷贝，你就很难想象最终结果是什么 库函数的实现不是唯一的，所以结果是一个不可定义的 开发人员理解库函数能更好的使用，但是不要惧怕使用  是的，说的正是我所讲的。原来memcpy也会存在优化的问题，我说呢在测试memcpy重叠覆盖的问题时，怎么一直不按照一个一个字节来覆盖，比如输入abcdefg,结果是abababab，可时间结果是ababcdefefg....正在郁闷呢。再请教下，怎么看编译器的优化方式呢？

引用 12 楼 zhao4zhong1 的回复:[quote=引用 10 楼 zhao4zhong1 的回复:] 因为 copy的语义是操作后新目标和旧源内容相同且旧源的内容保持不变。 move的语义是操作后新目标和旧源内容相同且旧源的内容不一定保持不变。  所以 在源和目标内存覆盖的情况下，根本不可能实现copy！只能实现move    如果连这两者的语义都分不清的码农非要在不可能实现copy的情况下使用copy，那只能后果自负了！[/quote]  是的，这种情况直接使用move就可以避免了，不用考虑覆盖的可能性了。

引用 6 楼 kaiandshan 的回复:不好意思，都是“随机性”这个词惹的祸，如果des和src指向不同的空间，这些函数都可以使用；如果指向同一段内存，就会存在空间覆盖的问题，这种情况在函数使用者看来也是可以预见的。 动态分配的内存在堆中，比较难预见。 如果是编写的时候定义好的，在栈区的内存，一般会影响这个数组后面的变量的值。如果覆盖的更多。那就是黑客攻击的范畴了。

楼主的意思是，会越界吧？越界确实会改变其他内容的值，甚至改变程序的代码。那啥，黑客经常用这种方式进行攻击。 VC有提供安全的函数。 可以查到。前面几楼也已经说过了。

不都在用吗 strcpy，写的时候应该知道你操作的对象是否可能重叠啊。  也可以用 strncpy版本，可以指定要拷贝的字符串的最大长度， 确保你准备的 目标内存足够大

存在覆盖 但谁告诉你覆盖有什么随机性?  a = 99; a原来的数据被覆盖了 ? 但 哪里来的毛线随机性?

晕，随机性不是说不知道会不会覆盖 随机性是说覆盖以后不知道会发生什么 而覆不覆盖，是你可以通过仔细来避免的

这种情况可由写代码的人杜绝。


Question: 求教结构体指针

1-赋值运算 2-memcpy

引用 7 楼 zhao4zhong1 的回复:[quote=引用 2 楼 user-8 的回复:] （*p1） = （*p2） p1[0]=p2[0];//这样是不是看起来更好懂一些？[/quote] 但是，既然用链表，还是鼓励交换链域而非交换数据域的。参考下面： //带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

引用 2 楼 user-8 的回复:（*p1） = （*p2） p1[0]=p2[0];//这样是不是看起来更好懂一些？

直接解引用 传值啊 if 同一个类型的 memset也行呀

引用 楼主 zjjsfny 的回复:结构体变量可以直接A=B 把结构体变量所有成员的值全给结构体变量A 你试试弹性数组成员，看能不能从A到B！ 但是链表中。如果我有两个结构体指针。分别指向P1，P2 那如何才能一次把P2中的成员值全都赋给P1。我只试了一个个的p->这样指。但如果成员多的话。比较麻烦。求告知。 struct t {/* ... ... */} * pt1, * pt2; /* ... ... */ * pt1 = * pt2;

试试运算符重载

定义一个函数.用函数copy

（*p1） = （*p2） 这样即可

（*p1） = （*p2）


Question: c语言如何计算不定积分？（不要用函数库，说下具体的实现方法）

程序公式推导，以前大学时老师曾写过一个极简单的例子，比如(a+b)^2 能算出来等于a^2 + 2ab+b^2，只不过不定积分比这个难度大多了。

不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……  “跨语言、跨机，跨操作系统，跨硬件平台，跨国，跨*.*的”苦海无边， 回头是“使用共享纯文本文件进行信息交流”的岸！

Matlab是C/C++编的。我猜。

实现不定积分需要进行符号计算吧，这个比较难。如果是计算定积分，楼主不妨用矩形法，梯形法，Simpson法，Newton-Cotes quadrature rule为关键词搜索一下。

百科了下不定积分的定义： 设F(x)是函数f(x)的一个原函数，我们把函数f(x)的所有原函数F(x)+ C(其中，C为任意常数）叫做函数f(x)的不定积分，又叫做函数f(x)的反导数。  不定积分的结果是一组函数族F(x)+ C，那么关键就是找出各阶符号的系数了？

用数学的方法会吗？先写下伪代码。然后再翻译成编程语言的代码。


Question: 关于c学习过程中的一些疑惑！

谢谢各位大虾的回答。 昨天下乡了，没有及时结贴。

引用 4 楼 zxh707wk 的回复:引用 3 楼 zhao4zhong1 的回复:赵老师那段话怎么说来着 查MSDN是Windows程序员必须掌握的技能之一。  作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。

1 是 2 没有，double是8字节，存储的不是小数点的字符串，是尾指形式，可以看看格式 3 看你怎么输入到a了，a不可能输出2.3的，只能是2 4 抛弃这个编译器 5 同上

{     for(int i=0;i<10;i++)   //这个i的作用域在两个{}之间     scanf("%d",&score[i]);   //存储数据的数组score作用域是整个函数，所以后面可以用 } int i=100;

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

是 不用 无法判断，输入小数会自动转成int型整数，丢失小数部分 是的，VC6.0不算局部变量，在VS中算

是 没有 会直接取整 编译器的问题

引用 3 楼 zhao4zhong1 的回复:赵老师那段话怎么说来着

2 f  The precision value specifies the number of digits after the decimal point. If a decimal point appears, at least one digit appears before it. The value is rounded to the appropriate number of digits.  Default precision is 6; if precision is 0, or if the period (.) appears without a number following it, no decimal point is printed.   3 #include <stdio.h> #include <string.h> char s[80]; int i; char c; int main() {     while (1) {         printf("Input a integer:");fflush(stdout);         rewind(stdin);         fgets(s,80,stdin);         if (strlen(s)>10) {             printf("Input too long(>9)!\n");             continue;         }         if (2==sscanf(s,"%d%c",&i,&c)) {             if ('\n'==c) {                 printf("%d is a integer.\n",i);                 break;             }         }         if ('\n'==s[strlen(s)-1]) s[strlen(s)-1]=0;         printf("\"%s\" is NOT a integer!\n",s);     }     return 0; }

是，如果下面还有scanf %c，则会接受，若是其他的scanf（%d，%f）则没事 默认输出小数位数都取6位，不过不同的编译器，ide支持标准的程度不同，所有些ide不是显示6位 默认取整，不过自己可以进行判断，比如if(d == int(d) )     printf("d是整数\n"); else     printf("d是小数\n");   作用域限定，是可以的


Question: 求帮忙解释一下

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

for(i=1;i<=10;i++){gets(name[i];scanf("%d",&s);)} 这个语法都有问题

你的括号写错地方了吧，而且在scanf后面要用getchar清空缓存区的换行符

楼主基础性知识呢？ gets怎么能这么用，还有scanf的name[i]，怎么没有&

gets(name[i];scanf("%d",&s);)   这个是什么鬼？

&name[i]

因为  scanf  是 遇到 一个 空格符 为分割的 而gets 是 遇到换行符的， 也就是你用gets 你的 姓名 和分数 必须 分两行。  相反，如果你的姓和名之间有空格，用scanf估计就满足不了


Question: 帮忙看看哪里有问题

/* praise1.c -- 使用不同类别的字符串 */ #include<stdio.h> #define PRAISE "What a super marvelous name!" int main(void) {  char name[40];  printf("What's your name?\n");  scanf_s("%s", name,40);  printf("Hello, %s. %s\n", name, PRAISE);  return 0; } //What's your name? //Hilary Bubbles //Hello, Hilary. What a super marvelous name! //

帮帮忙阿。帮帮忙阿

还是没用,显示错误

#include<stdio.h> #define PRAISE "What a super marvelous name!" int main(void) { 	char name[40]; 	printf("What's your name?\n"); 	gets(name); 	printf("Hello, %s. %s\n", name, PRAISE); 	return 0; }

还是不行，用的是vs2013

scanf_s("%s", name, 40);  改成这样试试

scanf_s少了一个参数，要加上最大长度限制 而且scanf_s只有VC支持


Question: C多文件编译和include的用法

用gcc做预编译 (-E)选项， 然后你就理解#include到底是干什么用的。

不要include .c 文件，除非有充足的理由这么做

重复定义了fun3.  把头文件包含进来时，头文件的内容和当前文件就形成一个编译单位，同一个编译单位内不能出现同ID的重复定义，多次声明可以

没试过这样用

Q2：1.每个编译单元各自独立编译，链接成一个可执行模块即可；2.条件编译 Q3：标准头文件都有条件编译，不会出现重包含

原来“每个源文件是一个编译单元，各自编译，然后才链接起来成为可执行文件”，难怪我include文件会报错，不include反而正常，还没接触到编译原理，学include时想到的，学习了

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

在c语言里面include源代码是一种编程技巧也很常用，很多工程师这么干。 但需要注意几点： 1. 既然已经include xx.c/xxx.cpp了就不要再在工程里添加这个文件了。不然会被编译2次，而且容易有问题。 你的工程中可以把3.cpp拿掉，因为1.cpp已经include 3.cpp所以不需要再在工程添加编译3.cpp了。 2. 被include的文件里面函数或全局变量如果不需要其他文件使用的话最好是static类型。这样一个源文件被多个.c include也不会报冲突。

可以Include #include后，编译器会将include的文件内容拷贝到当前文件中，这样的话，将会导致重复定义的错误。应当避免这样的用法。  而且，编译器将.cpp .c .cc等各种源文件视为编译单位

重复定义，楼主好浪

没试过这样用

include可以include任意文件   和文件后缀无关  你甚至可以在你的Source Files里添加个名字叫a.bdfadfdsafd的文件 然后别的文件一样可以include它 只不过，人们一般把c++的源代码的文件后缀约定为.h和.cpp而已  你喜欢你可以写成.head .c 或者其他  这样约定是有道理的，任何变量，不论数据还是函数，都可以声明无数次但是定义只能定义一次 因此，人们把声明写在.h文件里  定义写在.cpp里  这样需要哪个变量或者函数的时候，只需要include声明这个变量或者函数的.h文件即可  即使这个文件被include了很多次 也没关系  因为声明可以声明无数次 但是定义，只能定义一次   如果出现重复定义，程序会在链接是报错（LNK型错误）  所以，你当然可以include一个里面有某些数据或函数的定义的cpp  或许你这样做程序也可以正常运行  但这也只是因为你恰好只include了一次这个cpp，如果你在另一个文件里也include这个cpp   就会报错  记住，定义只能出现一次，而声明可以出现无数次----只要不要出现文件的互相include  一般在头文件里，我们会放变量和函数的声明，另外还可以放const修饰的数据，还可以放inline函数 const修饰的数据默认类型是static的，如果你强行用extern修饰一个const  一样不应该放在可能被include多次的在头文件里 而inline函数可以放在头文件里，是因为inline被编译器处理成一种copy机制，类似#define，任何使用某个inline函数的文件都应该在使用前写一次这个inline函数   因此放到头文件里，哪儿用到了就在哪儿include  比较方便

注意报错的是3.cpp这个文件，而不是被拷贝到1.cpp里的那份3.cpp代码

值得研究下去，要弄懂了才是学到东西

分清编译和链接 每个源文件是一个编译单元，各自编译，然后才链接起来成为可执行文件 你这个写法，虽然include会展开，使得1.cpp能编译通过，但3.cpp编译通不过 另外如果不是为了研究，不要include源文件

include 在预编译阶段会做展开，把内容include进来  但是一般IDE会把cpp文件认为是编译单元

这个。。。你是要研究编译器吗？ 看你的代码好像是个新手啊，嘿嘿 好好理解一下声明、编译、链接吧


Question: 清华2012考研机试的一道题《求1和2的个数》别人的一份代码不太懂

引用 4 楼 a1193561652 的回复:[quote=引用 3 楼 nishizhenlige 的回复:] [quote=引用 1 楼 a1193561652 的回复:] 按我理解他的大致计算方式是：比如输入12345，那么先算F(1)，再由F(1)算出F(12)，依次再算出F(123)，F(1234)，F(12345)； 主要计算的就是rslt=(rslt-cnt)*10+num*2+cnt*(t+1)+min(t,2);这一句了。 rslt是结果；num是实际输入的数；cnt是仅仅num这个数中1,2的数量； 首先认为已经算出了F(12)=rslt，需要算F(123) 1.显然12变成了12X的形式，所以原来1-11中每一个数都可以加上一个个位(因为不知道个位是不是9，所以最后一个12不能乘10，以后单独计算)，而个位是从0-9，所以原来的每个数都有10中变化，而最后一个数12的1,2的数量为cnt，所以有(rslt-cnt)*10,； 2.上一步中余有一个12没有计算，显然12X这个数的个位只能是0-3，所以有cnt*(t+1)； 4.上面的记算中都没有考虑对个位为1,2的记数，10-120中个位为1,2的显然是每10个数中有2个，所以有num*2 3.第一步还有一个0没计算，若为0则只有个位有值，直接判断就好了，min(t,2)；  非常感谢，很有帮助 不过我有点点不太明白的地方 第四条中说10-120每10个数就有两个，所以num*2，可是如果12X中的X小于2的话，不就不是两个了么，比如121[/quote] 恩，写错了一点，num*2是计算00-11共12个数，就是把第一步没算的0包含进去了；min(t,2)，是计算最后一个数12X的情况。[/quote]  恩恩，O(∩_∩)O谢谢

引用 3 楼 nishizhenlige 的回复:[quote=引用 1 楼 a1193561652 的回复:] 按我理解他的大致计算方式是：比如输入12345，那么先算F(1)，再由F(1)算出F(12)，依次再算出F(123)，F(1234)，F(12345)； 主要计算的就是rslt=(rslt-cnt)*10+num*2+cnt*(t+1)+min(t,2);这一句了。 rslt是结果；num是实际输入的数；cnt是仅仅num这个数中1,2的数量； 首先认为已经算出了F(12)=rslt，需要算F(123) 1.显然12变成了12X的形式，所以原来1-11中每一个数都可以加上一个个位(因为不知道个位是不是9，所以最后一个12不能乘10，以后单独计算)，而个位是从0-9，所以原来的每个数都有10中变化，而最后一个数12的1,2的数量为cnt，所以有(rslt-cnt)*10,； 2.上一步中余有一个12没有计算，显然12X这个数的个位只能是0-3，所以有cnt*(t+1)； 4.上面的记算中都没有考虑对个位为1,2的记数，10-120中个位为1,2的显然是每10个数中有2个，所以有num*2 3.第一步还有一个0没计算，若为0则只有个位有值，直接判断就好了，min(t,2)；  非常感谢，很有帮助 不过我有点点不太明白的地方 第四条中说10-120每10个数就有两个，所以num*2，可是如果12X中的X小于2的话，不就不是两个了么，比如121[/quote] 恩，写错了一点，num*2是计算00-11共12个数，就是把第一步没算的0包含进去了；min(t,2)，是计算最后一个数12X的情况。

引用 1 楼 a1193561652 的回复:按我理解他的大致计算方式是：比如输入12345，那么先算F(1)，再由F(1)算出F(12)，依次再算出F(123)，F(1234)，F(12345)； 主要计算的就是rslt=(rslt-cnt)*10+num*2+cnt*(t+1)+min(t,2);这一句了。 rslt是结果；num是实际输入的数；cnt是仅仅num这个数中1,2的数量； 首先认为已经算出了F(12)=rslt，需要算F(123) 1.显然12变成了12X的形式，所以原来1-11中每一个数都可以加上一个个位(因为不知道个位是不是9，所以最后一个12不能乘10，以后单独计算)，而个位是从0-9，所以原来的每个数都有10中变化，而最后一个数12的1,2的数量为cnt，所以有(rslt-cnt)*10,； 2.上一步中余有一个12没有计算，显然12X这个数的个位只能是0-3，所以有cnt*(t+1)； 4.上面的记算中都没有考虑对个位为1,2的记数，10-120中个位为1,2的显然是每10个数中有2个，所以有num*2 3.第一步还有一个0没计算，若为0则只有个位有值，直接判断就好了，min(t,2)；  非常感谢，很有帮助 不过我有点点不太明白的地方 第四条中说10-120每10个数就有两个，所以num*2，可是如果12X中的X小于2的话，不就不是两个了么，比如121

1 c(n) 求出n中1和2的个数 2 dp(n)=dp(n-1)+c(n) 3 dp(1)=1，记录一下算过的数即可


Question: c语言的字符串数组问题

引用 5 楼 czarten 的回复:static 修饰符使得变量被放在全局数据区，在编译时就初始化，所以必须赋常量，而classPathName和hotkeyclassName都是变量，编译时不知道其值。  改成这样，就是在运行时赋值了，就没有问题：  #include <stdio.h> int main(int argc, char *argv[]) {     static const char *classPathName = "com/android/browser/BrowserUtil";     static const char *hotkeyclassName = "com/iiu/setting/hotkey/MouseUtil";     static const char *className[2];     className[0]=classPathName;     className[1]=hotkeyclassName;     int i = 0;     for(i=0; i < 2; i++)     {         printf("%s\n", className[i]);     }     return 0; }   而且我觉得，你这个不管是static还是const都加得有点莫名，看不懂加在这里意义是什么。 static修饰局部变量，使其在函数退出时不销毁，main一般不用多次调用吧 const如果你是想让classPathName不能被再次赋值，应该改成 static char *  const classPathName  这个嘛，我只是把某个项目里要修改的代码段抠出来单独编译测试，谢谢你的解释

引用 3 楼 was595 的回复:[quote=引用 1 楼 user-3 的回复:] 代码没问题啊，难道你用的vc6？不行就这么写 static const char *className[2]={"com/android/browser/BrowserUtil","com/iiu/setting/hotkey/MouseUtil"}; 或者下面才是你想要的效果 	struct ClassName 	{ 		const char *classPathName; 		const char *hotkeyclassName; 	}; 	ClassName cn{"com/android/browser/BrowserUtil","com/iiu/setting/hotkey/MouseUtil"};   去掉className的static就好了。。。完蛋全忘了[/quote]  你用const修饰这个指针数组  难道意思不是指针指向的内容不能改变？这和你去掉static有什么关系？

引用 1 楼 user-3 的回复:代码没问题啊，难道你用的vc6？不行就这么写 static const char *className[2]={"com/android/browser/BrowserUtil","com/iiu/setting/hotkey/MouseUtil"}; 或者下面才是你想要的效果 	struct ClassName 	{ 		const char *classPathName; 		const char *hotkeyclassName; 	}; 	ClassName cn{"com/android/browser/BrowserUtil","com/iiu/setting/hotkey/MouseUtil"};   去掉className的static就好了。。。完蛋全忘了

引用 1 楼 user-3 的回复:代码没问题啊，难道你用的vc6？不行就这么写 static const char *className[2]={"com/android/browser/BrowserUtil","com/iiu/setting/hotkey/MouseUtil"}; 或者下面才是你想要的效果 	struct ClassName 	{ 		const char *classPathName; 		const char *hotkeyclassName; 	}; 	ClassName cn{"com/android/browser/BrowserUtil","com/iiu/setting/hotkey/MouseUtil"};   你说的这个方法，都成功，只是不明白我的写法里，用gcc编译也出错


Question: c语言中这两种读 位数据的方法，哪个效率高？

按照程序变成汇编来说，第一种效率高，直接根据偏移取得值，cmp，第二种需要&运算 结果再 cmp

现在的计算机已经无所谓这点效率差别了

循环个一亿次怕也难分高下. 如果只是为了判断是否等于1, 用if(xxx == 1)岂不是更好? 难道就为省略那几个字母?

效率差别很小的，可以忽略！ 推荐用方法二，因为bit-field不可移植，不同的编译器会有不同的结果     An implementation may allocate any addressable storage unit large enough to hold a bit-field.  If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit.  If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined.  The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined.  The alignment of the addressable storage unit is unspecified.

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

你要比较 将两种方法分别循环10000次 获取执行时间 就分出高低来了 又何必问

个人认为是直接做与或非运算效率高一些~~~请问楼主比较这个效率的目的是？？

个人觉得第一种可阅读性强一点,看着舒服一点

方法一和方法二  不等价  根本没必要比较效率


Question: 解决稳定婚姻问题中遇到的结构体问题

引用 4 楼 czarten 的回复:typedef struct后面的大括号里，写的是结构体的成员  int rank[n];  int order[n];  int final[n]; 你这样写意味着，每一个boy结构体，都含有n个rank，n个order和n个final 而你又定义了n个boy 总共就有n平方个rank，n平方个order……  我脑残了，稳定婚姻问题的确是这样的没错

不知道 是默认使用同一片内存么

不知道，求解释

int rank[n];                 int order[n];                 int final[n]; 。。。你真的知道你这么写导致什么结果么


Question: cannot convert parameter 1 from 'char' to 'char []

一进来就被这switch吓尿了。。。。。咱们写代码是为了简化人的操作，写个这么nb的switch图啥啊。。。  尤其是这么简单的switch处理，唉。。。简化一下就是个这： *(p+z) == (*(p+z)-96)%26+97;   //'a'的ascii好像是97来着，没验证

其实楼主的标题 cannot convert parameter 1 from 'char' to 'char []  已经给了提示了啊 不能将一个参数char到char[]  这个switch写的的却是有点儿，，

char c=trans(b);

引用 1 楼 q3733353520 的回复: char trans(char a[])//trans函数需要的参数类型是 char []返回值类型是char char c[]=trans(b[0]);//  但是你给它传的是char 类型 ，返回的是char[]类型  怎么改？谢谢。

该说的上面都说了，char[] 相当于指针，和char不一样的 你这个switch也是厉害  if(*(p+z) == 'z') {     *(p+z) = 'a'; } else {     *(p+z) = *(p+z) + 1; }

参数其实需要一个 char*


Question: 刚入门，一疑惑求解答

应该是i和j反了

我看明白了，楼主是不是把“=”当成数学上的等号了

j都没有给过值，你要他输出什么

理解了 我之前学过一点点的python 就想看看在C语言中i=5, j=i, i=6;这样的结果是怎样的 现在知道了

引用为什么出来是这样的呢，而不是5，4或者是5，5 楼主你说，为什么要出现这样的结果   i, j没有初始化，里边是个垃圾值，后来i=4，i++，但是j没有改变，所以只会输出i的值为5

j没有初期化啊


Question: c、C++ 这用法麻烦解释下呢？

Test[1].fun_reve = syw_test_reve;     Test[2].fun_send = syw_test_send;  这只是给结构体中的函数指针赋值, 并没有调用函数. 调用的方法见1楼. 有个疑问:你的结构体中定义的Union是干什么的?\ union  是我以后要封装的数据，现在是随便写的，现在没什么意义。  谢谢各位，懂了哈

先给函数指针赋值之后就可以像 1L那样调用了。  不过你的结构中搞的这个联合没多大意义撒。

Test[1].fun_reve(100); 就这样调就行了。


Question: 求助，快速排序，不知道错哪了

# define swap(x,y) ({int t; t=x; x=y; y=t;})  void QuickSort2(int *arr,int left,int right) {     int i,j,k;     i=left;     j=right;     k=arr[left];     if(left>right)         return ;     while(i<j) {         while(arr[j]>k&&i<j)             j--;         if(i<j) {             swap(arr[i],arr[j]);         }         while(arr[i]<k&&i<j)             i++;     }     swap(arr[i],k);     QuickSort2(arr,left,i-1);     QuickSort2(arr,i+1,right); }

/** @r:要排序的数组 @s:排的起点，从0开始 @e:排的终点，从n-1开始 */ void quicksort(int r[1001],int s,int e) {    int t = r[s];//哨兵，为开头的那个    int f = s+1;    int b = e;//f为前向指针，从s+1开始，b为反向指针，从e开始    int m = 0;    if(s>=e)return;//退出条件        while(f<=b)    {        while(f<=b&&r[f]<=t) f++;//在前面找比哨兵大的元素        while(f<=b&&r[b]>=t) b--;//在后面找比哨兵小的元素        //交换这两个元素        if(f<b){             m = r[f];             r[f] = r[b];             r[b] = m;             f++;    b--;        }    }    //交换哨兵和r[b],r[b]肯定要比哨兵小    r[s] = r[b];    r[b] = t;    //排两边的    quicksort(r,s,b-1);    quicksort(r,b+1,e); }  来自  http://www.2cto.com/kf/201109/105097.html

swap写的不好，不是在两个while后直接swap  下面是我修改测试过的 void QuickSort2(int *arr,int left,int right) {     int i,j,k;     i=left; j=right; k=arr[left];     if(left>right) 		return ;     while(i!=j)     { 		while(arr[j]>=k&&i<j) 			j--; 		arr[i] = arr[j];  		while(arr[i]<=k&&i<j) 			i++; 		arr[j] = arr[i];  // 		if(i<j) // 		{ // 			swap(arr[i], arr[j]);      //         }        } 	arr[i] = k;     //swap(arr[i],arr[left]);     QuickSort2(arr,left,i-1);     QuickSort2(arr,i+1,right); 	 }

先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\qsort.c

比如降序排序 快速排序就是每一轮排序后，前一部分 小于 分隔值 后一部分 大于 分隔值，然后再递归对这两部分应用排序，直到所有数据降序为止，所以才有每次找到一对值(> 分隔值, < 分隔值)，就需要把它们交换

为神马 要把循环里面的 i 和 j 的循环 颠倒？


Question: 完全一样的C语言代码，为什么用cin就wa 用scanf就ac。

叫什么名字无所谓吧

cin是C++的东西呀，要求用C语言，怎么可以用cin。。。

引用 1 楼 zhao4zhong1 的回复:乍看起来c++的cin、cout在输入、输出上比c的scanf、printf简单，不用格式控制符！ 但是不用格式控制符，输入输出恰好是你期望的格式的时候好说；等到输入输出不是你期望的格式的时候，你就会觉得还是用格式控制符更方便、更靠谱。 摒弃cin、cout！ 使用scanf、printf。  那您会吗？ 怎么看?

引用 1 楼 zhao4zhong1 的回复:乍看起来c++的cin、cout在输入、输出上比c的scanf、printf简单，不用格式控制符！ 但是不用格式控制符，输入输出恰好是你期望的格式的时候好说；等到输入输出不是你期望的格式的时候，你就会觉得还是用格式控制符更方便、更靠谱。 摒弃cin、cout！ 使用scanf、printf。您的意思是说可能 电脑在cin的时候把输入的数据存为另一种  不是我想要的格式对吧？

楼主,  说好的C语言啊，  cin >>  是C++的好不好！


Question: 求大神指导，Reason: Incompatible library version: 这个咋办？

在线坐等


Question: 有关二维数组的一道OJ题

跟踪调试吧，这个基本功要掌握，很多问题都可以解决的。

更正一下：  //指针作为参数 int biggest(array **p,int m,int n); --> int biggest(array *p,int m,int n); 2维数组传递-> biggest(&a[0][0], m ,n); max1=(*p).data;  //或者  //数组作为参数 int biggest(array p[],int m,int n); biggest(a[0], m ,n); max1=p[0].data;

int biggest(array **p,int m,int n); --> int biggest(array *p,int m,int n); 2维数组传递-> biggest(&a[0][0], m ,n); max1=(*p).data;  //或者 int biggest(array p[],int m,int n); biggest(a[0][0], m ,n); max1=p[0].data;

int biggest(array **p,int m,int n); --> int biggest(array *p,int m,int n); 2维数组传递-> biggest(&a[0], m ,n); max1=(*p).data;  //或者


Question: 在学习递归，计算整数的幂，包括负幂，不知道为什么有错误？求指教

楼主的第二个括号的等号变成了赋值号了

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

pow运算其实可以自底向上运算的 #include <stdio.h>                                                                                class Solution {                                                                        public:                                                                                double pow(double x, int n) {                                                           if (n == 0) {                                                                           return 1.0f;                                                                    }                                                                                bool sign = n < 0;                                                                  unsigned int m = sign ? -n : n;                                                     double ret = 1.0;                                                                   while (m) {                                                                             if (m & 1) {                                                                            ret *= x;                                                                       }                                                                                m >>= 1;                                                                            x *= x;                                                                         }                                                                                return sign ? 1 / ret : ret;                                                    }                                                                           };                                                                                int main()                                                                          {                                                                                Solution s;                                                                         printf("%lf\n", s.pow(1.00000, -2147483648));                                       return 0;                                                                       }

# include <stdio.h> double mi(double x, int y);  int main(void) {     double x;     int p;     scanf("%lf",&x);     scanf("%d",&p);     printf("%lf",mi(x,p));     return 0; }  double mi(double x, int p) {     if (p>0)         return x*mi(x,p-1);     if (p==0)////////////////////////         return 1.0;     if (p<0)         return 1/mi(x,-p); }


Question: 三分贴

如果大家的长度是一样的话，你爱怎么转就怎么转 编译器里默认没定义类型的数据都是int 在32位机器里int是32位的，所以size_t 与 0 比较不会有警告  如果你需要保险一点的方法，就把下面说的类型换一下： INT -> INT_PTR UINT -> UINT_PTR DWORD(ULONG) -> DWORD_PTR(ULONG_PTR)

有没有问题可以在64位系统下试试就知道了~~~

虽然强制类型转换就是干这个的，但还是看了在64位环境下对应汇编指令后我才会彻底放心。  理解和讨论之前请先学会如何观察！  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  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对应的汇编并单步执行观察相应内存和寄存器变化。）


Question: 求助一个问题。困扰我几天了。

谢谢楼上几位的热心回答。我找到问题了。是微软浮点数没初始化的问题。只要在MALLOC下面加上p1->score=0;就可以解决了。   http://blog.163.com/tab_98/blog/static/119240972012102404641288/ 这篇文章有介绍。哎~~~终于解决了。好几次被这个问题搞得抓狂。

typedef struct st { 	int num; 	float score; 	struct st *next;  }stu;  #define LEN sizeof(stu)  int _tmain(int argc, _TCHAR* argv[]) { 	 	stu *p1; 	p1=(stu*)malloc(LEN); 	scanf("%d%f",&p1->num,&p1->score); 	return 0; } 这样再错就见鬼了， 你那样不报错就简直是。。。 struct * next; 这是啥

拿VC6试了一下，确实如楼主所说 但在我的MinGW上直接编译报错，怀疑 struct *next; 这种写法只有VC支持，不过这应该不是问题所在 但是MinGW上编译通过后，运行没有任何错误，猜测还是VC6的问题

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

楼主想做个学生类的链表吧。VC6有些地方做得不太好，毕竟有点老了。是不是要clean一下。

引用 1 楼 zjjsfny 的回复:我是楼主。但现在问题是主要把&p1->score前面的&去掉。运行一遍。然后再加上&再运行就正常了。到底是怎么回事。两次操作后。最终代码和之前出错是一样的。为什么这样一操作就行了呢。我要郁闷死了。 有可能前面编译器抽了，重新build一下后就好了。

代码编译不过需要 修改为 typedef struct stu  { int num; float score; struct stu *next; }stu; 没发现有什么问题

我试了试一切正常呀，不过我用的VS2010不知道有没有关系。

typedef struct  { 	int num; 	float score; 	struct stu *next; }stu; 试试这样呢


Question: 求助：如何获取标签地址 C或者汇编都行

仅供参考#include <stdio.h> int main() {     void *p1,*p2;     __asm {         mov p1,offset LAB         lea eax,LAB         mov p2,eax     }     printf("p1==%p,p2==%p\n",p1,p2); LAB:     return 0; }

GNU  扩展可以 &&label ... ARMCC 应该不支持.. 你在ARM的CPU上跑 X86指令这都算啥事啊..

有啊 int main() {   void *p   __asm mov p offset LAB LAB:   return 0; }  但是上面的嵌入ADS就会报错，提示没有offset,,所有想问一下子ARM平台怎么实现上面的操作

有啊 int main() {   void *p   __asm p offset LAB LAB:   return 0; }  但是上面的嵌入ADS就会报错，提示没有offset,,所有想问一下子ARM平台怎么实现上面的操作

ARM没嵌入汇编？

我以为 offset 伪指令可以通用，所以想问一下在ARM下如何实现，我用的是ADS编译器，不支持GCC


Question: 我想在C语言中建立一个数组，这个数组中每一个格子  都存放一个数组  求解怎么写？

typedef char str[NAME_MAX + 1]; str array[12];


Question: c/c++ 递归 栈溢出问题，请教各位

不减就会无限递归下去，当然会溢出了。


Question: 这2张指针内存分配的示意图可能是哪本书里的？

引用 8 楼 wangjun403 的回复:年前买的  图灵程序设计丛书：深入理解C指针  http://item.jd.com/11412004.html 答案被你公布了 我迟早也要公布的，我是想看看还有其它哪些经典的C语言的书里有类似的图解的，以证明这本书的内容是否有包含在其它一本讲解C语言的书里的。

再看看。。

到百度贴吧问一下吧，那里小白多，看过你这本书的应该还有些记忆。而且那里图片不用点击进来就能看见。

引用 4 楼 u010165006 的回复:[quote=引用 3 楼 nadleeh123 的回复:] [quote=引用 楼主 u010165006 的回复:] 《C Primer Plus》有这样的图吗？  这样子也不好,变种形似有可能又不认识了,老实看《C Primer Plus》 另外关于内存, 堆栈, 寻址这些玩意儿,要想真正搞清楚,还得玩玩汇编,而且是不止一种体系结构的汇编.[/quote] 《C Primer Plus》有这样的图吗？[/quote] 貌似真没见过老外的书有这样的图，把一段函数的指令空间 和栈空间一个一个挨着给你标出来。

引用 3 楼 nadleeh123 的回复:[quote=引用 楼主 u010165006 的回复:] 《C Primer Plus》有这样的图吗？  这样子也不好,变种形似有可能又不认识了,老实看《C Primer Plus》 另外关于内存, 堆栈, 寻址这些玩意儿,要想真正搞清楚,还得玩玩汇编,而且是不止一种体系结构的汇编.[/quote] 《C Primer Plus》有这样的图吗？

引用 楼主 u010165006 的回复:  《C Primer Plus》有这样的图吗？  这样子也不好,变种形似有可能又不认识了,老实看《C Primer Plus》 另外关于内存, 堆栈, 寻址这些玩意儿,要想真正搞清楚,还得玩玩汇编,而且是不止一种体系结构的汇编.

干啥执着于这两张图，  反正谭浩强的书里没有。

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


Question: 本人刚入门，求解

很有意思啊引用 6 楼 zhao4zhong1 的回复:Finding prime numbers - Kenneth Haugland Different schemas for finding prime numbers explained with code http://www.codeproject.com/Articles/429694/Finding-prime-numbers

引用 5 楼 Data_Flow 的回复:2是素数吧=-O 输出3-100间所有的素数

2是素数吧=-O

类似的这些问题，建议楼主自己按照数学原理来写代码，这样能更深入的理解。 刚入门，看别人的代码，个人觉的不是很好，可以参考思路。 素数即为除了1和它本身以外任何数都不能整除他的数 那么我们就能判断2不是素数 3是素数，因为3/1 = 3（整除） 3/3=1(整除) 3/2=1.5（不能整除） 4不是素数，因为除了1和4之外，4还能被2整除。 那么根据这个思路，代码就可以这样写  int main(void) int num = 4; int i = 2; while(i < num) {  if ((num %  i) == 0)  {       printf("%d不是素数!\n",num);       break; }  }

这个网上很好找 参考一下吧——http://blog.csdn.net/u012421456/article/details/19074525

一个比较快的方法叫筛法 #include <iostream> #include <cmath> #define Ni 10000000 using namespace std; int prime[Ni]; bool vis[Ni]; int Prime(int n)//筛法构造1～n的素数表(反回有多少个素数) {     int i,j,c=0;     memset(vis,0,sizeof(vis));     for(i=2;i<=n;i++) if(!vis[i])     {         prime[c++]=i;         for(j=i*i;j<=n;j+=i) vis[j]=1;     }     return c; } int main() {     int i,n,m;     cin>>n;     m=Prime(n);     for(i=0;i<m;i++)     {         cout<<prime[i]<<' ';     }     cout<<endl; }

搜索，素数的检测方法。


Question: 求高手解答，这个题有什么规律吗，时间限制解决不了

引用 4 楼 zjq9931 的回复:引用 3 楼 lyglovezyl 的回复:[quote=引用 1 楼 zjq9931 的回复:] n-1的连加。能给一个具体公式吗 仔细看了一下，是我想简单了。这个题目应当是考空间换时间的题。 就是先把结果存起来。然后，输入数字的时候找结果就可以了。 就是先在自己的机器上求出结果。然后把结果放到代码里面，然后查表就好。[/quote]我的代码还是时间超限 #include <stdio.h> #include <stdlib.h> #define N 10000000 long long m[1000001]; int main(int argc,const char*argv[]) { int* phi; int i,j,n,k; char* prime; prime=(char*)malloc((N+1)*sizeof(char));  prime[0]=prime[1]=0;  for(i=2;i<=N;i++)  prime[i]=1;  for(i=2;i*i<=N;i++)  if(prime[i])  for(j=i*i;j<=N;j+=i)  prime[j]=0;  //这段求出了N内的所有素数  phi=(int*)malloc((N+1)*sizeof(int));  for(i=1;i<=N;i++)  phi[i]=i;  for(i=2;i<=N;i++)  if(prime[i]) for(j=i;j<=N;j+=i) phi[j]=phi[j]/i*(i-1);//此处注意先/i再*（i-1)，否则范围较大时会溢出   for(k=2;k<=1000000;k++)   {       m[1]=0,m[2]=1;       m[k]=m[k-1]+phi[k];   } while(scanf("%d",&n)!=EOF&&n!=0) {       printf("%lld\n",m[n]); } return 0; } 用欧拉函数的思想做的

引用 5 楼 lyglovezyl 的回复:引用 4 楼 zjq9931 的回复:[quote=引用 3 楼 lyglovezyl 的回复:] [quote=引用 1 楼 zjq9931 的回复:] n-1的连加。能给一个具体公式吗 仔细看了一下，是我想简单了。这个题目应当是考空间换时间的题。 就是先把结果存起来。然后，输入数字的时候找结果就可以了。 就是先在自己的机器上求出结果。然后把结果放到代码里面，然后查表就好。[/quote]我的代码还是时间超限 #include <stdio.h> #include <stdlib.h> #define N 10000000 long long m[1000001]; int main(int argc,const char*argv[]) { int* phi; int i,j,n,k; char* prime; prime=(char*)malloc((N+1)*sizeof(char));  prime[0]=prime[1]=0;  for(i=2;i<=N;i++)  prime[i]=1;  for(i=2;i*i<=N;i++)  if(prime[i])  for(j=i*i;j<=N;j+=i)  prime[j]=0;  //这段求出了N内的所有素数  phi=(int*)malloc((N+1)*sizeof(int));  for(i=1;i<=N;i++)  phi[i]=i;  for(i=2;i<=N;i++)  if(prime[i]) for(j=i;j<=N;j+=i) phi[j]=phi[j]/i*(i-1);//此处注意先/i再*（i-1)，否则范围较大时会溢出   for(k=2;k<=1000000;k++)   {       m[1]=0,m[2]=1;       m[k]=m[k-1]+phi[k];   } while(scanf("%d",&n)!=EOF&&n!=0) {       printf("%lld\n",m[n]); } return 0; } 用欧拉函数的思想做的[/quote] 大数的计算量太大，肯定是空间换时间了。因为内存限制很大。完全可以存起来，用的时候查表就好了。

引用 1 楼 zjq9931 的回复:n-1的连加。能给一个具体公式吗

引用 3 楼 lyglovezyl 的回复:引用 1 楼 zjq9931 的回复:n-1的连加。能给一个具体公式吗 仔细看了一下，是我想简单了。这个题目应当是考空间换时间的题。 就是先把结果存起来。然后，输入数字的时候找结果就可以了。 就是先在自己的机器上求出结果。然后把结果放到代码里面，然后查表就好。

加上欧拉数吧

n-1的连加。


Question: MATLAB怎么仿真博弈

得自己写。不过可以搜索一下别人提供下载的代码，或者使用专门的博弈仿真工具，国外有些小工具、小软件，具体叫啥忘了。


Question: 求助:两程序调用但不等待执行的问题

winexec？ 执行A的时候有没有时间长度限制，如果A还没有运行完毕也关闭？


Question: 世界最快的排序算法之一

引用 1 楼 zouzhipeng1717 的回复:时间复杂度越低，代码越多~ 话不是这么说 一般会跟空间复杂度对立

时间复杂度越低，代码越多~


Question: C内存问题，求教育。

指针就是整数，怎么打都行。但是这于这个整数很大，所以用十六进制来打最适用。  printf("%08X",  p); printf("%u", p);   用%d不好，因为这样会打印成负数，不直观。 http://www.afanihao.cn/c_guide/ ，第3章  引用 14 楼 ovoovo 的回复:打印指针用%p

我很欣赏你这个抓细节的严谨态度，赞一个～！  你自己看看我给你的这个反汇编的结果：   栈里不是先进后出吗，怎么char 和int 的存储不是相间，而是分类存储，并且z存储在a前面？ 这个，是没问题的，你看图，以及我做的标记就知道了。  至于为什么不是相间排列的，这个是编译器的原因： 你可以写代码看下，一般情况VC6编译器输出的sizeof(int)=4, sizeof(char)=1，在32位处理器上，数据32位对齐时候处理器性能最佳，编译器便优化了变量排列方式，使之对其。  还有，给你点建议，变量地址一般用16进制无符号整型形式表示，例如printf( "%#X", &a );

自己反汇编，瞅瞅

不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);或者cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。

编译器优化了吧

这四个变量在函数内并非是连续排列的，如果你是在结构体中定义这四个变量，更具研究意义

引用 17 楼 u010572380 的回复:输出地址为什么用%d呢，应该用%p不是么 本来在printf已经指定了输出的是地址&a，如果此时用p%，输出的是保存&a这个地址的地址了。

地址都是无符号数，输出的地址都成了有符号数了，把%d改为%u，再分析内存分配。

引用 5 楼 czarten 的回复:栈是先进后出没错 问题是没有人规定先定义的变量就要先进栈 引用 8 楼 user-17 的回复:局部变量是在调用栈上，但是没有什么进出的关系，参数才是按顺序进栈出栈 理论上局部变量的顺序由编译器决定  正解，另外建议楼主用%p来显示指针指向的地址

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

VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533

打印指针用%p

引用 12 楼 paschen 的回复:[quote=引用 5 楼 czarten 的回复:] 栈是先进后出没错 问题是没有人规定先定义的变量就要先进栈 引用 8 楼 user-17 的回复:局部变量是在调用栈上，但是没有什么进出的关系，参数才是按顺序进栈出栈 理论上局部变量的顺序由编译器决定  正解，另外建议楼主用%p来显示指针指向的地址[/quote] 乱七八糟。 你可以说“指针的内容”，或者指针指向的类型，或者指针指向的对象或者函数，指针能指向地址，不伦不类闻所未闻。

输出地址为什么用%d呢，应该用%p不是么

你要输出内存的地址应该用％ｐ而不是％ｄ

引用 1 楼 u010820228 的回复:ubuntu 14.04 系统。 c没有明确规定变量的入栈顺序 对于int a； int b； char c； . . . unsigned int x; 这种代码，没有必要非要遵守某种顺序，反而某些特苏体系结构的cpu（mips）对与非（4B）对齐内存地址的访问有额外开销，编译器为了降低这种开销发生的次数，入栈顺序的确会发生改变，比如你的b和z会放到一起去，这样只有1次，如果按你代码顺序的话就有3次

栈是先进后出没错 问题是没有人规定先定义的变量就要先进栈

首先，变量申请后，操作系统会给这个变量分配空间（随机选择内存区域进行优化存放），栈是先进后出，只是这个程序里面没有用到而已


Question: CreateEvent 和CreateMutex的区别

假如我有1个数据接收线程，10个数据处理线程，1个缓冲区，1个同步对象。 当缓冲区为空时，10个数据处理线程均WaitForSingleObject一个同步对象，阻塞住，等待数据接收线程接收到数据并写入到缓冲区后，数据接收线程通过改变同步对象的状态，让10个数据处理线程同时放行，并发地计算、处理缓冲区中的数据。那么这个同步对象，用Mutex还是Event好？如果用Mutex的话，数据接收线程ReleaseMutex，此时10个WaitForSingleObject的线程，只会放行一个，不会同时放行10个。而如果用一个手工重置的Event，可以很简单的实现这一点。 总之Mutex和Event，从字面上看已经很明白了，一个侧重于“互斥”，即多个线程互斥地访问同一个变量、资源。另外一个侧重于“事件”，即通过对Event对象设置“有信号”还是“无信号”，来通知其它线程。

Event侧重事件是否发生 Mutex侧重唯一性

Event和Mutex是完全不同的用来做线程同步的概念, 你查查资料

《Windows核心编程》


Question: 如何让一个DLL随目录下的exe文件启动

都是NB人物啊，这里真是卧虎藏龙。。。。。搞得我的不会分配可用分了。。

看 exe 写的时候 load 的 dll 是什么名字，把 dll 改为相应的名字。。。

在我的认知里，替换库是一个很麻烦的事情。 1.第一个你必须弄清楚的是，原库的导出函数列表。如果这个库还包含有导出类（比如COM）之类的东西，我觉得还是放弃吧。 导出函数名很好得到，但函数参数就稍微有点费劲。  2.对库进行修改时，在我的认知里，大约有两种方式：1）直接在二进制代码上动手，这要求你对汇编甚至机器语言比较熟悉，有比较强的逆向能力，对文件结构也很清楚，并且不适合大幅度修改；2）将原DLL改名，新建一个与原DLL同名的DLL，在新的DLL重建导出函数列表：对于不需要动的地方，直接调用原DLL对应的函数。  3.对于你的问题，你确定a.exe中会加载b.dll吗？如果不确定这一点，建议还是用全局钩子之类的东西，来对a.exe的进程进行监控。

你说的这个技术叫dll劫持.   这个技术得以实现, 是因为一个exe的运行肯定会依赖很多dll, 而exe自己只是根据名字加载dll, 并不知道这个dll是否被修改过. 所以你完全可以自己写一个同名的dll覆盖掉原来的dll  (前题是有相同的导出函数), 这样程序加载时, 就会调用你自己的dll了.  外挂可能hook掉socket通信的dll, 甚至有些外挂为了多开, 还会hook掉 d3d相关的dll来减少资源加载.  至于你的场景,  因为exe已经固定,  那么它会加载的dll也是固定的.  你要想能加载你的dll, 那么你就需要知道这个exe加载了哪些dll, 有哪些dll你可以实现并修改, 这样才有可能你把自己的b.dll加载到a.exe中去.

1. 找一个exe调用的DLL，放到一个同名的DLL（自己的）在目录下即可。（这种最简单） 2. 修改PE的导入表，增加一个自己DLL的函数调用。（找工具即可） 3. 在A.EXe加个壳，类似于detour，运行时注入dll （需要自己编码）

引用 1 楼 jiangsheng 的回复:取决于人家代码怎么写的 LoadLibrary("WSOCK.DLL")_//在当前搜索路径查找并加载 LoadLibraryEx("WSOCK.DLL",LOAD_LIBRARY_SEARCH_SYSTEM32)_//在系统目录查找加载 清单里加了WinSxS的会去先找WinSxS  你回答过我3个问题，其中一个还是在msdn回答的，那时候我就在想为什么你这么nb。

引用 1 楼 jiangsheng 的回复:取决于人家代码怎么写的 LoadLibrary("WSOCK.DLL")_//在当前搜索路径查找并加载 LoadLibraryEx("WSOCK.DLL",LOAD_LIBRARY_SEARCH_SYSTEM32)_//在系统目录查找加载 清单里加了WinSxS的会去先找WinSxS 是不是说知道名字，把楼主写的动态库改成对应的名字，然后放到程序路径或系统路径中，就可以了？ 如果两个路径都放动态库，那肯定是用新的动态库么？


Question: goto语句

编译通不过，有什么提示吗

引用 楼主 cheng401733277 的回复:下面是一条普通的跳转语句：   ...... goto label; ...... lable: ......   相信大家都使用过，但标签地址，相信就不是很多人都用过了。 什么是标签地址，说简单了就是标签的地址，标签也有地址的。而获得标签的地址就要使用&&符号获得，并且这个地址要存储在一个空(void)类型的指针中。下面举一个例子来说明如果使用标签地址： [cpp] view plaincopyprint? /* gotoaddr.c */   #include <stdio.h>   #include <time.h>   int main(int argc,char *argv[])   {       void *target;       time_t now;       now = time((time_t *)NULL);       if(now & 0x0001)           target = &&oddtag;       else           target = &&eventag;       goto *target;   eventag:       printf("The time value %ld is even/n",now);       return(0);   oddtag:       printf("The time value %ld is odd/n",now);       return(0);   }     编译：gcc gotoaddr.c 执行：./a.out 我机子上的输出是这样的： The time value 1264225490 is even   在上面的代码中，我们可以看到用时间来获得一个随机数now，然后根据now值的奇偶性来跳转到不同的地方。 上面的例子是一种使用标签地址的普通用法，我们还可以把标签地址存入数组中，然后根据数组索引的不同跳转到不同的地方，如下： [cpp] view plaincopyprint? void *loc[] = { &&label1, &&label2, &&label3, &&label4 };       . . .   goto *loc[i];     标签地址可以让我们更灵活的使用跳转语句 ：） 上面的是在别人博客里面看到的，他用的是GCC,但是我弄到VC上编译不通过，想问一下如果在VC上怎么实现上面的灵活跳转？ 有goto干嘛不用goto,linux内核源码那么多goto也没说出现你们所谓的问题,关键还是看人.

goto引用一个大家的话：C语言中的贱民。。。

不知道..........  不过楼主，这种技术即使可行，也没必要，数学上已经证明了c语言去掉goto的完备性了～～换句话说，c语言可以用其他关键字来实现goto    所以建议楼主无需纠结这类技术

跟直接goto 标签有什么区别？

有些可能是GCC的扩展功能，或者VS没实现这个标准功能。  没事就不要用goto，即使你完全掌握了goto，能确保自己写出的代码完全没有问题，但换个人来维护你的代码，谁能保证那人也是goto大师。

再古灵精怪的goto语句和标签地址、标签地址数组、……也比不上嵌入汇编。

在古灵精怪的goto语句和标签地址、标签地址数组、……也比不上嵌入汇编。


Question: C语言定时器问题

引用 2 楼 lineage191 的回复:SetTimer(1,1000,NULL); 不要加：：作用域，这是调用全局的函数，而你的回调函数是null肯定不响应 此处要如上调用CWnd下的对应函数，当回调函数填null时，wm_timer消息会产生，从而调用对应的OnTimer响应函数 没看明白不加::的原因

引用 4 楼 michael2988 的回复:你在消息映射的地方有没有加 ON_WM_TIMER()   BEGIN_MESSAGE_MAP(CDlgFastApproachCTR, CDialog)     ON_WM_TIMER() END_MESSAGE_MAP() 就是你说的这个原因，实在是太感谢了！

引用 2 楼 lineage191 的回复:SetTimer(1,1000,NULL); 不要加：：作用域，这是调用全局的函数，而你的回调函数是null肯定不响应 此处要如上调用CWnd下的对应函数，当回调函数填null时，wm_timer消息会产生，从而调用对应的OnTimer响应函数发帖之前我就试过SetTimer(1,1000,null)了，发现还是没有调用

引用 1 楼 user-4 的回复:在你的按钮中设置的定时器事件并没有设置timer procedure。看下win32的SetTimer函数。你说的是什么意思？ 不太明白


Question: [问题求助] vc++6.0问题，高手进！

关于vc++6.0的工作组怎么弄成图片这样子？ 答：遇到微软的工具，请多用鼠标点点，这是不变的真理。  比如我手中有高一凡的数据结构源码，分别有.c、cpp、.h的文件怎么把他们关联起来进行编译运行呢？ 答：用鼠标点点看，或者问高一凡。

别说你是学编程的人

导入呀- -

但鄙人对VC 6这种垃圾不了解，哈哈哈引用 2 楼 sholber 的回复:应邀前来回复，但鄙人对VC 6这种垃圾不了解。

vc6不死的神话

引用 1 楼 zhao4zhong1 的回复:文件、新建、工程、Win32 Console Application、工程：003 确定、…… 在Source Files上点鼠标右键、添加.c和.cpp 在不需要的.c或.cpp上点鼠标左键、按Del键删除 在Header Files上点鼠标右键、添加.h  偶然看到vc6的问题，已经很久没搞过了。来怀念一下~~

实在→是在

引用 2 楼 sholber 的回复:应邀前来回复，但鄙人对VC 6这种垃圾不了解。 关键是此“鄙人”实在VC6诞生之后生的。

应邀前来回复，但鄙人对VC 6这种垃圾不了解。


Question: 求帮助！！！

楼上正解，楼主的代码统计的是所有人所有学科不低于平均分的总科数。

for(i = 0;i < n; i ++)         {             flag = 1;             for(j = 0;j < m; j ++)             {                 if(a[i][j] < aver2[j])                 {                     flag = 0;                     break;                 }             if(flag)                 cnt ++;             }         } 大括号换个位置试试看 for(i = 0;i < n; i ++)         {             flag = 1;             for(j = 0;j < m; j ++)             {                 if(a[i][j] < aver2[j])                 {                     flag = 0;                     break;                 }            }             if(flag)                 cnt ++;         }


Question: C语言编写PDF输出中文的一些问题

CID (Character identifier)就是字符识别码，在组成方式上分成CIDFont，CMap表两部分。CIDFont文件即总字符集，包括了一种特定语言中所有常用的字符，把这些字符排序，它们在总字符集中排列的次序号就是各个字符的CID标识码(Index)；CMap(Character Map)表即字符映射文件，将字符的编码(Code)映射到字符的CID标识码(Index)。CID字库完全针对大字符集市场设计，其基本过程为：先根据Code，在CMap表查到Index，然后在CIDFont文件找到相应的字形数据。


Question: 类似01背包问题，求最优解决方案

贴个动规的，如果想求所有最优解用回溯也可以啊  #include <stdio.h>                                                               #include <stdlib.h>                                                                                int knapsack(int num, int capacity, int *weight_arr, int *value_arr, int *is_picked) {                                                                                int i = 0;                                                                       int j = 0;                                                                       int **array = (int **)calloc(num + 1, sizeof(int *));                            int **prev_capacity = (int **)calloc(num + 1, sizeof(int *));                    i = 0;                                                                           for (; i < num + 1; ++i) {                                                           array[i] = (int *)calloc(capacity + 1, sizeof(int));                             prev_capacity[i] = (int *)calloc(capacity + 1, sizeof(int));                 }                                                                                i = 1;                                                                           for (; i < num + 1; ++i) {                                                           j = 1;                                                                           for (; j < capacity + 1; ++j) {                                                      if (weight_arr[i - 1] > j) {                                                         array[i][j] = array[i - 1][j];                                                   prev_capacity[i][j] = j;                                                     } else {                                                                             if (array[i - 1][j] > array[i - 1][j - weight_arr[i - 1]] + value_arr[i - 1]) {                     array[i][j] = array[i - 1][j];                                                   prev_capacity[i][j] = j;                                                     } else {                                                                             array[i][j] = array[i - 1][j - weight_arr[i - 1]] + value_arr[i - 1];                     prev_capacity[i][j] = j - weight_arr[i - 1];                                 }                                                                            }                                                                            }                                                                            }                                                                                i = num;                                                                         j = capacity;                                                                    for (; i > 0; --i) {                                                                 if (prev_capacity[i][j] != j) {                                                      is_picked[i - 1] = 1;                                                            j = prev_capacity[i][j];                                                     }                                                                            }                                                                                int ret = array[num][capacity];                                                  i = 0;                                                                           for (; i < num + 1; ++i) {                                                           free(array[i]);                                                                  free(prev_capacity[i]);                                                      }                                                                                free(array);                                                                     free(prev_capacity);                                                             return ret;                                                                  }                                                                                int main()                                                                       {                                                                                int capacity = 10;                                                               int num = 6;                                                                     int weight_arr[] = {2, 3, 1, 4, 6, 5};                                           int value_arr[] = {5, 6, 5, 1, 19, 7};                                           int *is_picked = (int *)calloc(num, sizeof(int));                                                                                int i = 0;                                                                       printf("<<<<<input<<<<<\n");                                                     for (; i < num; ++i) {                                                               printf("%d:weight=%d value=%d\n", i, weight_arr[i], value_arr[i]);           }                                                                                printf(">>>>>\n");                                                               printf("max weight:%d\n", capacity);                                                                                int ret = knapsack(num, capacity, weight_arr, value_arr, is_picked);             i = 0;                                                                           printf("<<<<<output<<<<<\n");                                                    for (; i < num; ++i) {                                                               if (is_picked[i] == 1) {                                                             printf("%d:weight=%d value=%d\n", i, weight_arr[i], value_arr[i]);           }                                                                            }                                                                                printf(">>>>>\n");                                                               printf("max value:%d\n", ret);                                                                                free(is_picked);                                                                 return 0;                                                                    }

怎么算最优方案没定义？

就是啊，什么算最优 我们以前将01背包时用的就是动态规划算法


Question: 急！c读取视频数据时如何跳过包头并另存为文件？

读完    AOS_UINT16  uLen;   // the data package length, the data len must less than 65535. 后，需要跳过后面的     AOS_UINT16  uMilliSecond; // the data reveived time offset in second, in millisecond     AOS_TIME_T  uSeconds 继续读数据  因为AOS_UINT16肯定占2字节 AOS_TIME_T假定占SIZEOF_AOS_TIME_T字节 所以共需要跳过2+SIZEOF_AOS_TIME_T个字节。

楼主可以尝试： 题中： 1、zxel 为包头标识，当读取到的 zxel 时被认为是一个数据包的开始。 2、跳过包头部分（sizeof(PACKAGE_HEAD)），读取数据到另一个文件中。 3、从图1，可以以zxel 为结束或者说是下一次读取的开始，同时可以写入特殊字符作为视频数据部分的分割符。 直至读取结束...

可能描述上不是很清楚，画个图可能会更明白点 原始数据如图1，最终需要的结果如图中2所示，可以根据包头里的ulen确定这个包的大小，每个包的结构都是完整的且没有垃圾数据。把最后读到的数据再保存到一个新的文件即可。

引用 8 楼 duoduodxyyy 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 不一定对，仅供参考： #include <stdio.h> #include <string.h> #if 0 /**包头的标识**/ #define SFUNIT_PACKAGE_HEAD htonl(('z' << 24 ) | ('x' << 16) | ('e' << 8) | ('l'))  //zxel   /**构造数据包头**/     stPackHead.uKey          = SFUNIT_PACKAGE_HEAD;     stPackHead.uLen          = (AOS_UINT16)ulDataBufferLen;     stPackHead.uMilliSecond  = (AOS_UINT16)(pstRcvTime->tv_usec / 1000);     stPackHead.uSeconds.time = pstRcvTime->tv_sec;   /**包的结构**/ typedef struct _PACKAGE_HEAD_ {     AOS_UINT32  uKey;   // before each data package, is a magic words, should be SFUNIT_PACKAGE_HEAD     AOS_UINT16  uLen;   // the data package length, the data len must less than 65535.     AOS_UINT16  uMilliSecond; // the data reveived time offset in second, in millisecond     AOS_TIME_T  uSeconds;     // the data reveived time, it is a absult time, in second }PACKAGE_HEAD; #endif #define SIZEOF_AOS_TIME_T 2 //假定AOS_TIME_T类型占用16位即2字节 char s[5]; int c; unsigned short uLen; int i,offset; FILE *fi,*fo; int main(int argc,char **argv) {     if (argc<3) {         printf("%s inputfile outputfile\n",argv[0]);         return 1;     }     fi=fopen(argv[1],"rb");     if (NULL==fi) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     fo=fopen(argv[2],"wb");     if (NULL==fo) {         fclose(fi);         printf("Can not create file [%s]!\n",argv[2]);         return 3;     }     s[4]=0;     while (1) {         c=fgetc(fi);         if (EOF==c) break;         s[0]=c;         c=fgetc(fi);         if (EOF==c) break;         s[1]=c;         c=fgetc(fi);         if (EOF==c) break;         s[2]=c;         c=fgetc(fi);         if (EOF==c) break;         s[3]=c;         if (0==strcmp(s,"zxel")) {             if (1!=fread(&uLen,2,1,fi)) break;             fseek(fi,2+SIZEOF_AOS_TIME_T,SEEK_CUR);             for (i=0;i<uLen;i++) {                 c=fgetc(fi);                 if (EOF==c) break;                 fputc(c,fo);             }             if (EOF==c) break;         } else {             offset=ftell(fi);             printf("Format Error at file [%s] offset %09d(0x%08x),Expect 'zxel' but '%s'!",argv[1],offset,offset,s);             break;         }     }     fclose(fo);     fclose(fi);     return 0; }  您好，还想问下您，#define SIZEOF_AOS_TIME_T 2    这个#define 是什么意思?在fseek的偏移量中也有加这个值，不太明白，能否讲解下？很感谢！[/quote]不好意思，可能我问的有歧义，本意是想问为什么会加上：SIZEOF_AOS_TIME_T  ，在fseek的时候:2+SIZEOF_AOS_TIME_T ，这个地方也不太明白.....

就是我猜想在你系统环境下AOS_TIME_T这个数据类型大概是占16位即2个字节的。 如果实际上不是，比如是32位即4个字节的话，只要修改 #define SIZEOF_AOS_TIME_T 2 为 #define SIZEOF_AOS_TIME_T 4 再重新编译链接即可。

引用 7 楼 zhao4zhong1 的回复:不一定对，仅供参考： #include <stdio.h> #include <string.h> #if 0 /**包头的标识**/ #define SFUNIT_PACKAGE_HEAD htonl(('z' << 24 ) | ('x' << 16) | ('e' << 8) | ('l'))  //zxel   /**构造数据包头**/     stPackHead.uKey          = SFUNIT_PACKAGE_HEAD;     stPackHead.uLen          = (AOS_UINT16)ulDataBufferLen;     stPackHead.uMilliSecond  = (AOS_UINT16)(pstRcvTime->tv_usec / 1000);     stPackHead.uSeconds.time = pstRcvTime->tv_sec;   /**包的结构**/ typedef struct _PACKAGE_HEAD_ {     AOS_UINT32  uKey;   // before each data package, is a magic words, should be SFUNIT_PACKAGE_HEAD     AOS_UINT16  uLen;   // the data package length, the data len must less than 65535.     AOS_UINT16  uMilliSecond; // the data reveived time offset in second, in millisecond     AOS_TIME_T  uSeconds;     // the data reveived time, it is a absult time, in second }PACKAGE_HEAD; #endif #define SIZEOF_AOS_TIME_T 2 //假定AOS_TIME_T类型占用16位即2字节 char s[5]; int c; unsigned short uLen; int i,offset; FILE *fi,*fo; int main(int argc,char **argv) {     if (argc<3) {         printf("%s inputfile outputfile\n",argv[0]);         return 1;     }     fi=fopen(argv[1],"rb");     if (NULL==fi) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     fo=fopen(argv[2],"wb");     if (NULL==fo) {         fclose(fi);         printf("Can not create file [%s]!\n",argv[2]);         return 3;     }     s[4]=0;     while (1) {         c=fgetc(fi);         if (EOF==c) break;         s[0]=c;         c=fgetc(fi);         if (EOF==c) break;         s[1]=c;         c=fgetc(fi);         if (EOF==c) break;         s[2]=c;         c=fgetc(fi);         if (EOF==c) break;         s[3]=c;         if (0==strcmp(s,"zxel")) {             if (1!=fread(&uLen,2,1,fi)) break;             fseek(fi,2+SIZEOF_AOS_TIME_T,SEEK_CUR);             for (i=0;i<uLen;i++) {                 c=fgetc(fi);                 if (EOF==c) break;                 fputc(c,fo);             }             if (EOF==c) break;         } else {             offset=ftell(fi);             printf("Format Error at file [%s] offset %09d(0x%08x),Expect 'zxel' but '%s'!",argv[1],offset,offset,s);             break;         }     }     fclose(fo);     fclose(fi);     return 0; }  您好，还想问下您，#define SIZEOF_AOS_TIME_T 2    这个#define 是什么意思?在fseek的偏移量中也有加这个值，不太明白，能否讲解下？很感谢！

引用 3 楼 duoduodxyyy 的回复:[quote=引用 楼主 duoduodxyyy 的回复:] 求代码实现：   数据data中包含不定数量的数据包，每个数据包里存的都是视频数据，现在需要读取data中数据的过程时跳过PACKAGE_HEAD，读取完毕以后把跳过PACKAGE_HEAD的纯视频数据另存为一个(纯码流的)文件中,读取数据的过程中只要遇到 zxel 就认为是读到一个包头。    /**包头的标识**/ #define SFUNIT_PACKAGE_HEAD htonl(('z' << 24 ) | ('x' << 16) | ('e' << 8) | ('l'))  zxel   /**构造数据包头**/     stPackHead.uKey          = SFUNIT_PACKAGE_HEAD;     stPackHead.uLen          = (AOS_UINT16)ulDataBufferLen;     stPackHead.uMilliSecond  = (AOS_UINT16)(pstRcvTime->tv_usec / 1000);     stPackHead.uSeconds.time = pstRcvTime->tv_sec;   /**包的结构**/ typedef struct _PACKAGE_HEAD_ {     AOS_UINT32  uKey;   // before each data package, is a magic words, should be SFUNIT_PACKAGE_HEAD     AOS_UINT16  uLen;   // the data package length, the data len must less than 65535.     AOS_UINT16  uMilliSecond; // the data reveived time offset in second, in millisecond     AOS_TIME_T  uSeconds;     // the data reveived time, it is a absult time, in second }PACKAGE_HEAD; 引用 1 楼 zjq9931 的回复:fseek 就可以了啊。能给个具体实现么？之前尝试过最后得到的数据总是不对。谢谢！上面回复的表情不知道怎么加进去了，是没有那个表情的。[/quote] 其实我也不太明白你说的情况，但是你都把条件列出来了，按道理不应当分不清数据啊。 你的问题是什么？有没有跟踪调试？ 绝大多数问题，跟踪调试都能找到根源的。

引用 楼主 duoduodxyyy 的回复:求代码实现：   数据data中包含不定数量的数据包，每个数据包里存的都是视频数据，现在需要读取data中数据的过程时跳过PACKAGE_HEAD，读取完毕以后把跳过PACKAGE_HEAD的纯视频数据另存为一个(纯码流的)文件中,读取数据的过程中只要遇到 zxel 就认为是读到一个包头。    /**包头的标识**/ #define SFUNIT_PACKAGE_HEAD htonl(('z' << 24 ) | ('x' << 16) | ('e' << 8) | ('l'))  zxel   /**构造数据包头**/     stPackHead.uKey          = SFUNIT_PACKAGE_HEAD;     stPackHead.uLen          = (AOS_UINT16)ulDataBufferLen;     stPackHead.uMilliSecond  = (AOS_UINT16)(pstRcvTime->tv_usec / 1000);     stPackHead.uSeconds.time = pstRcvTime->tv_sec;   /**包的结构**/ typedef struct _PACKAGE_HEAD_ {     AOS_UINT32  uKey;   // before each data package, is a magic words, should be SFUNIT_PACKAGE_HEAD     AOS_UINT16  uLen;   // the data package length, the data len must less than 65535.     AOS_UINT16  uMilliSecond; // the data reveived time offset in second, in millisecond     AOS_TIME_T  uSeconds;     // the data reveived time, it is a absult time, in second }PACKAGE_HEAD; 引用 1 楼 zjq9931 的回复:fseek 就可以了啊。能给个具体实现么？之前尝试过最后得到的数据总是不对。谢谢！上面回复的表情不知道怎么加进去了，是没有那个表情的。

能给个具体实现么？之前尝试过最后得到的数据总是不对。谢谢！

fseek 就可以了啊。


Question: 关于linux下的C出现Segmentation fault的问题 谢谢！

引用 10 楼 tdvblueness 的回复:折腾半天，原来是磁盘没空间了。。。谢谢各位！ 请检查每个函数的返回值。

引用 7 楼 zhao4zhong1 的回复:楼主实在学不会加载core文件用bt命令看Call Stack的调试方法的话，参考下面：  有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行！ 写日志到文件参考下面： #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <io.h> #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  _vsnprintf         vsnprintf #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     _vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} int main(int argc,char * argv[]) {     int i; #ifdef WIN32     InitializeCriticalSection(&cs_log); #else     pthread_mutex_init(&cs_log,NULL); #endif     for (i=0;i<10000;i++) {         Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);     } #ifdef WIN32     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_log); #endif     return 0; } //1-78行添加到你带main的.c或.cpp的那个文件的最前面 //81-85行添加到你的main函数开头 //89-93行添加到你的main函数结束前 //在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中 好的，我试一下，非常感谢

折腾半天，原来是磁盘没空间了。。。谢谢各位！

再问一下各位，刚才在windows下测试了一下，同样的程序，只是改成了windows的头文件，运行成功，查看了一下linux下的文件属性，-rw-r--r--，应该也是对的，能大致推测一下是什么问题么，程序调试了好几次，windows下没有任何错误

http://blog.csdn.net/haoel/article/details/2879  gdb调试的教程。

产生  段错误 一定是你访问了不存在的内存或使用野指针造成的， 仔细检查你的程序， 光用文字没法说清楚。

引用 2 楼 zhao4zhong1 的回复:进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令 你好，有一个core_pattern的文件，没有“core.数字”类型的文件，需要开启什么吗，linux刚接触，麻烦了

在你的循环中已经打开的文件夹下，还有文件夹吗，  在你打开文件夹的时候有没有避开  “.” ".." 这两个文件夹。。

程序的大致流程是  定义全局变量  while （还有文件） { 调用模块1 写文件1 调用2 写文件2 调用3 写文件3 }


Question: C语言 vc++2010调试内存界面问题

在IDE中打开你的这个.c/.cpp文件的时候，使用WinHex软件在整个内存中搜索“#include "stdafx.h"”

记得有看到过C可以打印出这样的内容 0x000B43A8  00 00 06 00 66 00 65 00 # i c l u d e < s 0x000B43C8  04 00 69 00 79 00 75 00 t i o d . h > 0x000B43E8  74 00 79 00 61 00 62 00  我随便写的，就是像这样格式的，后面显示的是代码

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

引用 2 楼 ruying1389279 的回复:00 00 00 00 00 00 06 00 79 00 61 00 6e 00 76 00 61 00 72 00  ]2..i?..n?..........y.a.n.v.a.r. 0x000B43A8  00 00 06 00 66 00 65 00 76 00 72 00 61 00 6c 00 00 00 05 00 61 00 70 00 72 00 65 00 6c 00 00 00  ....f.e.v.r.a.l.....a.p.r.e.l... 0x000B43C8  04 00 69 00 79 00 75 00 6e 00 00 00 04 00 69 00 79 00 75 00 6c 00 00 00 08 00 73 00 65 00 6e 00  ..i.y.u.n.....i.y.u.l.....s.e.n. 0x000B43E8  74 00 79 00 61 00 62 00 72 00 00 00 07 00 6f 00 6b 00 74 00 79 00 61 00 62 00 72 00 00 00 06 00  t.y.a.b.r.....o.k.t.y.a.b.r.....  n.o.y.a.b.r.....d.e.k.a.b.r.....   ??..??..m{..??..jD..??..??..s{.. ....f.e.v.r.a.l.....a.p.r.e.l...   ..i.y.u.n.....i.y.u.l.....s.e.n.   t.y.a.b.r.....o.k.t.y.a.b.r..... 想知道这些是什么意思?代表的什么   n.o.y.a.b.r.....d.e.k.a.b.r.....  ??..??..m{..??..jD..??..??..s{.. 有的数据有文字意义, 有的本身就不是文字 如果你定义了char *p  "hello world ". 找到p的地址,是可以看到 hello 的world的,

内存界面 右键可以选 ansi或者unicode显示  你说的显示代码的是不是反汇编? 设个断点,停住时, 按下alt+8


Question: C写文件与磁盘缓冲的疑问（小白求教育）

你看到的文件是由fopen产生的，数据变化你要看文件大小

楼上的楼上正解～

那是底层的事情，你想多了  间隔 100ms 算间隔吗？不是你去感受到的间隔，100ms 多少条指令过去了？ 如果我写入一个文件下一条指令是读取怎么办？会出错吗？ 既然有缓冲，你看到文件在磁盘上，那么就一定在磁盘上吗？ 你通过系统看到 D 盘多了一个文件，那也可以是个缓存 所以你自己来设计缓存机制，也不可能是写入进缓存，读取跳过缓存，否则请解决上面那一堆的问题  总之你想多了，思路逻辑上就不对，如果你是硬件/驱动开发的工程师再深入考虑这些

创建文件和写文件不是一回事！


Question: 问个malloc后指针使用的问题

够大就直接用，不够大就 free/malloc 或者 realloc，不需要了就 free.

是realloc

空间分配给你就是你的了, 不需要free之后再分配.  彻底不需要时,再free  空间不够就, 重新申请一个大的, 把原来的数据拷贝过去, 在把原来的指针free, 使用新的指针. 或者用remalloc函数


Question: 测试c调用c++，但不知道怎么编译这段代码

引用 3 楼 wangzuxi 的回复:g++ -Wall -g -c -o cppExample.o cppExample.cpp ar rcs cppExample.a cppExample.o gcc -Wall -g -o main main.c cppExample.a   不胜感激

linux上

在linux上进行么？ 还是在windows上？windows上的话vs不就足以解决了么？ 同关注。


Question: VC定时器的问题

引用 2 楼 u014274707 的回复:[quote=引用 1 楼 from2015 的回复:]  #include <stdio.h> #include <windows.h>  int main(int argc, char* argv[]) { 	int sleepCount = 0; 	int pre = 0; 	int num = 0; 	printf("Hello World!\n");     while(1)     { 		scanf("%d", &num); // 取值 		if (pre - num > 100 || num - pre > 100) 		{ 			printf("do something.\n"); 		}  		else 		{ 			printf("congtinue.\n"); 		} 		 		Sleep(1000); // 等待1秒     } // while(1); 	 	 	return 0; }  这样行不行？你是新手吧。首先你写的那个是个死循环，其次线程休眠和定时器是不同的[/quote]  嗯。向各位学习。

下载这个看看http://www.codefans.net/soft/23871.shtml

仅供参考#pragma comment(lib,"user32") #include <stdio.h> #include <time.h> #include <sys/timeb.h> #include <windows.h> char datestr[16]; char timestr[16]; char mss[4]; void log(char *s) {     struct tm *now;     struct timeb tb;      ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,s); } VOID CALLBACK myTimerProc1(   HWND hwnd, // handle of window for timer messages   UINT uMsg, // WM_TIMER message   UINT idEvent, // timer identifier   DWORD dwTime // current system time ) {  log("In myTimerProc1\n"); } VOID CALLBACK myTimerProc2(   HWND hwnd, // handle of window for timer messages   UINT uMsg, // WM_TIMER message   UINT idEvent, // timer identifier   DWORD dwTime // current system time ) {  log("In myTimerProc2\n"); } int main() {     int i;     MSG msg;      SetTimer(NULL,0,1000,myTimerProc1);     SetTimer(NULL,0,2000,myTimerProc2);     for (i=0;i<20;i++) {         Sleep(500);         log("In main\n");         if (GetMessage(&msg,NULL,0,0)) {             TranslateMessage(&msg);             DispatchMessage(&msg);         }      }     return 0; } //2012-07-26 17:29:06.375 In main //2012-07-26 17:29:06.875 In myTimerProc1 //2012-07-26 17:29:07.375 In main //2012-07-26 17:29:07.875 In myTimerProc2 //2012-07-26 17:29:08.375 In main //2012-07-26 17:29:08.375 In myTimerProc1 //2012-07-26 17:29:08.875 In main //2012-07-26 17:29:08.875 In myTimerProc1 //2012-07-26 17:29:09.375 In main //2012-07-26 17:29:09.890 In myTimerProc2 //2012-07-26 17:29:10.390 In main //2012-07-26 17:29:10.390 In myTimerProc1 //2012-07-26 17:29:10.890 In main //2012-07-26 17:29:10.890 In myTimerProc1 //2012-07-26 17:29:11.390 In main //2012-07-26 17:29:11.890 In myTimerProc2 //2012-07-26 17:29:12.390 In main //2012-07-26 17:29:12.390 In myTimerProc1 //2012-07-26 17:29:12.890 In main //2012-07-26 17:29:12.890 In myTimerProc1 //2012-07-26 17:29:13.390 In main //2012-07-26 17:29:13.890 In myTimerProc2 //2012-07-26 17:29:14.390 In main //2012-07-26 17:29:14.390 In myTimerProc1 //2012-07-26 17:29:14.890 In main //2012-07-26 17:29:14.890 In myTimerProc1 //2012-07-26 17:29:15.390 In main //2012-07-26 17:29:15.890 In myTimerProc2 //2012-07-26 17:29:16.390 In main //2012-07-26 17:29:16.390 In myTimerProc1 //2012-07-26 17:29:16.890 In main //2012-07-26 17:29:16.890 In myTimerProc1 //2012-07-26 17:29:17.390 In main //2012-07-26 17:29:17.890 In myTimerProc2 //2012-07-26 17:29:18.390 In main //2012-07-26 17:29:18.390 In myTimerProc1 //2012-07-26 17:29:18.890 In main //2012-07-26 17:29:18.890 In myTimerProc1 //2012-07-26 17:29:19.390 In main //2012-07-26 17:29:19.890 In myTimerProc2

引用 1 楼 from2015 的回复: #include <stdio.h> #include <windows.h>  int main(int argc, char* argv[]) { 	int sleepCount = 0; 	int pre = 0; 	int num = 0; 	printf("Hello World!\n");     while(1)     { 		scanf("%d", &num); // 取值 		if (pre - num > 100 || num - pre > 100) 		{ 			printf("do something.\n"); 		}  		else 		{ 			printf("congtinue.\n"); 		} 		 		Sleep(1000); // 等待1秒     } // while(1); 	 	 	return 0; }  这样行不行？你是新手吧。首先你写的那个是个死循环，其次线程休眠和定时器是不同的


Question: c语言之函数指针，对这个指针的理解

引用 10 楼 lineage191 的回复:看到头像激动了一下，再看小弟 彻底失望不过还是解答下 首先编译器如何识别你是一个指针，定义指针的时候要有*，char*  是指针的类型，其中char标示指针指向的类型，*标示的这是一个指针， [char *(pf)(char *p1,char *p2) 这是声明了一个函数（把括号去掉这就是一个函数，带不带括号含义是一样的） [char *(*pf)(char *p1,char *p2) 按照上面指针的理解，[char *(pf)(char *p1,char *p2) 是指针指向的函数类型，*标示pf是一个指针，这个时候要加括号了 不然就成 返回类型是char**的函数了， 问题二：可以理解成二级指针 感谢大神~~~

引用 10 楼 lineage191 的回复:看到头像激动了一下，再看小弟 彻底失望不过还是解答下 首先编译器如何识别你是一个指针，定义指针的时候要有*，char*  是指针的类型，其中char标示指针指向的类型，*标示的这是一个指针， [char *(pf)(char *p1,char *p2) 这是声明了一个函数（把括号去掉这就是一个函数，带不带括号含义是一样的） [char *(*pf)(char *p1,char *p2) 按照上面指针的理解，[char *(pf)(char *p1,char *p2) 是指针指向的函数类型，*标示pf是一个指针，这个时候要加括号了 不然就成 返回类型是char**的函数了， 问题二：可以理解成二级指针 五十步笑百步。

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

仅供参考//char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组的每个元素为一类指针，该类指针指向一类函数，该类函数无参数，返回一类指针，该类指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*(*x[3])())[5];//是个数组，大小为3     char (*(*x0  )())[5];//数组的元素，是个函数指针     char (*( x00 )())[5];//函数原型，参数为空，返回值为指针     char (*  x000   )[5];//返回值      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]

谢谢各位大神的回答，小弟受教了~~~ 那我是不是可以认为函数指针其实就是存储了函数地址的指针（有点类似二级指针的意思），那我在其它函数中（或者main函数中）通过调用这个函数地址的地址，然后来访问它~请问大神：我这样理解还有问题吗?(小弟愚钝，恳请赐教）

1、写成char *(pf)(char *p1,char *p2)，其含义是返回指针的函数。 2、可以这样理解。

char *  (*pf)  (char *p1,char *p2) 函数返回类型         函数变量(或函数指针变量)              函数参数

char *(*pf)(char *p1,char *p2)   是声明了一个具有两个参数并有返回值的函数指针，返回值为字符指针型，两参数均为字符指针。 char *(pf)(char *p1,char *p2)    是声明了一个函数，这个函数具有两个参数并有返回值。返回值为字符指针型，两参数均为字符指针型。  详解： 首先看第一个： char *          （*pf)               (char *p1,char *p2) ; 按我的空格把他看成三个部分，正好与函数声明/定义时的形式相同：返回值类型声明符、地址（函数名或指针名，本质都是个地址）、参数表列 我们重点分析第二部分：按上述分开来看，（*pf）是一个地址，那么pf就是地址的指针，所以，我们在应用时让pf指向一个相同返回值和相同参数表列的函数 那么再看第二个： char *       (pf)         (char *p1,char *p2) 按上述分析，pf就是一个地址，这和常见的函数是一样的  下面，我来给你说一下怎么理解函数指针这个东西： 首先看下面的概念： 指针：即地址 指针变量：即值为一个变量地址（指针，下同）的变量 函数指针变量：即值为一个函数首地址的变量  所谓函数，其实就是过程，就是大量指令的集合。在C语言中，函数名是指令集合的首地址的一个常量表示，你可以用函数运算符“（）“进行使用。 eg：a是个地址，那么a（）就是对a进行函数调用，在现在编译器中，该做法已不被允许，但是可以作为例子来学习。。。 函数指针变量，本质是一个指针变量，它的值是一个函数名（指针），用上例那种不被允许的方式给你说明如下： a依旧是个地址，pa是个与a类型相对应的指针，令pa=a;pa();便与上述的a()是同一座用。 在正常使用时，我们经常如下使用： void fac(void) { printf("hello!\n"); }  int main(void) { void (*p)(void);  p=fac; p(); fac();  return 0; }  满意请采纳，不满意请追问

4楼说的对~~  char *(*pf)(char *p1,char *p2) 就是名字叫pf，类型是char *()(char *p1,char *p2)函数的指针

如果不是 (*pb)(....) 而是pb（...）的话  那怎么编译怎么区分一个函数和函数指针？

这块最头疼了，每次弄明白了下次也会忘记……

int *pi  char *()(char *p1,char *p2)  *pf  =>  char *(*pf)(char *p1,char *p2)  类型 * 名  这东西就是这样的吧


Question: 函数指针 的理解

费那事！ __asm {   sub eax,eax  call eax }

((void (*) ()) 0) (); 这涉及到至少两个方面的知识：类型转换、类型名。 最直观地，它是一个函数调用，因为最右边是一对括号(/* …… */) () 其次，里面是一个强制类型转换，操作数是0-------(/* …… */) 0 再次，因为涉及到类型转换，所以，0左边的括号内部一定是个类型名--------- (void (*) () 到这一步，就很清楚了，它是一个指针，指向返回void类型的函数。 我的意思是再改一改： ((void (*) ()) 0) (); (* (void (*) ()) 0) (); ((void (*) (void)) 0) (); (* (void (*) (void)) 0) ();

定义一个函数指针,指向0地址, 应该算是一个复位函数,即PC指针指向0地址.


Question: C语言 对用户输入的任意数组进行冒泡排序

malloc 动态开辟 free释放

1、题中应该会给一个上限，比如说(n<10) 2、那么就定义一个长度为10的数组，然后再输入用户想要的数组长度，当然此时n<10，（可以对用户输入进行限制） 3、之后就是依次输入数据，再冒泡排序，输出

动态内存分配malloc,free

两个方法，一个申请足够大的数组，然后自己跟据输入来定义长度（不推荐，但是现在适合你） 第二种：动态申请空间，输入一个申请一个，最后别忘了释放掉然后使指针归0（你好像还没学）

或者你预先定义一个足够大的数组，并记录你实际输入的个数，排序时按照这个大小进行排序，  选定一个特殊字符，遇到时 break 就好了

换个方式，先输入长度，再输入数据

while((scanf("%d", &size) != 1) {     ...     array = (int *)malloc(sizeof(int) * size);     ... }

好吧

malloc,realloc,free

这个书本上有例子吧？ 照着例子来就好了。 至于数组大小的问题，后面学到了动态分配内存后再考虑。一步一步走，不要走还不会就想跑。


Question: 想顺利过计算机二级的童鞋请点这里哦！

考了n遍还是没有过，真是日了狗了！

引用 56 楼 fanlvlgh 的回复:正在热血复习中...  加油，希望你可以考出好成绩，另外祝你新年快乐。

正在热血复习中...

我考一次就过了，没报过培训班，只看过教材，而且很少看。

努力考级中

什么鸟，没事多找大神问一问，谦虚一点，什么考不过

大学本科如果是学习计算机，毕业之后就应该是4级了。是计算机专业的还需要考这些课程？

引用 40 楼 Sandrer 的回复:说句实在话，我工作了10年了 毕业证是化学专业，其它啥证都没有 刚毕业出来花了400块，做了一个计算机专业的毕业证、四级计算机证、二级英语证 大公司都不管学历只关经验，所以有啥证都无所谓； 小公司需要学历，你把证件交给他们，反正他们也不会去查还是无所谓 这年头在国内啥都要证，但真正用到的就永远只有那么几个 所以其它无伤大雅的就随随便便可以啦   说得有道理，谢谢分享。

引用 38 楼 jsjxieyang 的回复:原来我一直是无证上岗呢

引用 23 楼 stable000 的回复:这么多搞IT的连二级都过不了？瞬间觉得自己竞争力很强

考C的话 你们就买本 c primer plus 这本书不要太经典

http://nianjian.xiaze.com/tags.php?/%E5%90%89%E6%9E%97%E7%A4%BE%E4%BC%9A%E7%BB%8F%E6%B5%8E%E7%BB%9F%E8%AE%A1%E5%B9%B4%E9%89%B4/1/13423640268/ 我只是来拿个注册码，不要打我

第一次考不过再报名考一次，直至通过为止。

还没开始考，会不会很难呀

努力在考级中

我汗 二级这么简单的东西……我不是来秀优越的←_←

原来我一直是无证上岗呢


Question: 返回值

运气好。

为什么没有指定返回值，下面可以正确使用上面的指针

引用 7 楼 CharlesSimonyi 的回复:C++编译器是不会允许这种编译通过的。C语言编译器报出一个warning C4716仍然允许编译通过。 最后输出了正确的结果，是因为巧合。 你把代码写成这样：  #include <stdio.h> #include <stdlib.h>  typedef struct Node { 	int name; 	int *age; }Node;  Node* foo() { 	int n = 10; 	int *pn = &n; 	Node *p = malloc(sizeof(Node)); 	printf("%p\n", p); 	p->age = 0; 	p->name = 0; 	*pn = 50; 	//return p; }  void main() { 	printf("main----%p\n", foo()); }  就无法输出一致的结果了。 至于为什么，查看反汇编代码就明白了，函数的返回值是保存在eax寄存器里。 有return p;的情况下，反汇编代码是这样的：  return p;的作用是把指针p指向的地址保存到eax寄存器里。 foo()函数返回后，foo()的调用者从eax寄存器中取值，即取到了foo()函数的返回值。  如果把return p;注释掉，反汇编代码是这样的：  很巧，p->name = 0;时，把p指针指向的地址放到了eax寄存器中，并且后来没有再修改eax寄存器了， 所以eax寄存器中一直保存着p指针的值，直到foo()函数返回时，仍然保存着， 所以foo()函数的调用者，取foo()函数的返回值，即取eax寄存器的值时，取到了正确的结果 同意楼上说法，是属于巧合的情况，指针指到其他的地方就不会有这种现象了，受教了！

一般返回值是放到某些寄存器里面，这里那个寄存器刚好存的是那个指针，所以……。

返回值通常保存在eax寄存器中。  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  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对应的汇编并单步执行观察相应内存和寄存器变化。）

不是编译器问题，我用vs2013和ubuntu都试过了，一个情况，但是如果注释掉上面那个初始化的话就是野指针了。

编译器问题，我这里VisualStudio2010如果注释掉return p;是无法编译通过的


Question: icmpv6 NS

二层 三层信息是这样的！！！！！！ 上面写错了。。   /* 发送端:   IP:  2001:da8:b001::1       MAC:      33:33:FF:00:00:02  接收端:  IP:   2001:da8:b001::2       MAC:     00:0C:29:5E:2E:24  */


Question: 已知ISA地址port与DATA port,怎样输出读取的值?

zhao4zhong1  赵4老师 : 我是为了获取CPU风扇转速的,所要读的数据在SUPERIO(ITE8277F)的0DH寄存器中(8bit),(地址port 0XA35，数据port 0xA36),WINIO中使用GetPortVal(),要怎么用?直接是GetPortVal(0xA35,value,1)吗?

搜“WinIO.SYS”

补充一下,我是要在windows下读取.WINDOWS 7 谢谢了!


Question: 在树中找到一个特定节点问题？？？大神们进

引用 2 楼 lincolnandlinda 的回复:是不是两叉树?是多叉树，也是自学好多不懂

是多叉树，也是自学好逗不懂

是不是两叉树?

return find(child) || find(next) , 不要再递归prev了


Question: C语言error link2001

函数前面没有类的名字        类名：：delay200ms（）{}

看有帮助没——http://blog.csdn.net/CHUKAIHUA/article/details/5543140

你是怎么调用这个函数的？


Question: C入门问题，求大神解答！！！

％前面的空格，在输入可以忽略前面的所有空白符（空格，制表符，吃掉回车）

吃掉回车的作用吧

搜嘎，感谢各位 了

codeblocks10.05，如果去掉空格，的确会直接请求输入 应该是消除上面的回车  上面输入数据后，缓冲区还有回车符，下面的scanf字符就会读取这个回车，所以用空格消除

没用过pelles c, 不过，如果确实是这情况，应该就是楼上说的吃掉上一次输入的回车。百度一下吧，scanf的输入缓冲

吃掉输入的回车是什么意思？  还有我用的环境是pelles c

没有影响吧？ 那个完全是正常的，而且我也运行了下你的程序，去掉空格正常运行 看截图  环境  Dev c++

吃掉输入的回车。


Question: c语言结构体数组全局变量?

全局变量当然可以啦

可以 这个问题楼主自己试一下就知道了  另外， include写错了 还有半角全角的字符问题，注意一下


Question: C语言I/O编程中一个小问题

EOF是int型。

char型，int型，double型都是浮云，所有数据在计算机中都是以二进制的形式表示的。char,int,double是便于我们人类理解。

如果将ch声明为char型，就无法区别 文件中读出字符'\xff'，即char型的-1 和 已到文件末尾，无法读出任何字符，返回-1 了。

函数返回值是int型


Question: C语言中链表指向问题？

画好图一条条线对应过来就好了

你这是要排序么？

十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495

仅供参考//带表头结点的单向链表 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

你认认真真，仔仔细细搞，完全能搞定的！！！


Question: 大家学习C和C++都使用什么编译器

引用 3 楼 u010016404 的回复:windows上用VS，Linux上用GCC。 +10086

IDE集成 GCC

C语言编译器：gcc,ucc,tcc,pcc

linux GCC/g++

vc++,gc++

gcc 不习惯在windows上编程

VS2010，值得你选择

win+cygwin+gcc+netbeans

windows上用Visual Studio在装上VA插件就好了，如果学的是MFC用VC 6.0比较好，不是的话用VS 2008及之前的版本就可以，感觉VS 2010之后的版本就比较慢了 另外说一句，最好不要用VS，因为用了之后再用其他的就感觉很渣了

GCC......

用的VS。  不过你学习能力强的话，建议你用GCC，自己写makefile。VS替用户做了很多事。

目前刚开始学，用codeblock 主要是vs太大了，小水管不知道要下到什么时候...

gcc+sublime text 或vim  Mac 下 gcc+TextMate

VS 2013.手残就用这个。

主要看泥选择的平台啊

我用的是vs

Linux     gcc

如果将来想做嵌入式、移动开发或者Linux平台建议用gcc。 如果将来想做桌面开发从VS入手是不错的选择。


Question: 链表问题。。

PNode Creat_List() { 	int i; 	PNode pHead = NULL, pTail, pNew = NULL; 	pHead = (PNode)malloc(sizeof(Node)); 	pTail = pHead;//头尾原来没连起来 	if (pHead == NULL) 	{ 		printf("内存分配失败！"); 		exit(-1); 	} 	else 	{ 		int len;//定义节点长度 		printf("请输入学生总数："); 		scanf("%d", &len); 		for (i = 0; i < len; ++i) 		{ 			pNew = (PNode)malloc(sizeof(Node)); 			printf("请输入学生编号："); 			scanf("%d", &pNew->id); 			printf("请输入学生姓名："); 			scanf("%s", pNew->name); 			pNew->pnext = NULL; 			pTail->pnext = pNew;//尾巴添加一个 			pTail = pNew; 		} 	} 	return pHead; }

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。  仅供参考//假设带表头结点的单向链表头指针为head，试编写一个算法将值为5的结点插入到连接表的第k个结点前，删除第k个节点，并对该链表进行排序。 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> //

引用 2 楼 q3733353520 的回复:不会崩溃啊，我用你的程序是没有崩溃的，不过你的尾插入法是有问题的 我是VS2013，输完崩溃了。你说的问题在哪。。

不会崩溃啊，我用你的程序是没有崩溃的，不过你的尾插入法是有问题的

为什么输入数值完直接崩溃了


Question: VS2013编译驱动提示

向darknightghost学习！

引用 6 楼 qq_16319743 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 驱动不能在VS IDE中调试吧。  只是想编译成SYS文件 然后放到虚拟机调试  并不想让SYS在主机上运行[/quote] 我在楼上已经告诉你怎么弄了,百度上搜"vs2012配置双机调试"很多教程的 给你一篇我搜到的http://blog.sina.com.cn/s/blog_79ba23780101qx4y.html vs2012和vs2013配置方法完全相同

右键项目->属性->调试->要启动的调试器里选Debugging Tools for Windows - Kernel Debugger 然后Remote Computer Name里选Configure 接下来如果你英文不是烂到家了的话就是傻瓜化操作, 调试时点绿色三角号旁边的小三角号,选Debugging Tools for Windows - Kernel Debugger 再点击I Know..........那个选项,至于虚拟机的配置网上到处都有 配置好虚拟机,开机,拷过去运行,接着调试 操作和调试用户层程序差不多 注意断点必须要让调试暂停一下才能生效  vs2012以后的版本调试驱动都很方便的,就是内存不够会卡

引用 1 楼 zhao4zhong1 的回复:驱动不能在VS IDE中调试吧。  只是想编译成SYS文件 然后放到虚拟机调试  并不想让SYS在主机上运行

引用 1 楼 zhao4zhong1 的回复:驱动不能在VS IDE中调试吧。  请问下啊  我按照网上教程配置的VS能编译出

引用 2 楼 darknightghost 的回复:sys不能直接运行,要以服务的形式加载. 而且我想问一句,兄弟你在作死么?敢在本机调试驱动. 驱动要在另外一台电脑或虚拟机里调试,建议百度一下vs2013怎么双机调试驱动. 你要知道驱动是在系统核心运行的,一旦有bug,蓝屏是最好的情况,更严重的可能损坏硬盘数据,甚至看到电脑冒出袅袅青烟都有可能.  谢谢提醒啊  我是想在本机上编译成xxxx.sys文件  然后在把xxxx.SYS复制到虚拟机里测试的

hal是系统的，要在本机调不怕麻烦在win7可能只能kdprint了，很久不写sys了，很怀念以前用softice的时代

驱动不能在VS IDE中调试吧。


Question: for循环是不是必须正数？

引用 12 楼 lin5161678 的回复:我不是楼主  你贴的图 语法是错的  比如  for(;;) ; 这个for 语句是符合语法的  但是不符合你给出的这张图里面的说法 你给的图 for后面的只能跟 复合语句  而for 的语句是 for 后面可以写任何语句 复合语句仅仅是 其中一种   后面的说明中  由0个或多个逗号分开的增量语句  这个说法也是错的  那只是表达式 不能是语句 你不可以写 for(;; ++i;) ; 而++i; 才是你所谓的 增量语句  ++i 只是表达式  基础概念混乱 是错了，没细心看 这个的确有问题

for中第二句条件不满足，不会执行下面的*计算。

引用 5 楼 u012421456 的回复:楼主认为哪里说错了我不是楼主  你贴的图 语法是错的  比如  for(;;) ; 这个for 语句是符合语法的  但是不符合你给出的这张图里面的说法 你给的图 for后面的只能跟 复合语句  而for 的语句是 for 后面可以写任何语句 复合语句仅仅是 其中一种   后面的说明中  由0个或多个逗号分开的增量语句  这个说法也是错的  那只是表达式 不能是语句 你不可以写 for(;; ++i;) ; 而++i; 才是你所谓的 增量语句  ++i 只是表达式  基础概念混乱

这样才可以啊。 for(i=-3; i<0; i++)

引用 8 楼 xiaopao319 的回复:[quote=引用 楼主 I_better 的回复:] 例： int i,m=1; for(i=-3;i>0;i++)  m=m*i;  此时就不执行循环了，直接m=1 问题在哪？  测试条件不成立，直接没有循环，什么都没有做，m就自然等于1了[/quote]       已验证，确实如此哦！

引用 楼主 I_better 的回复:例： int i,m=1; for(i=-3;i>0;i++)  m=m*i;  此时就不执行循环了，直接m=1 问题在哪？  测试条件不成立，直接没有循环，什么都没有做，m就自然等于1了

for (A;B;C) D; //等价于 {  A;  while (1) {   if (!(B)) break;   D;   C;  } }

引用 2 楼 lin5161678 的回复:-3 > 0  不成立 直接退出循环  请问 这有什么不对吗 楼主所说的"问题在哪" 你这不是知道吗

引用 2 楼 lin5161678 的回复:-3 > 0  不成立 直接退出循环  请问 这有什么不对吗 没什么不对啊！ 这张图也没说这不对啊  引用里面的说法是错的 for语句的语法不是这样的 楼主认为哪里说错了

1.可以为负数 2.首先i=-3，然后i>0吗？NO，所以不循环

引用 1 楼 u012421456 的回复: 你贴的图 里面的说法是错的 for语句的语法不是这样的

-3 > 0  不成立 直接退出循环  请问 这有什么不对吗


Question: 请问输出结果是什么？(printf("%d,%d",*(a+1),*(ptr-1));)

一般我个人不推荐这么用

2，5 C语言指针与数组名

2和5 ，a+1 是数组的首地址加一，就相当于，加一，*（a+1）=2，而&a+1是整个数组地址加一，ptr指针会指到元素5的后面故*（ptr-1）=5啦！

我机器上输出2，5   感觉你的*ptr=(int *)(&a + 1);中，&a是地址的地址，然后又强制转换成int*，为啥要这么用呢？纯粹为了玩地址啊？


Question: matlab中如何找到数组中某个数值的索引的问题

MATLAB貌似以前会一点

我作图像处理的仿真时也遇到过这种问题，比如要找到图像中满足某个条件的位置，再对这些位置的像素拿出来处理 但有时矩阵中有时没有这样条件的点，像这样：  clc; clear all; close all; a=[1.5,2.3,3;4,5,6;7,8,9]; [x,y]=find(a>10); a(x,y)=a(x,y)+100;


Question: C语言/判断一个数是否为素数

#include <stdio.h>  int main(void) {         int i   = 0;         int n   = 0;         printf("请输入一个数:");         scanf("%d",&n);         for(i=2; i<n; i++){                 if(n%i==0){                         printf("您输入的%d不是素数\n",n);                         break;                 }else{                         printf("您输入的%d是素数\n",n);                         break;                 }         }         return 0; }

sqrt(n)

引用 5 楼 sbvsa 的回复: #include"stdafx.h" #include<stdio.h> #include<math.h> int main(void){     int i,n;      printf("请输入一个数:");     scanf("%d",&n);     printf("\n");      for(i=2;i<=sqrt(n);i++)         if(n%i==0){             printf("您输入的%d不是素数\n",n);             break;         }      if(i>k)         printf("你输入的%d是素数\n",n);      return 0; }    这里 if (i>k)  的 K是什么变量啊，我看不懂，难道是个特殊的值吗 我是新手

引用 5 楼 sbvsa 的回复: #include"stdafx.h" #include<stdio.h> #include<math.h> int main(void){     int i,n;      printf("请输入一个数:");     scanf("%d",&n);     printf("\n");      for(i=2;i<=sqrt(n);i++)         if(n%i==0){             printf("您输入的%d不是素数\n",n);             break;         }      if(i>k)         printf("你输入的%d是素数\n",n);      return 0; }  这个是不是还要处理一下输入1的情况，1不是素数也不是合数

另外，注意下代码格式 改用花括号的就用花括号括起来

C语言基础要稳扎稳打

不好意思没修改变量k 请把k改成sqrt(n)

引用 3 楼 FUHAODAASD 的回复:2楼那样字改你输入1还是素数，但是你不是素数啊 你说的对

引用 1 楼 layershow 的回复:错误还真是不少 if(n%i==0)printf("您输入的%d不是素数\n",n);break; else printf("您输入的%d是素数\n",n);  不要在循环里打印，用个变量 if 要用大括号 int flag = 0;  for (...) { if (n%i == 0) {     flag = 1;     break; } }  if (flag) {     printf("您输入的%d不是素数\n",n); } else {     printf("您输入的%d是素数\n",n); }  2楼那样字改你输入1还是素数，但是你不是素数啊

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


Question: 关于指针赋值的问题，求大神

gets()是需要内存空间的，如果不赋值的话，p是个野指针，而且并没有内存空间，运行报错的吧

第二个程序把gets(p)写到P=str上面 那么P是没有初始化的指针，它的指向我们并不知道，所以调用gets()就会段错误。  程序是一步一步往下执行的

我失误了下 其实gets(p)和下面一行的顺比掉换也一样不影响结果

p = str ， 那么p 就是str， 一样的访问。

首先2个程序都是正确的，第一个程序是先给P所指的对向赋值（使用前先赋值），而第二个程序我把gets(p)写到P=str上面运算结果就不对了，我想知道为什么指针指向整形数据是先赋值，指向数组怎么就后赋值了呢  写的没错啊， 不存在先赋值后赋值的问题。

因为第一个 scanf 操作的是 a 和 b  不是 p1 p2 第二个gets 操作的是 p ，如果gets 操作的是 str 那也是没问题的


Question: 新手C语言编程遇到问题求助

文本存储数字存储的其实是数字字符，当然也可以用二进制格式存储，不过我猜你应该用的是字符的格式

引用 4 楼 Data_Flow 的回复:1.你用的文件应该是文本文件吧，里面存储的是字符。用fread读取的数据也是字符，是不会转化成浮点数的，方差的输出注定是错的。 2.我觉得问题在remind函数，当文件指针是stdin的时候我不知道能不能用remind。这只是我的初步想法，不知道对不对。  等我调试下，我再来哈，一起探讨～ fread（）函数不能打开文本文件里存储的数字吗

还有你要用fread，打开文本应该用二进制模式打开。

比如用WinHex软件查看一个号称里面保存了一个double小数0.5的文件, 如果你看到的是30 2E 35，那么你应该用f=fopen(...,"r");fscanf(f,"%lf",&d);fclose(f); 如果你看到的是00 00 00 00 00 00 E0 3F，那么你应该用f=fopen(...,"rb");fread(&d,8,1,f);fclose(f);

引用 1 楼 zhao4zhong1 的回复:电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,fread,fwrite,fgetc,fclose  //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了 没懂。。是不能用fread（）函数吗


Question: 头插建立单链表，疑似指针越界，大侠帮看下

“多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，搬手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

#include <stdio.h> #include <malloc.h>   //单链表类型定义 typedef struct  LNode {     int data;     struct LNode *next; }LinkList;     //Function 1:头插法建立单链表 void CreateLinkList(LinkList **L,int n,int *a)  //这里应该传址 {     LinkList *s; 	int i;      *L=(LinkList*)malloc(sizeof(LinkList));        //建立头结点     (*L)->next=NULL;       for (i=0;i<n;i++)        //这样才不会越界     {         s=(LinkList*)malloc(sizeof(LinkList));           s->data=a[i];         s->next=(*L)->next;         (*L)->next=s;     }       }// End Of Function CreateLinkList()     //Function 2：输出链表 void DisplayLinkList(LinkList *L) {     while(L->next!=NULL)     {         printf("%d    ",L->next->data);  //头节点并没有存储数据，所以从第一个节点开始输出 		L=L->next;     } 	putchar(10);   }//End Of Function DisplayLinkList()   int main() {     LinkList *L;     int a[9],i,n;     n=9;       for (i=0;i<n;i++)     {         a[i]=i;         printf("%d    ",a[i]);     }           printf("\n*************************通过数组建立链表***********************\n\n");         CreateLinkList(&L,n,a);  //传址     DisplayLinkList(L);           return 0; }

头结点不要输出   void DisplayLinkList(LinkList *L) {     LinkList *d=L->next;     while(d)     {         printf("%d    ",d->data);         d=d->next;     }  }//End Of Function DisplayLinkList()   数组a[9]下标最大为8，里面的<=改成<

另外楼主的输出也写错了  判断条件如果是L->next!=NULL的话，是不会输出最后一个链表的

#include <stdio.h> #include <malloc.h>  //单链表类型定义 typedef struct  LNode { 	int data; 	struct LNode *next; }LinkList;  //Function 1:头插法建立单链表 void CreateLinkList(LinkList **L, int n, int *a) { 	LinkList *s,*s1;  	s = (LinkList*)malloc(sizeof(LinkList));        //建立头结点 	s->next = NULL; 	*L = s;//将L指向头结点 	s1 = s; 	s->data = a[0];  	for (int i = 1; i < n ; i++)//是<n 	{ 		s = (LinkList*)malloc(sizeof(LinkList)); 		s->data = a[i]; 		s1->next = s; 		s1 = s; 	} 	s->next = NULL;//尾结点的next指向NULL }// End Of Function CreateLinkList()   //Function 2：输出链表 void DisplayLinkList(LinkList *L,int n) { 	for (int i=0; i < n;i++) 	{ 		printf("%d    ", L->data); 		L = L->next; 	}  }//End Of Function DisplayLinkList()  int main() { 	LinkList *L = NULL; 	int a[9], i, n = 9; 	for (i = 0; i < n; i++) 	{ 		a[i] = i; 		printf("%d    ", a[i]); 	} 	printf("\n*************************通过数组建立链表***********************\n\n"); 	CreateLinkList(&L, n, a); 	DisplayLinkList(L,n); 	return 0; }   感觉楼主的连接方式好奇怪。。。不过原码是即使把等号去掉也会报错吧，操作越界了，因为L的next虽然一直在变化，但是没有把s一个一个的连接。。。 我不知道头插法是不是我的代码的意思。。应该是需要两个临时变量才能把表链起来吧（如果不改变头结点的）  LinkList *s;是创建一个LinkList类型的指针 LinkList  s;是创建一个LinkList类型的结构体  至于我的代码显示的是0~8.这不是问题，只要在main里面把的a[i]=i，改为a[i]=i+1就好了，

数组9个元素，a[0]到a[8]，你的两处for循环都访问了不存在的a[9]，应把 i<=n 改为 i<n LinkList  s; //创建一个LinkList结构体 LinkList *s; //创建一个指向LinkList结构体的指针


Question: C语言全局结构体数组，调试监视问题

没有的，程序单步调试完student stu都没有值，一只是显示的那样

引用 5 楼 adusuccessfully 的回复:请问LZ用的是什么编译工具？怎么会有#include "stdafx.h"这一头文件？？ 下面是我在VS2010上调试的结果：   vc++2010学习版

student不是变量  stu也没有值吗?

输入的for循环输入完，还是看不到，显示的还是那样子

我看你调试的时候还执行的代码还停在main函数第一行，这个时候还没有对stu赋值啊， 你要按F10逐过程往下走，代码对stu赋了值，才能看到变化啊


Question: 关于加窗插值FFT计算中插值的问题

你好，请问楼主是怎么做的呢？具体程序能贴出来吗？这在做这个有点疑问。谢谢

引用 3 楼 blues_more 的回复:引用 1 楼 user-2 的回复:只要fft再ifft回来总共除了n就行，具体是fft时候除还是ifft时候除还是两边各除sqrt(n)这看需求。但是除以N之后，幅值变的很小很小啊，这显然是不对的，请问可以详细解释一下吗？ 怎么不对。本身频域就没有准确的定义，差一个常数完全不是问题，你根据你自己的需求找到一个合适的缩放就行。缩放值和n有关系是因为如果不调整常数直接做fft+ifft的话，效果是原信号加大n倍，所以为了让fft+ifft能变换回原来的信号，这回路上总共要除一个n，这就是1L的意思。

但是除以N之后，幅值变的很小很小啊，这显然是不对的，请问可以详细解释一下吗？


Question: windows 下 pro*c 编译问题

gcc first.c -lclntsh


Question: C 中 CHAR  处理成 16进制时，自动补位了？

你可以把char改成unsigned char试一下，那样0x80仍然是正的，就没有这个问题   #include <stdio.h> int main() {     char c1=0x80;     unsigned char c2=0x80;     printf("%02x\n", c1);     printf("%02x\n", c2);     return 0; }

%x 为  unsigned  int

recvbuf是char型的吧？ char是一个字节的，所以0x7F以上就是负数了 而%x是用来输出int的，所以你的char会被扩展到4字节，对于0x7F，扩展后是0x0000007F，前面的0可省略，所以仍然输出0x7F 对于0x80，扩展后就是0xFFFFFF80了，前面的F不能省略，所以会输出来 至于%02x里的02，是不足2位补到2位，但超过2位不会截断


Question: c primer plus 第九章练习题8

引用 4 楼 xiaopao319 的回复:[quote=引用 3 楼 Data_Flow 的回复:] 请看楼上的楼上 还有当p小于0时你忘记加括号了 p-1要改成p+1 楼上解答完全正确！！！！！赞[/quote]  谢谢各位，我真是大傻逼。 。。。

引用 1 楼 czarten 的回复:if (p = 0) if (p == 0)  谢谢你，，我真是大傻逼。。。

引用 3 楼 Data_Flow 的回复:请看楼上的楼上 还有当p小于0时你忘记加括号了 p-1要改成p+1 楼上解答完全正确！！！！！赞

请看楼上的楼上 还有当p小于0时你忘记加括号了 p-1要改成p+1

if (p = 0) if (p == 0)

楼主请看楼上！


Question: 怎么理解从动态二维数组是真正的指针，而数组不是真正的指针这个问题？

谢谢各位，我知道问题原因了，是我自己看错代码了。。。。我才发现，那个一维的地方是两次malloc。。所以offset不一定会是20，这下明白了，谢谢各位，结贴了

引用 15 楼 u013585046 的回复:专业的做法是看符号名的属性！  静态数组名和指针变量名都是符号，它们可以有相同的值（如将数组名赋值给指针变量时），但符号的属性是不一样的，数组名是只读属性，指针变量则是可写的，所以不能将指针变量反向赋值给数组名！  有兴趣可以去分析可执行文件的格式，特别是符号表部分，对各种符号属性就会有更深的理解了。  这个好，谢谢

引用 16 楼 zhao4zhong1 的回复:这辈子头次在此贴看到内存窗口按无符号10进制显示字节值（0..255），有一种打通任督二脉的奇怪感觉！  小弟第一次看这种东西，未免有些不懂。。所以就乱看了。。不过好像16进制也是这样的？所以我想知道我问的那个问题的答案

引用 16 楼 zhao4zhong1 的回复:这辈子头次在此贴看到内存窗口按无符号10进制显示字节值（0..255），有一种打通任督二脉的奇怪感觉！ 哈哈，打通任督二脉

引用 13 楼 zhao4zhong1 的回复:严重怀疑楼主根本没看过内存窗口。 内存窗口和监视窗口不是一回事！  哦哦是，我一直误以为内存窗口就是监视窗口。。。  看了下，这两个区间好像是不连续的。。。可是为什么会这样呢？用malloc不是创建的是一片连续的区间吗？  前面那个一维的指针和二维的指针的指向不一样我可以理解。。因为malloc了两次，那么这个又是什么情况呢？

严重怀疑楼主根本没看过内存窗口。 内存窗口和监视窗口不是一回事！

引用 11 楼 zhao4zhong1 的回复:打开内存窗口看看不会吓死人的； 没有内存窗口有时是无法发现问题的。  关键是vs那个就是看的内存。。。。  我就是不懂喂什么offset一个是20，一个是80

打开内存窗口看看不会吓死人的； 没有内存窗口有时是无法发现问题的。

引用 3 楼 zhao4zhong1 的回复:VC调试时按Alt+6,打开内存窗口看动态二维数组和静态二维数组对应的内存不就啥都明白了吗。 正解！ 只看Watch窗口是不够的。

那为什么如我4楼说的那个。。。  为什么offset会一个是20，一个是80...

栈指针比较好看，看一下esp的值，跟这个差不多地址

小弟也是在学习这方面知识，恳请大神指教，谢谢

引用 5 楼 derekrose 的回复:你的命题首先就不准确  额，我本来是想问用动态创建的二维数组和静态的二维数组的区别的。。。发了贴就不能改了。。

你的命题首先就不准确

const int rows = 2, cols = 5;  	int i, j, num = 0; 	int arr[2][5]; 	int **matrix = (int **)malloc(rows*sizeof(int *)); 	for (i = 0; i<rows; i++) 	{ 		matrix[i] = (int *)malloc(cols*sizeof(int)); 		for (j = 0; j<cols; j++) 			matrix[i][j] = arr[i][j] = ++num; 	}  那比如说这个吧，我是从论坛某个帖子复制的，看了下内存地址，静态二维数组的第一维相差20个offset（sizeof(int)*5），那为什么动态二维数组的offset不是20而是80呢？  再看了下首地址，动态二维数组的首地址不是matrix[0]的地址，而数组的首地址和matrix[0]一样，所以“指针的指针”是这个意思吗？

指针可以赋值改地址 数组名不行 左值右值不要搞混了

数组名不能被赋值


Question: 有关栈的问题

sqStack  s;  createstack(&s); 这是创建了一个结构体s，然后把它的地址交给createstack，createstack根据这个地址就能找到你创建的结构体s，并对其进行操作; sqStack  *s; createstack(s); 这个只是创建了一个指向结构体的指针，而没有创建结构体，createstack沿着这个指针找到的是一个不存在的结构体，并试图对其成员进行操作，当然会崩掉


Question: C中关于数据和该数据相关的函数或方法的封装性

好，不错

问题是什么？


Question: 新人C语言求助

也就是说无论我输入什么，它都会自动转换成ASCii码值去计算谢谢大神指点

数据类型问题。

你用getchar，取的是字符，不是数字，ch的值应该是这个字符的ASCII码值，所以会有问题！


Question: AIX系统UNICODE转中文

对电脑而言没有乱码，只有二进制字节；对人脑才有乱码。啊 GBK:0xB0 0xA1,Unicode-16 LE:0x4A 0x55,Unicode-16 BE:0x55 0x4A,UTF-8:0xE5 0x95 0x8A  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。


Question: AIX系统UNICODE转中文

这问题弄好几天了。真的不知道怎么弄了。求大神帮忙了。


Question: 这段代码错在哪里？错误是function 'int __cdecl stub(int ,int )' already has a body 执行 cl.exe

#include<stdio.h> #include <iostream> int stub(int,int); using namespace std; void main() { 	int x1,x2; 	printf("please enter the first number:"); 	cin>>x1; 	fflush(stdin); 	printf("please enter the second number:"); 	cin>>x2; 	stub(x1,x2); }  int stub(int x,int y) { 	printf("%d\n",x+y); 	return 0; }  1、正如一楼所说，stub函数声明后面没有加分号； 2、stub函数定义后面要有int型的返回值； 3、楼主定义的x1,x2，都是int型的，而get插入函数是从标准输入里读取下一个字符，返回类型为int型，返回值为用户输入的ASCⅡ码，出错返回-1。看楼主的意思是求两个整数的和，所以这样做不对。

int stub(int,int);//分号  void main()


Question: 程序员面试宝典little endian系统 变量存放问题

引用 5 楼 Yick__ 的回复:[quote=引用 3 楼 luciferisnotsatan 的回复:] struct里总共有9个bit，所以2字节大。b1是0～4bit位，b2是7，8比特位  memcpy了EM，内存里就是 01000101（E）01001101 （M）  因为是小字节序，所以 15～0 bit位为 0100110101000101 红色b1补位后为5，绿色b2补位（有符号）后，就是-2菜鸟请教一下问题，从宏观上看结构体内的空间字节是要对齐的，那么更细致一些，位是不是也要对齐一下呢？[/quote] 大小端只针对字节，不针对bit位。 而且只针对超过1字节的基本类型（如short，int，long），不针对非基本类型，比如char sz[20]，char数组就不用考虑。int arr[20], 你只要考虑arr数组里的每个元素的大小端，但整个数组不用管。

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

引用 3 楼 luciferisnotsatan 的回复:struct里总共有9个bit，所以2字节大。b1是0～4bit位，b2是7，8比特位  memcpy了EM，内存里就是 01000101（E）01001101 （M）  因为是小字节序，所以 15～0 bit位为 0100110101000101 红色b1补位后为5，绿色b2补位（有符号）后，就是-2菜鸟请教一下问题，从宏观上看结构体内的空间字节是要对齐的，那么更细致一些，位是不是也要对齐一下呢？

这是个细致活，我以前也有想到过，但从来没有遇到过。

为什么会有这样的输出？ 想问一下楼主了解位域的知识吗？ 了解memcpy函数的用法吗？