Question: 一道面试题，有点懵了

学习++ C

引用 42 楼 zhouxiaofeng1021 的回复:[quote=引用 32 楼 sholber 的回复:] [quote=引用 30 楼 zhouxiaofeng1021 的回复:] [quote=引用 13 楼 sholber 的回复:] [quote=引用 11 楼 zhouxiaofeng1021 的回复:]  int a[8]; int *p=a;下列中不是表示a[1]的是： A、a+1    B. p+1     C. a++      D. ++p A：语法错误 BD： 指向a[1] C:语法错误吧 笑话！A怎么就语法错误了？： int a [8]; int * p = a + 1;[/quote]  你觉得我说的是笑话！请说出理由啊！ 别动不动就笑话！ 你这么SB！ 数组a的地址值是不允许变得！ [/quote] 说脏话烂嘴呀，要注意啊。 还有，是“变的”，不是“变得”，注意文化修为啊，否则很可怕了。嘎嘎~ 数组a的地址不允许变，那别的东西的地址就可以随便变了？这种思想认识很可怕啊！[/quote] 老子就骂你了！怎么了！ 你要想别人不骂你！你先得尊重别人！  [/quote] 什么老子不老子的，在我眼里全是喷孙。

引用 32 楼 sholber 的回复:[quote=引用 30 楼 zhouxiaofeng1021 的回复:] [quote=引用 13 楼 sholber 的回复:] [quote=引用 11 楼 zhouxiaofeng1021 的回复:]  int a[8]; int *p=a;下列中不是表示a[1]的是： A、a+1    B. p+1     C. a++      D. ++p A：语法错误 BD： 指向a[1] C:语法错误吧 笑话！A怎么就语法错误了？： int a [8]; int * p = a + 1;[/quote]  你觉得我说的是笑话！请说出理由啊！ 别动不动就笑话！ 你这么SB！ 数组a的地址值是不允许变得！ [/quote] 说脏话烂嘴呀，要注意啊。 还有，是“变的”，不是“变得”，注意文化修为啊，否则很可怕了。嘎嘎~ 数组a的地址不允许变，那别的东西的地址就可以随便变了？这种思想认识很可怕啊！[/quote] 老子就骂你了！怎么了！ 你要想别人不骂你！你先得尊重别人！

引用 44 楼 zhouxiaofeng1021 的回复:[quote=引用 43 楼 sholber 的回复:] [quote=引用 42 楼 zhouxiaofeng1021 的回复:] [quote=引用 32 楼 sholber 的回复:] [quote=引用 30 楼 zhouxiaofeng1021 的回复:] [quote=引用 13 楼 sholber 的回复:] [quote=引用 11 楼 zhouxiaofeng1021 的回复:]  int a[8]; int *p=a;下列中不是表示a[1]的是： A、a+1    B. p+1     C. a++      D. ++p A：语法错误 BD： 指向a[1] C:语法错误吧 笑话！A怎么就语法错误了？： int a [8]; int * p = a + 1;[/quote]  你觉得我说的是笑话！请说出理由啊！ 别动不动就笑话！ 你这么SB！ 数组a的地址值是不允许变得！ [/quote] 说脏话烂嘴呀，要注意啊。 还有，是“变的”，不是“变得”，注意文化修为啊，否则很可怕了。嘎嘎~ 数组a的地址不允许变，那别的东西的地址就可以随便变了？这种思想认识很可怕啊！[/quote] 老子就骂你了！怎么了！ 你要想别人不骂你！你先得尊重别人！  [/quote] 什么老子不老子的，在我眼里全是喷孙。[/quote] 不知道是哪个傻逼先喷粪 傻逼[/quote]  彼此彼此，五十步笑百步。

引用 43 楼 sholber 的回复:[quote=引用 42 楼 zhouxiaofeng1021 的回复:] [quote=引用 32 楼 sholber 的回复:] [quote=引用 30 楼 zhouxiaofeng1021 的回复:] [quote=引用 13 楼 sholber 的回复:] [quote=引用 11 楼 zhouxiaofeng1021 的回复:]  int a[8]; int *p=a;下列中不是表示a[1]的是： A、a+1    B. p+1     C. a++      D. ++p A：语法错误 BD： 指向a[1] C:语法错误吧 笑话！A怎么就语法错误了？： int a [8]; int * p = a + 1;[/quote]  你觉得我说的是笑话！请说出理由啊！ 别动不动就笑话！ 你这么SB！ 数组a的地址值是不允许变得！ [/quote] 说脏话烂嘴呀，要注意啊。 还有，是“变的”，不是“变得”，注意文化修为啊，否则很可怕了。嘎嘎~ 数组a的地址不允许变，那别的东西的地址就可以随便变了？这种思想认识很可怕啊！[/quote] 老子就骂你了！怎么了！ 你要想别人不骂你！你先得尊重别人！  [/quote] 什么老子不老子的，在我眼里全是喷孙。[/quote] 不知道是哪个傻逼先喷粪 傻逼

引用 19 楼 my_live_123 的回复:int a[8]; int *p=a;下列中不是表示a[1]的是： A、*(a+1)    B. *(p+1)     C. *a++      D. *++p 这样出题才是合理的 我也觉得这样才对

数组名是一种常量地址，无法进行加减。

引用 6 楼 sholber 的回复:int a [8]; int * p = a; 下列中不是表示a[1]的是：****** 评注：表示a[1]？表示个鹿啊！a[1]的类型是int，ABCD都不正确。语文都没学好还出题目。混帐。 如果你是问“ABCD中，哪一个不是指向a[1]”，则只能选C了。想点赞来着，可惜没这个功能，没办法丢个板砖吧，不要介意

引用 34 楼 sholber 的回复:[quote=引用 33 楼 misskissC 的回复:] [quote=引用 6 楼 sholber 的回复:]  int a [8]; int * p = a; 下列中不是表示a[1]的是：****** 评注：表示a[1]？表示个鹿啊！a[1]的类型是int，ABCD都不正确。语文都没学好还出题目。混帐。 如果你是问“ABCD中，哪一个不是指向a[1]”，则只能选C了。  （猜：）sholber平时看书看得仔细，加上已经拥有的基础知识，能够看懂书中所述。但很多初学者看书比较浮躁，一本书看似很快看完了，但没有看懂书中的知识即没有收获。所以，跟sholber不一样之处表现为“基础 + 看书习惯”。如果做到了这一点，sholber就不会说混账啦。 [/quote]  Li贤哥+八小子＝八贤王，嘎嘎~ 貌似你写了一篇汇编语言的帖子，既然如此钟情于斯，那你为何不读一读《x86汇编语言：从实模式到保护模式》？[/quote]  欧克，加入书单，择时读之。昵称已改

引用 33 楼 misskissC 的回复:[quote=引用 6 楼 sholber 的回复:]  int a [8]; int * p = a; 下列中不是表示a[1]的是：****** 评注：表示a[1]？表示个鹿啊！a[1]的类型是int，ABCD都不正确。语文都没学好还出题目。混帐。 如果你是问“ABCD中，哪一个不是指向a[1]”，则只能选C了。  （猜：）sholber平时看书看得仔细，加上已经拥有的基础知识，能够看懂书中所述。但很多初学者看书比较浮躁，一本书看似很快看完了，但没有看懂书中的知识即没有收获。所以，跟sholber不一样之处表现为“基础 + 看书习惯”。如果做到了这一点，sholber就不会说混账啦。 [/quote]  Li贤哥+八小子＝八贤王，嘎嘎~ 貌似你写了一篇汇编语言的帖子，既然如此钟情于斯，那你为何不读一读《x86汇编语言：从实模式到保护模式》？

引用 6 楼 sholber 的回复:int a [8]; int * p = a; 下列中不是表示a[1]的是：****** 评注：表示a[1]？表示个鹿啊！a[1]的类型是int，ABCD都不正确。语文都没学好还出题目。混帐。 如果你是问“ABCD中，哪一个不是指向a[1]”，则只能选C了。  （猜：）sholber平时看书看得仔细，加上已经拥有的基础知识，能够看懂书中所述。但很多初学者看书比较浮躁，一本书看似很快看完了，但没有看懂书中的知识即没有收获。所以，跟sholber不一样之处表现为“基础 + 看书习惯”。如果做到了这一点，sholber就不会说混账啦。

C

引用 24 楼 aboayan 的回复:我觉得应该是D，C虽然语法错误，但是D肯定是不指向A[1]的，执行后p指向A[1]，但是整个语句指向A[0]，所以我认为是D++在前面是先执行后引用的！

你把ABCD 都写上去就行了！

引用 30 楼 zhouxiaofeng1021 的回复:[quote=引用 13 楼 sholber 的回复:] [quote=引用 11 楼 zhouxiaofeng1021 的回复:]  int a[8]; int *p=a;下列中不是表示a[1]的是： A、a+1    B. p+1     C. a++      D. ++p A：语法错误 BD： 指向a[1] C:语法错误吧 笑话！A怎么就语法错误了？： int a [8]; int * p = a + 1;[/quote]  你觉得我说的是笑话！请说出理由啊！ 别动不动就笑话！ 你这么SB！ 数组a的地址值是不允许变得！ [/quote] 说脏话烂嘴呀，要注意啊。 还有，是“变的”，不是“变得”，注意文化修为啊，否则很可怕了。嘎嘎~ 数组a的地址不允许变，那别的东西的地址就可以随便变了？这种思想认识很可怕啊！

引用 12 楼 sholber 的回复:[quote=引用 11 楼 zhouxiaofeng1021 的回复:]  int a[8]; int *p=a;下列中不是表示a[1]的是： A、a+1    B. p+1     C. a++      D. ++p A：语法错误 BD： 指向a[1] C:语法错误吧 笑话！A和C怎么就语法错误了？： int a [8]; int * p = a + 1; ++ p;[/quote]   引用 19 楼 my_live_123 的回复:int a[8]; int *p=a;下列中不是表示a[1]的是： A、*(a+1)    B. *(p+1)     C. *a++      D. *++p 这样出题才是合理的 就是就是！！！

引用 13 楼 sholber 的回复:[quote=引用 11 楼 zhouxiaofeng1021 的回复:]  int a[8]; int *p=a;下列中不是表示a[1]的是： A、a+1    B. p+1     C. a++      D. ++p A：语法错误 BD： 指向a[1] C:语法错误吧 笑话！A怎么就语法错误了？： int a [8]; int * p = a + 1;[/quote]  你觉得我说的是笑话！请说出理由啊！ 别动不动就笑话！ 你这么SB！ 数组a的地址值是不允许变得！

选C 首先数组不支持自增操作，即使假设数组支持这种操作，那a++就等同于a[0]，++a才等同于a[1]

稍微了解C语言发展史的人都知道，先有不符合任何公开标准的C语言编译器，然后才有C语言语法标准。

答案选C  就是数组名地址和指针


Question: C语言编程将整数1分解成若干个几分之一的和

或参考下面：//求从Begin到End的正整数中挑出任意个数使其总和为Sum的所有方案 #include <stdio.h> int Begin,End,Sum; int j; int o[1000]; long n; void combsum(int b,int e,int s,int d) {     int i;      if (e>s) e=s;     for (i=e;i>=b;i--) {         if ((i+b)*(i-b+1)/2<s) break;         o[d]=i;         if (s-i<=0) {             n++;             printf("%8ld:",n);             for (j=0;j<=d;j++) printf("%d ",o[j]);             printf("\n");         } else {             if (d+1<1000) combsum(b,i-1,s-i,d+1);             else {                 printf("Error:Too deep.\n");                 return;             }         }     } } int main() {     printf("Input Begin,End,Sum:");fflush(stdout);     scanf("%d,%d,%d",&Begin,&End,&Sum);     n=0L;     combsum(Begin,End,Sum,0);     printf("Total:%ld\n",n);     return 0; }

在给定数x的约数之中寻找n个约数使得之和等于x 参考下面： //n个(2<=n<=20)整数(整数范围-10<=x<=10)，判断是否可以从这n个数中找到若干个数，其和为10 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <algorithm> using namespace std; int MAXN=20; int MINN=2; int x[20]; int n,i,j,k,sum; int main() {     srand((unsigned)time(NULL));     n=MINN+rand()%(MAXN-1);     for (i=0;i<n;i++) {         x[i]=-10+rand()%21;         printf("%d,",x[i]);     }     printf("\n");     sort(&x[0],&x[n]);     do {         for (i=2;i<=n;i++) {             sum=0;             k=n/2-i/2;             for (j=k;j<k+i;j++) {                 sum+=x[j];             }             if (10==sum) {                 for (j=k;j<k+i;j++) {                     if (j==k+i-1) {                         printf("%d==10\n",x[j]);                     } else {                         printf("%d+",x[j]);                     }                 }                 printf("YES\n");                 return 1;             }         }     } while (next_permutation(&x[0],&x[n]));     printf("NO\n");     return 0; }

仅供参考：

等式可以认为是(a1+a2+...am)/K，很好理解，a1,...am必然是K的所有约数的和的组合。因此最后题目就是转化为求一个数K的所有约数（质因子），题目K最大才30，之后求出所有约数中,n个数的和等于K的组合。 比如：K=30，30=2*3*5，根据“约数个数定理”，约数有8个，除去自己本身就剩7个，为1,2,3,5,6,10,15,如果你输入n=4，那么就是求这7个约数中，哪4个相加正好等于30的所有组合，根据组合原理，C(7,4)才210中组合，因此循环不会很久。 题目没规定K值，因此，需要K从1到30循环，对每一次循环的K，找出所有所有约数，并对所有约数个数不小于n的情况，循环找出所有n个约数等于K的组合。 建议搜索： 1、约数个数定理 2、求求一个数的所有约数（或者质因子） 3、从N个数中任选M个数相加的和等于K（循环应该就能解决）

引用 2 楼 lovesmiles 的回复:加了限制项n 时，就更加好办了，就是求n个数相加等于30 样例的1/2 1/3 1/8 1/24你这么做能出来？

其实就是整数分解的变体 比如 (18 + 12 + 4 + 2) / 36 = 1. 为了保证分子是1，那么分子必须是分母的约数。为了保证和为1，那么约数之和必须等于分母 故：在给定数x的约数之中寻找n个约数使得之和等于x

加了限制项n 时，就更加好办了，就是求n个数相加等于30

给个思路你： 1=30/30  这个分母就是30，分子也是30，将分子的30做分解就可以了。列出1-29之内相加等于30的各种可能，然后将这些数和分母约分就可以了 比如:30=2+3+25 则1=(2+3+25)/30 1=1/15+1/10+5/6


Question: 位字段结构体疑问

理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

位字段在内存紧张的单片机中用的比较多点

他这样初始化是不是直接略过了结构体中未命名的字段了呢--->是直接忽略了

引用 5 楼 sholber 的回复:结构或者联合的成员不一定非得有名字。如果在一个位字段的声明中只有声明指定符、冒号和宽度，而没有声明符，则声明的是一个未命名的位字段。因为没有名字，所以该成员无法在程序中引用。它唯一的用处是填充，使它所在的结构或者联合具有你所希望的内部布局。在下面的例子中，未命名的位字段成员改变了结构的大小和对齐： struct t {char c; int: 16;}; 如果可能的话，几个相邻的位字段可以共用同一个承载它们的存储单元。当然，也有办法明确禁止这种安排，那就是，在你不希望与其它位字段共用存储单元的那个位字段后边，插入一个宽度为0的位字段。注意，宽度为0的位字段只适用于结构类型，在联合类型中不起作用。在下例中，因为不允许共用同一个存储单元，所以，两个结构类型的大小可能会有一倍的差距： struct a {int i:3, j:5;}; struct b {int i:3, :0, k:5;}; 如上例所示（struct b的声明），因为宽度为0的位字段只是用来告诉C的实现，它前面的位字段不欢迎其它位字段与它共享同一个存储空间，所以，在声明一个宽度为0的位字段时，不允许提供声明符。不过，声明指定符还是必须有的。在下面的例子中，声明符i是不能出现的，但任何声明都至少有一个类型指定符： struct m {char c; int i:0;};	//无效。 struct n {char c; int : 0;};	//有效。  我觉得你说的很详细，很明白，让我搞懂了这个问题！谢谢！

引用 1 楼 user-5 的回复:以前节省内存的方法，能不用就尽量不用，麻烦！ 1 确实是占位用，拼成一个字节 2 int为32位，如果前面定义已经占用了24位，下一个字段是9位，那么这个字段从下一个int开始对齐，空的8位不使用 3 说它麻烦是它的标准规定由实现定义，就是说是以int对齐还是char对齐看编译器 你第二点里说的是不是因为下一个字段是9位，超出了第一个int里剩余的8位的量，所以从下一个32位的int的第一个位开始将这个9个位的字段对齐。是这样理解的吧。还有就是现在真的很少用位字段了吗。。。如果是这样的话，我就少废点时间看这个了，今天刚把位操作这章的习题做完。 最后感谢你的回答。


Question: 基础编程题求问

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

引用 9 楼 u012421456 的回复:[quote=引用 6 楼 shiny8 的回复:] 别的先不说，af数组什么情况？ 数组下标从0开始！！！[/quote]  问题就在这里！！！太感谢了！！！！

遍历数组是 32-99的平方值构成数值

从第一个开始 1024 若能开方：将数字重组找到能开方的数值配对(可能大于一组？)，并将所有数值从遍历数组中删除  下一个... 9999至！  可能效率也不太高

1000 - 9999 总共就这么多四位数，循环一次，找到所有能开根号的数，再搜索配对。

我觉得遍历次数一点也不多。

给个算法就行，我就是想完善一下自己的算法。

引用 6 楼 shiny8 的回复: 别的先不说，af数组什么情况？ 数组下标从0开始！！！

