Question: 关于模块化编程.....

小到以函数为单元测试，然后以文件为单元测试，接着以大模块为单元。 总之先确认每个小模块都能正确运行。 修改增删都能以模块操作。对其他模块影响很小。

引用 2 楼 qq_18237229 的回复:引用 1 楼 cyd54454 的回复:简单的就是一个函数一个功能，一次测试一个函数，确定其功能是正常的。比如说，你要写入一个数，把这个数+1后，输出，就可以分成，get_num(),increase_num(),print_num()三个函数。先测试3个函数功能是否正确，在正确的基础上，看看组合起来测试是否正确。那那三个函数测试的时候怎么看出效果？ 调试

模块化，也就是高内聚，低耦合！ 相互不依赖，彼此独立开来，每个模块，能在一个main函数的启动下，正常运行。。

可以看看这几个——http://wenku.baidu.com/view/8b6bf3ecaeaad1f346933fbf.html ——http://wiki.mbalib.com/wiki/模块化设计 ——http://blog.csdn.net/zhzht19861011/article/details/5974945

单元测试，先测试一个单元（小到一个函数），然后再集成测试。。。


Question: 给定任意张牌，输出牌数最多的顺子

引用 5 楼 zilaishuichina 的回复:[quote=引用 4 楼 wu4357815 的回复:] [quote=引用 3 楼 zilaishuichina 的回复:] 扑克牌  按点数总共13张    bool hasPoker[13] ; 用来保存某个点数有没有 初始全部标记为false， 然后 遍历你的pai数组，那个点数有就标记为true  然后遍历hasPoker， 统计连续的true最多的是从几到几， 就可以了 那请问怎么统计呢。。。[/quote]   	int currTrue = 0; 	int currBegin = -1; 	int maxTrue = 0; 	int maxBegin = -1; 	for (int i = 0; i < 13; i++) 	{ 		if (hasPoker[i]) //当前是true，计数+1 		{ 			currTrue++; 			if (-1 == currBegin)//第一个true，记录下标 			{ 				currBegin = i; 			} 		} 		else //当前是false，也就是顺子断掉了 		{	 //看当前统计出来的数字，是否比历史最高数字还要大 			 //是，则更新历史记录，并清空当前记录 			if (currTrue > maxTrue) 			{ 				maxTrue = currTrue; 				maxBegin = currBegin; 				currTrue = 0; 				currBegin = -1; 			} 		} 	} 	if (currTrue > maxTrue) 	{ 		maxTrue = currTrue; 		maxBegin = currBegin; 		currTrue = 0; 		currBegin = -1; 	} 	printf("最大连续张数%d,起始点数%d\n", maxTrue, maxBegin+1); [/quote] 经过我的多次实践，你的程序有错误。  #include <iostream> void get123(int a[],int len); void main() { 	int pai[]={6,7,9,11,12}; 	//int pai[]={0,0,1,1,1,1,1,0,0,1,1,1,1}; 	get123(pai,5); } void get123(int a[],int len) { 	int hasPoker[13]; 	for(int i=0;i<13;i++) hasPoker[i]=0; 	for(i=0;i<len;i++) 	{ 		if(hasPoker[a[i]-1]==0) hasPoker[a[i]-1]=1; 	} 	for(i=0;i<len;i++) 		std::cout<<a[i]<<","; 	std::cout<<"\n"; 	for(i=0;i<13;i++) 		std::cout<<hasPoker[i]; 	std::cout<<"\n"; 	int currTrue = 0; 	int currBegin = -1; 	int maxTrue = 0; 	int maxBegin = -1; 	for (i = 0; i < 13; i++) 	{ 		if (hasPoker[i]) //当前是true，计数+1 		{ 			currTrue++; 			if (-1 == currBegin)//第一个true，记录下标 			{ 				currBegin = i; 			} 		} 		else //当前是false，也就是顺子断掉了 		{     //看当前统计出来的数字，是否比历史最高数字还要大 			 //是，则更新历史记录，并清空当前记录 			if (currTrue > maxTrue) 			{ 				maxTrue = currTrue; 				maxBegin = currBegin; 				currTrue = 0; 				currBegin = -1; 			} 		} 	} 	if (currTrue > maxTrue) 	{ 		maxTrue = currTrue; 		maxBegin = currBegin; 		currTrue = 0; 		currBegin = -1; 	} 	printf("最大连续张数%d,起始点数%d\n", maxTrue, maxBegin+1); 	if(maxTrue>=5) 	{ 		for(int i=maxBegin+1;i<maxTrue+ maxBegin+1;i++) 			std::cout<<i<<" "; 	} }

引用 7 楼 wu4357815 的回复:经过我的多次实践，你的程序有错误。   修改如下  int currTrue = 0; 	int currBegin = -1; 	int maxTrue = 0; 	int maxBegin = -1; 	for (int i = 0; i < 13; i++) 	{ 		if (hasPoker[i]) //当前是true，计数+1 		{ 			currTrue++; 			if (-1 == currBegin)//第一个true，记录下标 			{ 				currBegin = i; 			} 		} 		else //当前是false，也就是顺子断掉了 		{     //看当前统计出来的数字，是否比历史最高数字还要大 			//是，则更新历史记录，并清空当前记录 			if (currTrue > maxTrue) 			{ 				maxTrue = currTrue; 				maxBegin = currBegin; 			} 			currTrue = 0;//这里之前写错了，不管currTrue， maxTrue谁大谁小，都要清空当前记录 			currBegin = -1; 		} 	} 	if (currTrue > maxTrue) 	{ 		maxTrue = currTrue; 		maxBegin = currBegin; 	}

应该自己动手写一下的。出了问题再拿出来讨论

引用 2 楼 wu4357815 的回复:[quote=引用 1 楼 liuhengxiao 的回复:] 这个应该不是很难吧？  先把数组的内容从小到大有序排序 最大的顺子就是，从数组第一个元素到最后一个正好是一个顺子  用一个数保存最大顺子的长度 数组下标递增，做元素数值++对比，达到顺子要求并且比当前最大长度大的话 就替换，并记录这个最大顺子 一直到数组的倒数第四个元素结束（顺子长度大于5嘛）  代码还是自己写的比较好，在这里伸手要代码不是很好的样子，貌似  菜鸟分析，高手勿喷！ 你根本就没懂我的意思，那比如3,5,5,6,7,8,9，这样的牌型呢，第一个并不是顺子的起始牌[/quote]  3,5,5,5,6,7,8,9,不满足顺子要求啊 难道我红字说明的不明白。。。

引用 4 楼 wu4357815 的回复:[quote=引用 3 楼 zilaishuichina 的回复:] 扑克牌  按点数总共13张    bool hasPoker[13] ; 用来保存某个点数有没有 初始全部标记为false， 然后 遍历你的pai数组，那个点数有就标记为true  然后遍历hasPoker， 统计连续的true最多的是从几到几， 就可以了 那请问怎么统计呢。。。[/quote]   	int currTrue = 0; 	int currBegin = -1; 	int maxTrue = 0; 	int maxBegin = -1; 	for (int i = 0; i < 13; i++) 	{ 		if (hasPoker[i]) //当前是true，计数+1 		{ 			currTrue++; 			if (-1 == currBegin)//第一个true，记录下标 			{ 				currBegin = i; 			} 		} 		else //当前是false，也就是顺子断掉了 		{	 //看当前统计出来的数字，是否比历史最高数字还要大 			 //是，则更新历史记录，并清空当前记录 			if (currTrue > maxTrue) 			{ 				maxTrue = currTrue; 				maxBegin = currBegin; 				currTrue = 0; 				currBegin = -1; 			} 		} 	} 	if (currTrue > maxTrue) 	{ 		maxTrue = currTrue; 		maxBegin = currBegin; 		currTrue = 0; 		currBegin = -1; 	} 	printf("最大连续张数%d,起始点数%d\n", maxTrue, maxBegin+1);

引用 3 楼 zilaishuichina 的回复:扑克牌  按点数总共13张    bool hasPoker[13] ; 用来保存某个点数有没有 初始全部标记为false， 然后 遍历你的pai数组，那个点数有就标记为true  然后遍历hasPoker， 统计连续的true最多的是从几到几， 就可以了 那请问怎么统计呢。。。

引用 1 楼 liuhengxiao 的回复:这个应该不是很难吧？  先把数组的内容从小到大有序排序 最大的顺子就是，从数组第一个元素到最后一个正好是一个顺子  用一个数保存最大顺子的长度 数组下标递增，做元素数值++对比，达到顺子要求并且比当前最大长度大的话 就替换，并记录这个最大顺子 一直到数组的倒数第四个元素结束（顺子长度大于5嘛）  代码还是自己写的比较好，在这里伸手要代码不是很好的样子，貌似  菜鸟分析，高手勿喷！ 你根本就没懂我的意思，那比如3,5,5,6,7,8,9，这样的牌型呢，第一个并不是顺子的起始牌


Question: C语言free函数出错，求解！

引用 20 楼 godbreak 的回复:我是无语了，char*的指针当然是+1，问题不在指针加一，而在于系统维护的内存分配表根本就没有加一后指针对应的内存块，所以free失败。你的表述“实际已经free了第十一个字节”绝对是错的。 貌似是酱紫的哦，系统没有给这个+1后的地址分配过内存空间，这个时候去释放没有申请的空间，这才是报错原因。我理解错了。。。sorry

引用 19 楼 liuhengxiao 的回复:[quote=引用 15 楼 godbreak 的回复:] [quote=引用 11 楼 liuhengxiao 的回复:] 刚又做了个实验 #include <stdio.h> #include <stdlib.h>  int main(int argc, _TCHAR* argv[]) { 	char *p =(char *)malloc(10); 	p++; 	free(p); 	return 0; }  这个的报错结果和你的一致，我申请了10个字节空间，释放之前把P的位置向后移动了1个字节，在free的时候，系统会free10个字节的空间，但实际已经free了第十一个字节，free一个没有malloc的空间，这报错，应该能理解了吧  我没记错的话，系统会记录分配出去每个内存块对应的首地址和长度，所以当你指针++，根本就不是free到第是一个，而是找不到此地址对应的内存块，所以free失败。[/quote] 你的印象是错的。。。指针自增移动的地址是根据指针类型进行判断，而不是你说的地址内存块，这里p是char *，自增后地址+1，而不是+10 [/quote]  我是无语了，char*的指针当然是+1，问题不在指针加一，而在于系统维护的内存分配表根本就没有加一后指针对应的内存块，所以free失败。你的表述“实际已经free了第十一个字节”绝对是错的。

引用 15 楼 godbreak 的回复:[quote=引用 11 楼 liuhengxiao 的回复:] 刚又做了个实验 #include <stdio.h> #include <stdlib.h>  int main(int argc, _TCHAR* argv[]) { 	char *p =(char *)malloc(10); 	p++; 	free(p); 	return 0; }  这个的报错结果和你的一致，我申请了10个字节空间，释放之前把P的位置向后移动了1个字节，在free的时候，系统会free10个字节的空间，但实际已经free了第十一个字节，free一个没有malloc的空间，这报错，应该能理解了吧  我没记错的话，系统会记录分配出去每个内存块对应的首地址和长度，所以当你指针++，根本就不是free到第是一个，而是找不到此地址对应的内存块，所以free失败。[/quote] 你的印象是错的。。。指针自增移动的地址是根据指针类型进行判断，而不是你说的地址内存块，这里p是char *，自增后地址+1，而不是+10

我也只能说到这了，反正你已经结贴了，不信自己打印下，看下你还能把链表遍历打印不。

这时候p变成了野指针，建议执行： p = null，不需要进行free。 free的后果是严重的，虽然没有报错：

这样修改后还是不完美的：  p这个list被破坏了。   引用 13 楼 jianfengtu 的回复:修改后的程序：   /*  * rl.c - Reverse a list  */  #include <stdlib.h> #include <stdio.h>  struct node {     int data;     struct node *next; };  struct node *create_list(int array[], int length) {     int i = 0;     struct node *head, *p;     head = (struct node *) malloc( sizeof(struct node) * length );     for ( i=0; i<length-1; i++ ) {         p = &(head[i]);         p->data = array[i];         p->next = &(head[i+1]);     }     p = &(head[i]);     p->data = array[i];     p->next = NULL;     return head; }  struct node *reserve_list(struct node *list) {     struct node *p, *prev, *next;      for (p = list, prev = NULL; p; p = next) {         next = p->next;         p->next = prev;         prev = p;     }      return prev; }  void free_list(struct node *list) {     free(list); }  int main() {     struct node *p, *p1;     int source[10] = {1,2,3,4,5,6,7,8,9,10};     p = create_list(source, 10);     p1 = reserve_list(p);     free_list(p); }

引用 11 楼 liuhengxiao 的回复:刚又做了个实验 #include <stdio.h> #include <stdlib.h>  int main(int argc, _TCHAR* argv[]) { 	char *p =(char *)malloc(10); 	p++; 	free(p); 	return 0; }  这个的报错结果和你的一致，我申请了10个字节空间，释放之前把P的位置向后移动了1个字节，在free的时候，系统会free10个字节的空间，但实际已经free了第十一个字节，free一个没有malloc的空间，这报错，应该能理解了吧  我没记错的话，系统会记录分配出去每个内存块对应的首地址和长度，所以当你指针++，根本就不是free到第是一个，而是找不到此地址对应的内存块，所以free失败。

引用 6 楼 jianfengtu 的回复:To bubu8633: 循环第一步是把表头元素置为表尾元素，所以next为NULL，没有错。  To jmppok: 我觉得list是一块内存，无论如何改变其中的值，都是被允许的。free函数不应该出错。  我在这里能够找到高手吗？  怎么说呢，改了下，看着张图：    我把你内部的变量p改为了tmp_p，这样比较清晰点。你传进来的list指针的next发生了改变。也就是你破坏了原来的链表，将原链表打断了。

To liuhengxiao: 你是对的，谢谢！

我个人认为的应该是这样的

仅供参考//将c:\\tmp文件夹下的所有文件的内容全部放到用malloc分配的内存中 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <io.h> struct FB {     char fn[256];     size_t fl;     char *b;     struct FB *next;     struct FB *prev; } *fh,*fb,*ft; char ln[256]; char fpn[256]; FILE *af; FILE *f; int L,n; int main() {     system("dir /b /a-d c:\\tmp\\*.* >c:\\allfn.txt");     af=fopen("c:\\allfn.txt","r");     if (NULL==af) {         printf("Can not open file c:\\allfn.txt!\n");         return 1;     }     fh=NULL;     fb=NULL;     n=0;     while (1) {         if (NULL==fgets(ln,256,af)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) ln[L-1]=0;         printf("read %s\n",ln);         strcpy(fpn,"c:\\tmp\\");         strcat(fpn,ln);         ft=(struct FB *)malloc(sizeof(struct FB));         if (NULL==ft) {             printf("Can not malloc ft!\n");             fclose(af);             return 2;//之前的malloc在main退出后由操作系统自动free         }         printf("ft[%d]==%p\n",n,ft);         strcpy(ft->fn,fpn);         f=fopen(fpn,"rb");         if (NULL==f) {             printf("Can not open file %s!\n",fpn);             fclose(af);             return 3;//之前的malloc在main退出后由操作系统自动free         }         ft->fl=_filelength(fileno(f));         ft->b=malloc(ft->fl);         if (NULL==ft->b) {             printf("Can not malloc ft->b!\n");             fclose(f);             fclose(af);             return 4;//之前的malloc在main退出后由操作系统自动free         }         printf("ft[%d]->b==%p\n",n,ft->b);         if (ft->fl!=fread(ft->b,1,ft->fl,f)) {             printf("fread error!\n");             fclose(f);             fclose(af);             return 5;//之前的malloc在main退出后由操作系统自动free         }         fclose(f);         ft->next=NULL;          if (NULL==fh) {             ft->prev=NULL;             fh=ft;         } else {             fb->next=ft;             ft->prev=fb;         }         fb=ft;         n++;     }     fclose(af);     printf("-----list-----\n");     for (ft=fh;NULL!=ft;ft=ft->next) {         printf("%8d %s\n",ft->fl,ft->fn);         if (NULL!=ft) fb=ft;     }     printf("-----free-----\n");     n--;     if (NULL!=fh) {         for (ft=fb->prev;NULL!=ft;ft=ft->prev) {             if (NULL!=ft->next->b) {                 printf("ft[%d]->b==%p\n",n,ft->next->b);                 free(ft->next->b);             }             if (NULL!=ft->next) {                 printf("ft[%d]==%p\n",n,ft->next);                 free(ft->next);             }             n--;         }         if (NULL!=fh->b) {             printf("ft[0]->b==%p\n",fh->b);             free(fh->b);         }         printf("ft[0]==%p\n",fh);         free(fh);     }     return 0; } //C:\tmp\tmp\Debug>dir /a-d c:\tmp // 驱动器 C 中的卷是 C_HD5_1 // 卷的序列号是 1817-D526 // // c:\tmp 的目录 // //找不到文件 // //C:\tmp\tmp\Debug>tmp //找不到文件 //-----list----- //-----free----- // //C:\tmp\tmp\Debug>dir /a-d c:\tmp // 驱动器 C 中的卷是 C_HD5_1 // 卷的序列号是 1817-D526 // // c:\tmp 的目录 // //2011-06-30  18:04            44,840 my_c.rar //2011-06-30  17:18             1,036 err.frm //2011-06-30  14:32            14,243 出租.txt //2011-06-28  12:08            23,681 MSDN98书签.txt //             4 个文件         83,800 字节 //             0 个目录 17,041,870,848 可用字节 // //C:\tmp\tmp\Debug>tmp //read my_c.rar //ft[0]==00421800 //ft[0]->b==00520068 //read err.frm //ft[1]==00421670 //ft[1]->b==0052AFC0 //read 出租.txt //ft[2]==00421530 //ft[2]->b==00378F28 //read MSDN98书签.txt //ft[3]==004213F0 //ft[3]->b==0052B3F8 //-----list----- // 44840 c:\tmp\my_c.rar //  1036 c:\tmp\err.frm // 14243 c:\tmp\出租.txt // 23681 c:\tmp\MSDN98书签.txt //-----free----- //ft[3]->b==0052B3F8 //ft[3]==004213F0 //ft[2]->b==00378F28 //ft[2]==00421530 //ft[1]->b==0052AFC0 //ft[1]==00421670 //ft[0]->b==00520068 //ft[0]==00421800 // //C:\tmp\tmp\Debug>

int main() {     struct node *p;     int source[10] = {1,2,3,4,5,6,7,8,9,10};     p = create_list(source, 10); //在这里p指针式指向的申请的堆的首地址     p = reserve_list(p); //这里执行完成以后，p指针指向的申请的堆的最后一个节点     free_list(p); //释放堆空间的时候，只释放了最后一个节点，别告诉我释放空间的时候能够智能化到倒着释放空间的 }  申请的空间中，每个节点对应的数据和地址没有改变，改变的只是链表顺序中的每个指针 在最后一步释放空间的时候，实际上就是释放的最后一个节点的空间，前面9个节点的空间都没有释放，你这个报错应该是内存泄露的报错吧？  菜鸟理解，高手勿喷！

楼上几位，人家的反转函数没问题，不要在这里找问题了吧？ 运行时候链表确实反转了，如图所示

调试一下，估计是reserve_list(p); 破坏了list

for (p = list, prev = NULL; p; p = next) {         next = p->next;         p->next = prev;//bug在这个地方，执行第一次循环就错了         prev = p;     }

首先你那个head要先初始化指向NULL，然后再对malloc返回值判断一下，使用函数要养成判断函数执行成功和失败的习惯楼主。

请注意，该链表是一次性分配的，在内存里面是个连续的空间。谢谢！


Question: 这些函数哪位大神能告诉我是什么意思

一层一层剥开来就行了

之前的有错误，丢了返回值类型： /* // 示例函数1： void fn1(void); // 示例函数2： int fn2(char **pp1, char **pp2); */ int main (int argc, char *argv[]) { 	// 声明一个指向该函数的指针变量 	// void (*pfn1)(void); 	// 将数值 0 转换为指向该函数的指针类型 	// (void (*)(void))0 	// 和指针变量一样前面加*引用该函数 	// *(void (*)(void))0 	// 调用该函数(不加星号同样可以调用) 	(*(void (*)(void))0)();  	// 声明一个指向该函数的指针变量 	// int (*pfn2)(char **, char **); 	// 将数值 0 强制转换为指向该函数的指针类型 	// (int (*)(char **, char **))0 	// 和指针变量一样前面加*引用该函数 	// *(int (*)(char **, char **))0 	// 调用该函数(不加星号同样可以调用) 	char *p1 = NULL; 	char *p2 = NULL; 	int ret = (*(int (*)(char **, char **))0)(&p1, &p2); 	 	return ret; }

// 示例函数1： void fn1(void) { } // 声明一个指向该函数的指针变量 void (*pfn1)(void); // 将数值 0 转换为指向该函数的指针类型 // (*)(void)0 // 和指针变量一样前面加*引用该函数 // *((*)(void)0) // 调用该函数(不加星号同样可以调用) *((*)(void)0)();  // 示例函数2： int fn2(char **, char **) { 	return 0; } // 声明一个指向该函数的指针变量 int (*pfn2)(char **, char **); // 将数值 0 强制转换为指向该函数的指针类型 // (*)(char **, char **)0 // 和指针变量一样前面加*引用该函数 // *((*)(char **, char **)0) // 调用该函数(不加星号同样可以调用) char *p1 = NULL; char *p2 = NULL; int ret = *((*)(char **, char **)0)(&p1, &p2);

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

给你推荐本书，上面有详细的解释。《c和指针》！

下面是我看到的一篇博客里的讲解，对你应该有帮助：        在指针函数中，有这样一类函数，它们也返回指针，但是这个指针不是指向int、char之类的基本类型，而是指向函数。对于初学者，别说写出这样的函数声明，就是看到这样的写法也是一头雾水。比如,下面的语句：           int (*ff(int))(int *, int);  我们用上面介绍的方法分析一下，ff首先与后面的“()”结合，即：           int (*(ff(int)))(int *, int);                   // 用括号将ff(int)再括起来  也就意味着，ff是一个函数。      接着与前面的“*”结合，说明ff函数的返回值是一个指针。然后再与后面的“()”结合，也就是说，该指针指向的是一个函数。  这种写法确实让人非常难懂，以至于一些初学者产生误解，认为写出别人看不懂的代码才能显示自己水平高。而事实上恰好相反，能否写出通俗易懂的代码是衡量程序员是否优秀的标准。一般来说，用typedef关键字会使该声明更简单易懂。在前面我们已经见过：           int (*PF)(int *, int);  也就是说，PF是一个函数指针“变量”。当使用typedef声明后，则PF就成为了一个函数指针“类型”，即：           typedef int (*PF)(int *, int);  这样就定义了返回值的类型。然后，再用PF作为返回值来声明函数:           PF ff(int);  转至：http://blog.sina.com.cn/s/blog_5e8facd20100qfpn.html

//C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+

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

路过。。。


Question: 请问各位大神以下的Keil编译错误是不是代码超过2KB了？？请问该怎么解决呢？

版本有问题，正常的Keil是收费的，LZ需要找个破解工具破解下才能舒服的用keil

印象当中是keil没有破解。搜 “51keil破解”


Question: 关于自学C语言

敲代码了么？ 读的懂，不一定写的出来的哦

动手实践第一

看的时候如果只是和看小说一样的看了一次，那就从新看，这次要边看边实际上机练习

先下载Win-TC，然后参考C:\Win-TC\tcstudy.chm

同是天涯沦落人！我跟你差不多，这玩意学完一本书，做了几个一般般的小软件后就去找开发团队吧。有开发团队愿意接纳你，里面有人带你，几个项目做下来，基本就算是入门了。可惜的是，愿意给咱提供机会的团队很少。个人建议，继续学习，一边学，一边找用人单位。最好是找那种对你比较包容的团队，一个压抑的环境下你学东西效率不会高的。对新手来说，自己压力大的同时还要时时担心被别人指责，这样的环境生活不爽，而且对自己最后一点的自信都可能失去。如果一时找不到合适的开发团队，不妨先去做测试，等待时机再谋转行开发。

书看完，习题做完

要自己写一些代码。。。然后调试查错。。先把基础过一遍吧。。

引用 1 楼 user-8 的回复:继续看书！！~~你要看的书还很多！~~非常多！真的！~~看你往哪个方向发展，比如我学WIN32，在啃《WINDOWS程序设计》如果是关于软件开发应该怎么看？比如处理一些数据什么的。

C语言进阶方面的书也很多，我是学的C++起步的，C语言只看了一本谭浩强的书，之后就是C++的各种书，C++ priner plus,C++primer,C++编程思想，再是现在WIN32

呵呵！~你会越学越发现自己的渺小与计算机世界的浩瀚，特别是给你一种你永远都学不到头的感觉！~~


竟然要用makefile 就不要用vs了。。

Makefile 不是linux 上的吗，怎么会用vs2013生成， 要么你装了qt助手！ 我自己一般习惯自己写！或许我孤陋寡闻了，等高手解答了！

引用 4 楼 zhao4zhong1 的回复:在MSDN中搜vcbuild和msbuild+1

在MSDN中搜vcbuild和msbuild


Question: C语言 标准问题

引用 15 楼 vcf_reader 的回复:不同版本有不同的实现  不同的编译器对C标准的支持程度不同

引用 15 楼 vcf_reader 的回复:不同版本有不同的实现

不同版本有不同的实现

引用 10 楼 wang0635 的回复:可以确定的。见C标准： When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded. If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a. 如     printf("%d, %d\n", -5 / 2, -5 % 2);     printf("%d, %d\n", -5 / -2, -5 % -2);     printf("%d, %d\n", 5 / -2, 5 % -2); 输出： -2, -1 2, -1 -2, 1楼主这个就能看明白了把

引用 8 楼 mymtom 的回复:如果被除数或除数为负数， / 和 % 操作符的结果不确定，所以尽量避免负数的这种运算； 如果确实需要，就要自己根据需要确定余数的符号，  “取余操作结果的正负由被除数决定” 我印象中有这么一句话，也一直这么认为的，因为目前接触的环境都是这个结果。。又一个误区。 看样子或许真跟平台有关了。多谢版主。 楼主可以给个总结。

C99 中 6.5.5 引用 13 楼 mymtom 的回复:这明显是断章取义啊，就算你见过的所有编译器的结果都是是这样，并不能说明其他编译器的结果也是这样。 我不是道你的那几句话从哪里来的，我没有正式的C89标准，但是有一份C89草案里关于 % 操作符的完整描述是这样的：  3.3.5 Multiplicative operators  Syntax            multiplicative-expression:                   cast-expression                   multiplicative-expression *  cast-expression                   multiplicative-expression /  cast-expression                   multiplicative-expression %  cast-expression  Constraints     Each of the operands shall have arithmetic type.  The operands of the % operator shall have integral type.  Semantics     The usual arithmetic conversions are performed on the operands.     The result of the binary * operator is the product of the operands.     The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder.  In both operations, if the value of the second operand is zero, the behavior is undefined.     When integers are divided and the division is inexact, if both operands are positive the result of the / operator is the largest integer less than the algebraic quotient and the result of the % operator is positive.  If either operand is negative, whether the result of the / operator is the largest integer less than the algebraic quotient or the smallest integer greater than the algebraic quotient is implementation-defined, as is the sign of the result of the % operator.  If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a .

引用 10 楼 wang0635 的回复:可以确定的。见C标准： When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded. If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a. 如     printf("%d, %d\n", -5 / 2, -5 % 2);     printf("%d, %d\n", -5 / -2, -5 % -2);     printf("%d, %d\n", 5 / -2, 5 % -2); 输出： -2, -1 2, -1 -2, 1 这明显是断章取义啊，就算你见过的所有编译器的结果都是是这样，并不能说明其他编译器的结果也是这样。 我不是道你的那几句话从哪里来的，我没有正式的C89标准，但是有一份C89草案里关于 % 操作符的完整描述是这样的：  3.3.5 Multiplicative operators  Syntax            multiplicative-expression:                   cast-expression                   multiplicative-expression *  cast-expression                   multiplicative-expression /  cast-expression                   multiplicative-expression %  cast-expression  Constraints     Each of the operands shall have arithmetic type.  The operands of the % operator shall have integral type.  Semantics     The usual arithmetic conversions are performed on the operands.     The result of the binary * operator is the product of the operands.     The result of the / operator is the quotient from the division of the first operand by the second; the result of the % operator is the remainder.  In both operations, if the value of the second operand is zero, the behavior is undefined.     When integers are divided and the division is inexact, if both operands are positive the result of the / operator is the largest integer less than the algebraic quotient and the result of the % operator is positive.  If either operand is negative, whether the result of the / operator is the largest integer less than the algebraic quotient or the smallest integer greater than the algebraic quotient is implementation-defined, as is the sign of the result of the % operator.  If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a .

两个符号不同的数相除 在程序中的规则 和 数学 中的规则是不一样的  数学中的规则 参考 带余除法，带余除法规定余数r >= 0  编程中 % 这个叫取模， 取模 != 取余  对于整型数a，b来说，取模运算或者求余运算的方法都是： 1.求商： c = a/b; 2.求模/余数： r = a - c*b. 求模运算和求余运算在第一步不同:  取模运算在取c的值时，向0 方向舍入(fix())；而取余运算在计算c的值时，向负无穷方向舍入(floor())。 例如：计算-7 / 4 那么：a = -7；b = 4； 第一步：求整数商c，c求出来是 -1.75。求模运算c = -1（向0方向舍入），求余c = -2（向负无穷方向舍入）； 第二步：计算模和余数，公式相同，但因c的值不同，求模时r = -3，求余时r = 1。

你初中数学没学吗

引用 6 楼 mymtom 的回复:[quote=引用 3 楼 call_from_dream 的回复:] 数学上怎样，编译器一般都会尊重数学结果的，除非发生内存溢出，精度不够什么的。毕竟，编译器也是根据实际问题的模型去解决问题的。个人认为：当a ＜ 0 ， b ＞０时，　ｑ不会为正，顶多是0，不然就是负数。 楼主都说了q的正负是由编译器决定的。 [/quote]  版主有没有一些建设性的意见？？

引用 3 楼 call_from_dream 的回复:数学上怎样，编译器一般都会尊重数学结果的，除非发生内存溢出，精度不够什么的。毕竟，编译器也是根据实际问题的模型去解决问题的。个人认为：当a ＜ 0 ， b ＞０时，　ｑ不会为正，顶多是0，不然就是负数。 楼主都说了q的正负是由编译器决定的。

引用 1 楼 user-11 的回复:还有一个东西叫虚拟机呢。  虚拟机？？？　　Java吗？？？  C语言有什么虚拟机？？？

还有一个东西叫虚拟机呢。


Question: linux c上printf函数实现问题

还有记得一定养成好的习惯，有open必有close，你给出的demo里面。你open了ttt.c这个文件却没有close，虽然程序结束会自动关闭所有打开的file descriptor，但是主动自觉的去关闭自己已经打开的file descriptor是个好习惯。 God bless you

lz看这个，what will happen？ #include<unistd.h> #include <sys/types.h> #include <sys/stat.h> #include<fcntl.h> #include<stdio.h>  int main(void) {      int fd;       fd = open("./hello.c",O_WRONLY|O_APPEND,0644);      dup2(fd,1);      printf("fd,%d &fd :%p",fd,&fd);       close(fd);       return 0 ; }

引用 15 楼 u011367985 的回复:明白了，有点打错了

引用 5 楼 misskissC 的回复:在2‘s complement下，以%d访问&i值若最高位，若&i的最高位为1则会被当成负数。如果要输出&i的值： printf("%u\n", &i);  or printf("%p\n", &i);  我是问为什么打印不出i=1，不是打地址，%u打出啦一个很大的数

引用 8 楼 chenzhuoxue 的回复:i 里的值1就是文件描述符，不需要打它的地址 。  你要用%d打印它的地址， 你加一个强制转化试试      （int）&i 这会报错的

明白了，有点打错了

学习了~~~

引用 12 楼 DIGGOD 的回复:因为i是局部变量，放在stack中. 一个程序的内存stack一般放在高地址， 所以i的地址接近0x80000000, 以%d打印的话，如果最高位是1就会被当作负数打印出来。请问该用什么打呢？另外我打的是数值，和地址有什么关系

引用 6 楼 zxh707wk 的回复:打印地址可以用十六进制格式输出 +1

引用 8 楼 chenzhuoxue 的回复:i 里的值1就是文件描述符，不需要打它的地址 。  你要用%d打印它的地址， 你加一个强制转化试试      （int）&i地址可没有正负位

打印地址可以用十六进制格式输出

引用 2 楼 u011367985 的回复:[quote=引用 1 楼 user-8 的回复:] 你打印的是i的地址, 确定这个是你的意图? 是打印啦i的地址，我觉得i应该等于文件描述符1，这样printf才能打印到ttt[/quote] 嗯,明白你的意思了, 我对这个现象也挺好奇, 不过我这里的现象跟你好像不太一样. 我在open之后, i确实是1但printf打印不到 ttt.c 里面, 但 write(1,"abcde",5);这样可以. 猜想因为printf其实还是跟stdout直接关联的, 直接把FILE里的 descriptor关掉再开, 可能没那么无缝对接吧. 至少设备类型就不一样.  gcc version 4.9.1

楼主在看《LC编程一站式学习》？ &i类型与%d的不匹配，类型转换（unsigned  to signed）得到结果。

引用 1 楼 user-8 的回复:你打印的是i的地址, 确定这个是你的意图? 是打印啦i的地址，我觉得i应该等于文件描述符1，这样printf才能打印到ttt

你打印的是i的地址, 确定这个是你的意图?


Question: linux下面curses库的应用出现问题

不要沉啊，求大神指教！

大神呢刚加了分，求解决方案

对于这种刚发的帖子，我总是毫不犹豫的顶了。如果火了就是个前排，可以混个脸熟，说不定谁好心就给粉了…稳赚不赔；如果沉了就感觉是我弄沉的，很有成就感，还能捞经验。


Question: linux 在使用2M带宽网络进行socket通信时创建socket失败

你用多少台电脑做客户端的？

这是服务端代码，bind了就是服务端的，客户端只是循环的connect 没什么东西

服务端的代码有么？

socket创建部分我可以拿出来，但是感觉跟代码无关，我本地测试没问题，经2M网络测试不可以， 感觉也有可能我select时参数不对         if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)         {             //_socket_errno = CONN_SOCKET_ERR;              close(sockfd);             return -1;         }          bufSize = 131072;          if(setsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&bufSize,sizeof(bufSize))<0)         {             //printf(" telcom SO_SNDBUF err\n");         }         if(setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&bufSize,sizeof(bufSize))<0)         {             //printf(" telcom SO_RCVBUF err\n");         }         if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&bufSize,sizeof(bufSize))<0)         {             //printf(" telcom SO_REUSEPORT err\n");         }  printf("bind(sockfd,(struct sockaddr *)&srvAddr,sizeof(srvAddr))\n");         if(bind(sockfd,(struct sockaddr*)&srvAddr,sizeof(srvAddr))<0) 以上是我创建socket时候的参数 希望能对应我2M网络环境给予分析，非常感谢

请贴下关键代码。


Question: 请教一个数组的问题，谢谢

要么使用一个整数记住行数，要么使用特殊值标识空行，否则是没有其他办法的。 所以，才会有封装出来的容器：vector。用着方便。

引用 4 楼 u011718046 的回复:[quote=引用 3 楼 misskissC 的回复:] 如：         int i, j;         char ename[11][10];          for ( i = 0; i < 3; ++i) {                 for (j = 0; j < 10; ++j){                         ename[i][j] = i + j;                 }         }   在程序中记住i的值。   我没想明白一个问题，就是 char xx[10] 其实是一个字符串 ，那么怎么来表示一个字符串数组呢？ 比如 aa12 ff66 3300 [/quote] 字符串（字符数组）char  xx[10];每个元素存一个字符。 字符串数组 char  *xx[10];每个元素可以存一个字符串的首地址。

结贴的时候给点分，不懂可以细聊。

char ename[11][10];  上面这句，你已经定义了字符串数组，表示11行字符串，每行字符串可以有10个字符。

你定义n行的数组可以可以随便填几行，但不能超过n行，内核不会知道你填了几行，它为你分配了你定义的数组所需要的空间，就算你不填里面数组里还是有别的东西的了，所以不会知道你插不插入。所以定义时最好先初始化，不然打印的时候会出现很多乱码。

引用 3 楼 misskissC 的回复:如：         int i, j;         char ename[11][10];          for ( i = 0; i < 3; ++i) {                 for (j = 0; j < 10; ++j){                         ename[i][j] = i + j;                 }         }   在程序中记住i的值。   我没想明白一个问题，就是 char xx[10] 其实是一个字符串 ，那么怎么来表示一个字符串数组呢？ 比如 aa12 ff66 3300

可以, 但C语言没法知道你只有3行, 除非你用额外的机制区分, 比如没数据的行用一个特殊的值表示

记住你插入三行的这个变量值。


Question: 数组作为参数传递或返回值的相关问题

不可以传数组，所谓的传数组实质上传的都是数组的指针/数组名/首地址，所以访问传递的指针指向的内容，就可以实现“双向传递”了。 另外，一般需要传递数组长度，以避免指针访问越界。

思考一下为什么没人将整个互联网内容作为函数参数或返回值呢？

引用 1 楼 zxhuser-5 的回复:双向传值 #include <stdio.h>  void start_num(int a[],int len) { 	int i; 	for(i=0;i<len;i++) 	{ 		a[i]=i; 	} }  void put_num(int a[],int len) { 	int i; 	for(i=0;i<len;i++) 	{ 		printf("%3d",a[i]); 	} }  int main() { 	int a[10]; 	start_num(a,10); 	put_num(a,10); 	getchar(); 	return 0; }  OR    void start_num(int  *a,int len) {     int i;     for(i=0;i<len;i++)     {         a[i]=i;     } }

一维数组 void fun(int *a)，或 void fun(int a[]) 二维数组 A[10][5] void fun(int a[][5]) 以此类推。 传递的是地址，可以在调用函数里用读、写进行传递


Question: error C2228: left of '.GetPos' must have class/struct/union type

引用 2 楼 angel_su 的回复:就是说m_sldThresh和m_editThresh不是类或结构体不能使用.操作符，估计你那两个变量是指针吧，改->试试...+!

大神都在哪

引用 4 楼 qq_19530589 的回复:引用m_sldThresh这个变量怎么定义的  这段程序是我在网上下的   可是他并没有定义 它  必须有定义，在别的文件里吧。  估计这是指针，用 m_sldThresh->GetPos(); 试试看


Question: 想学一下c语言

如果你是相关专业的大一学生 就跟着学校课程 再买本好书   如果周围没有环境 可以选择《写给大家看的C语言书》或者《head first C》，比较轻松 好入门


Question: 求助，自己写的课设。。。好晕。。不会调试了。。求帮忙。。。万谢

设置断点调试是学编程的人员必须学会的，只要学会熟练使用，许多问题其实可以自己找出问题

引用 6 楼 haltwang 的回复:设个断点，单步调试，对理解程序最好了 这个。。。怎么弄啊，可以详细说一下嘛。。。

引用 7 楼 addsspu 的回复:void insert_flight(fly *P, char *plane_num, char *city1, char *city2, char *time1, char *time2, int plane_room, float price, float zhekou, int sit) {     fly *q;     q = (fly*)malloc(sizeof(fly));     strcpy_s(q->plane_num, plane_num);     strcpy_s(q->city1, city1);     strcpy_s(q->city2, city2);     strcpy_s(q->time1, time1);     strcpy_s(q->time2, time2);     q->plane_room = plane_room;     q->price = price;     q->zhekou = zhekou;     q->sit = sit;    //p应该是已经那好的链表的表头吧，你在准备在首位置插入吗？如果是请看下面     q->next = p->next;     p->next=q; } 谢谢层主，再遇到解决不了的困难还可以找你伐

引用 4 楼 u012421456 的回复:这一段是插入操作，但是每次插入之后就把原来的取代了 那你想怎样 不知道为什么，把它注释了却又好了 你是想知道这个原因还是怎么 课设，本来愿意好好回答的就很少或几乎没有，你问题又不清楚，那。。。 坐等楼下大神吧 是插入操作，插入新的数据，但不是取代原来的。 包括创建数据的时候，假如输入两组数据，查询时候只会显示第二组的数据，这样子。

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

引用 16 楼 qq_18237229 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] 仅供参考//假设带表头结点的单向链表头指针为head，试编写一个算法将值为5的结点插入到连接表的第k个结点前，删除第k个节点，并对该链表进行排序。 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> // 这个差不多单链表的操作都有了吧，，，我会仔细看的，觉着会有启发 [/quote] 不是沉迷于代码，要明白思想。

引用 11 楼 zhao4zhong1 的回复:仅供参考//假设带表头结点的单向链表头指针为head，试编写一个算法将值为5的结点插入到连接表的第k个结点前，删除第k个节点，并对该链表进行排序。 #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <time.h> struct NODE {     int          data;     struct NODE *next; } H,*head,*p,*q,*s1,*s2,*s3,*s4,*s; int i,j,k,n,t,m; int main() {     srand(time(NULL));      //填写头节点数据     H.data=-1;     H.next=NULL;     head=&H;      //创建10个节点的单链表     p=head;     for (i=0;i<10;i++) {         q=(struct NODE *)malloc(sizeof(struct NODE));         if (NULL==q) return 1;         q->data=rand()%100;//填写0..99的随机值         q->next=NULL;         p->next=q;         p=q;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将值为5的结点插入到单链表的第k个结点前     k=3;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=(struct NODE *)malloc(sizeof(struct NODE));             if (NULL==q) return 1;             q->data=5;             q->next=p->next;             p->next=q;             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //删除第k个节点     k=5;     n=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         n++;         if (k==n) {             q=p->next;             if (q) {                 p->next=q->next;                 free(q);             }             break;         }         p=p->next;     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //从小到大排序     for (p=head;p!=NULL && p->next!=NULL;p=p->next) {         for (q=p->next;q!=NULL && q->next!=NULL;q=q->next) {             if (p->next->data > q->next->data) {                  //交换data //              printf("swap %02d %02d\n",p->next->data,q->next->data); //              t=p->next->data;p->next->data=q->next->data;q->next->data=t;                  //或者                  //交换next //              printf("swap %02d %02d\n",p->next->data,q->next->data);                 s1=p->next;                 s2=p->next->next;                 s3=q->next;                 s4=q->next->next;                  if (s2!=s3) {                      p->next=s3;                     s3->next=s2;                      q->next=s1;                     s1->next=s4;                 } else {                      p->next=s3;                     s3->next=s1;                            q=s3;                     s1->next=s4;                 }                  //输出整个单链表 //              s=head->next; //              while (1) { //                  if (NULL==s) { //                      printf("\n"); //                      break; //                  } //                  printf("%02d->",s->data); //                  s=s->next; //              } //              getchar();             }         }     }      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //将单链表中前 m 个结点和后 n 个结点进行互换,m+n为链表总长10     m=4;     n=6;     k=0;     p=head;     while (1) {         if (NULL==p) {             break;         }         k++;         if (m+1==k) {             q=p;         }         s=p;         p=p->next;     }     s1=head->next;     head->next=q->next;     s->next=s1;     q->next=NULL;      //输出整个单链表     s=head->next;     while (1) {         if (NULL==s) {             printf("\n");             break;         }         printf("%02d->",s->data);         s=s->next;     }      //释放所有节点     p=head->next;     while (1) {         if (NULL==p) {             break;         }         q=p->next;         free(p);         p=q;     }      return 0; } //18->94->58->17->27->20->43->57->75->78-> //18->94->05->58->17->27->20->43->57->75->78-> //18->94->05->58->27->20->43->57->75->78-> //05->18->20->27->43->57->58->75->78->94-> //43->57->58->75->78->94->05->18->20->27-> // 这个差不多单链表的操作都有了吧，，，我会仔细看的，觉着会有启发

引用 10 楼 qq_18237229 的回复:[quote=引用 6 楼 haltwang 的回复:] 设个断点，单步调试，对理解程序最好了 这个。。。怎么弄啊，可以详细说一下嘛。。。[/quote]这个差不多单链表的操作都有了吧，，，我会仔细看的，觉着会有启发

引用 12 楼 u012421456 的回复:设置断点会不？以C-Free为例，在光标处，快捷键F10，然后进行调试（不是编译链接构建执行什么的，是调试），接着开始单步执行，如下图   点击调试后，这几个按钮，最左边是单步执行，其他按钮的功能自己可以尝试着看看 嗯嗯嗯，我试着学着用！谢谢了！

设个断点，单步调试，对理解程序最好了

楼下正解

啥叫课设。。

没人么。。。。。

好多bug。。。这还是刚开始。。估计以后还会麻烦大家。。。我思维固定了。。。半天弄不出来。。。


Question: AT89S52用C语言编是否可以完成以下方案

定时器1用来产生定时中断控制输出信号 定时器2由四个按键控制，接同一个外部中断，在单片机外部另接其他引脚加以区分，当任一按键按下时，在外部中断处理函数中修改频率，如果按键依然是按下状态，则开始定时器2，，计满1.5s（至于怎么实现1.5s再想办法吧，好像不能直接实现1.5s），定时器2溢出，在定时器超时处理函数中，快速修改频率并刷新显示，当按键状抬起产生中断时，定时器2复位

看你的频率最大是99就当100吧，周期是 10ms, 如果占空比是1%，那%1 高电平的时间就是 10ms /100 = 0.1ms, 定时器刚好满足out,可out*的宽度是out的1/3，这个用定时器实现不了，当然用C语言实现不了。  结论就是如果用定时器来产生pwm不可行。 如果你的晶振是12M的，那指令周期就是T = 12 × 1/12M × 4 = 4uS。  要想实现这个方案，只能用汇编来写，利用汇编指令来延时来达到输出pwm波形。

能把，楼上正解

能把，楼下正解


Question: 文件结尾问题

这颜色亮瞎眼...

充满激情的颜色！

1.在linux的stty raw模式中，输入什么就直接扔getchar，不缓存 2.一般情况下，控制台输入的内容先扔缓存，按回车之后表明输入结束，getchar才从缓存中取数据返回 读到EOF结束符如果EOF前有其它数据，这个EOF表示是这些数据的结束,之后输入的任何数据都不要让getchar读，而非本次输 入的结束，只有前面没有数据的EOF才算是一次输入的结束，这样的EOF可以起到如下作用： 因为回车符也算一个字符，一次输入结束有时不打算把回车符计算进去，比如，第一次输入123，第二次输入时，我们希望从123之后 接着输入abc，而非另起一行，这时，如果输入123回车，再输入abc回车，得到的是 123 123 abc abc 所以这时应该输入123EOF回车，然后输入abc回车，得到的是 123EOF 123abc abc

Linux：Ctrl+D Windows：Enter，Ctrl+Z，Enter

这颜色。。。 这代码。。。 这路径名。。。 看着真TM蛋疼。。。

这颜色亮瞎... 前面没有内容 也就是新的一行才行

在一行的开始处键入ctrl^Z表示结束。

abdd^Z 4    用你的代码运行没有问题。你看看运行环境吧

虽然有点看明白  但你把ch定义为整形了，而EOF好像是字符吧


Question: 新手求教导。。。。。。。。求大神帮忙

http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装

引用 7 楼 u012421456 的回复:C-Free5.0——http://download.csdn.net/detail/u012421456/7374337哎呦喂，csdn下载页改版了

不管用啥，一开始就用 反汇编 练习着可能学得更快。

vc、vs2013、wintc、cfree、Dev c++、gcc

有链接么 顺便指导下安装就好了 我可是 菜鸟中的菜鸟

用linux吧，gnu 编译器比较好。

-->virtual box-->linux-->gcc/g++


Question: 求解，vs08 想在定义的函数里包含头文件

引用 4 楼 Mr_Tutu 的回复:引用 2 楼 user-4 的回复:what 不对 means？？  应该是 ctype.h 吧

本人很懒，不想打这么长的代码

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

引用 5 楼 zilaishuichina 的回复:引用 4 楼 Mr_Tutu 的回复:[quote=引用 2 楼 user-4 的回复:] what 不对 means？？  应该是 ctype.h 吧[/quote]我去！！谢谢啊

引用 2 楼 user-4 的回复:what 不对 means？？

what 不对 means？？


查查控制台相关的WIN32API，我记得应该是有光标定位的函数的。

引用 1 楼 movsd 的回复:conio.h文件是有的，gotoxy函数是没有的，那个是TC里的函数 那我在vs2008里面怎么运行这个程序呢

conio.h文件是有的，gotoxy函数是没有的，那个是TC里的函数

引用 7 楼 movsd 的回复:[quote=引用 5 楼 zxx150633 的回复:] [quote=引用 4 楼 movsd 的回复:]  COORD stCoord; HANDLE hConsoleOut=GetStdHandle(STD_OUTPUT_HANDLE); stCoord.X=20; stCoord.Y=10; SetConsoleCursorPosition(hConsoleOut,stCoord);  我是储蓄者，不太明白这是什么意思呢 [/quote] 自己写个gotoxy  void gotoxy(short int x,short int y) { 	COORD stCoord; 	HANDLE hConsoleOut=GetStdHandle(STD_OUTPUT_HANDLE); 	stCoord.X=x; 	stCoord.Y=y; 	SetConsoleCursorPosition(hConsoleOut,stCoord); } [/quote]+1

引用 5 楼 zxx150633 的回复:[quote=引用 4 楼 movsd 的回复:]  COORD stCoord; HANDLE hConsoleOut=GetStdHandle(STD_OUTPUT_HANDLE); stCoord.X=20; stCoord.Y=10; SetConsoleCursorPosition(hConsoleOut,stCoord);  我是储蓄者，不太明白这是什么意思呢 [/quote] 自己写个gotoxy  void gotoxy(short int x,short int y) { 	COORD stCoord; 	HANDLE hConsoleOut=GetStdHandle(STD_OUTPUT_HANDLE); 	stCoord.X=x; 	stCoord.Y=y; 	SetConsoleCursorPosition(hConsoleOut,stCoord); }

conio.h不是C标准库中的头文件，在C standard library，ISO C 和POSIX标准中均没有定义。  如果需要使用此头文件，可以从互联网下载。

引用 4 楼 movsd 的回复: COORD stCoord; HANDLE hConsoleOut=GetStdHandle(STD_OUTPUT_HANDLE); stCoord.X=20; stCoord.Y=10; SetConsoleCursorPosition(hConsoleOut,stCoord);  我是储蓄者，不太明白这是什么意思呢


Question: 多出来的一个字节去哪里了

上面已经回答完了。。。

是对齐的结果。  long的长度是4，struct name被分配4的倍数的空间，比123大的最小的4的倍数是124 所以总长度就是 4 + 124 ＝ 128

内存自动对齐的原因，这个需要看计算机组成原理

感谢各位，学习了

引用 10 楼 w673339759 的回复:[quote=引用 9 楼 misskissC 的回复:] 内存对齐。   还有字节在末尾。  《C和指针》、《C常见问题集》、《Linux C 编程一站式学习》等书都有介绍 “内存对齐”。 long的开始地址和结构体成员的开始地址相差4，即long的大小，我觉的还有必要看下myName的结束地址; 那么为了内存对齐，提高运行效率而补齐字节是不是无法访问到啊？ 在64系统下做了个实验，发现long的大小是8，nam结构体大小是123，但是test的大小是136，name的大小不是因该补齐到124么，加上long的8字节是132，为何是136 [/quote]   printf("sizeof test = %d\n", sizeof(test)); printf("shbzNum start address: %p\n", &test.shbzNum); printf("myName start address: %p\n", &test.myName); printf("myName's fName address: %p\n", test.myName.fName); printf("myName's mName address: %p\n", test.myName.mName); printf("myName's lName address: %p\n", test.myName.lName);   可以看到到底是哪里出现了 “间隙”。

引用 10 楼 w673339759 的回复:[quote=引用 9 楼 misskissC 的回复:] 内存对齐。   还有字节在末尾。  《C和指针》、《C常见问题集》、《Linux C 编程一站式学习》等书都有介绍 “内存对齐”。 long的开始地址和结构体成员的开始地址相差4，即long的大小，我觉的还有必要看下myName的结束地址; 那么为了内存对齐，提高运行效率而补齐字节是不是无法访问到啊？ 在64系统下做了个实验，发现long的大小是8，nam结构体大小是123，但是test的大小是136，name的大小不是因该补齐到124么，加上long的8字节是132，为何是136 [/quote]  myName的结束地址应该是以下输出的“结果” -1. INFO *ptest = &test; ptest++; printf("End of myName's address is:%p\n", ptest);

内存对齐； 请参考：http://blog.csdn.net/yusiguyuan/article/details/23104353

引用 9 楼 misskissC 的回复:内存对齐。   还有字节在末尾。  《C和指针》、《C常见问题集》、《Linux C 编程一站式学习》等书都有介绍 “内存对齐”。 long的开始地址和结构体成员的开始地址相差4，即long的大小，我觉的还有必要看下myName的结束地址; 那么为了内存对齐，提高运行效率而补齐字节是不是无法访问到啊？ 在64系统下做了个实验，发现long的大小是8，nam结构体大小是123，但是test的大小是136，name的大小不是因该补齐到124么，加上long的8字节是132，为何是136

字节对齐，没有了！ 楼上说的空结构体不对的

编译器对变量存储的一个特殊处理。为了提高CPU的存储速度，编译器对一些变量的起始地址做了“对齐”处理。在默认情况下，规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。 类型 对齐方式（变量存放的起始地址相对于结构的起始地址的偏移量） Char 偏移量必须为sizeof(char)即1的倍数 int 偏移量必须为sizeof(int)即4的倍数 float 偏移量必须为sizeof(float)即4的倍数 double 偏移量必须为sizeof(double)即8的倍数 Short 偏移量必须为sizeof(short)即2的倍数

另外，不要在定义41这样古怪的数组长度了，你最好定义成48，这样能够提高程序运行的速度！空的字节就让他空着吧，这就要用空间换时间，至于为这样能够提高程序运行速度，仔细学习学习计算机原理就知道了！

数据对齐的原因，你的结构体大小实际是127字节，你自己看别扭不？编译器在对你的程序优化的时候，自动对齐到128个字节大小，这样能够提高程序运行速度，你的程序没有错，只是有一个字节空在那里，永远也永不到了。

空结构体的大小为1  typedef struct info { 	/* 空结构体 */ }INFO;  int main() { 	printf("%d\n", sizeof(INFO));  // 结果为1 	return 0; }


Question: 求解释下这个代码的思路

KISS！ Don‘t Make Me Think! //n=1, //1 //n=2, //12 //34 //n=3, //126 //357 //489 //n=4, //  1  2  6  7 //  3  5  8 13 //  4  9 12 14 // 10 11 15 16 //n=5, //  1  2  6  7 15 //  3  5  8 14 16 //  4  9 13 17 22 // 10 12 18 21 23 // 11 19 20 24 25 //之字形 //模仿蚂蚁爬的过程 #include <stdio.h> #define MAXN 9 int m[MAXN][MAXN]; int i,x,y,dx,dy,n,n2,k; void main() {     for (i=1;i<=MAXN;i++) {         n2=i*i;         k=1;         if (n2>9) k=3;         x=0;         y=0;         dx=1;         dy=-1;         n=1;         m[y][x]=n;         while (1) {             if (n>=n2) break;             n++;             x=x+dx;             y=y+dy;             if (y>=i) {                 x=x+2;                 y=i-1;                 dx=1;                 dy=-1;             }             if (x>=i) {                 y=y+2;                 x=i-1;                 dx=-1;                 dy=1;             }             if (y<0) {                 y=0;                 dx=-1;                 dy=1;             }             if (x<0) {                 x=0;                 dx=1;                 dy=-1;             }             m[y][x]=n;         }         for (y=0;y<i;y++) {             for (x=0;x<i;x++) {                 printf("%*d",k,m[y][x]);             }             printf("\n");         }         printf("-------------%d--------------\n",i);     } } //1 //-------------1-------------- //12 //34 //-------------2-------------- //126 //357 //489 //-------------3-------------- //  1  2  6  7 //  3  5  8 13 //  4  9 12 14 // 10 11 15 16 //-------------4-------------- //  1  2  6  7 15 //  3  5  8 14 16 //  4  9 13 17 22 // 10 12 18 21 23 // 11 19 20 24 25 //-------------5-------------- //  1  2  6  7 15 16 //  3  5  8 14 17 26 //  4  9 13 18 25 27 // 10 12 19 24 28 33 // 11 20 23 29 32 34 // 21 22 30 31 35 36 //-------------6-------------- //  1  2  6  7 15 16 28 //  3  5  8 14 17 27 29 //  4  9 13 18 26 30 39 // 10 12 19 25 31 38 40 // 11 20 24 32 37 41 46 // 21 23 33 36 42 45 47 // 22 34 35 43 44 48 49 //-------------7-------------- //  1  2  6  7 15 16 28 29 //  3  5  8 14 17 27 30 43 //  4  9 13 18 26 31 42 44 // 10 12 19 25 32 41 45 54 // 11 20 24 33 40 46 53 55 // 21 23 34 39 47 52 56 61 // 22 35 38 48 51 57 60 62 // 36 37 49 50 58 59 63 64 //-------------8-------------- //  1  2  6  7 15 16 28 29 45 //  3  5  8 14 17 27 30 44 46 //  4  9 13 18 26 31 43 47 60 // 10 12 19 25 32 42 48 59 61 // 11 20 24 33 41 49 58 62 71 // 21 23 34 40 50 57 63 70 72 // 22 35 39 51 56 64 69 73 78 // 36 38 52 55 65 68 74 77 79 // 37 53 54 66 67 75 76 80 81 //-------------9--------------

我稍微改了一下，调整了方向和楼主画的矩阵一致，取消了两重循环提高了效率。 #include <stdio.h>  #define M 50  void main() {     int i,j,n,count = 1;     int row_min, row_max;     int dada[M][M];     printf("Input n(0~%d):",M);     scanf("%d",&n);     if (n >= M) {         return;     }     for(i=1;i<=2*n-1;i++)    {         if (i <= n) {             row_min = 1;             row_max = i;         } else {             row_min = i - n + 1;             row_max = n;         }         if (i%2 == 0)         {             for (j=row_min;j<=row_max;j++)             {                 dada[j][i+1-j] = count++;             }         }         else         {             for (j=row_max;j>=row_min;j--)             {                 dada[j][i+1-j] = count++;             }         }     }     for (i=1;i<=n;i++)     {         for (j=1;j<=n;j++)         {             printf("%5d",dada[i][j]);         }         printf("\n\n");     } }

引用 2 楼 brookmill 的回复:这个思路就是直接把人画这个矩阵的思路用代码写出来了，所以不难理解。关键在于看懂这一句： dada[j][k] = count++; 这说明，不管怎么循环，给数组赋值的次序是按照自然数递增顺序的，从1、2、3直到100。所以，对这个矩阵的遍历赋值，必然是按照对角线左下、右上、左下、右上这样循环依次进行的。 不过楼主的代码和楼主贴出来的运行结果好像不太一样，方向正好相反。 以下注释以n=10为例     for(i=1;i<=2*n-1;i++)    { // 一共19条对角线，第一条是1，第二条是2和3，第三条是4、5、6，……第18条是98和99，第19条是100         if ((i+flag)%2)// 这个控制前进的方向，奇数对角线是从右上到左下，偶数对角线从左下到右上。这个flag其实没用，可以删掉。         { // 这是从右上到左下，也就是1， 4、5、6， 11、12、13、14、15， ……             for (j=1;j<=n;j++)// 从上到下遍历矩阵的每一行             {                 for (k=1;k<=n;k++)// 从左到右遍历本行的每一列。这个循环反过来写也可以，因为每行最多只有一个符合条件的位置                 {// 这个双重循环，遍历了整个矩阵的100个位置，效率有点低                     if (j+k == i+1)// 如果该位置刚好处在现在处理的对角线上，就给赋值                     { // 比如，第三条对角线，i=3，也就是4、5、6，条件是j+k==4，满足条件的是dada[1][3]、dada[2][2]、dada[3][1]                         dada[j][k] = count++; ...         else         { // 这是从左下到右上，也就是2、3， 7、8、9、10， ……             for (j=n;j>=1;j--)// 从下到下上遍历矩阵的每一行             {                 for (k=n;k>=1;k--)// 从右到左遍历本行的每一列。这个循环反过来写也可以，因为每行最多只有一个符合条件的位置

这段代码是干什么的？


Question: 为什么字符串常量能直接给一个字符指针变量赋值呢？

你为什么 不换一个printf试试呢

一个字符串常量就是一个字符数组，它表示指向字符串首地址的指针。  比如这个例子：  void main() { 	printf("%s\n", "hello");     // 输出hello 	printf("%s\n", "hello"+1);   // 首地址+1，输出ello 	printf("%s\n", "hello"+2);   // 首地址+2，输出llo }

因为在C89标准出来的时候，已经有海量的这样的不顾const特性的代码存在了。 所以，C、C++标准只好在这个地方绕了一个小弯。 知道就行了，别深究了。

m存的是M的首地址，哪有问题了？

C语言没有定义专门的字符串数据类型，实际通过字符数组实现

是存这个字符串的首地址及h的地址;


Question: int值转换为字符串，%s格式化输出不来？

引用 7 楼 cyd54454 的回复:ps[size-1-k]=(n>>k)&01+'0';这句，+优先级高于&，相当于是ps[size-1-k]=(n>>k)&(01+'0');不知道楼主本意y应该是这样吧：ps[size-1-k]=((n>>k)&01)+'0';谢谢

...warning: suggest parentheses around '+' in operand of '&' [-Wparentheses]                  ps[size-1-k]=(n>>k)&01+'0';

书上的习题，刚好那一张讲的就是位操作

你这代码想干啥，怎么用位运算了？

好眼神，但是请关注重点

不知道你自己调试了没，因为数组第一个元素就是'\0' (gdb) p ps[0]   $9 = 0 '\000'

看来lz用的是虚拟机


Question: vs2010 mci问题

以前没用过VS，不了解宽字符这些。感谢诸位大神！！！！

诶 ... 后面加上 wait 试试看呢 ...

有兴趣的可以看看我的用C控制Word文档视频，可以学到不少东西。视频地址如下 http://v.youku.com/v_show/id_XNzU2NjYxNTk2.html  想要清楚的视频，在我的帖子下留下QQ

VC2010默认是使用UNICODE，也就是宽字符，VC6使用的是ASCII字符，所以，以后在用VC21010的是有，先看看是不是宽字符，还是ASCII字符，这个首先要搞明白。

引用 7 楼 user-4 的回复:没加L mciSendString(L"open D:\\1.mp3 alias mywav",0,0,0)；+1怎么会这样

把代码展开之后就是这样     mciSendString(L"open \"d:\\1.mp3\"",NULL,0,NULL); //打开设备     mciSendString(L"play \"d:\\1.mp3\" repeat",NULL,0,NULL); //播放

引用 5 楼 gpp135 的回复:wsprintf这个函数都查不到？

mciSendString("open D:\\1.mp3 alias mywav",0,0,0)； 这是第一行

引用 4 楼 zxh707wk 的回复:[quote=引用 3 楼 gpp135 的回复:] [quote=引用 2 楼 zxh707wk 的回复:] 你没加" 是说哪没加啊[/quote]你不会自己看代码吗，百度谷歌随你查的居然不去搜[/quote] 我当然是查了各种没查到才来论坛问的啊，你看明白题再说好吗，你要不爱教别墨迹没用的

引用 3 楼 gpp135 的回复:[quote=引用 2 楼 zxh707wk 的回复:] 你没加" 是说哪没加啊[/quote]你不会自己看代码吗，百度谷歌随你查的居然不去搜

引用 2 楼 zxh707wk 的回复:你没加" 是说哪没加啊

你没加"

为什么要分开好几步写啊？？？ 求大神啊？？？


Question: 为什么说霍夫曼编码的符号频数压缩到可用一个字节(8位)表示时,没有哪一个符号的霍夫曼编码会大于16位?

我说说我的想法. 其实和16这个数没关系,因为计算机中最小的操作单位是字节(8位),所以如果8位不能表示完整的编码的话,就得扩展为16位.就这么简单

引用 7 楼 angel_su 的回复:不会证明，不过可以想象最小频的节点，最多8次加权就达256，假设剩余都节点是256的话，那就是深度最多8的满树，所以最小频节点深度不超过16，而深度对应编码的位数... 你这个16所以得毫无道理啊,我就问为啥是16,而不是14,12,10呢?

2楼那位说拿笔画画就知道答案,真问他答案他又说不出来

引用 4 楼 amoyman 的回复:拿一个例子，仔细用笔模拟一下，就什么都清楚了。 例子中的数据不要太多，不然会晕的 那为什么不超过16位?

那为什么不超过16位?

书上应该写得很清楚了，为了用短编码来表示常出现的字，那么，那些不常出现的，就必然会超越256

引用 1 楼 amoyman 的回复:好好看书，是教科书，不是现在的那些所谓的科幻小说（特别是那些没学过计算机的人写电脑方面的小说） 没看懂什么意思


Question: 输入任意结点的双向链表删除问题

引用 3 楼 angel_su 的回复:双向链表不需要p2指针来记录前驱，直接遍历即可，所以没有你说左边右边的问题...  这个代码不是输入头结点开始遍历，而是输入这个链表中任一结点指针去遍历，所以有可能需要向左和向右遍历两次寻找需要删除的结点。

引用 3 楼 angel_su 的回复:双向链表不需要p2指针来记录前驱，直接遍历即可，所以没有你说左边右边的问题...+1，双向链表不需要记住前一个节点

你就是看看百度百科也好啊！  传送门

if(p)是判断这个指针是否有效，如果有效则删除这个结点。 你的代码有问题啊，p1,p2都没有指向实例化对象，只是声明了指针，你访问node成员运行不会出错吗？


Question: 各位大虾请指教！

少个;？

引用 楼主 u012611445 的回复:#ifndef _BOARD_H_ #define _BOARD_H_  #ifdef __STDC__ /* Type of physical port bitmap */  typedef uint8 pbmp_t;  #endif /* __STDC__ */  #define CFG_SWITCH_VLAN_INCLUDED (1)  /* Number of units */ #define BOARD_NUM_OF_UNITS              (1)  /* Maximal number of ports (may be different than actual port co  结果： ..\SRC\BOARD.H(54): error C129: missing ';' before 'pbmp_t'  #ifndef _BOARD_H_ #define _BOARD_H_  #ifdef __STDC__ /* Type of physical port bitmap */  typedef unsigned char uchar; typedef uchar	uint8;  typedef uint8 pbmp_t;  #endif /* __STDC__ */  #define CFG_SWITCH_VLAN_INCLUDED (1)  /* Number of units */ #define BOARD_NUM_OF_UNITS              (1)  /* Maximal number of ports (may be different than actual port co

这段代码如果uint8能识别的话，没什么问题，可能别的地方引起的

楼上所言极是

uint8 可有定义？


Question: 《C程序设计语言》（Dennis M. Ritchie   Brian W. Kernighan）中一个例题看不懂

引用 11 楼 chlth007 的回复:引用 7 楼 wanght99 的回复:[quote=引用 6 楼 chlth007 的回复:] [quote=引用 5 楼 wanght99 的回复:] [quote=引用 3 楼 chlth007 的回复:] [quote=引用 1 楼 wanght99 的回复:] 执行程序, 随便敲内容, 满意了之后告知程序输完了(Linux是Ctrl-D, Windows好像是Ctrl-Z), 然后程序会输出你输入的总行数.不管用啊。是我没操作好、？ 你是怎么执行的? 现象是什么? 是不是你输入完之后窗口直接关闭了?[/quote] 好了，我忘了敲回车了。请问Ctrl-Z是做什么的，我看完一本书了，没遇到这个东东，能讲解一下吗？[/quote] EOF是文件到末尾的工具, 但从终端没法直接输入EOF, 所以就把让Ctrl-Z起到EOF的作用, 按Ctrl-Z的时候, getchar()就返回EOF了.[/quote]请问第七行中的c我可以定义成char吗？与定义成int有什么区别？[/quote]  不能改成char getchar返回的是Int, 之所以不返回char就是为了区分EOF, char的值域是0-255, EOF跟任何 char的值不一样, 这样才能起到区分的作用. 你如果把c写成char, 那就会发生强制类型转换, 转换成char值之后, 就没法再判断EOF了.

引用 7 楼 wanght99 的回复:引用 6 楼 chlth007 的回复:[quote=引用 5 楼 wanght99 的回复:] [quote=引用 3 楼 chlth007 的回复:] [quote=引用 1 楼 wanght99 的回复:] 执行程序, 随便敲内容, 满意了之后告知程序输完了(Linux是Ctrl-D, Windows好像是Ctrl-Z), 然后程序会输出你输入的总行数.不管用啊。是我没操作好、？ 你是怎么执行的? 现象是什么? 是不是你输入完之后窗口直接关闭了?[/quote] 好了，我忘了敲回车了。请问Ctrl-Z是做什么的，我看完一本书了，没遇到这个东东，能讲解一下吗？[/quote] EOF是文件到末尾的工具, 但从终端没法直接输入EOF, 所以就把让Ctrl-Z起到EOF的作用, 按Ctrl-Z的时候, getchar()就返回EOF了.[/quote]请问第七行中的c我可以定义成char吗？与定义成int有什么区别？

引用 8 楼 u012421456 的回复:顾名思义，统计输入内容的行数 EOF的用法——http://nylzhaowei.blog.163.com/blog/static/14303922006112012447234/谢谢

引用 7 楼 wanght99 的回复:引用 6 楼 chlth007 的回复:[quote=引用 5 楼 wanght99 的回复:] [quote=引用 3 楼 chlth007 的回复:] [quote=引用 1 楼 wanght99 的回复:] 执行程序, 随便敲内容, 满意了之后告知程序输完了(Linux是Ctrl-D, Windows好像是Ctrl-Z), 然后程序会输出你输入的总行数.不管用啊。是我没操作好、？ 你是怎么执行的? 现象是什么? 是不是你输入完之后窗口直接关闭了?[/quote] 好了，我忘了敲回车了。请问Ctrl-Z是做什么的，我看完一本书了，没遇到这个东东，能讲解一下吗？[/quote] EOF是文件到末尾的工具, 但从终端没法直接输入EOF, 所以就把让Ctrl-Z起到EOF的作用, 按Ctrl-Z的时候, getchar()就返回EOF了.[/quote]谢谢

引用 6 楼 chlth007 的回复:引用 5 楼 wanght99 的回复:[quote=引用 3 楼 chlth007 的回复:] [quote=引用 1 楼 wanght99 的回复:] 执行程序, 随便敲内容, 满意了之后告知程序输完了(Linux是Ctrl-D, Windows好像是Ctrl-Z), 然后程序会输出你输入的总行数.不管用啊。是我没操作好、？ 你是怎么执行的? 现象是什么? 是不是你输入完之后窗口直接关闭了?[/quote] 好了，我忘了敲回车了。请问Ctrl-Z是做什么的，我看完一本书了，没遇到这个东东，能讲解一下吗？[/quote] EOF是文件到末尾的工具, 但从终端没法直接输入EOF, 所以就把让Ctrl-Z起到EOF的作用, 按Ctrl-Z的时候, getchar()就返回EOF了.

引用 5 楼 wanght99 的回复:引用 3 楼 chlth007 的回复:[quote=引用 1 楼 wanght99 的回复:] 执行程序, 随便敲内容, 满意了之后告知程序输完了(Linux是Ctrl-D, Windows好像是Ctrl-Z), 然后程序会输出你输入的总行数.不管用啊。是我没操作好、？ 你是怎么执行的? 现象是什么? 是不是你输入完之后窗口直接关闭了?[/quote] 好了，我忘了敲回车了。请问Ctrl-Z是做什么的，我看完一本书了，没遇到这个东东，能讲解一下吗？

引用 3 楼 chlth007 的回复:引用 1 楼 wanght99 的回复:执行程序, 随便敲内容, 满意了之后告知程序输完了(Linux是Ctrl-D, Windows好像是Ctrl-Z), 然后程序会输出你输入的总行数.不管用啊。是我没操作好、？ 你是怎么执行的? 现象是什么? 是不是你输入完之后窗口直接关闭了?

引用 2 楼 zxh707wk 的回复:引用 1 楼 wanght99 的回复:执行程序, 随便敲内容, 满意了之后告知程序输完了(Linux是Ctrl-D, Windows好像是Ctrl-Z), 然后程序会输出你输入的总行数.+1具体怎么操作，我怎么操作不好呢。


Question: 用C语言自己实现strcat时遇到的小问题

你的编译应该不通过，函数返回char*，不能返回char。 如果返回s，只会影响函数的返回值（如果你不使用这个返回值的话，在你看来结果没啥影响），s在经过循环之后已经改变了指向，所以要想得到正确的字符串首地址，必须临时保存起来

在一个字符串追加另一串字符串，你的return不知道有什么用，似乎对结果没影响~

引用 2 楼 lisong694767315 的回复:1、首先，my_strcat函数应该返回des而不是*des 2、不定义des直接返回s，那么你得到的永远是空字符串，因为s指向字符串的末尾，而不是字符串的开头额。。。明白了。 不过难道是编译器除了问题，我改成return *s，结果也是对的

楼上正解！！！

如果不定义*des，结果是错误的。s指向的地址已经改变了，不在指向字符串的首地址了


Question: 自己定义了一个函数调用时出现程序停止工作

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

引用 5 楼 amoyman 的回复:[quote=引用 3 楼 zxh707wk 的回复:] 本人很懒，不想自己去打代码编译  是啊，为什么不用CODE而要用图片呢[/quote]不好意思哈，新人，我觉得图片看着更爽，复制下来看着又多又密，有种不想看的感觉，下次注意

这个问题，断点然后单步很快就能定位问题了， 数组越界可能性比较大

引用 3 楼 zxh707wk 的回复:本人很懒，不想自己去打代码编译  是啊，为什么不用CODE而要用图片呢

引用 3 楼 zxh707wk 的回复:本人很懒，不想自己去打代码编译  ++

本人很懒，不想自己去打代码编译

char s[256]; itob(300, s); cout << s << endl; //0X12c return 0;  没问题啊，是不是你的调用代码有什么问题

我们仔细看，你看看你传进去的数组的大小是否够大，如果超出边界了，肯定有问题，传个大数组试试，另外你的办法也挺别扭的。


Question: 求c语言比较好的教学视频！！！急需，各位大神求指导

建议你看书，看视频效率比较低，然后多敲代码。过来人建议，希望有用。

视频耗时，容易走神  还是看书比较好的

http://vs2003.net  不是最好的，但是看了肯定是有好处的,只教有缘人

对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！

郝斌的还不错  楼主可以看看

只用大脑和眼睛而不用小脑和手，是永远学不会C/C++或者任何一门软件开发语言的！

郝斌的还不错

翁恺的视频，记得要多加练习，多敲代码

而且看视频容易走神，多看书理论过了，再敲代码！

看视频是最慢最不推荐的一种学习方式。

看书吧

看视频感觉比看书累


Question: 初学c的一个小问题

引用 3 楼 T5500 的回复:因为在IDE Console中运行的关系吧，在终端下运行就是正常的输入输出顺序了  果然是的。。。。

引用 1 楼 T5500 的回复:你指什么顺序？  不是应该是 数字: 1 is 1  吗

你指什么顺序？


Question: C语言实现Word文档全控制

楼主还在吗，现在求视频还可以不？ 3191881056@qq.com

suozhaoyu0530@163.com  现在才看到，不知道晚不晚

1196124882@qq.com  楼主给我也发一份吧，谢谢啦

414079745@qq.com  谢谢

1113501978 楼主好人，给我也发一份吧，急用啊

楼主可以给我发一份清楚地吗 最近正好想弄关于这个的  麻烦您了  76132665  谢谢啦

后面关键的事件监视没有了啊。。。。。。。。。。。。。。

楼主还留意这个贴么？邮箱是：ooqazoo@sina.com。而且我想问一下如何用c++而不是mfc去读取word文档

1442454823果然不清晰 啊

楼主，我现在想用c或c++编程实现将word 文档中所有的图片提取出来并自动保存到一个文件夹中，我看百度上有手动的：打开word文档，然后点击“文件——另存为——‘保存类型’选择HTML格式”，即生成同名文件夹里都是该word文档的图片。我想将这个过程用C或C++实现一下。我现在再看楼主在优酷上传的视频，视频不清晰啊，我刚刚看一，想问楼主传的3个视频里有没有这个内容，能给我发一份清晰的视频吗？我的邮箱是874651570@qq.com   非常感谢！

每个coclass就是一个组件，Application就代表整个word的EXE。  类型库是一个库信息，相当于C里面的.h头文件，只不过形式不一样而已。 Application组建当然有自己的UUID了。

我看了LZ的视频，有几个问题想请教： 1、是不是一个应用软件内包含多个COM组件，比如像 在word里，我发现有很多CoClass,是不是每个CoClass 都是一个COM组件？ 2、类型库是干什么的？它里面只包含接口吗？类型库 内是否也包含CoClass组件类？ 3、我看你程序，好像是用Application这个组件来启动  word的，word本身也有UUID吧，为什么不用word本身的 UUID来启动呢？

楼主，还不如放上代码+注释更受欢迎啊


Question: 请教一个PRO*c的问题，谢谢

我也遇到了相似问题。 写在PRO*C里面的数组存储的值在一个while循环后就不见了。 声明为全局变量也是一样。

引用 4 楼 cyd54454 的回复:看你定义在函数体外还是函数体内，函数体外就是全局的，存在数据段里。函数体内是局部的，存在栈里（不加static修饰的）。EXEC SQL BEGIN DECLARE SECTION;EXEC SQL BEGIN DECLARE SECTION;只是声明其之间的这些变量是用在数据库上的，就算你注释掉，程序也是一样运行。如果要放堆里，就要自己malloc 为啥要malloc啊？定义在main函数外不行么？  "EXEC SQL BEGIN DECLARE SECTION;EXEC SQL BEGIN DECLARE SECTION;只是声明其之间的这些变量是用在数据库上" 啥意思啊？啥是用在数据库上？  谢谢

没用过。。。

引用 5 楼 u011718046 的回复:为啥要malloc啊？定义在main函数外不行么？  "EXEC SQL BEGIN DECLARE SECTION;EXEC SQL BEGIN DECLARE SECTION;只是声明其之间的这些变量是用在数据库上" 啥意思啊？啥是用在数据库上？ 谢谢 PRO*C还是以C语言为宿主语言，所以其变量的存放规则是和普通C程序一样的。定义在函数体外的变量只是存在数据段里（一个C程序分布：代码段，数据段，bss段，堆，栈）。那两句话只是声明这些变量是程序与Oracle通信的桥梁，程序的输入数据通过这些变量传递给Oracle，反之，Oracle的输出数据又通过这些变量传递给程序。还有点我说错了，那两句话和预编译的参数parse有关,默认parse=full,所以这两句可以去掉,如果parse=none,那么所有SQL要用到的变量必需加在这两句之间。。。

引用 2 楼 u011718046 的回复:[quote=引用 1 楼 Oringe_new 的回复:] 应该是栈。。。。。 其实当你用proc*c把PC文件 宏展开后生成xx.c文件就看到这几个变量是什么存在了 谢谢，那怎样才能放到堆 里呢？或者全局区呢？[/quote] 太久没搞了  以前工作的时候还会搞一下 不清楚了

引用 1 楼 Oringe_new 的回复:应该是栈。。。。。 其实当你用proc*c把PC文件 宏展开后生成xx.c文件就看到这几个变量是什么存在了 谢谢，那怎样才能放到堆 里呢？或者全局区呢？


Question: C语言入门问题

引用 5 楼 zhao4zhong1 的回复:教用数组作函数参数的教材和老师都在装13  请用脚后跟思考一下为什么不把整个互联网内容当函数参数传来传去呢？！  你回答的太深奥了 我实在难以理解

我还是没有懂啊啊啊 求帮忙

你没懂我的意思啊 我说的是iArrayName[10] 中的iArrayName是数组名

1、int iArrayName 和int iArrayName[10]你觉得那个是数组 。第一个显然是整形变量，第二个才是数组。 2、传地址只是告诉你在哪里数组的地址在哪里，大小啥的之前就做好处理了‘。

引用 11 楼 cyd54454 的回复:[quote=引用 10 楼 xhw88398569 的回复:] 书扔了吧，刚才感觉程序有问题，没有返回值，也没有使用指针，怎么给主函数的数组赋的值？？还以为是没见过的特殊的用法。。。。编译运行各种警告，以及段错误。。。还有，你确定iArrayName[10]是指真个数组？而不是数组溢出第10个元素？？ 赵老师说的很对（虽然懒得看他的模板），问之前自己先敲一遍。。。 还真没看main函数，这书扔了吧，分明传的该数组首地址偏移10的数据，实参和形参类型不匹配是妥妥的了。[/quote] 说的有些道理哦

引用 4 楼 cyd54454 的回复:Dispaly(int iArrayName*) == Dispaly(int iArrayName[]) == Dispaly(int iArrayName[10]) ,这个10只是个提示作用。在函数形参列表中的数组，可视为指针，写成数组形式，可读性好些，让你一眼看去就知道这函数需要的参数是10个元素的数组。iArrayName[i] == *(iArrayName+i)，自然取出的是相对于iArrayName偏移量为i的值。 改个错误Dispaly(int *iArrayName)

引用 10 楼 xhw88398569 的回复:书扔了吧，刚才感觉程序有问题，没有返回值，也没有使用指针，怎么给主函数的数组赋的值？？还以为是没见过的特殊的用法。。。。编译运行各种警告，以及段错误。。。还有，你确定iArrayName[10]是指真个数组？而不是数组溢出第10个元素？？ 赵老师说的很对（虽然懒得看他的模板），问之前自己先敲一遍。。。 还真没看main函数，这书扔了吧，分明传的该数组首地址偏移10的数据，实参和形参类型不匹配是妥妥的了。

在这边iArrayName和iArrayName[10]一样都可以看做是数组名，把数组的起始地址传到了函数中，去掉[10]应该也是对的。

计算机组成原理→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",...);】来理解指针的本质， 而要依赖调试时的反汇编窗口中的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

引用 6 楼 Cristiano001 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 教用数组作函数参数的教材和老师都在装13  请用脚后跟思考一下为什么不把整个互联网内容当函数参数传来传去呢？！  你回答的太深奥了 我实在难以理解[/quote] 我的意思是容量大如数组这种东西根本不适合将其副本当函数参数传来传去（很多编译器在此时会优化为不生成副本，直接传指针）。 所以说研究数组作函数参数传递的傲骄语法是某种程度上的浪费生命！ 楼下同意的顶顶。


引用 3 楼 u011836122 的回复:你是要在main函数里调用func对吧？  前面已经声明过了，调用的时候加void（加返回值类型）是不对的！ 谢谢，谢谢，的确是这样的！

引用 3 楼 u011836122 的回复:你是要在main函数里调用func对吧？  前面已经声明过了，调用的时候加void（加返回值类型）是不对的！ 哦，就是说后面就不用加void了吧？

引用 2 楼 zhao4zhong1 的回复:你把源代码后缀改为.c再试试。不行啊

你把源代码后缀改为.c再试试。

vs没升级一次，都会增加很多错误检查。


Question: 指针和typedef使用问题，求解

引用 11 楼 Windeal 的回复:[quote=引用 5 楼 shenchenman 的回复:] [quote=引用 4 楼 Windeal 的回复:] typedef int arr5[5];   相当于  typedef  int[5]  arr5.  也就是把一个含有五个元素的整形数组定义成一种类型。      arr5就变成了一种类型名。  没有这么用的。int[5] 纯属瞎想 紧跟typedef的必须是内置类型 [/quote]   谁跟你说typedef只能紧跟内置类型的。typedef是为已有数据类型取一个别名，按你的对里，typedef怎么给结构体区别名，怎么给多重函数指针区别名？？？？  typedef struct {……}Mystruct； 岂不是要报错？？？ int[5]，是可以看成一个类型的，就像结构体可以看成一个类型一样。   这在分析数组定义的时候不就该明白了么[/quote] 感谢，现在理解多了

引用 12 楼 luo104660577 的回复:其实int arr1[5] 这个数组的类型你可以看做是 int [5] 就是包含5个int的数组， arr1 是他的变量名而已。 理解了

引用 5 楼 shenchenman 的回复:[quote=引用 4 楼 Windeal 的回复:] typedef int arr5[5];   相当于  typedef  int[5]  arr5.  也就是把一个含有五个元素的整形数组定义成一种类型。      arr5就变成了一种类型名。  没有这么用的。int[5] 纯属瞎想 紧跟typedef的必须是内置类型 [/quote]   谁跟你说typedef只能紧跟内置类型的。typedef是为已有数据类型取一个别名，按你的对里，typedef怎么给结构体区别名，怎么给多重函数指针区别名？？？？  typedef struct {……}Mystruct； 岂不是要报错？？？ int[5]，是可以看成一个类型的，就像结构体可以看成一个类型一样。   这在分析数组定义的时候不就该明白了么

引用 8 楼 haitunxiaomo 的回复:建议你看一下typedef的用法： http://www.cnblogs.com/csyisong/archive/2009/01/09/1372363.html 果然不错，重点是从右向左结合，先找变量

typedef 类型的识别： 先把 typedef去掉， 看看定义的变量(标识符)的类型 加上 typedef 就是用那个名字， 表示 不加typedef  定义同名变量(标识符)的， 那个变量(标识符)的类型   //例如，去掉typedef  int arr_10[10];      //arr_10 是个 int[10]; 即 10个元素的整型数组 //加上 typedef  typedef int arr_10[10]; //arr_10  就是 int[10] 这种类型的另一个名字,       //也就是说 arr_10，就是10个元素的整型数组，这种类型。

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

type对复合类型的掩饰的基本用法，没啥可说的 typedef int arr5[5];数组 typedef arr5 * p_arr5;指向数组的指针 typedef  p_arr5 arrp10[10];指向 指向数组指针数组 的指针

引用 5 楼 shenchenman 的回复:[quote=引用 4 楼 Windeal 的回复:] typedef int arr5[5];   相当于  typedef  int[5]  arr5.  也就是把一个含有五个元素的整形数组定义成一种类型。      arr5就变成了一种类型名。  没有这么用的。int[5] 纯属瞎想 紧跟typedef的必须是内置类型 [/quote] 请教这几个typedef语句该如何理解,是arr5[5]代表int吗？那么下面的typedef为何可以使用arr5,而不是arr5[5]

引用 4 楼 Windeal 的回复:typedef int arr5[5];   相当于  typedef  int[5]  arr5.  也就是把一个含有五个元素的整形数组定义成一种类型。      arr5就变成了一种类型名。 typedef int arr5[5];//相当于int[5] arr5;意味着arr5代表这个具有5个元素的int数组 typedef arr5 * p_arr5;//可以翻译成:int[5] * p_arr5吗？ typedef  p_arr5 arrp10[10];//可以理解为int[5] *[10] arrp10吗？

引用 4 楼 Windeal 的回复:typedef int arr5[5];   相当于  typedef  int[5]  arr5.  也就是把一个含有五个元素的整形数组定义成一种类型。      arr5就变成了一种类型名。  没有这么用的。int[5] 纯属瞎想 紧跟typedef的必须是内置类型


Question: code blocks编写的这段代码中，为什么strsep会报错

仅供参考#include <stdio.h> #include <string.h> char string[80]; char seps1[3]; char seps2[3]; char *token; char *zzstrtok (     char *string,     const char *control1,//连续出现时视为中间夹空token     const char *control2 //连续出现时视为中间无空token     ) {     unsigned char *str;     const unsigned char *ctrl1 = control1;     const unsigned char *ctrl2 = control2;     unsigned char map1[32],map2[32];     static char *nextoken;     static char flag=0;     unsigned char c;     int L;      memset(map1,0,32);     memset(map2,0,32);     do {         map1[*ctrl1 >> 3] |= (1 << (*ctrl1 & 7));     } while (*ctrl1++);     do {         map2[*ctrl2 >> 3] |= (1 << (*ctrl2 & 7));     } while (*ctrl2++);      if (string) {         if (control2[0]) {             L=strlen(string);             while (1) {                 c=string[L-1];                 if (map2[c >> 3] & (1 << (c & 7))) {                     L--;                     string[L]=0;                 } else break;             }         }         if (control1[0]) {             L=strlen(string);             c=string[L-1];             if (map1[c >> 3] & (1 << (c & 7))) {                 string[L]=control1[0];                 string[L+1]=0;             }         }         str=string;     }     else        str=nextoken;      string=str;     while (1) {         if (0==flag) {             if (!*str) break;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 break;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 string++;                 str++;             } else {                 flag=1;                 str++;             }         } else if (1==flag) {             if (!*str) break;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 flag=0;                 break;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 flag=2;                 break;             } else str++;         } else {//2==flag             if (!*str) return NULL;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 str++;                 string=str;                 flag=0;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 str++;                 string=str;             } else {                 string=str;                 str++;                 flag=1;             }         }     }     nextoken=str;      if (string==str) return NULL;     else             return string; } void main() {    strcpy(string,"A \tstring\t\tof ,,tokens\n\nand some  more tokens, ");    strcpy(seps1,",\n");strcpy(seps2," \t");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234| LIYI|China | 010 |201110260000|OK");    strcpy(seps1,"|");strcpy(seps2," ");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234|LIYI||010|201110260000|OK");    strcpy(seps1,"");strcpy(seps2,"|");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234|LIYI||010|201110260000|OK");    strcpy(seps1,"|");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",a");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",a,,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,a,,b,,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,,");    strcpy(seps1,",");strcpy(seps2," ");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    } } // //[A      string          of ,,tokens // //and some  more tokens,] //Tokens: // <A>, <string>, <of>, <>, <tokens>, <>, <and>, <some>, <more>, <tokens>, <>, //[1234| LIYI|China | 010 |201110260000|OK] //Tokens: // <1234>, <LIYI>, <China>, <010>, <201110260000>, <OK>, //[1234|LIYI||010|201110260000|OK] //Tokens: // <1234>, <LIYI>, <010>, <201110260000>, <OK>, //[1234|LIYI||010|201110260000|OK] //Tokens: // <1234>, <LIYI>, <>, <010>, <201110260000>, <OK>, //[a] //Tokens: // <a>, //[a,b] //Tokens: // <a>, <b>, //[a,,b] //Tokens: // <a>, <>, <b>, //[,a] //Tokens: // <>, <a>, //[a,] //Tokens: // <a>, <>, //[,a,,b] //Tokens: // <>, <a>, <>, <b>, //[,,a,,b,,] //Tokens: // <>, <>, <a>, <>, <b>, <>, <>, //[,] //Tokens: // <>, <>, //[,,] //Tokens: // <>, <>, <>, //[,,,] //Tokens: // <>, <>, <>, <>,

STRSEP Section: Linux Programmer's Manual (3 ) Updated: 1993-04-12  --------------------------------------------------------------------------------    NAME strsep - extract token from string    SYNOPSIS #include <string.h>  char *strsep(char **stringp, const char *delim);     DESCRIPTION If *stringp is NULL, the strsep() function returns NULL and does nothing else. Otherwise, this function finds the first token in the string *stringp, where tokens are delimited by symbols in the string delim. This token is terminated with a `\0' character (by overwriting the delimiter) and *stringp is updated to point past the token. In case no delimiter was found, the token is taken to be the entire string *stringp, and *stringp is made NULL.    RETURN VALUE The strsep() function returns a pointer to the token, that is, it returns the original value of *stringp.    NOTES The strsep() function was introduced as a replacement for strtok(), since the latter cannot handle empty fields. However, strtok() conforms to ANSI-C and hence is more portable.    BUGS This function suffers from the same problems as strtok(). In particular, it modifies the original string. Avoid it.    CONFORMING TO BSD 4.4    SEE ALSO index(3), memchr(3), rindex(3), strchr(3), strpbrk(3), strspn(3), strstr(3), strtok(3)  -------------------------------------------------------------------------------- Windows下没有strsep

引用 3 楼 mymtom 的回复:Windows的codeblocks的gcc编译器不带这个函数, Linux下才有 引用 4 楼 cyd54454 的回复:警告说明头文件里头没有这函数的声明，错误提示说明没有该函数的实现。然后赵老师说windows下没有该函数  -----------------------------------------------------------------------------------------------------------------------------------------------------------------  感谢两位的解答~~


Question: VS2013函数的一点问题。

不知道为什么在函数调用的时候加int在函数前面，这样的语法至少我没有见过

这样写也是错的


Question: 【求解】我定义的一个简单函数实参是32时就不正常了

赵老师说的对，你这样传的参数是int类型，32位的1，其int类型值为-1

将%d改为%u 所有int改为unsigned int

这是函数

结果太大了。你的int型更本装不了。


Question: 已初始化的变量a=1;然后a=m(1);但m并没有返回值，a为什么就变成未未知的了；

汇编是硬道理！！！！

引用 10 楼 ACMtop 的回复:[quote=引用 8 楼 dbzhang800 的回复:] [quote=引用 7 楼 ACMtop 的回复:] [quote=引用 5 楼 mymtom 的回复:]   #include<stdio.h>   int m(int a) {     if(a==1)         return 2;      printf("return %d\n", 9); }   int main(void) {     int min ;     min=3;     min=m(2);     printf("min=%d\n",min); }   为什么加了printf("return %d\n", 9);就有数值了什么情况[/quote]  建议你学学汇编，然后你就容易理解 函数调用时，究竟发生了什么了。不然，你就规规矩矩地写程序。[/quote]  汇编果然是道砍，寄存器变来变去搞不清，看来还是老实写程序了[/quote] 一开始也不明白，后来通过调试发现函数的返回值癌变的 是保存在EAX寄存器中的，而printf函数会改变EAX寄存器中的值，而改变的值等于printf输出的字符长度（注：\n也算一个字符）

不解释

函数m根本没有返回值，因为你传的是2，函数根本没有返回，也就是没有写AX的值，你得到的当然是假的了。

截图没完整

x86/linux/gcc平台 gcc  -g  min.c  -o min  objdump -dS min

2楼说的是对的。。。 没写返回值不代表函数不返回值 汇编 m函数返回值是放在eax寄存器里面 那为什么会返回9呢，并不是因为printf("return %d\n", 9);输出的是9 而是因为printf打印了9个字符，printf函数返回了9，存在了eax寄存器 m函数没有修改eax的值，然后实际上作为自己的返回值返回给main函数 这也就是为什么min最后为9。。。

引用 8 楼 dbzhang800 的回复:[quote=引用 7 楼 ACMtop 的回复:] [quote=引用 5 楼 mymtom 的回复:]   #include<stdio.h>   int m(int a) {     if(a==1)         return 2;      printf("return %d\n", 9); }   int main(void) {     int min ;     min=3;     min=m(2);     printf("min=%d\n",min); }   为什么加了printf("return %d\n", 9);就有数值了什么情况[/quote]  建议你学学汇编，然后你就容易理解 函数调用时，究竟发生了什么了。不然，你就规规矩矩地写程序。[/quote]  汇编果然是道砍，寄存器变来变去搞不清，看来还是老实写程序了

引用 4 楼 a345485527 的回复:gcc加上-Wall参数 gcc -Wall test.c  看看给你的是什么警告 warning: control reaches end of non-void function 就是说你的一些本应带有返回值的函数到达结尾后可能并没有返回任何值 没用gcc，按理说应该还是原值才对

引用 7 楼 ACMtop 的回复:[quote=引用 5 楼 mymtom 的回复:]   #include<stdio.h>   int m(int a) {     if(a==1)         return 2;      printf("return %d\n", 9); }   int main(void) {     int min ;     min=3;     min=m(2);     printf("min=%d\n",min); }   为什么加了printf("return %d\n", 9);就有数值了什么情况[/quote]  建议你学学汇编，然后你就容易理解 函数调用时，究竟发生了什么了。不然，你就规规矩矩地写程序。

引用 5 楼 mymtom 的回复:  #include<stdio.h>   int m(int a) {     if(a==1)         return 2;      printf("return %d\n", 9); }   int main(void) {     int min ;     min=3;     min=m(2);     printf("min=%d\n",min); }   为什么加了printf("return %d\n", 9);就有数值了什么情况

m函数中无默认返回值，编译不报错？

首先你的m函数有问题，在有问题代码的基础上讨论其他问题是没有意义的。  你的m函数返回值是一个int，不管你的代码中有没有return。没有return时，返回的是不受你控制的随机值。

变成eax的值了。 16位环境下变成ax的值。  计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。）

int 函数有点不对，if .... return 2,那另一个分支总的写吧，而且if(a==1)，不是赋值，是判断a是否等于1，楼主看书不仔细！  你在main里面,min = m(2), 不符合int 函数里面的判断

返回值未定义。可以是任何值，也可能任何值都不是。那么发生神马事情都有可能。

m不是没有返回值 而是返回值无法确定


Question: 关于sscanf的输入问题

引用5楼的回复 对于lz你的做法表示无法理解 怎么无法理解了

引用8楼angel_su的回复 sscanf_s不是sscanf，一个%s对应2个参数，具体去看文档。照理编译时应该有警告吧，不能无视阿... 谢啦  还以为一样呢····· 但编译时确实没有警告····

新建工程文件试试

新建工程文件还是错误，，不会是我的vs坏了吧

引用1楼的回复 sscanf_s(a, "%s%s", /*去掉&*/b, /*去掉&*/c);  去掉后还是出现相同的错误··

对于lz你的做法表示无法理解

用strcpy不行吗


Question: 帮我看看这个值是什么算出来的呢？

根据结构体bit的定义，它占用一个字节(3 + 2 + 3 = 8位)的内存空间  *c   =   0x99;  这条语句初始化了结构体变量s，0x99的二进制形式为10011001，此时内存中的状态：  100   11    001 c     b     a  其中结构体各字段的第一位数值为符号位 字段a是正数直接输出1 字段b是负数，需要对符号位进行扩展：11111111111111111111111111111111，将这个补码转换为原码就是-1 字段c也是负数，符号位扩展后为：11111111111111111111111111111100，转换成原码就是-4

struct   bit     {         unsigned int   a:3;       unsigned int   b:2;       unsigned int   c:3;   };


Question: Linux 条件变量 为什么要配合互斥锁

引用 楼主 forlove89 的回复:Linux 条件变量 为什么要配合互斥锁 进行操作 为什么不在条件变量内部不能自己实现互斥锁  因为物理微观上多线程cpu的出现，导致微观上数据的并发完全成为现实，所以为了保证数据的一致性，正确性， 涉及到共享的变量必须上锁，以保证该过程不会被打断，意外并发等造成的错误

来源man手册：A condition variable must always be associated with a mutex,  to  avoid        the race condition where a thread prepares to wait on a condition vari‐        able and another thread signals the condition  just  before  the  first        thread actually waits on it. 这应该能回答你的问题了


Question: 这个数组和地址的问题还是没弄懂

引用 11 楼 Cristiano001 的回复:[quote=引用 9 楼 w673339759 的回复:] 同意楼上的说法，对于指针的理解还要加深 void Evaluate（int *iArray）中符号*是右结合，从右向左看，传递过来的数组的地址是赋给iArray,而不是* iArray； 函数的参数声明了一个指针变量，用来存储数组的地址;函数中的声明int iArrayName[10]等价于int * iArrayName; 例如:char **p;可以理解为char (*(*(p)))；  你完美的解决了 我的问题 thanks[/quote] 多看看基础

引用 9 楼 w673339759 的回复:同意楼上的说法，对于指针的理解还要加深 void Evaluate（int *iArray）中符号*是右结合，从右向左看，传递过来的数组的地址是赋给iArray,而不是* iArray； 函数的参数声明了一个指针变量，用来存储数组的地址;函数中的声明int iArrayName[10]等价于int * iArrayName; 例如:char **p;可以理解为char (*(*(p)))；  你完美的解决了 我的问题 thanks

引用 3 楼 Cristiano001 的回复:[quote=引用 1 楼 lisong694767315 的回复:] iArray是数组的首地址，所以调用时相当于void Evaluate（int *iArray）  *iArray数组第一个元素，相当于iArray[0] *(iArray+1)是数组的第二个元素，相当于iArray[1] ... 以此类推  请问如果iArray是数组的首地址，那么调用时候如果变成了void Evaluate（int *iArray）这个括号里面的*iArray不是就变成iArray数组的首个元素了啊？[/quote] void Evaluate（int *iArray）这形参是个指针，说明传的是数组首地址，因此根据偏移i就可以得到该数组的所有值了，不管你用数组形式a[i]，还是解引用形式*(a+i)都是一样的

引用 6 楼 Cristiano001 的回复:[quote=引用 5 楼 lisong694767315 的回复:] [quote=引用 3 楼 Cristiano001 的回复:] [quote=引用 1 楼 lisong694767315 的回复:] iArray是数组的首地址，所以调用时相当于void Evaluate（int *iArray）  *iArray数组第一个元素，相当于iArray[0] *(iArray+1)是数组的第二个元素，相当于iArray[1] ... 以此类推  请问如果iArray是数组的首地址，那么调用时候如果变成了void Evaluate（int *iArray）这个括号里面的*iArray不是就变成iArray数组的首个元素了啊？[/quote]  *iArray是第一个元素的值啊[/quote]  问题就在这里，调用函数的实参传给被调用函数时候是地址，在被调用函数需要用的时候就变成值了 ，难道这是规定吗？？[/quote]  iArray是地址，*是取值运算符（C++中叫解引用运算符），*iArray就是取iArray地址中的值，所以*iArray是值。你还是去看看指针方面的书吧，推荐《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对应的汇编并单步执行观察相应内存和寄存器变化。）  想要从本质上理解C指针，必须学习汇编以及C和汇编的对应关系。 从汇编的角度理解和学习C语言的指针，原本看似复杂的东西就会变得非常简单！ 指针即地址。“地址又是啥？”“只能从汇编语言和计算机组成原理的角度去解释了。” 但我又不得不承认：  有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物；  而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。 而我本人属前者。  不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);】来理解指针的本质， 而要依赖调试时的反汇编窗口中的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

引用 5 楼 lisong694767315 的回复:[quote=引用 3 楼 Cristiano001 的回复:] [quote=引用 1 楼 lisong694767315 的回复:] iArray是数组的首地址，所以调用时相当于void Evaluate（int *iArray）  *iArray数组第一个元素，相当于iArray[0] *(iArray+1)是数组的第二个元素，相当于iArray[1] ... 以此类推  请问如果iArray是数组的首地址，那么调用时候如果变成了void Evaluate（int *iArray）这个括号里面的*iArray不是就变成iArray数组的首个元素了啊？[/quote]  *iArray是第一个元素的值啊[/quote]  问题就在这里，调用函数的实参传给被调用函数时候是地址，在被调用函数需要用的时候就变成值了 ，难道这是规定吗？？

引用 3 楼 Cristiano001 的回复:[quote=引用 1 楼 lisong694767315 的回复:] iArray是数组的首地址，所以调用时相当于void Evaluate（int *iArray）  *iArray数组第一个元素，相当于iArray[0] *(iArray+1)是数组的第二个元素，相当于iArray[1] ... 以此类推  请问如果iArray是数组的首地址，那么调用时候如果变成了void Evaluate（int *iArray）这个括号里面的*iArray不是就变成iArray数组的首个元素了啊？[/quote]  *iArray是第一个元素的值啊

帮帮忙在线等待

引用 1 楼 lisong694767315 的回复:iArray是数组的首地址，所以调用时相当于void Evaluate（int *iArray）  *iArray数组第一个元素，相当于iArray[0] *(iArray+1)是数组的第二个元素，相当于iArray[1] ... 以此类推  请问如果iArray是数组的首地址，那么调用时候如果变成了void Evaluate（int *iArray）这个括号里面的*iArray不是就变成iArray数组的首个元素了啊？

iArray作为参数传递给Evaluate，他就是数组的首地址，即指向数组的指针。那么他指向形参  iArrayName的首地址。 即iArray数组和iArrayName数组存储在同一片内存空间，所以改变iArrayName即改变iArray


Question: 问下显示行数的软件是什么？

vc里面的一个选项吧。。。有个是否显示行号的选项

vim qtcreator == 很多。


Question: windows核心编程上的，完整性级别 ，貌似出现一个bug ？欢迎高手参与讨论

赵老师的意思应该说是，这个installer不是安装程序用的，而是安装操作系统用的。  就是你在一台裸机上面，什么操作系统也没有，你要在上面安装windows操作系统，你运行的安装程序，这个东西的级别才叫installer.因为系统都是它装的，所以它的级别是最高的。  也只能是装系统时用，装完系统估计就没它什么事了。

引用 9 楼 u012879787 的回复:[quote=引用 7 楼 truexf 的回复:] 进程完整性级别不存在install，可以这么认为，system是最高级别。如果说有，好吧，那也行，但是谁也没见过，谁也用不上。或许只有微软自己用。 引用 8 楼 taodm 的回复:好吧，楼主new了一个2个对象，于是因为重婚被警察带走了。  我找到出处了   http://www.symantec.com/connect/articles/introduction-windows-integrity-control  Determining trustworthiness using WIC  In order to police the interactions between objects, Windows must first determine the trustworthiness, or integrity level of each object. WIC assigns one of the following six integrity levels to each object:     Untrusted – processes that are logged on anonymously are automatically designated as Untrusted Low – The Low integrity level is the level used by default for interaction with the Internet. As long as Internet Explorer is run in its default state, Protected Mode, all files and processes associated with it are assigned the Low integrity level. Some folders, such as the Temporary Internet Folder, are also assigned the Low integrity level by default. Medium – Medium is the context that most objects will run in. Standard users receive the Medium integrity level, and any object not explicitly designated with a lower or higher integrity level is Medium by default. High – Administrators are granted the High integrity level. This ensures that Administrators are capable of interacting with and modifying objects assigned Medium or Low integrity levels, but can also act on other objects with a High integrity level, which standard users can not do. System – As the name implies, the System integrity level is reserved for the system. The Windows kernel and core services are granted the System integrity level. Being even higher than the High integrity level of Administrators protects these core functions from being affected or compromised even by Administrators.   Installer – The Installer integrity level is a special case and is the highest of all integrity levels. By virtue of being equal to or higher than all other WIC integrity levels, objects assigned the Installer integrity level are also able to uninstall all other objects. 你们看吧[/quote]  顶起来啊

引用 7 楼 truexf 的回复:进程完整性级别不存在install，可以这么认为，system是最高级别。如果说有，好吧，那也行，但是谁也没见过，谁也用不上。或许只有微软自己用。 引用 8 楼 taodm 的回复:好吧，楼主new了一个2个对象，于是因为重婚被警察带走了。  我找到出处了   http://www.symantec.com/connect/articles/introduction-windows-integrity-control  Determining trustworthiness using WIC  In order to police the interactions between objects, Windows must first determine the trustworthiness, or integrity level of each object. WIC assigns one of the following six integrity levels to each object:     Untrusted – processes that are logged on anonymously are automatically designated as Untrusted Low – The Low integrity level is the level used by default for interaction with the Internet. As long as Internet Explorer is run in its default state, Protected Mode, all files and processes associated with it are assigned the Low integrity level. Some folders, such as the Temporary Internet Folder, are also assigned the Low integrity level by default. Medium – Medium is the context that most objects will run in. Standard users receive the Medium integrity level, and any object not explicitly designated with a lower or higher integrity level is Medium by default. High – Administrators are granted the High integrity level. This ensures that Administrators are capable of interacting with and modifying objects assigned Medium or Low integrity levels, but can also act on other objects with a High integrity level, which standard users can not do. System – As the name implies, the System integrity level is reserved for the system. The Windows kernel and core services are granted the System integrity level. Being even higher than the High integrity level of Administrators protects these core functions from being affected or compromised even by Administrators.   Installer – The Installer integrity level is a special case and is the highest of all integrity levels. By virtue of being equal to or higher than all other WIC integrity levels, objects assigned the Installer integrity level are also able to uninstall all other objects. 你们看吧

好吧，楼主new了一个2个对象，于是因为重婚被警察带走了。

引用 5 楼 u012879787 的回复:引用 4 楼 zxh707wk 的回复:[quote=引用 3 楼 zhao4zhong1 的回复:] 你试试安装Windows操作系统本身说明lz并没有深思熟虑  这install 级别，我在有的有上，是找不到的。  是[/quote]  msdn上看到一文章提到有install级别。  可见微软的技术很狗屎，不统一，众说纷纭

引用 4 楼 zxh707wk 的回复:引用 3 楼 zhao4zhong1 的回复:你试试安装Windows操作系统本身说明lz并没有深思熟虑  这install 级别，我在有的有上，是找不到的。  是

你试试安装Windows操作系统本身

引用 1 楼 zhao4zhong1 的回复:此install非彼install  那请问是什么？  有高手知道吗？   高手们总是说，亲自验证读书  这些问题，都是我验证无效，深思熟虑后，才能咨询的。

此install非彼install