晚上写了一个，已测试正确，供楼主参考 代码如下： #include <iostream> using namespace std;  int cmp(const void*a,const void*b) { 	return *(int*)a -*(int*)b; }   //将每一位数字存入数组 void getNumber(int num,int a[]) { 	int i = 4; 	while (i) 	{ 		a[--i] = num % 10; 		num /= 10; 	} }  //按位比较两个数组的每一位数字 int Compare(int a[],int b[]) { 	int i; 	int count = 0; 	for (i=0;i<4;i++) 	{ 		if (a[i]==b[i]) 		{ 			count ++; 		} 		else 			continue; 	} 	if(count == 4) 		return 1; 	else 		return 0; } int main() { 	int i; 	int j; 	int a[4]; 	int b[4]; 	for (i = 32 ;i < 100; i++) 	{ 		getNumber(i*i,a); 		qsort(a,4,sizeof(a[0]),cmp);//排序 		for(j= i+1 ;j< 100; j++) 		{ 			getNumber(j*j,b); 			qsort(b,4,sizeof(b[0]),cmp);//排序 			if(Compare(a,b)) 			{ 				cout << "{"<<i<<","<<j<<"}"<<endl; 			} 		} 	} 	return 0; }

这个没有多少运算量，32-100的平方数，对每个平方数归并到各个组

各位大神，我想知道为什么我输出的值后一个正确，前一个就不对了呢~am的值我没有变过啊。。。  #include <stdio.h> #include <stdlib.h> int main() { 	int a,am,b,bm,i,j,t,f,k;     int af[4],bf[4];     a=32;     t=0;         bm=0;     while(a*a<=9999)     {        am=a*a;                 af[1]=am%10;        af[2]=am%100/10;        af[3]=am/100%10;        af[4]=am/1000;       for (i=1;i<=3;i++)        {          for (j=1;j<=3;j++)          {            if (af[j]<af[j+1])            {                         t=af[j];              af[j]=af[j+1];              af[j+1]=t;            }                    }        }       t=0;      for (b=a+1;b*b<=9999;b++)        {          bm=b*b;          bf[1]=bm%10;          bf[2]=bm%100/10;          bf[3]=bm/100%10;          bf[4]=bm/1000;          for (i=1;i<=3;i++)          {            for (j=1;j<=3;j++)              if (bf[j]<bf[j+1])              {                t=bf[j];                bf[j]=bf[j+1];                bf[j+1]=t;                //printf("%d  ",t);              }            }           f=1;           for (i=1;i<=4;i++)           {             if (af[i]!=bf[i])              {               f=0;               break;             }           }           if (f==1) printf("%d,%d\n",am,bm);        }        a++;      }     	system("pause"); 	return 0; }


Question: casio dt930 串口发送数据

比如： param=B_9600|PARI_NON|CHAR_8|STOP_1|SI_ON|XON_XOFF|RTS_ON|ER_OFF;

引用 1 楼 zhao4zhong1 的回复:搜“串口调试助手源代码” 好的 我去看看 c语言的串口源码；  我在网上下的dt930 开发手册中看到了一些关于串口的函数，但是我还是有些不理解     这个函数里面的第二个参数 _UW param 我应该怎么传值， UW 类型相当于c中 unsigned long  /* 32-bit integer without symbol*/  期望大家可以帮我解答，谢谢。

搜“串口调试助手源代码”


Question: Cfree中*.h使用问题

谢谢----------------

你c-free什么版本？ 我只用过5.0 就放到工程的存放头文件的文件夹中啊

那个文件叫什么？？

放在和.cpp相同文件夹下 #include "xxxx.h"


Question: 求助，安装SDK遇到如下问题

IE版本比较低或者没装吧 安装高版本IE重启下就可以了吧 我觉得这个google翻译都可以帮你搞定

错误提示写的很明显啊？

IE安全级别的问题？

你电脑上没装IE？


Question: 一维数组求学生最大成绩以及最小成绩

引用 2 楼 FUHAODAASD 的回复:楼上的 我想知道我错在哪里啊  问题有两： 1. 数组越界，LS有讲。 2. 比较判断弄反。

LS正解 不知道楼主为什么会想要a[i+1]， 这样当i=4的时候还会导致数组取索引越界  只要比较当前索引的值和最大最小值，来判定是否用当前索引的值替换最大最小值就可以了

楼上的 我想知道我错在哪里啊

#define n 5 void main() { float a[n],max,min; int i; for(i=0;i<n;i++) scanf("%f",&a[i]); max=min=a[0];         for(i=1;i<n;i++) { if(max<a[i]) max=a[i]; if(min>a[i])  min=a[i]; } printf("%f,%f\n",max,min); }


Question: 关于静态库的问题

建议LZ看下《程序员的自我修养 --链接、装载与库》

楼上正解，顶一下。。。

静态库链接，是把静态库完整拷贝一份到编译出来的可执行文件中，会增大可执行文件的大小，这是第一个问题，而当多个不同的程序都链接了一个静态库，而同时运行时，内存中是会存在多份静态库的拷贝，而动态库则在内存中只存在一份拷贝


Question: Uva 1589 xiangqi, WA了n次了，寻大神找找错误

代码就不看了，我记得以前WA的原因是王车在一起，下一步王吃掉车就活了没判断到，你看看有没有这个问题


Question: Uva 1589 xiangqi,   WA了n次了，寻大神找找错误

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


Question: 头晕的指针

thankyou

#include<stdio.h>  int main(void) { int a=2; int *i=&a; int' to 'int *' printf("%d\n",*i);//值 printf("%d\n",i);//地址值 printf("%d\n",&a);//地址值 return 0; }

int main(void) { int *i,a; a=2; i=&a; printf("%d\n",i);//地址 printf("%d\n",&a);//地址 printf("%d\n",*i);//值 return 0; }


Question: 回文字符

引用 5 楼 crasylph 的回复:[quote=引用 3 楼 axiqia 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。受教了，谢谢。可是代码运行的结果是正确的，可是提交后 是WA，实在是有点头大，才发帖的[/quote]  等等你确定你的输出格式对吗。。我怎么觉得最后多打了个换行？[/quote] 格式不对不应该是PE吗

引用 3 楼 axiqia 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。受教了，谢谢。可是代码运行的结果是正确的，可是提交后 是WA，实在是有点头大，才发帖的[/quote]  等等你确定你的输出格式对吗。。我怎么觉得最后多打了个换行？

引用 3 楼 axiqia 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。受教了，谢谢。可是代码运行的结果是正确的，可是提交后 是WA，实在是有点头大，才发帖的[/quote]  WA一般是边界条件没有考虑好，导致一些边界上的测试数据过不了

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


Question: c语言编写小游戏思路

《Visual C++ 游戏开发经典案例详解》

大学里抄点游戏思路没啥，你也可以自己想一个（可能一段时间也没好点子，这样会比较受挫）。就算一个工作多年的游戏设计师，也不一定能立马想出一个好点子。  设计思路上个人建议，想要做的出彩，就先去玩一些经典的FC小游戏，这些基本上一两天能通关，浪费时间不长，又能学习前人的一些经验，设计上参考这些游戏的点子，代码么可以自己写。 仅仅为了交个作业，完成以下任务，建议直接贪吃蛇，俄罗斯方块，连连看等这些抄烂的，保证能快速完成。  实现思路上个人建议，既然是小游戏，还是全部自己动手写比较好，不要用游戏引擎，CSDN博客上有大神 介绍全套的 WIN32 下超级玛丽 实现，可自行搜索参考。核心的东西都是一样用C可以实现，界面和图形绘制显示，要根据不同平台进行针对学习。  还可以参考一下云风的 游戏程序设计 以及他早年编写的 风魂++引擎，可以学习的地方很多。  纯手打，接点分。

引用 2 楼 li824814957 的回复:可是那样不就是抄袭别人的吗？？ 你的意思是自己写一个别人从来没写过的游戏？ 楼主既然说了是想引用练练手，  但又引用半点思路都没有 还不看看别人的思路？ 反正是练手

引用 2 楼 li824814957 的回复:可是那样不就是抄袭别人的吗？？ 只是学习

同问，有什么方面的书籍或者知识要了解？感觉用c从学习语言的可是化界面的编程差距好大。

可是那样不就是抄袭别人的吗？？

网络上搜，一搜一大堆，简单的游戏，猜数字、贪吃蛇等，源码都有的


Question: 找bug

缺少头文件，还有main函数里，b,c没有初始化、

引用 1 楼 user-6 的回复:看上去b c 没房子住  +1

在调用fun 函数前没有 给第2 3 个参数分配空间

b和 c 指针没初始化

*b=a[0];如果是想让b指向a[0]的话应该用b=&a[0]; fun(a,b,c); printf("%d,%d",*b,*c); 在某些逻辑下，fun中会出现c未被初始化的情况。

看上去b c 没房子住


Question: 关于gets_s 可选函数读取键盘输入问题，就大神解答！！！

int mygets(char *n,int L,int minv,int maxv) {

int mygets(char *n,int L,minv,maxv) {  int i,v;  rewind(stdin);  if (NULL==fgets(n,L,stdin)) return 0;  for (i=L-1;i>=0;i--) if (n[i]=='\n') {n[i]=0;break;}  if (1!=sscanf(n,"%d",&v)) return 0;  if (minv<=v && v <=maxv) return 1;  return 0; }  ... if(!mygets(number,LEN,1,999)){ ...


Question: 怎么使用自己编译的dll或exe里面的文本文件

搜从资源中释放文件 http://www.cnblogs.com/rogee/archive/2010/12/17/1909204.html

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

引用 3 楼 antiwise 的回复:估计我这个帖子的标题说的太模糊了导致1楼的回答（对我没什么帮助），2楼说的在帖子里我已经提到了，我知道怎么使用资源文件来释放vbs那个文本文件。其实如果解决了能把资源文件的引入的原始文件随着工程一起编译的话，也可以，比如我在本机引的资源文件在C盘，别个机子没有CP盘引的那个文件，或者放到了D盘，而且修改了引的文件里的内容，又把工程给我，我需要的是新的工程+新的资源引的文件！！！  真看不懂你说什么.  1 资源文件本来就是要编译进exe的. 编译后, 资源文件是在exe中, 而不是在机器中 http://blog.csdn.net/wangningyu/article/details/4378378  2你要别人修改过的文件, 你就管他要啊. qq传, 拿U盘自己考. 拆他硬盘都行.


Question: 近来学习编程，想知道静态库与动态库之间的区别

C语言的静态库与动态库对比分析，各有长短                库:  指由标准常用函数编译而成的文件，旨在提高常用函数的可重用性，减轻开发人员负担。常用的sdtio.h，math.h等库便是C函数库的冰山一角。                     1.静态库:指编译链接阶段将整个库复制到可执行文件                             1.1优点：静态链接的程序不依赖外界库支持，具有良好的可移植性。                             1.2缺点:  每次库更新都需要重新编译程序，即使更新很小或只是局部。                             1.3缺点：每个静态链接的程序都有一份库文件，存储时增加了硬盘空间消耗，运行时则增加了内存消耗。                     2.动态库:指直道运行时才将库链接到可执行程序                             1.1优点:  动态链接方式的程序不需要包含库（编辑链接时节省时间），占用的空间小很多。                             1.2优点:  运行时系统内存只需提供一个共享库给所有程序动态链接，内存消耗减少。                             1.3缺点:  需要系统中动态库支持才可运行，可能有动态库不兼容问题                 小结：在linux系统中:静态库.a                                                         动态库.so                                在windows中:静态库.lib                                                         动态库.dll


Question: 对于const的疑问

我来试着解释下楼主所谓的  “节约内存”  首先程序有四个空间（）： 栈： 由操作系统提供，是个数据结构。底层支持，专门寄存器处理。先进后出。  堆：任意存取，首地址记录堆空间大小，可以动态扩容。  数据段：     1、只读数据段；const修饰变量（不会被更改）      2、已初始化读写数据段；静态变量被初始化/全局变量被初始化      3、未被初始化数据段；静态、全局变量未被初始化。（Linux下有bss段保存）  程序代码区：函数体二进制代码。  解释下楼主所谓的“节约”吧：  一个函数的执行是在栈空间执行，就算你在函数里面const也会在静态区间开辟空间保存。 我想节约的话也也是函数执行的栈空间节约。。  然而静态空间是在程序一开始执行就存在分配内存的。  宏只是替换，依旧要被编译器替换后编译 所以，我觉得楼主的纠结毫无意义，，

变量赋值没什么分配内存的说法 而你的例子const对象明显比宏多占了8个字节

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

引用 3 楼 zhao4zhong1 的回复:不要纠结各种常量了，这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢！  const的思想不是能否修改，而是程序优化。

闻所未闻，岂有此理，信口雌黄，道听途说，通过歪门邪道学的C。

我想告诉你的是， 如果用vs， 所有的pi值 也就是3.14159 都会优化成一个const值，位于常量区。最后只要定义是const的都直接应用该值 可以找书看看，const的变量最后生成exe都存哪儿了。 你可以测试一下 看看你上面例子 变量的地址是不是一样， 如果一样说明他们引用的就是一个值， 开优化，不开优化都试试。你会找到你要的答案的


Question: c函数体内extern

服了你们了 编译的splayer，里面包含了一个libavcodec项目， rv10.c AVCodec rv10_decoder = {     "rv10",     CODEC_TYPE_VIDEO,     CODEC_ID_RV10,     sizeof(MpegEncContext),     rv10_decode_init,     NULL,     rv10_decode_end,     rv10_decode_frame,     CODEC_CAP_DR1,     .long_name = NULL_IF_CONFIG_SMALL("RealVideo 1.0"),     .pix_fmts= ff_pixfmt_list_420, }; allcodecs.c  void avcodec_register_all(void) {... 	extern AVCodec rv10_decoder;  	avcodec_register( &rv10_decoder ); ... } 这样编译不过libavcodec\allcodecs.c(96) : error C2143: 语法错误 : 缺少“;”(在“类型”的前面)  extern AVCodec rv10_decoder;  void avcodec_register_all(void) {... 	avcodec_register( &rv10_decoder ); ... } 这样就过了

你看的是什么书啊，真是。。。  http://www.afanihao.cn/c_guide/

exern是用来申明全局变量的，函数体内的变量是局部变量

引用 15 楼 my_live_123 的回复:[quote=引用 2 楼 sholber 的回复:] 是 extern struct A a; 不是 extern A a;  另外，C禁止空的结构{}。 你加上不加上都是不对的。 C的结构体中不允许extern的，一旦使用外连接存储对象，在构建符号表的时候，无法确定结构体的大小，必定报错的。这和使用static还不一样[/quote] 悲剧`没有仔细审题被抓了小辫子``

引用 2 楼 sholber 的回复:是 extern struct A a; 不是 extern A a;  另外，C禁止空的结构{}。 你加上不加上都是不对的。 C的结构体中不允许extern的，一旦使用外连接存储对象，在构建符号表的时候，无法确定结构体的大小，必定报错的。这和使用static还不一样

引用 13 楼 qq_21456317 的回复:所以我觉得你 extern   A; extern   a; 试试。 我傻逼了，这样语法错误，你得先引用那个你自己定义的类型，才能引用这种类型的变量，要不然你直接在另一个文件中重新定义一次A?

所以我觉得你 extern   A; extern   a; 试试。

有两种声明，一种是定义声明一种是引用声明，在对一个文件作用域的已在另一个文件定义的变量引用时，要用到extern，你看你在其他文件先后定义了一种新结构A类型，又用这种A类型定义了一个变量a，但是你在另一个文件中只引用声明了一次。

引用 10 楼 gqjjqg 的回复:引用 9 楼 sx5486510 的回复:[quote=引用 8 楼 gqjjqg 的回复:] 楼主都不了 声明和定义。求指导，哪里有问题  简单来说就是：定义某种类型(struct A)的对象(a)之前，必须要声明该类型。  多看看课本。[/quote][img=https://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/001/face/40.gif][/img

引用 4 楼 sx5486510 的回复:[quote=引用 2 楼 sholber 的回复:] 是 extern struct A a; 不是 extern A a;  另外，C禁止空的结构{}。我只是举例，不要在乎这些细节[/quote]  你就是错在细节。

楼主在“另一个文件中”都没有定义struct A, 自然是不行的。

引用 9 楼 sx5486510 的回复:引用 8 楼 gqjjqg 的回复:楼主都不了 声明和定义。求指导，哪里有问题  简单来说就是：定义某种类型(struct A)的对象(a)之前，必须要声明该类型。  多看看课本。

引用 8 楼 gqjjqg 的回复:楼主都不了 声明和定义。求指导，哪里有问题

楼主都不了 声明和定义。

引用 5 楼 mymtom 的回复:楼主在“另一个文件中”都没有定义struct A, 自然是不行的。在一个.c中定义struct A a;现在另外一个.c的某个函数中声明extern struct A a;为什么会编译不过，是vs不支持什么标准还是什么原因？

引用 2 楼 sholber 的回复:是 extern struct A a; 不是 extern A a;  另外，C禁止空的结构{}。我只是举例，不要在乎这些细节

顶楼上 ~~~~~~~

表示A类型未定义，包含定义A类型的头文件即可


Question: 怎么清除netlink socket的缓冲区

while循环条件确定是正确的吧？ 不太懂，关注。


Question: 简单复习一下三年没怎么用的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: c语言 函数十六进制转换成ascii怎么写啊

理解数组和内存

引用 2 楼 luciferisnotsatan 的回复:没看懂1f 41 怎么转成38 30 30 31 。  lz你确定是ascII转换？字符 1 对应的是 0x31这个值[/quote  [quote=引用 楼主 yang627468471 的回复:] 列如十六进制1f 41 转换成 ascii 码 是38 30 30 31 大神求解啊，困扰了写一个函数  将1F41转化为十进制就是8001 8的ascii编码就是38 0是30 1是31 就行了

char s1 = 0x1f;

int hex=0x1f41; char s[10]; int L,i; sprintf(s,"%X",hex); L=strlen(s); for (i=0;i<L;i++) printf("%d ",s[i]);


Question: 这样的封装有什么意义

请牢记：源代码本身的书写是否结构化或面向对象或符合设计模式或敏捷…并不重要，重要的是你是否使用结构化或面向对象或符合设计模式或敏捷…的方法命名标识符、阅读、修改、检查、测试源代码。  意思是你程序结构看上去再合理，再简洁，也不一定比看上去一团乱麻的程序结构在运行或修改时更不易出错，更方便修改，出错了更容易找到哪里出错和具体出错的原因，更容易改正错误。  试对比 图书馆（对图书的分类够结构化了吧） 和 搜索引擎（可看作是扁平化任何结构数据，仅支持全文检索） 哪个处理信息更方便、更高效。  所以 与其费劲去重构代码让其看上去更简洁、更合理 不如费劲学习grep、sed、awk、……这类全文搜索和批处理编辑的工具。  结构越复杂，越难修改，越难除错。 有时（甚至大多数时候），看上去越合理、越简洁的代码，运行起来性能越差，出错时查找原因越难，找到出错原因后改正越费劲。  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George

嗯，就这个类来说，没啥必要，代价有点大。 要是每个类都这么干，那别写代码了。  引用 4 楼 chuansunshine 的回复:代理模式， 如果后期要做扩展有很多好处。 比如更改内存申请方式， 虽然还有其他的作用， 但是此处没看出优势

因为楼主你点进去那文章看看，人家用C来模拟OOP,当然看起来蛋疼啦 人家是用来学习用的

楼主奇怪：怎么操纵结构成员。 实际不需要，因为通过接口函数完成功能。如果作者加几个接口函数，楼主就明白了。差在没有功能性的接口函数。

还有就是调用次数很多的话, 节省劳动量, 代码看着也干净点

typedef struct Point point; point * new_point(); //newer a point object void free_point(point *point_);// free the allocated space 理解上面3行是关键  使用： point p = new_point();//生成 //使用  free_point(p);//销毁

比如，当Point变成 x y z三个分量是，不会修改 .h 文件，所有#include “point.h”的代码都不会重新编译。节省编译时间，提高开发效率。


Question: 二进制文件换成txt文件时，fread，fwrite和fprintf,fscanf怎么改

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


Question: 字符串连接问题

谢谢 回复 问题已解决！多谢！

在VS2013上跑了一遍，把gets改成了gets_s  ansi ， Unicode； 编译为C，C++都没问题

多了什么？我复制了一遍，没发现有问题。

使用了什么字符集？ansi？unicode？


Question: 长整数加减计算器的实现

使用Openssl中的 BIGNUM，可以实现任意长度的整数的运算。

仅供参考：#include <stdio.h> #include <string.h> #define MAXLEN 1000 char a1[MAXLEN]; char a2[MAXLEN]; static int v1[MAXLEN]; static int v2[MAXLEN]; static int v3[MAXLEN]; int i,j,n,L,z; void main(void) {     scanf("%d",&n);     for (j=0;j<n;j++) {         scanf("%s%s",a1,a2);          L=strlen(a1);         for (i=0;i<L;i++) v1[i]=a1[L-1-i]-'0';          L=strlen(a2);         for (i=0;i<L;i++) v2[i]=a2[L-1-i]-'0';          for (i=0;i<MAXLEN;i++) v3[i]=v1[i]+v2[i];          for (i=0;i<MAXLEN;i++) {             if (v3[i]>=10) {                 v3[i+1]+=v3[i]/10;                 v3[i]=v3[i]%10;             }         }          printf("Case %d:\n", j+1);         printf("%s + %s = ", a1, a2);          z=0;         for (i=MAXLEN-1;i>=0;i--) {             if (z==0) {                 if (v3[i]!=0) {                     printf("%d",v3[i]);                     z=1;                 }             } else {                 printf("%d",v3[i]);             }         }         if (z==0) printf("0");          printf("\n");     } } //Sample Input //3 //0 0 //1 2 //112233445566778899 998877665544332211 // //Sample Output //Case 1: //0 + 0 = 0 //Case 2: //1 + 2 = 3 //Case 3: //112233445566778899 + 998877665544332211 = 1111111111111111110

+8234567890 +5655456545 —————— 手算加减法的步骤模拟一下  两个数先调整成绝对值大的在前，小的在后，绝对值大的若为负数做一下变换 比如 -53322 + 999 变换为 -(53322 - 999)


Question: 学K&R的C程序设计语言第一章的这个程序就卡住了

我这样跟你说吧，你按enter以为是‘\n’,编译器是没法是别的，所以只有按EOF程序才会停止，在控制台EOF是按ctrl+ z，你可以试试肯定就行了！

引用 9 楼 episode1994 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  Dev C++调试不好用，趁早换。 谢谢回复，我现在还在c的入门阶段，理解语法等等，DEV是看网易云课堂上老师用的，老师贴的程序结构确实清楚了很多。。对于小白能不能推荐个IDE呢？VC每次都要新建工程。。[/quote] 你为什么不 建一个比如test工程，使用源文件test.cpp 以后每次写了比如MyProg123.cpp，将MyProg123.cpp拷贝覆盖test.cpp，重建test工程，运行test.exe调试，通过后将test.cpp拷贝覆盖MyProg123.cpp 呢？

引用 9 楼 episode1994 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  Dev C++调试不好用，趁早换。 谢谢回复，我现在还在c的入门阶段，理解语法等等，DEV是看网易云课堂上老师用的，老师贴的程序结构确实清楚了很多。。对于小白能不能推荐个IDE呢？VC每次都要新建工程。。[/quote] CFree

引用 7 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  Dev C++调试不好用，趁早换。 谢谢回复，我现在还在c的入门阶段，理解语法等等，DEV是看网易云课堂上老师用的，老师贴的程序结构确实清楚了很多。。对于小白能不能推荐个IDE呢？VC每次都要新建工程。。

引用 3 楼 worldy 的回复:line都没有初始值，你拷贝什么？getchar（）函数。。。

line都没有初始值，你拷贝什么？

引用 1 楼 mynameislu 的回复:Copy 函数接收的两个参数其实就是字符串的首地址了，可是这段程序在控制台里运行不出来啊，输入一段字符按运行什么都没有

Copy 函数接收的两个参数其实就是字符串的首地址了，

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

引用 4 楼 my_live_123 的回复:程序没有错误啊 你的问题需要理解这段话 A function may change the values of its parameters, but these changes cannot affect the values of the arguments.  On the other hand, it is possible to pass a pointer to an object, and the function may change the value of the object pointed to. A parameter declared to have array or function type is adjusted to have a pointer type as described in 6.9.1. 以及参考C99的6.7.5.3条款 关键是我用DEV C++和VC6.0 运行出来都是：输入一行字符串，按enter键就换行，继续输入还是这样，也没输出。。


Question: C中变量名储存在哪？

引用 8 楼 zhao4zhong1 的回复:存在编译器比如gcc或g++所管理的数据结构中。 有时候会从这个数据结构（即符号表）中导出到调试辅助用的exe文件或pdb文件中一份。

变量名只是地址标识符,为了程序员的方便. 你可以随便拿一个应用程序,然后进行反汇编,就可以看到编译后的实际内存分布. 里面的变量名全部变成了内存地址或者各种寄存器.  参考《程序员的自我修养》 参考 汇编语言

变量名存放在变量名表

参考《程序员的自我修养》

变量名是 写代码的人 写给编译器看的  编译器看完就扔了  不用存

估计懂汇编等语言的人，可能比较清楚 就我个人理解， 我觉得C++这些变量名称，函数名称等等，在高级语言中，只是方便给我们看的，并不是方便给电脑看的 所以需要，C++编译链接等等过程，转化成电脑可以理解的语言，就是二进制一堆数字吧，比如地址等等 这样就没有必要存储变量名称 个人理解，纯属于

编译后，名字都变为了地址，没有名字信息

我理解，变量名只是代表一个内存区域，供编译器使用的。

编译原理：存放到“符号表”中。

反汇编看小，变量名只是地址标识符

这个需要参考汇编语言，当变成汇编时，只会出现对应变量地址 。可以看下深入理解计算机系统。

存在编译器比如gcc或g++所管理的数据结构中。


Question: const修饰的只读变量必须在定义的同时初始化，这是为什么？

引用 3 楼 taodm 的回复:因为语言标准的规定。 你完全可以自己造一个新语言，const的可以不同时初始化。 不要把自己绕太深了。如果是标准规定的话，这样理解起来会更好

如果不在定义的时候初始化，他就会是一个随机值，之后又不能赋值，那要他有什么用。

因为它在语义上是不可修改的。


Question: 一道关于C语言的题

逆序输出

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

这个程序作用是eg  你输入mylove  输出是evolym，里面的i=5是限制可倒的字符，你阔以试试哦

一个简单的递归调用，你输入五个字符：如 abcde 它会给你逆序输出：edcba 至于为什么会逆序输出？你画下递归调用图就明白了

你运行一下试试就知道了！


Question: c primer plus第十四章 练习题2

引用 3 楼 guicaisa 的回复:[quote=引用 1 楼 zhangxiangDavaid 的回复:] 题目的意思是在程序中你可用数字或字符代替月份，这不是要你同一个程序处理三种输入，选一个即可。  难道是我想复杂了吗。。[/quote] 想复杂了

引用 1 楼 zhangxiangDavaid 的回复:题目的意思是在程序中你可用数字或字符代替月份，这不是要你同一个程序处理三种输入，选一个即可。  难道是我想复杂了吗。。

觉得应该将monthn定义成2个元素的char型数组然后用%s接收；再判断monthn，name，abbrev中的一个是合理的表达就得到月份；


Question: 结果为什么是多少，为什么？

40, 1 Array在main函数中sozeof值为40，即4*10，在foo函数内sizeof的值为4，即一个指针的大小。该结果显示，数组Array作为函数参数被自动转化为指针了，发生了隐式的指针化。


Question: 文件的理解

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

引用 1 楼 user-3 的回复:看英文,不要看中文, 另外要看完.(下面的英文应该让你更好懂)  Files are logical units of information created by processes. A disk will usually contain thousands or even millions of them, each one independent of the others. In fact, if you think of each file as a kind of address space, you are not that far off, except that they are used to model the disk instead of modeling the RAM. 的确，明白了

我理解的不深，但我知道电脑文件都是二进制存储的，那么你可把它看做地址空间吧


Question: 关于指针的一些问题

人家是初学者。。。。  引用 3 楼 zhao4zhong1 的回复:计算机组成原理→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

"cannot convert from 'const int' to 'int *" 很明白吧  类型不符 int* i=2 不对  *yy 指针当做数组使用

#include<stdio.h>  int main(void) {  int *i=2;//怎么改啊，请解释哈子C:\Users\toshiba\Desktop\指针.cpp(6) : error C2440: 'initializing' : cannot convert from 'const int' to 'int *'  printf("%d\n",i);  return 0;

#include<stdio.h>   int main(void)  {   char *yy= "abcdefghijk";  //定义指针，并指向字符串，yy保存了字符串的地址   while (*yy != '\0')  //*yy取值，表示获取yy保存地址所指向的值 第一次是‘a’  {  putchar(*yy); //输出yy所指向的字符   yy+=2;  //指针移动两个单位，如果上一次是a，这次指向c  if ('\0' == *(yy-1))  {  break;  }  }   return 0;  }  上面的*yy表示的是啥？是地址还是符号？ //取地址符号是&  #include<stdio.h>   int main(void)  {   int *i=2;   //我试了，语法错误，工具vs2008  printf("%d\n",i);   return 0;  } 为啥第二个程序中i表示的是值2？？？第一个程序yy表示的就不是值了？？

*yy表示你指向的字符串，yy表示这个字符串的地址 yy+2，表示地址移动两个字节。 而你第二个写的程序 int *i=2,实际上是初始化指针指向0x00.....2 这个地址，你使用%d输出了这个整数，所以输出是2，你可以编译下%p 输出下i。


Question: 关于C语言类型提升的问题

引用 4 楼 lgbxyz 的回复:[quote=引用 3 楼 fly_dragon_fly 的回复:] 标准规定需要提升  在标准的什么地方?[/quote] 没注意是c的问题，c标准好久没看，真不知道，只知道 C++11 5.3.1.10 只要c的话请忽略该回答

引用 4 楼 lgbxyz 的回复:[quote=引用 3 楼 fly_dragon_fly 的回复:] 标准规定需要提升  在标准的什么地方?[/quote] N1570, 6.5.3.3

Update

引用 3 楼 fly_dragon_fly 的回复:标准规定需要提升  在标准的什么地方?

标准规定需要提升

Update

layout src：显示源代码窗口 layout asm：显示反汇编窗口 layout regs：显示源代码/反汇编和CPU寄存器窗口 layout split：显示源代码和反汇编窗口


Question: 没有声明的函数为什么可以调用？

引用 13 楼 PhycoKnight 的回复:我的就是在A中实现的，在B中直接调用，我自己写的函数，确定自己没有声明过。  你的A.B中有一个是.h文件吧,   要么就是有同名函数, 或者编译器特殊.  至少在VC系列中, 这样的条件是不可能编译通过的.

引用 6 楼 sholber 的回复:我就不引用C标准的条款了，直接上截图，你怎么说：   大神太多，小白不好意思回复，希望回复对你有帮助   int i; 全局变量，默认为0，存放在bss段 属于弱符号，弱符号可以被引用，强符号就是存放在data段，也就是初始值非0； 强符号 强符号 强引用 报错，符号重定义 强符号 弱符号 弱引用 可行 弱符号 弱符号 弱引用 可行  还有函数也存在强弱，强弱符号之间的转换 看编译文档  如果将int i ；改为除int i= 0（全局变量int i = 0；其实和不初始化是一样的）外的初始化一定会报错；  至于 在头文件 中定义， 然后包含，编译器在编译源文件的时候经过预处理器预处理 输出源文件 将 宏处理命令解析成相对应的源代码 ,会报重定义错误 还有要看编译器怎么解析强符号与弱符号，上面的测试在gcc下面可通过,g++会报错。  关于弱定义的知识：http://www.educity.cn/wenda/308231.html

怎么还在讨论，还没有结帖啊？？ 既然如此，朕再来说几句。 早期的编译器允许这种做法，再现在的C标准要求函数使用前必须先声明，但看在那些业已存在的大量程序的面子上，有很多编译器直到现在还容许这种做法。

说下编译器和环境吧。 不然就会像 a+++b++a++一样，随编译器不同而结果不同。

引用 15 楼 xiaohuh421 的回复:[quote=引用 13 楼 PhycoKnight 的回复:]  我的就是在A中实现的，在B中直接调用，我自己写的函数，确定自己没有声明过。  你的A.B中有一个是.h文件吧,   要么就是有同名函数, 或者编译器特殊.  至少在VC系列中, 这样的条件是不可能编译通过的.  [/quote] 我做的是嵌入式的开发，我确实没有声明，也不是.h文件，用的IAR编译的，我仔细的想了想，return后面的那个函数是调用的一个库函数，对所有的文件都是公开的，那个库函数中的两个参数都是全局，可能这个是能够调用的原因吧

引用 8 楼 mymtom 的回复:[quote=引用 6 楼 sholber 的回复:] 我就不引用C标准的条款了，直接上截图，你怎么说：  加个编译  引用 楼主 PhycoKnight 的回复:我在文件 A.c 中定义了一个函数：  int fun(void) {         return  WM_GetDialogItem( g_hWin , ID_EDIT_0); } //其中 g_hWin 是整个工程的全局，ID_EDIT_0是A.c中的全局   然后 fun 这个函数没有声明过，但是我在 B.c 中调用的时候，直接就可以调用，为什么？ 是的，确实可以调用，但是这说明什么呢？C语言里，记住先声明后使用的原则吧。  #include <stdio.h>  int main(int argc, char *argv[]) {         double d;          d = log10(10);          printf("%f\n", d);          return 0; }  上面的程序，如果楼主有条件在AIX下运行，一定会有惊喜的。 [/quote]  以C标准文档为准。自己看吧，不费口水了。

只要声明全局变量就默认 前面加extern（程序员可以不加，但编译器默认加上）  百度来的

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

引用 6 楼 sholber 的回复:我就不引用C标准的条款了，直接上截图，你怎么说：  加个编译  引用 楼主 PhycoKnight 的回复:我在文件 A.c 中定义了一个函数：  int fun(void) {         return  WM_GetDialogItem( g_hWin , ID_EDIT_0); } //其中 g_hWin 是整个工程的全局，ID_EDIT_0是A.c中的全局   然后 fun 这个函数没有声明过，但是我在 B.c 中调用的时候，直接就可以调用，为什么？ 是的，确实可以调用，但是这说明什么呢？C语言里，记住先声明后使用的原则吧。  #include <stdio.h>  int main(int argc, char *argv[]) {         double d;          d = log10(10);          printf("%f\n", d);          return 0; }  上面的程序，如果楼主有条件在AIX下运行，一定会有惊喜的。

引用 12 楼 PhycoKnight 的回复:[quote=引用 1 楼 sholber 的回复:] 你怎么知道它没有声明过  因为是我自己写的。。。确实没有声明[/quote]  但是如果我在函数中传入一个参数，不声明的话就报错了

引用 9 楼 xiaohuh421 的回复:函数需要声明的情况是: 1. 函数是外部定义的, 即调用者看不到函数的实现时.   比如函数A在a.cpp中实现的, 函数B在b.cpp中实现的. 函数B要调用A,则需要先声明, 同样, A调用B也需要先声明. 2. 调用处, 函数还未实现.   比如函数A在第1行到15行.  函数B在17行到20行.  这时A调用B就需要先声明.  反过来B调用A的话, 因为A在B的前面已经实现, 所以就可以不用声明了.  我的就是在A中实现的，在B中直接调用，我自己写的函数，确定自己没有声明过。

引用 1 楼 sholber 的回复:你怎么知道它没有声明过  因为是我自己写的。。。确实没有声明

我就不引用C标准的条款了，直接上截图，你怎么说：

引用 3 楼 sholber 的回复:[quote=引用 2 楼 zhangxiangDavaid 的回复:] 在c语言中全局的函数和变量是对每个文件可见的，但在别的文件中变量需要用extern声明，才可用；而函数不需要 什么叫全局的？ 在A文件中声明的函数，若单独编译的话，能在B文件中看见？？ 我在A文件中有如下声明： int i = 0; 我在B文件中非得用 extern int i; 用 int i; 就不行？你肯定？？[/quote] 函数不需extern声明，即可在其他的文件可用，而变量必须用extern声明才可用。

因为C语言当年的垃圾规定。

引用 2 楼 zhangxiangDavaid 的回复:在c语言中全局的函数和变量是对每个文件可见的，但在别的文件中变量需要用extern声明，才可用；而函数不需要 什么叫全局的？ 在A文件中声明的函数，若单独编译的话，能在B文件中看见？？ 我在A文件中有如下声明： int i = 0; 我在B文件中非得用 extern int i; 用 int i; 就不行？你肯定？？

你怎么知道它没有声明过


Question: 菜鸟VC6.0报错One or more breakpoints are not positioned on valid lines.

为什么要用VC6呢？ 建议使用VS2008或以上版本，程序界面、帮助文档全中文。  珍惜生命，远离VC6

这种问题有时候真的是莫名其妙。 ①清理，重新编译； ②在工程中删除文件，然后再重新加入； ③删除工程目录下的debug目录，重新编译； ④重新安装VC6.0。  试试吧，这是我碰到这种情况时试过的方法。

试试在64为机器上的32位虚拟机中运行VC6

编辑、断点、Remove All、确定。


Question: 如何在节约内存的情况下存放一个位的数据

最简单， 最省事， 向八楼看齐。 不想用crt就 看9楼， 都是大神

1、用位运算，存到一个BYTE数组里，按位存、取值； 2、内嵌汇编。

//将0-7位当中的1位设置为1,指针b应该指向你分配的首地址 void setOneBit(byte*b,int pos) {  if(pos == 0)    *b = *b | 1; ....  else if(pos == 6)   *b = *b | 32 }

存到硬盘, 最节省内存

std::vector<bool>

引用 5 楼 cheng7068 的回复:这种采用位操作应该是最省内存空间的，采用union数据结构吧  这样挺好

c++ 里有bitset类型，有多少位就定义多少位，很省内存 example： #include  <bitset> bitset<30> bitvec; // bitvec含30位，每一位默认初始化为0  具体细节参考c++ primer

这种采用位操作应该是最省内存空间的，采用union数据结构吧

看你的数据有多少, 然后申请内存. unsigned char length[数据长度/8 + 1]; 然后按位操作即可, 最多浪费7bit.   如果考虑机器字啥的, 32位机: unsigned int length[数据长度/32 + 1]; 64位机: unsigned long length[数据长度/64 + 1];

stl 里的 bvector, 不谢！

不是可以定义这种吗： struct xxx { char data:1; }; 这种结构体其实还是要占用8个字节 楼主可以参考std::vector<bool>的实现，一个char表示8个数据

两种方案。 第一种是使用位字段，但相邻的位字段是否能挤在同一个存储单元里，是由Ｃ的实现决定，所以不保准； 第二种是自己用位操作运算符弄，这个麻烦，但效果也挺好。


Question: 请教typedef Node * List在使用过程中出现的一个问题

引用 5 楼 sholber 的回复:[quote=引用 4 楼 s3311427 的回复:] [quote=引用 3 楼 sholber 的回复:] [quote=引用 2 楼 s3311427 的回复:] [quote=引用 1 楼 sholber 的回复:] 这么半天也没有理睬篓猪，俺只好来说几句。 那么在定义函数是为什么是ListItemCount(const List *plist);而不是（ListItemCount（const List plist）？ 答：因为目的不同。plist是一个对象（即通常所谓的变量），如果它的类型是List，则它指向的对象也是实参所指向的对象，但在函数内部通过它改变不了实参本身的值。但如果它的类型是List *，则它指向实参，在函数内部可以改变实参的值，即，改变实参的指向。  如果ListItemCount(const List *plist)不就是等效于ListItemCount(const struct node * *plist);;那不就是定义了该函数接受的参数是一个指向结构体指针的指针吗？（是的。当然。）当我做List movies定义后，调用函数传递该参数时，  若是ListItemCount(const List *plist);那么在调用时不应该是ListItemCount(&moive); 若是ListItemCount(const List  plist)那么在调用时不应该是ListItemCount(movies)吗？（是的。当然。）  为什么在主函数中同时使用function（&movies）与function（movies）-----function泛指头文件中定义的函数（因为，前面说了，这两种参数形式的目的不同。）  多谢！还是有个问题，两种参数形式目的不同，那也应该是不同参数形式对应着不同的函数定义 程序中都是Initialize(const List* plist)与ListIsFull(const List * plist)这两种对应着可以改变实参指向的类型。 但是他们在传递参数是，一个使用的Initialize(&movies）一个使用ListIsFull（movies），这一点我还是没绕清楚，请指教……[/quote] 不可能混用的。如果形参是const List plist，则实参只能是movies，如果形参是const List * plist，则实参只能是&movies。因为movies是指针，则&movies是指向指针的指针嘛。[/quote] 请看图片，难道说是书本印刷错误？就是这里让我百思不得其解_(:з」∠)_[/quote]  人家用的是ListIsFull函数，不是ListIsEmpty函数。如果ListIsFull的原型是 ListIsFull (const List * plist) {/* …… */} 那就是书上错了。[/quote]   谢啦！书上除了Initialize是Initialize（&movies） 其他全是用的function（movies），而且函数原型都是function（const List * plist）

引用 4 楼 s3311427 的回复:[quote=引用 3 楼 sholber 的回复:] [quote=引用 2 楼 s3311427 的回复:] [quote=引用 1 楼 sholber 的回复:] 这么半天也没有理睬篓猪，俺只好来说几句。 那么在定义函数是为什么是ListItemCount(const List *plist);而不是（ListItemCount（const List plist）？ 答：因为目的不同。plist是一个对象（即通常所谓的变量），如果它的类型是List，则它指向的对象也是实参所指向的对象，但在函数内部通过它改变不了实参本身的值。但如果它的类型是List *，则它指向实参，在函数内部可以改变实参的值，即，改变实参的指向。  如果ListItemCount(const List *plist)不就是等效于ListItemCount(const struct node * *plist);;那不就是定义了该函数接受的参数是一个指向结构体指针的指针吗？（是的。当然。）当我做List movies定义后，调用函数传递该参数时，  若是ListItemCount(const List *plist);那么在调用时不应该是ListItemCount(&moive); 若是ListItemCount(const List  plist)那么在调用时不应该是ListItemCount(movies)吗？（是的。当然。）  为什么在主函数中同时使用function（&movies）与function（movies）-----function泛指头文件中定义的函数（因为，前面说了，这两种参数形式的目的不同。）  多谢！还是有个问题，两种参数形式目的不同，那也应该是不同参数形式对应着不同的函数定义 程序中都是Initialize(const List* plist)与ListIsFull(const List * plist)这两种对应着可以改变实参指向的类型。 但是他们在传递参数是，一个使用的Initialize(&movies）一个使用ListIsFull（movies），这一点我还是没绕清楚，请指教……[/quote] 不可能混用的。如果形参是const List plist，则实参只能是movies，如果形参是const List * plist，则实参只能是&movies。因为movies是指针，则&movies是指向指针的指针嘛。[/quote] 请看图片，难道说是书本印刷错误？就是这里让我百思不得其解_(:з」∠)_[/quote]  人家用的是ListIsFull函数，不是ListIsEmpty函数。如果ListIsFull的原型是 ListIsFull (const List * plist) {/* …… */} 那就是书上错了。

引用 3 楼 sholber 的回复:[quote=引用 2 楼 s3311427 的回复:] [quote=引用 1 楼 sholber 的回复:] 这么半天也没有理睬篓猪，俺只好来说几句。 那么在定义函数是为什么是ListItemCount(const List *plist);而不是（ListItemCount（const List plist）？ 答：因为目的不同。plist是一个对象（即通常所谓的变量），如果它的类型是List，则它指向的对象也是实参所指向的对象，但在函数内部通过它改变不了实参本身的值。但如果它的类型是List *，则它指向实参，在函数内部可以改变实参的值，即，改变实参的指向。  如果ListItemCount(const List *plist)不就是等效于ListItemCount(const struct node * *plist);;那不就是定义了该函数接受的参数是一个指向结构体指针的指针吗？（是的。当然。）当我做List movies定义后，调用函数传递该参数时，  若是ListItemCount(const List *plist);那么在调用时不应该是ListItemCount(&moive); 若是ListItemCount(const List  plist)那么在调用时不应该是ListItemCount(movies)吗？（是的。当然。）  为什么在主函数中同时使用function（&movies）与function（movies）-----function泛指头文件中定义的函数（因为，前面说了，这两种参数形式的目的不同。）  多谢！还是有个问题，两种参数形式目的不同，那也应该是不同参数形式对应着不同的函数定义 程序中都是Initialize(const List* plist)与ListIsFull(const List * plist)这两种对应着可以改变实参指向的类型。 但是他们在传递参数是，一个使用的Initialize(&movies）一个使用ListIsFull（movies），这一点我还是没绕清楚，请指教……[/quote] 不可能混用的。如果形参是const List plist，则实参只能是movies，如果形参是const List * plist，则实参只能是&movies。因为movies是指针，则&movies是指向指针的指针嘛。[/quote] 请看图片，难道说是书本印刷错误？就是这里让我百思不得其解_(:з」∠)_

引用 2 楼 s3311427 的回复:[quote=引用 1 楼 sholber 的回复:] 这么半天也没有理睬篓猪，俺只好来说几句。 那么在定义函数是为什么是ListItemCount(const List *plist);而不是（ListItemCount（const List plist）？ 答：因为目的不同。plist是一个对象（即通常所谓的变量），如果它的类型是List，则它指向的对象也是实参所指向的对象，但在函数内部通过它改变不了实参本身的值。但如果它的类型是List *，则它指向实参，在函数内部可以改变实参的值，即，改变实参的指向。  如果ListItemCount(const List *plist)不就是等效于ListItemCount(const struct node * *plist);;那不就是定义了该函数接受的参数是一个指向结构体指针的指针吗？（是的。当然。）当我做List movies定义后，调用函数传递该参数时，  若是ListItemCount(const List *plist);那么在调用时不应该是ListItemCount(&moive); 若是ListItemCount(const List  plist)那么在调用时不应该是ListItemCount(movies)吗？（是的。当然。）  为什么在主函数中同时使用function（&movies）与function（movies）-----function泛指头文件中定义的函数（因为，前面说了，这两种参数形式的目的不同。）  多谢！还是有个问题，两种参数形式目的不同，那也应该是不同参数形式对应着不同的函数定义 程序中都是Initialize(const List* plist)与ListIsFull(const List * plist)这两种对应着可以改变实参指向的类型。 但是他们在传递参数是，一个使用的Initialize(&movies）一个使用ListIsFull（movies），这一点我还是没绕清楚，请指教……[/quote] 不可能混用的。如果形参是const List plist，则实参只能是movies，如果形参是const List * plist，则实参只能是&movies。因为movies是指针，则&movies是指向指针的指针嘛。

引用 1 楼 sholber 的回复:这么半天也没有理睬篓猪，俺只好来说几句。 那么在定义函数是为什么是ListItemCount(const List *plist);而不是（ListItemCount（const List plist）？ 答：因为目的不同。plist是一个对象（即通常所谓的变量），如果它的类型是List，则它指向的对象也是实参所指向的对象，但在函数内部通过它改变不了实参本身的值。但如果它的类型是List *，则它指向实参，在函数内部可以改变实参的值，即，改变实参的指向。  如果ListItemCount(const List *plist)不就是等效于ListItemCount(const struct node * *plist);;那不就是定义了该函数接受的参数是一个指向结构体指针的指针吗？（是的。当然。）当我做List movies定义后，调用函数传递该参数时，  若是ListItemCount(const List *plist);那么在调用时不应该是ListItemCount(&moive); 若是ListItemCount(const List  plist)那么在调用时不应该是ListItemCount(movies)吗？（是的。当然。）  为什么在主函数中同时使用function（&movies）与function（movies）-----function泛指头文件中定义的函数（因为，前面说了，这两种参数形式的目的不同。）  多谢！还是有个问题，两种参数形式目的不同，那也应该是不同参数形式对应着不同的函数定义 程序中都是Initialize(const List* plist)与ListIsFull(const List * plist)这两种对应着可以改变实参指向的类型。 但是他们在传递参数是，一个使用的Initialize(&movies）一个使用ListIsFull（movies），这一点我还是没绕清楚，请指教……


Question: C语言使用默认浏览器打开指定网址应该怎么写？

windows 下可以 还可以调用   CreateProcess

第一部 获取 默认浏览器  这个  可以通过注册表获取到  构建一个字符串    比如： "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"  www.baidu.com  第三:  system(上面的字符串);

这个和 c 语言没有关系啊

引用 8 楼 cy88630 的回复:[quote=引用 5 楼 wanguser-3 的回复:] ShellExecute(NULL, "open", "http://www.baidu.com", NULL, NULL, SW_SHOWNORMAL);  能给一段完整的代码吗？[/quote] 就这一句啊，把网址替换掉就行了啊。你的程序在什么情景下用默认浏览器打开指定网址就把这句加进去就行了啊。 给你一个vs2008编译通过的最简单的代码吧：  #include "stdafx.h" #include <Windows.h>  int _tmain(int argc, _TCHAR* argv[]) { 	ShellExecute(NULL, L"open", L"http://www.baidu.com", NULL, NULL, SW_SHOWNORMAL); 	return 0; }

引用 5 楼 wanguser-3 的回复:ShellExecute(NULL, "open", "http://www.baidu.com", NULL, NULL, SW_SHOWNORMAL);  能给一段完整的代码吗？

引用 1 楼 tsh185 的回复:这个和 c 语言没有关系啊  用其他的写也可以的，只要能满足要求？能给一段完整的代码吗？谢谢！

引用 3 楼 huxueyan2008 的回复:直接给代码吧，就是一句关键代码：  #include<stdlib.h> int main() { 	system("explorer http://www.baidu.com"); //关键代码 	return 0; }   VS2010 编译测试通过。。  请问这个是按照系统默认浏览器打开的吗？


Question: C语言随机数产生

谢谢你！谢谢你！

#include<time.h> nt randm2n(int m, int n) { 	srand(time(0)); 	if (m > n) 		swap(m, n); 	return rand() % (n - m) + m; }

#include <time.h>  不好意思刚才打少了就发出去了- - void randomum(int n,int m) {       int i = 0,a[10];       for(;i < 10;i++)       {           srand((unsigned)time(NULL)*( i+1 ));           a[i]=rand()%m+n;        } }

#include <time.h>  void randomum(int n,int m) {       int i = 0;       for(;i < 10;i++)       {           srand((unsigned)time(NULL)*( i+1 ));  }


Question: 这个里面的嵌套到底是什么时候发生作用？

局部变量会覆盖全局变量。如果仅是在花括号里对全局变量赋值，那么赋值依然有效。仅当你在花括号里定义了新的同名的局部变量并赋值，才不会对全局变量的值造成影响。

score = a + 250;	//score         int score = 30;         printf("%d", score);	////score 30 这里没有添加换行符，这里的int score = 30是局部变量，在出了这个大括号就失效了，所以下下一句printf输出的是260、

两个相同的标识符，如果它们各自指示不同的实体，且属于同一个名字空间，要使它们不冲突，可以采用让它们的作用域重叠的办法。在这种情况下，外部块内的标识符被内部块中的同名标识符隐藏。

注意变量的生命周期及作用域  #include <stdio.h>  int main() {     int a = 20;	//a     int score = a + 100;	//score     printf("%d\n", score);	//score     {         int score = 50;         {             score = 10;			///score             printf("%d\n", score);	///score         }         a = 10;	//a     }     {         score = a + 250;	//score         int score = 30;         printf("%d", score);	////score 30     }          printf("%d\n", score);	////score 260     return 0; }  30260是因为你输出没有换行显示到一行了


Question: 请教下，为什么应该将变量b定义在变量a的前面？

能问出这是样的问题，说明确实是经过思考的了。 有的版本的编译器不支持int a = b;这样写，不管b有没有定义在a前面。这是一个具体编译器实现技术的问题。 建议LZ可以看一下编译原理的知识。

引用 13 楼 sholber 的回复:[quote=引用 2 楼 user-10 的回复:] 先定义后使用 引用 3 楼 starytx 的回复:因为编译到int a = b;的时候编译器不认识b是啥 引用 8 楼 worldy 的回复:int a = b;//因为要用到b，但此时b还没定义，会出错，因此b应该先定义     int b = 20;     double 2b = 1.55;//还能这样定义，lz神人也 引用 9 楼 zhangxiangDavaid 的回复:这是变量名字查找规则：C的名字查找规则是这样的，从名字出现处到名字所处的作用域的起始处，这一段进行查找。找到即不再查找，找不到就跳到上一层作用域继续查找。 所以无法找到b的声明，报错 引用 12 楼 xmnathan 的回复:int a = b; 你赋值给a一个还未存在的变量肯定不行啊 所以要先定义b  不定义就不能使用吗？我不这么认为。你们试试复合字面值： (int) {0} = 3; 如果你们认为它是变量，那么请先给变量下个定义。[/quote]  这个是傻？火星语言？不懂

引用 13 楼 sholber 的回复:[quote=引用 2 楼 user-10 的回复:] 先定义后使用 引用 3 楼 starytx 的回复:因为编译到int a = b;的时候编译器不认识b是啥 引用 8 楼 worldy 的回复:int a = b;//因为要用到b，但此时b还没定义，会出错，因此b应该先定义     int b = 20;     double 2b = 1.55;//还能这样定义，lz神人也 引用 9 楼 zhangxiangDavaid 的回复:这是变量名字查找规则：C的名字查找规则是这样的，从名字出现处到名字所处的作用域的起始处，这一段进行查找。找到即不再查找，找不到就跳到上一层作用域继续查找。 所以无法找到b的声明，报错 引用 12 楼 xmnathan 的回复:int a = b; 你赋值给a一个还未存在的变量肯定不行啊 所以要先定义b  不定义就不能使用吗？我不这么认为。你们试试复合字面值： (int) {0} = 3; 如果你们认为它是变量，那么请先给变量下个定义。[/quote] 不要偷换概念吧 类比楼主的问题 3是变量么？需要定义么？

引用 2 楼 user-10 的回复:先定义后使用 引用 3 楼 starytx 的回复:因为编译到int a = b;的时候编译器不认识b是啥 引用 8 楼 worldy 的回复:int a = b;//因为要用到b，但此时b还没定义，会出错，因此b应该先定义     int b = 20;     double 2b = 1.55;//还能这样定义，lz神人也 引用 9 楼 zhangxiangDavaid 的回复:这是变量名字查找规则：C的名字查找规则是这样的，从名字出现处到名字所处的作用域的起始处，这一段进行查找。找到即不再查找，找不到就跳到上一层作用域继续查找。 所以无法找到b的声明，报错 引用 12 楼 xmnathan 的回复:int a = b; 你赋值给a一个还未存在的变量肯定不行啊 所以要先定义b  不定义就不能使用吗？我不这么认为。你们试试复合字面值： (int) {0} = 3; 如果你们认为它是变量，那么请先给变量下个定义。

int a = b; 你赋值给a一个还未存在的变量肯定不行啊 所以要先定义b

规定

唉……来学习了，我只能说越简单的问题越难回答 还是等大神来从编译器、寄存器角度来解释吧。。

引用 14 楼 xmnathan 的回复:[quote=引用 13 楼 sholber 的回复:] [quote=引用 2 楼 user-10 的回复:] 先定义后使用 引用 3 楼 starytx 的回复:因为编译到int a = b;的时候编译器不认识b是啥 引用 8 楼 worldy 的回复:int a = b;//因为要用到b，但此时b还没定义，会出错，因此b应该先定义     int b = 20;     double 2b = 1.55;//还能这样定义，lz神人也 引用 9 楼 zhangxiangDavaid 的回复:这是变量名字查找规则：C的名字查找规则是这样的，从名字出现处到名字所处的作用域的起始处，这一段进行查找。找到即不再查找，找不到就跳到上一层作用域继续查找。 所以无法找到b的声明，报错 引用 12 楼 xmnathan 的回复:int a = b; 你赋值给a一个还未存在的变量肯定不行啊 所以要先定义b  不定义就不能使用吗？我不这么认为。你们试试复合字面值： (int) {0} = 3; 如果你们认为它是变量，那么请先给变量下个定义。[/quote] 不要偷换概念吧 类比楼主的问题 3是变量么？需要定义么？[/quote] 1，在没搞清楚什么是变量前，不要谈定义不定义； 2，你将变量的定义告诉我，我给你举一个反例。

引用 15 楼 worldy 的回复:[quote=引用 13 楼 sholber 的回复:] [quote=引用 2 楼 user-10 的回复:] 先定义后使用 引用 3 楼 starytx 的回复:因为编译到int a = b;的时候编译器不认识b是啥 引用 8 楼 worldy 的回复:int a = b;//因为要用到b，但此时b还没定义，会出错，因此b应该先定义     int b = 20;     double 2b = 1.55;//还能这样定义，lz神人也 引用 9 楼 zhangxiangDavaid 的回复:这是变量名字查找规则：C的名字查找规则是这样的，从名字出现处到名字所处的作用域的起始处，这一段进行查找。找到即不再查找，找不到就跳到上一层作用域继续查找。 所以无法找到b的声明，报错 引用 12 楼 xmnathan 的回复:int a = b; 你赋值给a一个还未存在的变量肯定不行啊 所以要先定义b  不定义就不能使用吗？我不这么认为。你们试试复合字面值： (int) {0} = 3; 如果你们认为它是变量，那么请先给变量下个定义。[/quote]  这个是傻？火星语言？不懂[/quote] 世界上最尴尬的事，就是以为别人说的是火星文，等明白过来，才发现自己已经OUT。搜索一下复合字面值。

引用 5 楼 starytx 的回复:[quote=引用 4 楼 sholber 的回复:] [quote=引用 3 楼 starytx 的回复:] 因为编译到int a = b;的时候编译器不认识b是啥 那为什么在a出现之前，goto a就认识呢？：     goto a;     int i = 0; a:     /* …… */[/quote]标签的作用域和普通变量不同，他的作用域是在最近的整个大括号内，所以可以这样使用，普通变量是从定义开始到大括号结束[/quote] 全是最近的大括号……你这个说法不精确啊： goto a; { a:; } 这是可以的。说明标号具有函数作用域，而不是最近的大括号。 变量之类的，这个“从定义开始”也不精确： int * * p (int, int) = /* …… */; 到底是从哪里开始呢？从int后面？从**后面？从p后面？从初始化器后面？

这个a不是变量，是标号。

引用 4 楼 sholber 的回复:[quote=引用 3 楼 starytx 的回复:] 因为编译到int a = b;的时候编译器不认识b是啥 那为什么在a出现之前，goto a就认识呢？：     goto a;     int i = 0; a:     /* …… */[/quote]标签的作用域和普通变量不同，他的作用域是在最近的整个大括号内，所以可以这样使用，普通变量是从定义开始到大括号结束

引用 3 楼 starytx 的回复:因为编译到int a = b;的时候编译器不认识b是啥 那为什么在a出现之前，goto a就认识呢？：     goto a;     int i = 0; a:     /* …… */

因为编译到int a = b;的时候编译器不认识b是啥

先定义后使用

简单地说的话，就是对象和函数类型的标识符必须在使用前加以说明；如果要复杂地说的话，和作用域的开始位置有关，你不能在作用域之外引用一个标识符。在这里，标识符b的作用域开始于它在声明时，其声明符完全出现之后： int main () {      int a = b;      int b/* b的作用域从这里开始 */ = 20;      /* …… */ }


Question: C语言中sizeof与strlen的区别

引用 1 楼 user-1 的回复:1. sizeof是操作符，strlen是库函数。  2. sizeof的参数可以使数据类型，变量，对象，结构体，数组等，返回其所占内存字节数。  3. strlen的参数只能是字符串，返回字符串的长度。  4. sizeof在编译时就运算出结果，strlen在运行时计算结果。  小结：sizeof计算的是分配内存的大小，计算的对象很广泛，包括数据类型，变量等等。strlen 则局限于字符串，并返回字符串的长度。需要特别注意的是，禁止空指针引用strlen  ，结果不确定。另外，strlen参数为字符串数组情况下，如果数组长度不大于字符个数，则无法再为字符串末尾添加"这个够全的


Question: 如何理解“条件运算符”的"自右至左“的结合性

优先级和结合性  只决定 运算符和哪些操作数结合  和求值顺序 毫无关系  举一个例子 a+b+c*d 完全可以 a求值 b求值 a+b求值 然后 c求值 d求值 c*d求值 最后 a+b + c*d 求值 完毕  这里加法完全可以比乘法先求值   而*优先级高 只决定了 a+b+c*d  表达的是 a+b+ (c*d) 而不是 (a+b+c)*d   a>b?c:d>e?f:g 这里根据结合性 只确定了 这个表达式是 a>b ? c : (d>e?f:g) 而不是 (a>b ? c : d>e) ? f :g 这才是 结合性的作用 和求值顺序无关

拿人脑当编译器。

引用 12 楼 lin5161678 的回复:优先级和结合性  只决定 运算符和哪些操作数结合  和求值顺序 毫无关系 我比较赞同，谢谢大家的讨论！！！

拿数学中的结合律来理解也可以，结合嘛——在一起也，右呢——方向噻！假设A + B + C,你赋予+一个新的概念，就像布尔当初给+赋予与的运算类似，你重新对符号+定义一种新的运算概念使得它是右结合性，那么你就不能用A + B得出E在 E+C得出最终结果。 而是反过来先算B+C，最后再+A，因此等价于A + (B + C)，那么这里的+是个抽象概念，若把+替换成实际的条件运算，您是否理解了呢？

条件运算符?:是右结合的。因此，表达式 a ? b : c ? d : e a ? b ? c : d : e 分别等同于 a ? b : (c ? d : e) a ? (b ? c : d) : e 要理解这样做的原理，只需要掌握两个原则： 1，从右边开始往左找，直至遇到第一个未被处理的“?”； 2，再从这个“?”开始往右找第一个遇到的“:”； 3，在“?”左边的操作数前加一个“(”，在“:”右边的操作数后加一个“)”； 4，返回1，继续处理其它条件运算符?:。

1、表达式a>b?c>d?e:f:g只能等价于a>b?(c>d?e:f):g，这属于运算符的嵌套，实际上是一个内层的条件运算符嵌套在一个外层的条件运算符中，这里根本不需要利用结合性来解释。  2、表达式a>b?c:d>e?f:g中出现了两个条件运算符，因为它们的结合性都是从右往左，意味着应该先算右边的条件运算， 因此         a>b?c:d>e?f:g 等价于     a>b?c:(d>e?f:g) 不等价于(a>b?c:d)>e?f:g

引用 3 楼 paschen 的回复:不要纠结这种问题，如果你觉得看不出来，就加上括号  参看：http://bbs.csdn.net/topics/370153775 引用 4 楼 user-9 的回复:语法，建议加括号吧 引用 5 楼 zxh707wk 的回复:考试才有的东西，代码是写给人看的，不是给机器看的  不明白就说不明白，不要找这个那个理由。捂着耳朵，蒙上眼睛，问题就不存在了？？

引用 6 楼 sholber 的回复:[quote=引用 3 楼 paschen 的回复:] 不要纠结这种问题，如果你觉得看不出来，就加上括号  参看：http://bbs.csdn.net/topics/370153775 引用 4 楼 user-9 的回复:语法，建议加括号吧 引用 5 楼 zxh707wk 的回复:考试才有的东西，代码是写给人看的，不是给机器看的  不明白就说不明白，不要找这个那个理由。捂着耳朵，蒙上眼睛，问题就不存在了？？[/quote]  我的队友写这种代码, 我会在心里问好他家人的. 当然每个人看法不一样. 我只是说一下我的

So, ++ a < ++ b ? ++ c < ++ d ? ++ e : ++ f : ++ g; equ.： ++ a < ++ b ? (++ c < ++ d ? ++ e : ++ f) : ++ g;

瞧瞧人家问的问题，这才叫问题呢！ 给定声明： int a = 0, b = 1, c = 2, x = 3, y = 4, z = 5; 则， a ? b : x ? y : z 等同于 a ? b : (x ? y : z) 这是因为，要先找到最右边的?，让它与旁边的操作数结合，而它后面最近的冒号也属于它的同类。而 a ? x ? y : z : b 等同于 a ? (x ? y : z) : b 原因同上。

考试才有的东西，代码是写给人看的，不是给机器看的

语法，建议加括号吧


Question: while（）循环使用free（）释放内存时，第二次出现Debug错误CrtIsValidHeapPointer

引用 1 楼 user-1 的回复:free(current);         current=current->next; ------> 要先保存next， 再释放current 不然current都释放掉了，有可能取不到它的next了 刚刚先保存current->next，然后再free（current），也同样出现这样的问题，而且这样不就会使头指针没有释放吗？

引用 1 楼 user-1 的回复:free(current);         current=current->next; ------> 要先保存next， 再释放current 不然current都释放掉了，有可能取不到它的next了  谢谢！理解错了   free(current);         current=current->next; 这种写法在没有保存下一个节点的地址的时候就全部释放了，所以第二次取不到current->next的地址 我添加了一个temp指针提前存放下一个节点的地址就OK了 	while(current != NULL) 	{ 		puts("Test1"); 		temp=current->next; //		current=current->next; 			puts("Test2"); 		free(current); 			puts("Test3"); 		current=temp; 	}


Question: 关于scanf输入与转换符不匹配的的问题

了解了： a和b都没有被scanf赋值。scanf读取到类型与控制符代表的类型不符合，所以 第一个scanf()读取到m，又把m送回到缓冲区，第二个scanf接着读，也是读到字符m，类型不对，送回缓冲区。、 所以缓冲区留下了 2个字符: 'm'      '\n' 输出的b是未初始化的垃圾值.

ps：技术好不代表是个好老师，有耐心的才是好老师 CSDN不缺技术好的，但十分缺少有耐心的。

int a, b;  //此处是未指定初值的初始化，a和b的值是个不确定值 scanf("%d", &a); //你输入了m，缓冲流中无法读取一个整数赋值给a，此行不起作用，被跳过 scanf("%d", &b); //缓冲流中仍然无法读取一个整数赋值给b，此行不起作用，被跳过 prinf("%d\n", b); //此处输出的是：b的那个最初的不确定值   //假定要让a、b分别接收3和5，可以采用如下输入 //输入：3(空格键)5回车 //输入：3(Tab键)5回车 //输入：3(回车键)5回车

哦，我看出来与缓冲区有关，可是缓冲区的问题我还没切研究。麻烦能用语言通俗的讲一下吗？

再供参考：#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; }

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


Question: 一个关于顺序表的错误，求大神指点

1) 2-1SeqList.h 改成如下:  #ifndef  _2_1SEQLIST_H   ///// #define _2_1SEQLIST_H   ///// #define MAXSIZE 100 .... int SeqListAll(MySeqListType *SL);//遍历顺序表中的内容 #endif   ////   2) 2-2SeqList.c 改成如下:  #include <stdio.h>    /////////// #include <string.h>   /////////// #include "2-1SeqList.h"  //////////   3) 2-3SeqListTest.c 改成如下:  #include <stdio.h>    /////////// #include <string.h>   /////////// #include "2-1SeqList.h"  //////////

#include"2-2SeqList.c" 包含 2-1SeqList.h 导致 一般.h定义函数，.c是实现文件


Question: 统计文本单词数程序 换行后不能再输入问题

引用 3 楼 mao_miaoxi 的回复:[quote=引用 2 楼 hnwyllmm 的回复:] if (ch == '\n')             cntline++; 如果换成while不就变成死循环了吗 应该是while (ch == '\n')  { cntline++; ch = getchar();}  if (!isspace (ch) && !inword)         {              cntword++;             inword = true;         }  楼主这段逻辑也有问题，'\n' \t'这种也是分隔符，但是没有起到楼主想要的效果  我明白我的错误了，谢谢你。  另外，我不知道你所说的第二个错误是怎么回事，因为这一段是《C Primer Plus》上的，我并没有改动，而且我运行的时候也没有出现问题。[/quote] 我说的第二个问题的意思是， if (ch == '\n')             cntline++; 改成while循环就变成了： while (ch == '\n')             cntline++; 但是ch的值不会改变，所以如果ch等于'\n'的时候，就变成了死循环

引用 2 楼 hnwyllmm 的回复:if (ch == '\n')             cntline++; 如果换成while不就变成死循环了吗 应该是while (ch == '\n')  { cntline++; ch = getchar();}  if (!isspace (ch) && !inword)         {              cntword++;             inword = true;         }  楼主这段逻辑也有问题，'\n' \t'这种也是分隔符，但是没有起到楼主想要的效果   函数说明 检查参数c是否为空格字符，也就是判断是否为空格(' ')、水平定位字符 ('\t')、归位键('\r')、换行('\n')、垂直定位字符('\v')或翻页('\f')的情况。[1]  返回值 若参数c为空格字符，则返回TRUE，否则返回NULL(0)。 附加说明 此为宏定义，非真正函数。  这是 isspace() 函数的百度百科说明。在代码中使用应该没有问题。

引用 2 楼 hnwyllmm 的回复:if (ch == '\n')             cntline++; 如果换成while不就变成死循环了吗 应该是while (ch == '\n')  { cntline++; ch = getchar();}  if (!isspace (ch) && !inword)         {              cntword++;             inword = true;         }  楼主这段逻辑也有问题，'\n' \t'这种也是分隔符，但是没有起到楼主想要的效果  我明白我的错误了，谢谢你。  另外，我不知道你所说的第二个错误是怎么回事，因为这一段是《C Primer Plus》上的，我并没有改动，而且我运行的时候也没有出现问题。

/*  * this code is copyed from <The C praogramming Language>  */ #include<stdio.h> #include<stdlib.h> #define IN 1 #define OUT 0  int main() { 	int c , nl , nw , nc , state;  	state = OUT; 	nc = nl = nw = 0; 	while((c = getchar()) != EOF) 	{ 		++nc;//the nunber of character plus one 		if(c == '\n') 			++nl;//the number of line plus one 		if(c == ' ' || c == '\n' || c == '\t') 			state = OUT; 		else if(state == OUT) 		{ 			nw++; 			state = IN; 		} 	} 	printf("%d %d %d\n",nl,nw,nc); 	exit(0); }


Question: 有5万个三维坐标点，怎样用“图”G(V,E)这种数据结构组织起来？？C/C++

单独存顶点和边

不是的，每个点只需要和与它最近的K个点相连。（K经验上取50）

用文件读写模拟内存读写。 参考_lseeki64函数

五万个点，每两个点之间的边都要计算距离，计算量和存储量都太大了吧


Question: 菜鸟关于字符串函数strcpy的疑惑

引用char *p;  这里p是一个指针变量，但没有指向任何地址，很多编译器将他直接置为NULL。  引用strpy(p,"abc");  如果编译器直接初始化为NULL，那么函数到p=0，会报你说的错误； 如果p初始化为进程内的地址，那么会出现不可预期的运行错误； 如果p初始化为进程外的地址，那运行时会报内存泄露错误。

无论p的初始值为多少。总是存在于内存中的地址。不妨碍复制和显示。  你的思想主要错在认为系统中有且只有你自己写的一个程序在运行【即使是这样，比如在纯DOS操作系统或者Linux的文本界面中也是危险的】  对于一个指针，是否初始化，都指向内存中的“有效”地址这种想法是不对的 根据你使用的编译器、IDE不同，可能会有不同的初始值 比如：0xCC、0x00、0xFF等 【http://blog.csdn.net/zhandoushi1982/article/details/6275429】【VC 0xCC的例子】  即便一个指针指向着内存中的有效地址，如果不控制它的数据类型【指针所指向内存的大小】，也很容易“越界访问”到别的程序或者自己程序的别的代码段的领域里去，会造成系统或者程序崩溃   形象点说：指针变量就像你的手指，内存数据就像一座大楼下面各家整齐的邮箱 如果是派发小广告：那么首先得把手指指向第一个邮箱，然后指定好邮箱大小，投递，下一个，判断是否是最后一个邮箱，继续投递 未经初始化的指针的行为，很像闭着眼睛随手一指，往里面投递【写入数据】。哦卖糕，我的手指【指针变量】怎么指向的不是邮箱，而是电梯，哦卖糕，怎么扔了一电梯的广告……

C标准的解释最权威，但不是那么通俗。我再结合标准补充几句： N1570，6.5.3.2： If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.102) ------------ 102) Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, and the address of an object after the end of its lifetime.  楼上的同学只注意到NULL指针，以及p所指向的对象的生存期结束之后的情况（我在前面的发言里也提及了），但没有注意到地址未正确对齐的情况。指针的值也是无效的情况也包括未对齐。

定义一个指针，如果上面代码位于函数内部，那么它的存储空间在栈帧上分配。如果不对其初始化，那么它可能是上个函数调用时使用栈帧时遗留下的数据或者第一次使用时的随机值或0。 对于一个不确定的值，它不一定是有效的进程地址空间内的地址。因此不一定可以用来解引用，之所以说不一定，是因为假如碰巧这个值处于进程地址空间之内，那么就可以正常访问，这种情况发生时属于一种安全漏洞。更多情况下是无效的值，访问时产生SIGSEGV- （invalid memory reference）信号，又称为“段错误”，即进程解引用了一个无效的内存。这意味着一个bug诞生了，最常见的操作是解引用NULL指针。此外，进程对此信号默认操作是中止程序的运行！ 你的问题可以用进程的地址空间来解答。每个进程都有自己的地址空间，OS为了自己的安全，它不会让进程访问所有的地址，而是一段固定的区间。 大致给你说这么多吧，如果想详细了解，自己多多学习研究吧！ 如果有不当之处，请大神指明，谢谢！

按C标准说法，如果一个左值实际上并未指示一个对象，或者引用一个过了生存期的对象，行为是未定义的； 生存期由存储期决定； C有静态、自动和指派三种存储期，以p为例，p自身可以具有静态或自动存储期，但是： p = malloc (/* ... */);    //p指向的对象具有指派存储期 p = a;    //若a是文件作用域，则p指向的对象具有静态存储期，若a在块内声明，则p指向的对象具有自动存储期。 检查你的程序，若p指向的对象与此都不符，则它符合上面第一行的说法，行为自然为定义。

p这个变量是存在的 ，p存储的地址未赋值， 访问p的存储值值时出现错误。系统为了保护，很多地址不能访问使用的。

引用 楼主 I_better 的回复:char *p; strpy(p,"abc"); puts(p);  这里会报错，书中解释为，p未初始化。所以“abc”被复制到任何地方 应改为 char *p; char b[50]; p=b; strpy(p,"abc"); puts(p);  而我的理解：无论p的初始值为多少。总是存在于内存中的地址。不妨碍复制和显示。 求问我的思想错在哪里  与其说是p未初始化，更准确的说是，LZ没有为p分配地址空间。

因为p指向的内存不是你自己分配的，而是随意乱指，那么你执行strcpy会把p所指向的内存原来的数据给覆盖掉，如果那片区域是别的程序正在使用的，那就可能会让别的程序出错了，因此为了安全起见，不应该这样做。

C语言是一个过程性语言，程序执行的每一个状态都要注意，正如1楼说的那样别的函数调用时，可能会改变数据，所以指针最好要初始化一下

这个字符串也是保存在常量区中 "也“字要去掉

char *p; 这句仅仅是告诉编译器留出4个字节来保存地址，这个地址并没有指向任何内存区域，所以没有办法往指针p复制字符。另外即使p指向字符串，比如  char *p = "hello"，这个字符串也是保存在常量区中，不能被修改。 char a[30] 声明了一块内存空间，大小30字节，所以能用strcpy来向其中复制字符串。

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

你的理解没有错， 可是既然没有定义的值，是不是乱拷贝呢，你的不知道拷贝到内存的哪里了？如果那快内存是操作系统的代码呢，那操作系统不就被你破坏了吗,所以说能复制，但是操纵系统 不让你复制． #include<stdio.h> #include<stdlib.h> #include<string.h>  int main() { 	char *p; 	p = (char *)malloc(sizeof(char) * 10);  	strcpy(p,"asdfg"); 	puts(p); 	exit(0); }

问题就出在"无论p的初始值为多少。总是存在于内存中的地址"上.当p使用的地址是另外程序使用时,就有可能被写入数据,结果就可能不是你所希望的"abc"了,所以,使用指针必须要初始化.


Question: 文件复制程序

你的问题是，char temp[81]申明后没有做格式化处理，就直接用了 .先使用void *memset( void *dest, int c, size_t count );将申请的内存格式化为0，就解决这个问题了。 memset(temp,0,81);

/*  * 本程序实现文件的复制，可复制文本文件和二进制文件  */ #include<stdio.h> #include<string.h> int main(int argc, char **argv) {     int c;      FILE *source,*targe;     if (!(argc>=3 && stricmp(argv[1],argv[2]) && NULL==fopen(argv[2],"rb"))) return 1;     source = fopen(argv[1],"rb");     targe = fopen(argv[2],"wb");     if(source && targe) {         while(1) {             c=fgetc(source);             if (EOF==c) break;             fputc(c,targe);         }         fclose(source);         fclose(targe);         return 0;     } }

for reference only! /*  * 本程序实现文件的复制，可复制文本文件和二进制文件  */  #include<stdio.h> #include<stdlib.h> int main(int argc, char **argv) { 	char buffer[10];  	FILE *source,*targe; 	source = fopen(argv[1],"rb"); 	targe = fopen(argv[2],"a+b");  	if(source && targe) 	{ 		while(fread(buffer,sizeof(char),1,source) > 0) 			fwrite(buffer,sizeof(char),1,targe);  		fclose(source); 		fclose(targe);  		return 0; 	} 	else 	{ 		fprintf(stderr,"can`t open file\n"); 		exit(0); 	} }

引用 1 楼 q3733353520 的回复: #include <stdio.h> # include <stdlib.h> int main(int argc, char * argv[]) { 	FILE * fd, * fs; 	char temp[81];  	if (argc != 3) 	{ 		fprintf(stderr, "Usage: %s filename\n", argv[0]); 		exit(1); 	} 	if ((fs = fopen(argv[1], "rb")) == NULL) 	{ 		fprintf(stderr, "Could not open the file \"%s\"\n", argv[1]); 		exit(2); 	} 	if ((fd = fopen(argv[2], "wb")) == NULL) 	{ 		fprintf(stderr, "Could not creat the output file.\n", argv[2]); 		exit(3); 	}  	int ret = fread(temp, sizeof(char), 81, fs);  	printf("temp = [%s] \n", temp); 	fwrite(temp, sizeof(char), ret, fd);  	return 0; }   文件复制成功了，，但是打印出来了还是很多的烫的乱码，这是咋回事呢。。


Question: 运算符优先级问题

你的两条语句从结果来说是一样的  第一种是没错的，大于号的优先级是比|| 高的

引用 6 楼 zhao4zhong1 的回复:搜“逻辑短路”一直觉得赵老师是个大水B，但关键时候，还是能够说道点子上去

引用 1 楼 paschen 的回复:加了括号会改变判断的顺序，有些时个可以提高效率  比如：  a || b， 如果表达式a是真，那么就不会再去执行表达式b  另外你的第一条也是可以的，没看出什么错误，你编译的错误是什么编译结果显示期望获得一个表达式

引用 4 楼 user-4 的回复:[quote=引用 3 楼 my_live_123 的回复:] 最短路径： A || B -当A为真时，B不再测试真假;只有当A假时，继续测试B； 不用你的实例了，抽象一下： 1-A || B ||C || D 2 -（A || B） || （C || D） 区别是 第2中情况比第1中情况运算的要多 A = 1，BCD任意， 则第一种只测试A就得出真的结果 第二种要测试A || B然后测试中间||才得到结果 但是结果是一样的 不对 对于第一种情况  需要求值 第一个 || 和 第二个 || 和第三个 || 对于第二种情况 只需要求值 第一个 || 和 第二个|| 就能得出结果了[/quote]  是的，我想错了！谢谢指正

搜“逻辑短路”

计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

引用 3 楼 my_live_123 的回复:最短路径： A || B -当A为真时，B不再测试真假;只有当A假时，继续测试B； 不用你的实例了，抽象一下： 1-A || B ||C || D 2 -（A || B） || （C || D） 区别是 第2中情况比第1中情况运算的要多 A = 1，BCD任意， 则第一种只测试A就得出真的结果 第二种要测试A || B然后测试中间||才得到结果 但是结果是一样的 不对 对于第一种情况  需要求值 第一个 || 和 第二个 || 和第三个 || 对于第二种情况 只需要求值 第一个 || 和 第二个|| 就能得出结果了


Question: linux系统 and c\c++ 爱好者 (提示 and) 团队组建！

支持 愿意一起学习

坚持才是成功的基础啊

在这儿招队友？  围观了

引用 楼主 y_abel_sv729 的回复:本人热爱计算机，热爱技术，想做一点东西有用的东西出来。   思想在于行动，但是一个人的力量总是那么渺小，面对系统，完全不能力所能及。   在这里希望热爱linux 热爱改变， 热爱底层，热爱硬件的朋友们   不管你是菜鸟，还是老鸟，希望你的加入。   梦想开发全新系统的你，共同组建团队。   梦想开发全新系统的你？？ 既然是全新系统，那在这里为什么要提linux呢？

《30天自制操作系统》   写得不错！ 看了一些。

没有信念，没有追求，那就没有我的生命。 我不想不等待别人给我想要的，因为别人做出的是别人想要的。而我的，那就是我自己给的。  你就慢慢等待你的热情消失吧。

热情是会很快消散的 少年

《30天自制操作系统》

有意向的发私信谢谢。

《一个操作系统的实现》也能瞅瞅


Question: memcpy内存重叠问题

引用 1 楼 zhao4zhong1 的回复:先弄清楚copy和move的语义： copy的语义是操作结束后，新目的的内容和旧源的内容一致，且保证旧源的内容不变。 move的语义是操作结束后，新目的的内容和旧源的内容一致，但不保证旧源的内容不变。  于是乎，当操作的内存重叠时，无论如何也不可能实现copy！  +1+1+1+1+1

引用 4 楼 chuansunshine 的回复: /*** *memcpy - Copy source buffer to destination buffer * *Purpose: *       memcpy() copies a source memory buffer to a destination memory buffer. *       This routine does NOT recognize overlapping buffers, and thus can lead *       to propogation. * *       For cases where propogation must be avoided, memmove() must be used. * *Entry: *       void *dst = pointer to destination buffer *       const void *src = pointer to source buffer *       size_t count = number of bytes to copy * *Exit: *       Returns a pointer to the destination buffer * *Exceptions: *******************************************************************************/  void * __cdecl memcpy (         void * dst,         const void * src,         size_t count         ) {         void * ret = dst;  #if defined (_M_IA64)          {           __declspec(dllimport)           void RtlCopyMemory( void *, const void *, size_t count );          RtlCopyMemory( dst, src, count );          }  #else  /* defined (_M_IA64) */         /*          * copy from lower addresses to higher addresses          */         while (count--) {                 *(char *)dst = *(char *)src;                 dst = (char *)dst + 1;                 src = (char *)src + 1;         } #endif  /* defined (_M_IA64) */          return(ret); }有兴趣可以翻到 C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\intel 里看看 memcpy.asm 的实现 实际上通常情况下 这种版本 c 代码 不会出现在实际使用中

memcpy 的具体实现很复杂的 ... 在数据量达/mem 16字节的对齐的情况下 会使用 movdqa 来拷贝 u/v 管道配对也是非常精准 ... 这种程度的 memcpy 没法跟系统比的 ... release 版本下 最多也就是 rep movsd 程度的优化 ...

直接转到定义， 看看怎么实现的

/*** *memcpy - Copy source buffer to destination buffer * *Purpose: *       memcpy() copies a source memory buffer to a destination memory buffer. *       This routine does NOT recognize overlapping buffers, and thus can lead *       to propogation. * *       For cases where propogation must be avoided, memmove() must be used. * *Entry: *       void *dst = pointer to destination buffer *       const void *src = pointer to source buffer *       size_t count = number of bytes to copy * *Exit: *       Returns a pointer to the destination buffer * *Exceptions: *******************************************************************************/  void * __cdecl memcpy (         void * dst,         const void * src,         size_t count         ) {         void * ret = dst;  #if defined (_M_IA64)          {           __declspec(dllimport)           void RtlCopyMemory( void *, const void *, size_t count );          RtlCopyMemory( dst, src, count );          }  #else  /* defined (_M_IA64) */         /*          * copy from lower addresses to higher addresses          */         while (count--) {                 *(char *)dst = *(char *)src;                 dst = (char *)dst + 1;                 src = (char *)src + 1;         } #endif  /* defined (_M_IA64) */          return(ret); } 自己看吧，亲

memcpy： To avoid overflows, the size of the arrays pointed by both the destination and source parameters, shall be at least num bytes, and should not overlap (for overlapping memory blocks, memmove is a safer approach).


Question: 华为OJ平台编译不过

你好，我想问下载了工程之后怎么做啊？他让上传的source压缩文件怎么弄啊？

知道了，我没有下载工程


Question: C语言如何实现类模板功能

把具体类型带入模板手动生成实例化的类，然后再把成员函数提出来改成接收类对象指针的普通函数。或者就凑或用宏模拟模板吧。

宏-强大的macro

cvtScaleAbs_得改成很多函数，cvtScaleAbs_SSE2里面的operator提出来改成函数，然后调用对应的就行了


Question: 怎么实现数据的可视化

谢谢大家的热心帮助！

就是想让你做个界面 比如说直方图啊， 饼图啊 找一下插件， 应该好弄，  这里是c/c++ 没有c++++的代码


Question: 调用libsvg出现问题

找到错误，是头文件被多次包含了

我不是写着错误在第二行吗？看清楚啊

偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。


Question: 如何在主函数中调用结构体中声明的函数

/*  * you mean this?  */  #include<stdio.h> #include<stdlib.h>  struct csdn { 	void (*fun)(char *); };  void f(char *s) { 	puts(s); }  int main() { 	struct csdn test; 	test.fun = f; 	test.fun("hello world"); 	exit(0); }

用函数指针，把函数指针作为结构体的一个成员，在结构体外可以call这个函数地址。C中函数指针的声明放在结构体外。如果已经在结构体中定义好了函数地址，直接call。  参考代码：   #include <stdio.h>  typedef void (*move_to)();  void fun();  struct Struct_MoveTO { 	int num; 	move_to moveto; } ;  void main() { 	struct Struct_MoveTO sm = {001, &fun}; 	sm.moveto(); }  void fun() { 	printf("hello\n"); }

是这个意思不？---> typedef struct svg_render_engine {      svg_status_t (* move_to) (void *closure, double x, double y);//1      svg_status_t (* line_to) (void *closure, double x, double y);//2      svg_status_t (* curve_to) (void *closure,         double x1, double y1,         double x2, double y2,         double x3, double y3);//3  } svg_render_engine_t;    svg_status_t move_to (void * closure, double x, double y)  {      /* …… */  }   svg_status_t line_to (void * closure, double x, double y)  {      /* …… */  }   svg_status_t curve_to (void * closure,         double x1, double y1,         double x2, double y2,         double x3, double y3) {     /* …… */ }  int main (void) {     svg_render_engine_t sre = {move_to, line_to, curve_to};     sre.move_to (/* …… */);     sre.line_to (/* …… */);     sre.curve_to (/* …… */); }

先赋值给有效的函数地址，然后就直接调用

svg_status_t user_move_to(void *closure, double x, double y); // declaration only  svg_render_engine_t e; e.move_to = user_move_to; // assignment e.move_to(...); // call

可以定义一个形参和返回值一样的函数，然后把结构体函数指针指向它

我测试了不行

svg_render_engine：：svg_render_engine_t.  svg_status_t (* move_to)（）; svg_render_engine：：svg_render_engine_t.   svg_status_t (* line_to)（）; svg_render_engine：：svg_render_engine_t.   svg_status_t (* curve_to)（）; 是不是这样的。

额，我标题写的有问题，我想问的是怎么在.C文件中来定义这3个函数。

svg_render_engine_t e1, *e2; svg_status_t r; void *closure; double x[3], y[3]; r = e1.move_to(closure, x[0], y[0]); r = e2->line_to(closure, x[0], y[0]); r = e2->curve_to(closure, x[0], y[0], x[1], y[1], x[2], y[2]);

先创建一个结构体变量，然后通过该变量调用……

取结构体对象的成员函数指针，调用 参考函数指针的调用


MoveWindow The MoveWindow function changes the position and dimensions of the specified window. For a top-level window, the position and dimensions are relative to the upper-left corner of the screen. For a child window, they are relative to the upper-left corner of the parent window's client area.   BOOL MoveWindow(   HWND hWnd,      // handle to window   int X,          // horizontal position   int Y,          // vertical position   int nWidth,     // width   int nHeight,    // height   BOOL bRepaint   // repaint flag );   Parameters hWnd  Handle to the window.  X  Specifies the new position of the left side of the window.  Y  Specifies the new position of the top of the window.  nWidth  Specifies the new width of the window.  nHeight  Specifies the new height of the window.  bRepaint  Specifies whether the window is to be repainted. If this parameter is TRUE, the window receives aWM_PAINT message. If the parameter is FALSE, no repainting of any kind occurs. This applies to the client area, the nonclient area (including the title bar and scroll bars), and any part of the parent window uncovered as a result of moving a child window. If this parameter is FALSE, the application must explicitly invalidate or redraw any parts of the window and parent window that need redrawing.  Return Values If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero. To get extended error information, callGetLastError.  Remarks If the bRepaint parameter is TRUE, the system sends the WM_PAINT message to the window procedure immediately after moving the window (that is, the MoveWindow function calls the UpdateWindow function). If bRepaint is FALSE, the system places the WM_PAINT message in the message queue associated with the window. The message loop dispatches the WM_PAINT message only after dispatching all other messages in the queue.   MoveWindow sends WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED, WM_MOVE, WM_SIZE, and WM_NCCALCSIZE messages to the window.   Windows CE: The bRepaint parameter is ignored and is assumed to be FALSE.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winuser.h.   Import Library: Use user32.lib.  See Also Windows Overview, Window Functions, SetWindowPos,UpdateWindow, WM_GETMINMAXINFO,WM_PAINT

为什么不单步到MoveWindow里面亲自查看一番呢？


Question: #define FIELD_SIZE(t,f)（sizeof(((t*)0)->f)) 为什么没有错误

想完全彻底弄懂sizeof，请参考gcc源代码中实现sizeof函数部分。

怎么像内核的代码   84 #define container_of(ptr, type, member) ({                      \  85         const typeof( ((type *)0)->member ) *__mptr = (ptr);    \  86         (type *)( (char *)__mptr - offsetof(type,member) );})  自己搜container_of宏的解析 其实这个工作是编译器的做的

sizeof是编译时确定，如果连编译器都无法确定语句的类型，又怎么生成执行代码呢？


Question: 编译原理与技术的题目,求答案及解答

Flex+Bison Lex+Yacc

《编译原理》瞅瞅吧


Question: find  命令的奇怪问题

提醒诸位：find是开源的。

引用 6 楼 from2015 的回复:[quote=引用 4 楼 caddor9100 的回复:] [quote=引用 3 楼 from2015 的回复:] find跟的不是正则表达式，是通配符——好像两者实质也差不多。  查找dir目录下以句点为结尾的文件，Linux下应该这样可以的  find dir -name "*."  1.   find -name '.'  find -name '\.'  有啥区别？  2.  为什么 find -name 后，可以加引号  而ls 则不行？ [/quote]  俩命令就是这么用的，习惯就好了，这个基本是不变的了。  linux上，find命令的参数先是要查找的目录，再是查找参数，最后是查找匹配串。  find -name '\.' 这个写法不对吧？你在什么上面用？ [/quote]   http://bbs.csdn.net/topics/390995329 高手帮忙看看这个帖子

引用 11 楼 lee244868149 的回复:find 命令确实是可以用正则表达式匹配的，但是限制是比sed ，grep命令大的多的  通过man可以看到find支持的正则主要有 ？ * .  这样极少数的匹配，所以你用的find -name '.$' 这样的命令，和你要表达的意思相差是非常远的，因为这条命令表示搜索 文件名是绝对 .$ ，肯定是搜索不到的。 1. find命令不支持$匹配，也没有^ 这样的匹配， 因为^ $ 分别代表行首和行尾，有时也表示文件开头和末尾，多用在文本匹配中，但是find是搜索文件而不是文本  2. 单引号和双引号的使用，这里使用单引号，就将字符串的扩展语义都去除了，只是看做单纯的字符串来处理，所以即使使用了正确的正则，在单引号里都是不会进行扩展的。  所以你想找个以点结尾的文件，这样写就可以了： find -name "*\."  多谢，不过纠正你的一个错误  find支持的. 和正则中的.不一样，正则中的. 是代表任意一个字符。  find中的. 是指一个ansii码，没有上面个的意义

引用 6 楼 from2015 的回复:[quote=引用 4 楼 caddor9100 的回复:] [quote=引用 3 楼 from2015 的回复:] find跟的不是正则表达式，是通配符——好像两者实质也差不多。  查找dir目录下以句点为结尾的文件，Linux下应该这样可以的  find dir -name "*."  1.   find -name '.'  find -name '\.'  有啥区别？  2.  为什么 find -name 后，可以加引号  而ls 则不行？ [/quote]  俩命令就是这么用的，习惯就好了，这个基本是不变的了。  linux上，find命令的参数先是要查找的目录，再是查找参数，最后是查找匹配串。  find -name '\.' 这个写法不对吧？你在什么上面用？ [/quote]  为啥不对？  转义符号

引用 4 楼 caddor9100 的回复:[quote=引用 3 楼 from2015 的回复:] find跟的不是正则表达式，是通配符——好像两者实质也差不多。  查找dir目录下以句点为结尾的文件，Linux下应该这样可以的  find dir -name "*."  1.   find -name '.'  find -name '\.'  有啥区别？  2.  为什么 find -name 后，可以加引号  而ls 则不行？ [/quote]  俩命令就是这么用的，习惯就好了，这个基本是不变的了。  linux上，find命令的参数先是要查找的目录，再是查找参数，最后是查找匹配串。  find -name '\.' 这个写法不对吧？你在什么上面用？

遇到不会使用的情况，建议看看man手册或help文档，搞懂一次，基本上你就会用所有命令了

引用 3 楼 from2015 的回复:find跟的不是正则表达式，是通配符——好像两者实质也差不多。  查找dir目录下以句点为结尾的文件，Linux下应该这样可以的  find dir -name "*."  1.   find -name '.'  find -name '\.'  有啥区别？  2.  为什么 find -name 后，可以加引号  而ls 则不行？

引用 1 楼 a30037338 的回复:文件名用通配符， 没见过用正则式的, 文件名后跟上路径 find -name "*.txt" /  *不就是正则？

文件搜索只有.和*吧- -

引用 8 楼 my_live_123 的回复:用"*."试试 man find  看7 L

用"*."试试 man find


Question: 邻接表存储数据

书中有例子，模仿做就是了


Question: redis获取sds字符串长度的疑问

因为当前s的地址相当于在buf的位置，减去sdshdr 的大小，正好指向了结构体的头


Question: pkcs7 生成带签名的数字信封

只能说明： 要么楼主搜例子的代码的功力不够 要么OpenSSL官方的例子代码典型性差  之所以我会这么光说不练，是因为我也没实际弄过。

不太好找，我想要个带签名的，不知道能不能提供代码参考一下。

openssl没自带相关例子代码吗？


置顶，求大神解释

引用 1 楼 user-1 的回复:int k=i;     for(;k<=j;k++){ ……这能不TLE么 刚写树状数组，不太明白，求可以详细说明下吗？

int k=i;     for(;k<=j;k++){ ……这能不TLE么


应该把保存信息的代码放在主窗口得到弹出窗口返回确认以后。 甚至应该弹出窗口返回确认发自定义命令消息给主窗口自己，主窗口收到该自定义命令消息后保存信息。

对话框不是主窗口的子窗口  lz可以在CreatDialog后，使用其返回的hDlg,使用SetProp将主窗口的的hWnd设置给hDlg 在需要对话框中，需要主窗口的位置，使用GetProp函数取出主窗口的hWnd


Question: C语言编程思维

写着写着你就会了！

看书+思考+实践，仅此而已

理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

多做养成的。 无从下手，做的少了，仅此而已。

一般都会有demo和注释

一步步抄下来，抄着抄着好像能理解一些了，这时候去看教程就好多了

要开发真正的项目, 写例子不行


Question: 奇怪的C错误

引用 11 楼 zxh707wk 的回复:引用 5 楼 mayo2012 的回复:不要把临时变量作为函数的返回值，尤其是指针。临时指针，一旦被调用的函数结束，该临时指针所指向的内存就会被收回。这个时候你再去访问这快内存，得到的值将是不确定的。+1  我看不一定。

static

只返回了一个局部指针，返回后，分配的栈空间已经被释放，所以得出的结果是错误的。严重的话，还会崩溃。

这个伙计压根就不知道对象的生存期和存储期是什么。

首先我说下楼主的代码：NODE2 *node最好给个null，NODE2 node[maxsize]={0};习惯。。  然后分析： NODE2 node[maxsize]; 这一句表示栈空间开辟一个maxsize大小的NODE2， 下面，你用了一个for循环来对栈空间赋值。 所以第一行输出正确。  再看第二行， 对于栈空间来说，在函数的退出时，内存被释放，但是释放！=销毁。。 也就说你前面对内存的赋值数据依旧存在，只是被系统的空闲空间链表记录了 所以你第二行是指定内存输出，所以依旧是数据。  第三行， 数据依在，但是是闲置空间。所以又有栈的开辟时，前面空间可能会被使用。 所以导致第三行部分数据不是你想的  char* run() { char buffer[2] = {0}; buffer[0]='1'; buffer[1]='2'; return buffer; } //你可以用for循环一个一个字符打印和直接输出字符串打印比较

#include<stdio.h> struct NODE2{ 	int x; 	int y; }; #define maxsize 20  struct NODE2 *readNode(){ 	static NODE2 node[maxsize]; 	int j; 	for(j=0;j<4;j++){ 			node[j].x = 1; 			node[j].y = 1; 	} 	printf("\n%d %d %d %d %d %d %d %d",node[0].x,node[0].y,node[1].x,node[1].y,node[2].x,node[2].y,node[3].x,node[3].y); 	return node; } void main(){ 	NODE2 *node; 	node = readNode(); 	printf("\nfirst:\n%d %d %d %d %d %d %d %d",node[0].x,node[0].y,node[1].x,node[1].y,node[2].x,node[2].y,node[3].x,node[3].y); 	printf("\nsecond wrong?\n%d %d %d %d %d %d %d %d",node[0].x,node[0].y,node[1].x,node[1].y,node[2].x,node[2].y,node[3].x,node[3].y); 	printf("\n"); }

NODE2 node[maxsize];  丢到函数体外面

static NODE2 node[maxsize];

不要用函数返回赋值，直接函数使用指针传参就行了

引用 1 楼 user-11 的回复:struct NODE2 *readNode(){     NODE2 node[maxsize];     int j;     for(j=0;j<4;j++){             node[j].x = 1;             node[j].y = 1;     }     printf("\n%d %d %d %d %d %d %d %d",node[0].x,node[0].y,node[1].x,node[1].y,node[2].x,node[2].y,node[3].x,node[3].y);     return node;  // 这里返回了栈上的东西，多半是错的。 } 以前用JAVA习惯了，以为这个是可以的，谁知道C的临时变量的和JAVA临时变量声明周期不一样，所以才弄错了。


Question: 关于指针类型的疑惑

指针的位数与机器支持的最大寻址范围有关，比如32位的操作系统下指针的位数为32位，64位的操作系统下指针的位数为64位，当然，在64位的系统下也可以写32位的兼容性程序。至于指针为什么需要类型，你想下，如果指针都是void的话，你指针多了，代码长了，能分辨哪个指针指向的是多少个字节空间吗？有可能就会出现越界访问，程序崩溃！

你知道寻址空间的大小么

你们说的都不对，不过我已经想到为什么了。嘻嘻

因为指针指向的对象的地址是四个或者八个字节大小，为了保存这个地址值，不就需要具有四个或者八个字节的变量了

因为指针即地址，16机制32位（64位），每8位一个字节；

内存决定的啊 指针就是内存的门牌号码


Question: 链表中的p和q是什么的缩写啊

这个问题问得好。。。 head,p,q 都是用来保存4字节的地址。 head是链表首地址，如果head作为函数参数传入，比如删除结点函数，这个地址会被push到栈中，子函数就从这个栈地址去取到链表首地址。 p,q 一般用来存放结点地址，编译器通常会把他们在内存中放到一起。无论是创建链表，删除链表结点，还是插入链表结点，CPU都需要记住当前和之前处理的结点地址，p就用来保存当前正在处理的结点地址，q用来保存之前处理过的结点地址。比如创建链表的时候，新建一个结点，得到新结点的地址，这个地址就保存在p中，这个地址需要放到之前处理过的结点的next域中，而q中就保存了之前刚处理过的结点的地址，之后q中的地址就过时了，于是用p中的地址来更新，p,q保存的地址就这样随着循环跳转不断变化，直到最后一个结点。 或许你会问为什么一定要用p，q来保存之前和当前结点的地址，用其他地址不行吗？当然可以，但前提是没有循环。计算机的强大就在于利用循环来实现自动化。要实现循环就必须保证每次循环都跳转到相同的偏移地址，而p和q就保证了每次循环都有相同的偏移地址。

哈哈，4楼正解

p= pointer，26字母序p的下一个字母是q，以此继续，以后你或许还会看到r,s用作指针 同理 索引标 i=index，下一个字母j,然后继续k,这三个常见 还有变量n = number，下一个m,以及初学程序最常见的a,b,c,d,e 数学中最常用的v,w,x,y,z 懂了不？这就叫传统

想了下，估计指针 pointer 的首字母是 p，所以平时的指针变量缩写为 p q 等； 就像因为整型 int，首字母 i，平时的整型变量都 i j k 什么的。

p: pointer q: next character of p,another pointer

不是就符合规则的变量标识吗


Question: 这段链表代码卡两天了一直找不到错误,程序媛自学好难

没有数据结构的代码

建议把功能分一下，  入链表 push 出链表pop 创建链表 create 遍历显示 show 这样你只关心每个功能的细节， 都混着写 很容易出错。

参考代码段 http://pan.baidu.com/s/17yIcQ

引用 24 楼 Data_Flow 的回复:楼上说10天学完CPP的 您老这是让人看完CPP吗？这分明是翻完CPP  没点钻劲儿还学什么计算机。话说当年俺第一次接触数据库，而且用电脑也不是很方便，只在床边坐了三天就翻完了厚厚的一本dBase 教程，然后扔掉书到别人的机房里验证所学去了。

楼上说10天学完CPP的 您老这是让人看完CPP吗？这分明是翻完CPP

对妹纸要温柔~引用 9 楼 sholber 的回复:p = q = (struct Info *) malloc(sizeof (struct Info *)); 神额，要分配的空间是一个指针的大小，而不是结构的大小？？      int a;//用户输入要进行的功能     int n = 0;     struct Info * head;     struct Info * p, * q; 声明这么多狗屁变量干甚？

case ‘1’:                 creat(head,&n,p,q);                 break;             case ‘2’:                 change(head);                 break;             case ‘3’:                 streichen;                 break;             case ‘4’:                 search;                 break;             case ‘5’:                 show(head);                 break;  上述的case 12345必须加单引号

引用 16 楼 user-13 的回复:[quote=引用 14 楼 sholber 的回复:] 学两个月还没学会C，可以改行了。要是让我当老师的话，勒令学生10天看完CPP，然后用标准文档强化训练。  大神  我最近也在自学C语言 不知道能不能请你当我的老师 指导下我啊  [/quote]  我贪财，学费贵。

引用 17 楼 cysccnu 的回复:p = q = (struct Info *) malloc(sizeof (struct Info *)); 这句只申请了4字节的内存空间，只能用来保存一个地址。而每一个结点至少需要4+20*1+10*1+4+4 = 42字节内存空间，所以会出错。  head是链表首地址，如果head作为函数参数传入，比如删除结点函数，这个地址会被push到栈中，子函数就从这个栈地址去取到链表首地址。 p,q 一般用来存放结点地址，编译器通常会把他们在内存中放到一起。无论是创建链表，删除链表结点，还是插入链表结点，CPU都需要记住当前和之前处理的结点地址，p就用来保存当前正在处理的结点地址，q用来保存之前处理过的结点地址。比如创建链表的时候，新建一个结点，得到新结点的地址，这个地址就保存在p中，这个地址需要放到之前处理过的结点的next域中，而q中就保存了之前刚处理过的结点的地址，之后q中的地址就过时了，于是用p中的地址来更新，p,q保存的地址就这样随着循环跳转不断变化，直到最后一个结点。 或许你会问为什么一定要用p，q来保存之前和当前结点的地址，用其他地址不行吗？当然可以，但前提是没有循环。计算机的强大就在于利用循环来实现自动化。要实现循环就必须保证每次循环都跳转到相同的偏移地址，而p和q就保证了每次循环都有相同的偏移地址。  评论：振振有词，毫无根据。 p = q = (struct Info *) malloc(sizeof (struct Info *)); 这句只申请了4字节（为啥是4字节？？）的内存空间，只能用来保存一个地址。而每一个结点至少需要4+20*1+10*1+4+4 = 42字节（为啥是42字节？？不会有内部填充吗？？）内存空间，所以会出错。 子函数？C里还有子函数？？ 至于p  q之类，就不说了。

引用 18 楼 sholber 的回复:[quote=引用 17 楼 cysccnu 的回复:] p = q = (struct Info *) malloc(sizeof (struct Info *)); 这句只申请了4字节的内存空间，只能用来保存一个地址。而每一个结点至少需要4+20*1+10*1+4+4 = 42字节内存空间，所以会出错。  head是链表首地址，如果head作为函数参数传入，比如删除结点函数，这个地址会被push到栈中，子函数就从这个栈地址去取到链表首地址。 p,q 一般用来存放结点地址，编译器通常会把他们在内存中放到一起。无论是创建链表，删除链表结点，还是插入链表结点，CPU都需要记住当前和之前处理的结点地址，p就用来保存当前正在处理的结点地址，q用来保存之前处理过的结点地址。比如创建链表的时候，新建一个结点，得到新结点的地址，这个地址就保存在p中，这个地址需要放到之前处理过的结点的next域中，而q中就保存了之前刚处理过的结点的地址，之后q中的地址就过时了，于是用p中的地址来更新，p,q保存的地址就这样随着循环跳转不断变化，直到最后一个结点。 或许你会问为什么一定要用p，q来保存之前和当前结点的地址，用其他地址不行吗？当然可以，但前提是没有循环。计算机的强大就在于利用循环来实现自动化。要实现循环就必须保证每次循环都跳转到相同的偏移地址，而p和q就保证了每次循环都有相同的偏移地址。  评论：振振有词，毫无根据。 p = q = (struct Info *) malloc(sizeof (struct Info *)); 这句只申请了4字节（为啥是4字节？？）的内存空间，只能用来保存一个地址。而每一个结点至少需要4+20*1+10*1+4+4 = 42字节（为啥是42字节？？不会有内部填充吗？？）内存空间，所以会出错。 子函数？C里还有子函数？？ 至于p  q之类，就不说了。[/quote]  没错，还是低调点好。。。

你可知道这样传递参数 void creat(struct Info * head, int * n, struct Info * p, struct Info * q) 在函数里面做这样的 head = xxx p = xxx q = xxx 更改结果都不会返回出去的.  用指针来返回值只能返回这种更改: head->xxx = xxx *head = xxx

找个好老公什么事都解决了，不用自己那么累了

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

void creat(struct Info * head, int * n, struct Info * p, struct Info * q) 	{ 		 		printf("请输入要创建的订单号,(如需返回上一层,请输入0)\n"); 		scanf("%d", &p->num); 		if (p->num == 0) 			return; 		printf("请输入订餐客户姓名\n"); 		scanf("%s", &p->name); 		printf("请输入预定就餐时间\n"); 		scanf("%s",&p->time); 		printf("请输入就餐人数\n"); 		scanf("%d", &p->number); 		 		q = (struct Info *)malloc(sizeof(struct Info *)); 		q->next = NULL; 		 		*n = *n + 1;  		if (*n == 1)     //如果是第一个结点,则head指向p 			head = p;  		p->next = q; 		p = q;  		return;  	}

sorry我搞错了 因为我一般不会这样写  p = (struct Info *)malloc(sizeof(struct Info *)); 这里只分配了一个指针大小的内存，而不是一个结构

引用 14 楼 sholber 的回复:学两个月还没学会C，可以改行了。要是让我当老师的话，勒令学生10天看完CPP，然后用标准文档强化训练。  大神  我最近也在自学C语言 不知道能不能请你当我的老师 指导下我啊

引用 14 楼 sholber 的回复:学两个月还没学会C，可以改行了。要是让我当老师的话，勒令学生10天看完CPP，然后用标准文档强化训练。 估计不是没学会C，是数据结构基础上不来吧！

creat函数 你要改变链表要传递的参数应该是指向链表第一个节点指针的指针。你其实可以把所有的项目再创建一个结构，这样变量太多了，可读性不好。


Question: 本人刚使用vs2010写c程序，循环判断条件有EOF，不过通过控制台输出的时候，必须使用两个Ctrl+Z才能终止？

先enter 在Ctrl+Z  要不然windows不认  1 2 3 EOF 不行  1 2 3 EOF 可以

我这边一个就可以了


Question: cfree遇到的

恩，感觉是字符编码的问题，可是大部分情况下是不会出现的，偶尔会出现，搞不懂

应该是编码问题。不支持中文注释。


Question: 请指教！float 数据类型

这个是float数据存储存在精度丢失问题，你可以上网查下float数据精度丢失就知道了。

这应该是与浮点数在计算机中的存储方式有关， 数据都是以二进制方式存储的，楼主可以参考一下——http://www.cnblogs.com/jillzhang/archive/2007/06/24/793901.html

说明内存中存储的值就是“100.099998” printf("b=%f\n", b ); 默认输出小数点后6位 printf("b=%0.1f\n", b );  试试

只知道，float类型是7位有效数字的显然 100.1 并没有超过 7位，为什么打印出来的结果是100.09998 ？  急求解释！


Question: error C2053: 'XXX' : wide string mismatch问题

TCHAR szWindowClass []=_T("窗口示例"); TCHAR szTitle []=_T("My Windows");

别用L"My Window", 用 _T宏应该可以了

TCHAR 是个宏，你没有打开宽字符编译，所以它被解释成了char，而不是wchar  L则告诉编译器，这是一个wchar，  也就是说，你把wchar赋给了char，所以你的编译器报错了。

宽字符串被分配给了一个不兼容的类型 https://msdn.microsoft.com/zh-cn/library/988h0zdd%28v=vs.90%29.aspx

#include<windows.h> #include<tchar.h>  LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);  int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,	LPSTR lpCmdLine,int nCmdShow) { 	WNDCLASSEX wcex; 	HWND hWnd; 	MSG msg; 	TCHAR szWindowClass []=L"窗口示例"; 	TCHAR szTitle []=L"My Windows";    这样的


Question: C语言中，如何为可变参数赋值？

引用 1 楼 zhao4zhong1 的回复:先 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\input.c你的回答好让人头大，不过还是感谢你热心回答~~我写出我要的函数了~~  int Scanf(FILE *fp, char *format,...) { 	int *i; 	char *ch; 	float *f; 	int count, k, len;		 	int tmp; 	 	len = strlen(format); 	 	va_list ap;	 	va_start(ap, format); 	 	count = 0; 	for(k=2; k<=len; k=k+2) 	{ 		if(format[k-1]=='c')		//读取字符 		{ 			ch = va_arg(ap, char*);			 			count += fscanf(fp, "%c", ch);		 		}	 		 		if(format[k-1]=='d') 		{ 			i = va_arg(ap, int*); 			 			while((tmp=getc(fp))!=EOF) 			{ 				if((tmp>='0' && tmp<='9') || tmp=='-') 				{ 					ungetc(tmp, fp); 					break; 				} 			} 			 			if(tmp!=EOF) 				count += fscanf(fp, "%d", i); 		}  		if(format[k-1]=='f') 		{ 			f = va_arg(ap, float*); 			 			while((tmp=getc(fp))!=EOF) 			{ 				if((tmp>='0' && tmp<='9') || tmp=='-') 				{ 					ungetc(tmp, fp); 					break; 				} 			} 			 			if(tmp!=EOF) 				count += fscanf(fp, "%f", f); 		} 	} 		 	va_end(ap); 	 	return count; }

引用 4 楼 yan597478677 的回复:厉害，我还没看到过这种东西，楼主求解这种技巧一般用在什么地方？我写了一个多项式的函数操作集合，但是在进行赋值时，需要从一个文档里依次读入系数值和指数值，文档中除了整数和小数还有别的字符，这时候就要自己设定一个读取函数进行录入了~~

C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\input.c：     1002:                     case _T('d') :    1003:     1004:                         if (_T('-') == ch) {    1005:                             ++negative;    1006:     1007:                             goto d_incwidth;    1008:     1009:                         } else if (_T('+') == ch) {    1010: d_incwidth:    1011:                             if (!--width && widthset)    1012:                                 ++done_flag;    1013:                             else    1014:                                 ch = INC();    1015:                         }    1016:     1017: getnum:    1018:                         if ( integer64 ) {    1019:     1020:                             while (!done_flag) {    1021:     1022:                                 if (_T('x') == comchr || _T('p') == comchr)    1023:     1024:                                     if (_ISXDIGIT(ch)) {    1025:                                         num64 <<= 4;    1026:                                         ch = _hextodec(ch);    1027:                                     }    1028:                                     else    1029:                                         ++done_flag;    1030:     1031:                                 else if (_ISDIGIT(ch))    1032:     1033:                                     if (_T('o') == comchr)    1034:                                         if (_T('8') > ch)    1035:                                                 num64 <<= 3;    1036:                                         else {    1037:                                                 ++done_flag;    1038:                                         }    1039:                                     else /* _T('d') == comchr */    1040:                                         num64 = MUL10(num64);    1041:     1042:                                 else    1043:                                     ++done_flag;    1044:     1045:                                 if (!done_flag) {    1046:                                     ++started;    1047:                                     num64 += ch - _T('0');    1048:     1049:                                     if (widthset && !--width)    1050:                                         ++done_flag;    1051:                                     else    1052:                                         ch = INC();    1053:                                 } else    1054:                                     UN_INC(ch);    1055:     1056:                             } /* end of WHILE loop */    1057:     1058:                             if (negative)    1059:                                 num64 = (unsigned __int64 )(-(__int64)num64);    1060:                         }    1061:                         else {    1062:                             while (!done_flag) {    1063:     1064:                                 if (_T('x') == comchr || _T('p') == comchr)    1065:     1066:                                     if (_ISXDIGIT(ch)) {    1067:                                         number = (number << 4);    1068:                                         ch = _hextodec(ch);    1069:                                     }    1070:                                     else    1071:                                         ++done_flag;    1072:     1073:                                 else if (_ISDIGIT(ch))    1074:     1075:                                     if (_T('o') == comchr)    1076:                                         if (_T('8') > ch)    1077:                                             number = (number << 3);    1078:                                         else {    1079:                                             ++done_flag;    1080:                                         }    1081:                                     else /* _T('d') == comchr */    1082:                                         number = MUL10(number);    1083:     1084:                                 else    1085:                                     ++done_flag;    1086:     1087:                                 if (!done_flag) {    1088:                                     ++started;    1089:                                     number += ch - _T('0');    1090:     1091:                                     if (widthset && !--width)    1092:                                         ++done_flag;    1093:                                     else    1094:                                         ch = INC();    1095:                                 } else    1096:                                     UN_INC(ch);    1097:     1098:                             } /* end of WHILE loop */    1099:     1100:                             if (negative)    1101:                                 number = (unsigned long)(-(long)number);    1102:                         }    1103:                         if (_T('F')==comchr) /* expected ':' in long pointer */    1104:                             started = 0;    1105:     1106:                         if (started)    1107:                             if (!suppress) {    1108:     1109:                                 ++count;    1110: assign_num:    1111:                                 if ( integer64 )    1112:                                     *(__int64 UNALIGNED *)pointer = (unsigned __int64)num64;    1113:                                 else    1114:                                 if (longone)    1115:                                     *(long UNALIGNED *)pointer = (unsigned long)number;    1116:                                 else    1117:                                     *(short UNALIGNED *)pointer = (unsigned short)number;    1118:     1119:                             } else /*NULL*/;    1120:                         else    1121:                             goto error_return;    1122:     1123:                         break;    1124:

引用 楼主 kangjianwei101 的回复:例如scanf("%d", &i)中，系统如何为i赋值？ 我知道一些可变参数的知识。例如在printf("%d",i);中，调用va_list ap等相关函数，可使va_list类型的ap指向字符i，此时i的内容已知，自然也就可以输出其值。但是在scanf("%d", &i)中，我的疑惑是&i取了整数i的地址，那么va_list类型的ap如何识别i并为其赋值呢？ 如果有大神能写出一个简单的例子更好，比如写一个函数如int Scanf(FILE *fp, char* format,...)以便从文件fp中根据format格式读取字符，函数的调用方式为Scanf(fp, "%d", &i)，i提前定义为int类型。  "%d" 指示了 &i是一个 int*类型的指针。

引用 2 楼 kangjianwei101 的回复:你这意思是让我看源码....我看C标准库这本书的源码了，我要是能看懂就不来这提问了 理解和讨论之前请先学会如何观察！  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后，就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

厉害，我还没看到过这种东西，楼主求解这种技巧一般用在什么地方？

那么va_list类型的ap如何识别i并为其赋值呢？  它是通过%d来做这个判断的，可以简单想象，有这样一小段代码：  if (!strcmp(format, "%d") {  *((int*)ap) = the_number_get_from_input; }


Question: 关于C语言 字符串中指定字符第N次出现时截取字符串问题

引用 6 楼 yan597478677 的回复:将第三个“，”换做“\0”不就行了? 谁告诉你源字符串是可写的了？

引用 6 楼 yan597478677 的回复:将第三个“，”换做“\0”不就行了?求实际操作

将第三个“，”换做“\0”不就行了?

标准库里没有现成函数。 不能用strtok，因为处理不了连续的逗号。

strtok() 用这个函数能解决吗？  引用 1 楼 zhao4zhong1 的回复://字符串 “123,456,789,0123456,123456” //返回 指定字符“，”第三次出现时 前面的字符串 //结果： “123,456,789” #include <stdio.h> #include <stdlib.h> #include <string.h> int main() {     char s[]="123,456,789,0123456,123456";     char t[256];     char *p,*q;     int n,L;      t[0]=0;     n=0;     p=s;     while (1) {         q=strchr(p,',');         if (NULL==q) break;         p=q+1;         n++;         if (3==n) {             L=__min(255,q-s);             strncpy(t,s,L);t[L]=0;             break;         }     }     printf("%s",t);//123,456,789     return 0; }

引用 1 楼 zhao4zhong1 的回复://字符串 “123,456,789,0123456,123456” //返回 指定字符“，”第三次出现时 前面的字符串 //结果： “123,456,789” #include <stdio.h> #include <stdlib.h> #include <string.h> int main() {     char s[]="123,456,789,0123456,123456";     char t[256];     char *p,*q;     int n,L;      t[0]=0;     n=0;     p=s;     while (1) {         q=strchr(p,',');         if (NULL==q) break;         p=q+1;         n++;         if (3==n) {             L=__min(255,q-s);             strncpy(t,s,L);t[L]=0;             break;         }     }     printf("%s",t);//123,456,789     return 0; } 标准库里没有方法可以直接解决这类问题吗？ 就像Oracle里得函数一样。。。

引用 9 楼 wangjinji123 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] [quote=引用 6 楼 yan597478677 的回复:] 将第三个“，”换做“\0”不就行了? 谁告诉你源字符串是可写的了？[/quote]如果可写 怎么写 啊。。。 疯了 就是不好使啊。。。[/quote] //字符串 “123,456,789,0123456,123456” //返回 指定字符“，”第三次出现时 前面的字符串 //结果： “123,456,789” #include <stdio.h> #include <stdlib.h> #include <string.h> int main() {     char s[]="123,456,789,0123456,123456";     char *p,*q;     int n,L;      n=0;     p=s;     while (1) {         q=strchr(p,',');         if (NULL==q) break;         p=q+1;         n++;         if (3==n) {             q[0]=0;             break;         }     }     if (3==n) printf("%s",s);//123,456,789     else printf("");//表示没找到第3次出现,的地方     return 0; }

引用 8 楼 zhao4zhong1 的回复:[quote=引用 6 楼 yan597478677 的回复:] 将第三个“，”换做“\0”不就行了? 谁告诉你源字符串是可写的了？[/quote]如果可写 怎么写 啊。。。 疯了 就是不好使啊。。。

#include<stdio.h> #include<string.h> #include<algorithm>  int main(){ 	char* str = "123,456,789,0123456,123456"; 	char sub[30]; 	int count = 0, index = 0; 	for (index = 0; index < strlen(str); ++index){ 		if (str[index] == ',') 			++count; 		if (count == 3) 			break; 	} 	strncpy(sub, str, index); 	sub[index] = '\0'; 	puts(sub); } //123,456,789


Question: 使用omp优化之后，运行时间却更长了，代码很简单，求解答

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

我的看法是：不是所有的东西都能优化。


Question: 昨天在微软官网下载了visual studio2013，编了个程序出错了。。。

哥们，你这个编译能过？？？？ 改成下面的代码就好了。 “5.0/9”这个是没错的。因为你前面是5.0 #include <stdio.h> int main() { float s; float a; printf("请输入需要转换的华氏温度："); scanf("%f", &a); s = (5.0 / 9)*(a - 32); printf("转换后的摄氏温度为：%f\n", s); return 0; }

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

#include <stdio.h> int main(){ 	float s; 	float a; 	printf("请输入需要转换的华氏温度："); 	scanf_s("%f", &a); 	s = (5.0 / 9)*(a - 32); 	printf("转换后的摄氏温度为：%f\n", s); 	return 0; }  把printf的&号去掉就行了。

两个错误  1. printf里不应取地址 2. 要将float转成double，让printf打印

printf("转换后的摄氏温度为：%f\n", &s); printf的时候就不用取地址符号了 printf("转换后的摄氏温度为：%f\n", s);

谢谢各位了！


Question: 这事肿么个情况

输出的最大值，printf的提示信息有误！修改下提示信息即可

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

同楼上~~楼主在第二个printf中的汉字解释跟程序不匹配，改成：  printf("两个数中的较大的一个为：%d\n",max);

你的函数find功能是找出两个数较大的一个，但是你输出的文字却写成两数之和了而已。


Question: 帮看下这个什么意思。。。。。

宏定义，上面是注释说明吧

VS IDE中，在不明白的符号上点鼠标右键，选转到定义。

宏啊。就是碰到 LLONG_MIN  就文本替换成 -__LONG_LONG_MAX__-1LL

宏展开，什么问题


Question: 如何解决C 语言执行结果窗口隐藏

引用 1 楼 user-6 的回复:main函数上一行 加#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup")  学习了~

引用 4 楼 a30037338 的回复:[quote=引用 1 楼 user-6 的回复:] main函数上一行 加#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup") +1 ， vs中把_tmain 改成main[/quote]+2

引用 1 楼 user-6 的回复:main函数上一行 加#pragma comment(linker,"/subsystem:windows /entry:mainCRTStartup") +1 ， vs中把_tmain 改成main

在main开始的地方 //隐藏窗口 	HWND hwnd = GetConsoleWindow();  	if (hwnd) 	{ 		// 让控件台程序最小化。 		ShowWindow(hwnd, SW_HIDE); 	}

你别用标准输入/输出。。