Question: 关于位运算做除法的问题

#include <xmmintrin.h> __m128 ConvertIntToFloatColor(__m128 scaleFactor, int r, int g, int b, int a) {     __m128i intColor = _mm_set_epi32(a, b, g, r);     __m128 floatColor = _mm_cvtepi32_ps(intColor);     floatColor = _mm_mul_ps(floatColor, scaleFactor);     return floatColor; }  __m128 AlphaBlend(__m128 srcColor, __m128 dstColor, __m128 oneOneOneZero, __m128 zeroZeroZeroOne) {     __m128 srcAlpha = _mm_shuffle_ps(srcColor, srcColor, _MM_SHUFFLE(3, 3, 3, 3));     __m128 dstAlpha = _mm_shuffle_ps(dstColor, dstColor, _MM_SHUFFLE(3, 3, 3, 3));     __m128 one = _mm_set1_ps(1.0f);     __m128 oneMinusSrcAlpha = _mm_sub_ps(one, srcAlpha);     __m128 outAlpha = _mm_add_ps(srcAlpha, _mm_mul_ps(dstAlpha, oneMinusSrcAlpha));     __m128 blended = _mm_add_ps(_mm_mul_ps(srcColor, srcAlpha),                                 _mm_mul_ps(_mm_mul_ps(dstColor, dstAlpha), oneMinusSrcAlpha));     blended = _mm_and_ps(blended, oneOneOneZero);     outAlpha = _mm_and_ps(outAlpha, zeroZeroZeroOne);      return _mm_or_ps(blended, outAlpha); }  void ConvertFloatToIntColor(__m128 floatColor, __m128 scaleFactor, int* r, int* g, int* b, int* a) {     floatColor = _mm_mul_ps(floatColor, scaleFactor);     __m128i intColor = _mm_cvtps_epi32(floatColor);     int* i = (int*)&intColor;     *r = i[0];     *g = i[1];     *b = i[2];     *a = i[3]; }  void TestBlend() {     __m128 oneOneOneZero;     __m128 zeroZeroZeroOne;     int* oneOneOneZeroPtr = (int*)&oneOneOneZero;     int* zeroZeroZeroOnePtr = (int*)&zeroZeroZeroOne;     oneOneOneZeroPtr[0] = 0xffffffff;     oneOneOneZeroPtr[1] = 0xffffffff;     oneOneOneZeroPtr[2] = 0xffffffff;     oneOneOneZeroPtr[3] = 0x00000000;     zeroZeroZeroOnePtr[0] = 0x00000000;     zeroZeroZeroOnePtr[1] = 0x00000000;     zeroZeroZeroOnePtr[2] = 0x00000000;     zeroZeroZeroOnePtr[3] = 0xffffffff;     __m128 scaleFactor0 = _mm_set1_ps(1.0f / 255.0f);     __m128 scaleFactor1 = _mm_set1_ps(255.0f);          __m128 red = ConvertIntToFloatColor(scaleFactor0, 255, 0, 0, 255);     __m128 green = ConvertIntToFloatColor(scaleFactor0, 0, 255, 0, 128);     __m128 color = AlphaBlend(green, red, oneOneOneZero, zeroZeroZeroOne);     int r, g, b, a;     ConvertFloatToIntColor(color, scaleFactor1, &r, &g, &b, &a);     printf("r %d, g %d, b %d, a %d\n", r, g, b, a); }  使用SSE计算的版本，注意两个缩放系数scaleFactor0和scaleFactor1， 因为是8bit转成的浮点数，所以scaleFactor0是1.0f / 255.0f, 而 scaleFactor1 是 255.0f

这里不应该用正片叠底，用第一个公式就行了。 原始图片只有RGB三个通道，这是不够的，需要添加alpha通道。 比如RGB(204,224,236)，添加alpha通道后就是RGBA(204,224,236,128)，此时alpha通道是128，也就是50%透明，然后套用第一个公式。 建议计算时将所有定点数转成0.0~1.0浮点数来计算，这样通用性高，色彩格式不仅仅只有8bit还有16bit、4bit等，全转成浮点数来计算只要修改一下色彩转换的代码就可以通用了

多谢各位，赵老师的资料收藏了，资料挺好，就是最近没什么心情看，年底各种破事，等忙完这段再看  引用 16 楼 zhao4zhong1 的回复:PHOTOSHOP图层混合模式的计算公式 http://www.360doc.com/content/14/0520/17/636843_379403237.shtml

引用 13 楼 fengswd 的回复:[quote=引用 11 楼 zhao4zhong1 的回复:] [quote=引用 10 楼 fengswd 的回复:] [quote=引用 9 楼 lm_whales 的回复:] 这个不需要这么麻烦吧,用alpha 通道处理就是了  好像是这个思路，但是通道只能解决一个像素点啊，它不能细分到红、绿、蓝各个颜色的处理撒。就像上面，白色的部分是rgb(255,255,255)，被处理后变成了RGB(204,224,236),变成了淡蓝色，alpha应该是不能做到这一点的吧？[/quote] 搜索一下PhotoShop图层选项、模式：正片叠底、……[/quote]  好像很难的样子啊，不太懂，以后再琢磨[/quote] 今日事，今日毕。 http://www.baidu.com/s?wd=Photoshop%20%E5%9B%BE%E5%B1%82%E8%BF%90%E7%AE%97&rsv_spt=1&issp=1&f=8&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=0&rsv_pq=c181593800000170&rsv_t=7f09kHnmWHnAsTHVETDUiBOrKPGJ3HqN7KQ6LXAncWU7wgoEJjgL4cp8az9feBqLcQBq&inputT=21915

引用 11 楼 zhao4zhong1 的回复:[quote=引用 10 楼 fengswd 的回复:] [quote=引用 9 楼 lm_whales 的回复:] 这个不需要这么麻烦吧,用alpha 通道处理就是了  好像是这个思路，但是通道只能解决一个像素点啊，它不能细分到红、绿、蓝各个颜色的处理撒。就像上面，白色的部分是rgb(255,255,255)，被处理后变成了RGB(204,224,236),变成了淡蓝色，alpha应该是不能做到这一点的吧？[/quote] 搜索一下PhotoShop图层选项、模式：正片叠底、……[/quote]  好像很难的样子啊，不太懂，以后再琢磨

感觉很热闹的样子

引用 9 楼 lm_whales 的回复:这个不需要这么麻烦吧,用alpha 通道处理就是了  好像是这个思路，但是通道只能解决一个像素点啊，它不能细分到红、绿、蓝各个颜色的处理撒。就像上面，白色的部分是rgb(255,255,255)，被处理后变成了RGB(204,224,236),变成了淡蓝色，alpha应该是不能做到这一点的吧？

这个不需要这么麻烦吧,用alpha 通道处理就是了

引用 6 楼 yaj_4010 的回复:楼主，不明白你是如何得到1.7这个数值的，但是想实现图中的效果是可以的，我以前实现过一个将选择的部分颜色变暗或者渐变的效果图，方法如下：首先要确定图片区域的范围， 然后在吧这个范围中的颜色值以一定的比例重画，已达到这个效果，这是一中方法，另一种方法是用两张或者多种以实现不同的效果。希望对楼主有点提示作用  你说的这个方法是提取像素然后设置新值最后重新设置回去吧？这样效果达到了，可是太慢了，就上图这么大小，框选的部分显示出来得1秒钟。鼠标框选就要即时反应出来，pdf估计是用其他的思路实现的。

引用 10 楼 fengswd 的回复:[quote=引用 9 楼 lm_whales 的回复:] 这个不需要这么麻烦吧,用alpha 通道处理就是了  好像是这个思路，但是通道只能解决一个像素点啊，它不能细分到红、绿、蓝各个颜色的处理撒。就像上面，白色的部分是rgb(255,255,255)，被处理后变成了RGB(204,224,236),变成了淡蓝色，alpha应该是不能做到这一点的吧？[/quote] 搜索一下PhotoShop图层选项、模式：正片叠底、……

引用 楼主 fengswd 的回复:被除数是个小于255的整数，除数是个小数比如1.7，用位运算得到结果，要求不能使用移位运算，也就是说只能用与、或、非、异或来完成，有没有这样的算法？小弟求教，越简单越好，算法越精辟越好，结果满意的话再追加50分  哪里出的这种问题。。。。尼玛不位移分解个屁，用算数位运算来做，这不坑爹么

引用 1 楼 user-7 的回复:怎么感觉象是数字电路，只能帮顶了  多谢

另外计算机的中的乘除都是可以用加减来实现的，这个要楼主去找一本操作系统的书去好好的复习一下如何用加减法实现乘除了

怎么感觉象是数字电路，只能帮顶了

引用 3 楼 nadleeh123 的回复:[quote=引用 楼主 fengswd 的回复:] 被除数是个小于255的整数，除数是个小数比如1.7，用位运算得到结果，要求不能使用移位运算，也就是说只能用与、或、非、异或来完成，有没有这样的算法？小弟求教，越简单越好，算法越精辟越好，结果满意的话再追加50分   哪里出的这种问题。。。。尼玛不位移分解个屁，用算数位运算来做，这不坑爹么[/quote]  我这不就是问一下有没有这样的运算么？ 还是把问题贴出来吧，   这是PDF文档里截的一幅图。图里蓝色的选择框是鼠标框选时的样子。如果用BiltBlt函数来做这个图形的话，可以是可以，但是我看了一下颜色的rgb值，发现被覆盖的部分是原像素颜色值除以1.7。但是BitBlt等函数的光栅操作只能是与、或、非，异或。所以就想知道到底怎么实现这样的选择框，其实类似的选择框在很多软件里都很常见，比如qq的截图功能。求这位大神告诉我办法，如果成功的话送再送上100分


Question: 求助大神

5楼正解

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

#include<stdio.h> struct student { 	int num; 	char name[20]; 	float score[3]; 	char sex; 	float aver; }stud[5]; int i; void save(struct student stud[]) { 	FILE *fp; 	if((fp=fopen("stu.dat","wb"))==NULL) 	{ 		printf("cannot open file\n"); 		return; 	} 	for(i=0;i<5;i++) 		if(fwrite(&stud[i],sizeof(struct student),1,fp)!=1) 			printf("file write error\n"); 	fclose(fp); } void readf1(struct student stud[]) { 	FILE *fp; 	if((fp=fopen("stu.dat","rb"))==NULL) 	{ 		printf("cannot open file\n"); 		return; 	} 	for(i=0;i<5;i++) 	{ 		if (fread(&stud[i],sizeof(struct student),1,fp)!=1) 			printf("file write error\n"); 	} } void readandsort(struct student stud[]) { 	FILE *fp; 	if((fp=fopen("stu.dat","r"))==NULL) 	{ 		printf("cannot open file\n"); 		return; 	} 	for(i=0;i<5;i++) 	{ 		if (fread(&stud[i],sizeof(struct student),1,fp)!=1) 	    	printf("file write error\n");  	} 	int i,j,k; 	struct  student temp; 	scanf("%d",&stud[i].num); 	scanf("%s",stud[i].name); 	scanf("%f",stud[i].score); 	scanf("%c",&stud[i].sex); 	stud[i].aver=(stud[i].score[0]+stud[i].score[1]+stud[2].score[2])/3; 	for(i=0;i<4;i++) 	{ 		k=i; 		for(j=i+1;j<5;j++) 		{ 			if(stud[j].aver>stud[k].aver) 			{ 				k=j; 				temp=stud[k]; 				stud[k]=stud[i]; 				stud[i]=temp; 			} 		} 	} 	for(i=0;i<5;i++)     printf("%4d",stud[i].num); 	printf("%-20s",stud[i].name); 	printf("%5f",stud[i].score); 	printf("%2c",stud[i].sex); 	printf("%5f",stud[i].aver); 	printf("\n");     fclose(fp); } void f2(struct student stud[]) { 	FILE *fp; 	if((fp=fopen("stud.dat","w"))==NULL) 	{ 		printf("cannot open file\n"); 		return; 	} 	for(i=0;i<5;i++) 	{         if(fwrite(&stud[i],sizeof(struct student),1,fp)!=1) 			printf("file write error\n");     } 	if((fp=fopen("sort.dat","r"))==NULL) 	{ 		printf("cannot open file\n"); 		return; 	}     for(i=0;i<5;i++) 	{ 		if (fread(&stud[i],sizeof(struct student),1,fp)!=1) 	    	printf("file write error\n"); 	} 	fprintf(fp,"%4d",stud[i].num); 	fprintf(fp,"%-20s",stud[i].name); 	fprintf(fp,"%5f",stud[i].score); 	fprintf(fp,"%2c",stud[i].sex); 	fprintf(fp,"%5f",stud[i].aver); 	fclose(fp); } void main() { 	struct student stud[5]={{10001,"qwe",100,100,100,'f'},{10002,"sdf",65,67,78,'m'}, 	{10003,"ert",89,67.98,'f'},{10004,"dgf",56,45,56,'m'},{10005,"uhj",87,74,68,'f'}}; 	void save(struct student stud[]); 	void readf1(struct student stud[]); 	void readandsort(struct student stud[]); 	void f2(struct student stud[]); } 为什么进不去。怎么引用。

楼主你把问题说清楚，是编译报错还是程序功能无法实现。如果是功能无法实现，再写写你想要什么功能，现在什么功能出错，顺便再把代码的简单思路注释上就好了。

引用 2 楼 longhaiyan3 的回复:有几个地方for循环的花括号都没有加上，好好检查代码吧，保证没有低级错误再看 for循环不一定要加花括号吧，如果他只是想循环执行下面的一条语句。 我编译就发现f2()函数最后差个花括号。 另外我看readandsort()函数里的 for(i=0;i<4;i++) { 		k=i; 		for(j=i+1;j<5;j++) 		    if(stud[j].aver>stud[k].aver) 			    k=j; 		{ 			temp=stud[k]; 			stud[k]=stud[i]; 			stud[i]=temp; 		} }这部分，编译是没问题，只是看着就像是括号打错位置了。

有几个地方for循环的花括号都没有加上，好好检查代码吧，保证没有低级错误再看

怎么错的


Question: 请教个问题，高手进，初学者请绕道。

楼主不就是个小白，还好意思说初学者绕道……

提这种问题有意义吗

再一点就是当这个代码在并行处理的时候是否会产生问题

引用 29 楼 sholber 的回复:换一个角度，考虑一个简化的模型：  int n = 1, m = n ++, a [m]; printf ("%d, %d, %d\n", n, m, sizeof a);  再审视一下，声明的过程，每个全声明符的位置，与序列点之间的关系。 这个问题我没有再回复是怕给了错误的引导，int n=1,m=n++, a[m];所有逗号和分号位置都有一个序列点，这个毫无疑问。支持的标准就是你帖的 end of a full declarator。从这样看代码没问题。但是有点奇怪的是 c++ 有说  int a, b, c; 基本上等于 int a; int b; int c;(以注脚的形式给出）注脚是不算在标准内的。而c99没找到相关的。还有一点要说明的是 逗号在这里只是个分隔符，那么是否意味着int a,b, c;可以是 int a; int c; int b; 至少目前我还没得到一个确切的答案，暂时认同 int n=1, m=n++, a[m];不会有问题。

钻牛角尖可以 ，但是不要标题党。

引用 楼主 sholber 的回复:{     int n = 1, a [n] [n++] [n++];     //请问是a [1][1][2]还是a[1][2][3]或者其它?     printf ("%d\n", sizeof a);     //这里写到标准输出的值是多少？       n = 1;     int b [n] [sizeof ++ n] [n];     //同上问。     printf("%d\n", sizeof a);     //同上问。 } 貌似定义数组的时候不能用变量，讨论这有意义吗

int a1[f()][g()][h()], a2[k()]; The compiler might call f, g, and h in any order, but it must have called all three before calling k.

引用 45 楼 zhao4zhong1 的回复:[quote=引用 43 楼 sholber 的回复:] [quote=引用 41 楼 zhao4zhong1 的回复:] 等楼主自己实现或参透g++（开源编译器）怎么实现的时候就会茅塞顿开了。  研究编译器怎么实现能解决问题吗？大师，你听说过实现定义的行为和未指定的行为吗？同一个问题，允许不同的编译器有不同的实现，你告诉我怎么参透，大师你真任性啊。[/quote] 在你自己照国际标准米的定义实际做出一个一米长的尺子的时候，你对实现定义的行为和未指定的行为就会茅塞顿开了。[/quote] 自顶！

引用 45 楼 zhao4zhong1 的回复:[quote=引用 43 楼 sholber 的回复:] [quote=引用 41 楼 zhao4zhong1 的回复:] 等楼主自己实现或参透g++（开源编译器）怎么实现的时候就会茅塞顿开了。  研究编译器怎么实现能解决问题吗？大师，你听说过实现定义的行为和未指定的行为吗？同一个问题，允许不同的编译器有不同的实现，你告诉我怎么参透，大师你真任性啊。[/quote] 在你自己照国际标准米的定义实际做出一个一米长的尺子的时候，你对实现定义的行为和未指定的行为就会茅塞顿开了。[/quote]  什么乱七八糟的……

引用 43 楼 sholber 的回复:[quote=引用 41 楼 zhao4zhong1 的回复:] 等楼主自己实现或参透g++（开源编译器）怎么实现的时候就会茅塞顿开了。  研究编译器怎么实现能解决问题吗？大师，你听说过实现定义的行为和未指定的行为吗？同一个问题，允许不同的编译器有不同的实现，你告诉我怎么参透，大师你真任性啊。[/quote] 在你自己照国际标准米的定义实际做出一个一米长的尺子的时候，你对实现定义的行为和未指定的行为就会茅塞顿开了。

（基于C99标准）首先C语言不允许定义动态数组，本身这段程序不管是否初始化都会编译出错。其次，编译器标准有所不同，就算通过编译，得到结果还是可能出现不同。最后，程序风格与规范问题。编写任何代码都不能依靠未定义的行为，也不应写出自己无法预测结果的代码。同小白，如有不对请轻喷

引用 41 楼 zhao4zhong1 的回复:等楼主自己实现或参透g++（开源编译器）怎么实现的时候就会茅塞顿开了。  研究编译器怎么实现能解决问题吗？大师，你听说过实现定义的行为和未指定的行为吗？同一个问题，允许不同的编译器有不同的实现，你告诉我怎么参透，大师你真任性啊。

等楼主自己实现或参透g++（开源编译器）怎么实现的时候就会茅塞顿开了。

引用 33 楼 zxh707wk 的回复:提这种问题有意义吗 LZ的意义是没事可以多研究研究C99标准

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

引用 34 楼 zf97576419 的回复:不好意思，我是小白，我也进来了。 c语言色灰色地带。。。 a[n][n+1]在vc下貌似直接报错吧。。。 在linux源代码你有还会发现有这样的写法。。  小白一个，说的不对轻喷 VC不支持C99标准的变量数组

引用 25 楼 worldy 的回复:int n = 1, a [n] [n++] [n++];  这样能通过编译??? 支持C99标准的编译器能编译


Question: C语言 堆栈 静态存储区

http://en.wikipedia.org/wiki/Memory_management#DYNAMIC http://en.wikipedia.org/wiki/Automatic_variable

1.你理解有误，堆才是向上的， 2.动态存储区就是堆，静态用来存储字符串常量，全局变量   3.上面说的都是操作系统里的，在数据结构中堆在是指栈，在一些编程题目会用到

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

理解和讨论之前请先学会如何观察！  计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）  栈中的基本变量退出其作用域时，没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时，会自动执行其析构函数，……  其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。  为什么要有数据结构这个东东？ 因为要将现实世界或者抽象理论中的各种数据保存在计算机外存（光盘、硬盘、U盘……）或内存（ROM、RAM、SRAM……）里面的二进制字节数组中。 然后让CPU这个只会执行预先保存好的加减乘除移位条件转移……等机器指令的家伙按照人的意志去处理这些数据。至于具体如何处理就是所谓算法。  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。

以32位操作系统为例，每一个应用程序都会对应4G的虚拟地址 （这里不讨论虚拟地址的概念，自己慢慢去学），  从 0x00000000  到  0xFFFFFFFF    从低地址到高地址， 其中存放数据的顺序如下， 0地址  -》 代码区 -》 全局区 -》 BSS 段 -》 堆  -》 栈 （栈后面还会有一小块内存存储当前系统的环境变量）-》 地址到3G 之后有操作系统的内核所持有， 应用程序无法使用3G - 4G这段虚拟地址。地址顺序由低到高。  代码区（只读常量区） ：  存放的内容是只读的， 包括已经初始化的具有常属性的 全局变量，和已经初始化的具有常属性的静态局部变量， 在代码区和全局区之间会存有字符串子面值。  全局区： 已经初始化的全局变量， 和静态局部变量.   BSS段：这个区域里只存储  未初始化的全局变量，   在程序一运行的时候， 该区域把这些全局变量全部清零， 之后就消失  堆： 存储程序中临时分配的内存  栈： 存储局部变量， 函数参数等  staitc const int  i = 10; //放在代码区 const char * str = "abcdefghjklm";  //在代码区和全局区之间， 此区域不可修改 int k = 100; // 代码区 void func( int temp, double db) //函数参数在栈区中 {      static const  int j = 100; //放在代码区      static int a = 100; //全局区      int * pa = (int*) malloc(sizeof(int) * 10); //在程序中临时分配的内存放在栈中      int h = 0; //存放在栈中     for(h = 0; h < 10 ; ++h)    {      ......    } }  其中前三个区域所占空间极小， 堆和栈可以有大量的空间，假设前面只占1M内存 从1M以后可能就是堆的起始点 ，假设堆占了500M。 从上往下增长  从3G开始， 以后是内核， 用户无法使用， 3G-1就是栈的起始点， 所以栈的大小只能从高地址到低地址，往上增长， 假设栈也只有500M。  堆和栈之间还用很多的空余， 这些空余的意义是假如程序运行中，堆的500M不够了， 就往下扩大， 栈也一样， 不够就往上增长。  顺便说一句， 搞嵌入式这些都不懂怎么搞

A  S  M

那请问大神：如果我要学习这方面的知识，我需要看哪方面的知识？ 本人是做嵌入式的（入行半年），以前大学学的是电子信息专业，对操作系统不是很清楚（学过VB和C语言，VB都忘光了~）

1.其实他们没什么特点,唯一的特点就是 栈的回收创建是系统来操作的,而堆的回收操作是由程序员来操作的  2.静态存储区会吧数据一直保留在程序结束！难道楼主说的动态是堆栈？那么就请看第一个,其实C语言没有动态存储区一说吧  3.当你在函数内部使用局部变量比如 int a = 10,char str[20]="1233333333"还有 调用函数的时候都会用到栈,在使用malloc申请的内存都是放在堆区的！比如 char * str = (char *)malloc(100*sizeof(char)); 堆区的数据需要程序员自己释放是否会容易造成内存泄漏

操作系统是基础中的基础，感觉你对操作系统不了解，还有你对程序的链接、装载也不了解。这些东西不是一言两语就能说明白的，即使告诉你堆、栈、静态区是什么，你也不会有一个感性的认识。所以最好的方法是把这些基础学牢了，语言啥的都是高级工具，然后学这些的时候你才会明白为什么，不然你在编程这块走的不会太远。慢慢来，不要太急，基础好了，这些以后就慢慢知道了。

堆是分配出来的，通过malloc这类函数， 栈是不需要分配，局部变量都属于这类。 其实不需要关心这么多的，你遇到的是什么问题

1，堆，栈指内存，内存里的东西能永久保留么？ 2，静态存储区指 静态变量（static），常量（const），全局变量。动态指堆（malloc分配的）和栈 3，代码里的变量，大多数不是用堆就是用栈。只有比较少的用静态存储。   感觉lz还是多看几遍书吧，书上讲的比较清楚（当然不包括中国的教科书）

感谢各位大神，拜读了~~~


Question: 宏使用遇到的小问题

两个阶段： for循环是运行阶段执行 宏是预编译阶段 在经过宏展开后代码就成为  for(char i = 1;i<10;i++)   CLEAR_ROW_i;   然后编译阶段 error：CLEAR_ROW_i未定义 LZ想做什么呢？ 即使展开成CLEAR_ROW_1然后循环中语句就是1;这一样是非法语句！

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

这是预编译时候发生的事情， 就是说此时for循环里面根的 i 的值还是未知的， 程序还没开始运行，  你一编译， 程序就被替换成这样 void fun() { 	for(char i = 1;i<10;i++) 		//CLEAR_ROW(i) ; 		CLIEAR_ROW_i;  //在预编译阶段， i的值未知， i只是一个符号， 不可能发生你想像的那样i = 1， i = 2.....  }

去看看模版元编程有你要的

把它写成函数传送参数不就行了。

引用 1 楼 pengzhixi 的回复:一个预编译期替换，一个运行期才能确定怎么可能呢那有没有什么宏方法能实现我上面的作用咧？

一个预编译期替换，一个运行期才能确定怎么可能呢


Question: 字符串切割函数的应用

仅供参考#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: // <> <> <> <>

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

代码整体的流程如下：  （1）判断参数s是否为NULL，如果是NULL就以传递进来的saveptr作为起始分解位置；若不是NULL，则以s开始切分。  （2）跳过待分解字符串开始的所有分界符。  （3）判断当前待分解的位置是否为'/0'，若是则返回NULL（联系到（一）中所说对返回值为NULL的解释）；不是则继续。  （4）保存当前的待分解串的指针token，调用strpbrk在token中找分界符：如果找不到，则将saveptr赋值为待分解串尾部'/0'所在的位置，token没有发生变化；若找的到则将分界符所在位置赋值为'/0'，token相当于被截断了（提取出来），saveptr指向分界符的下一位。  （5）函数的最后（无论找到还是没找到）都将返回。      这就是strtokr函数功能

没写注释见谅

#include<stdio.h> #include<stdlib.h> #include<string.h> char *strtokr(char *s,char *Delim,char **saveptr) { 	char *token=NULL; 	if(s==NULL) 	{ 		s=*saveptr; 	} 	s=s+strspn(s,Delim);   	if(*s=='\0') 	{ 		return NULL; 	} 	token=s; 	s=strpbrk(token,Delim); 	if(s==NULL) 	{ 		*saveptr=strchr(token,'\0'); 	} 	else 	{ 		*s='\0'; 		*saveptr=s+1; 	} 	return token; }  void Initial(char **p) { 	int i=0; 	for(i=0;i<20;i++) 	{ 		*(p+i)=NULL; 	} }  int main() { 	char s[100]="012 jiangcai english 100,013 lilei english 12,014 xiaohua english 90"; 	int i=0; 	char **outsaveptr=NULL; 	char **insaveptr=NULL; 	char **p=(char **)malloc(20*sizeof(char *)); 	char **q=p; 	char *buf=s; 	Initial(p); 	while(*q=strtokr(buf,",",outsaveptr)) 	{ 		buf=*q; 		while(*q=strtokr(buf," ",insaveptr)) 		{ 			q++; 			buf=NULL; 		} 		buf=NULL; 	} 	for(i=0;(*(p+i)!=NULL);i++) 	{ 		printf("%s\n",*(p+i)); 	}     	system("pause"); 	free(q); 	free(p); 	p=NULL;  	q=NULL; 	outsaveptr=NULL; 	insaveptr=NULL;  	return 0; }   我在vs2010中把楼主的程序格式调整了一下，这样看程序可能会懂得快些…… 楼主的程序编译没错，运行会崩~~~ 楼主的程序能不能说一下功能？？多一点变量和语句功能的注释，这让人也看得容易查错？？？

警告 i.cpp 39: 可能是不正确的赋值在 main 函数中 警告 i.cpp 41: 可能是不正确的赋值在 main 函数中 以上两条就是全部错误信息

char **p=(char **)malloc(20*sizeof(char *));  char **q=p;  char *buf=s;  我觉得这块有问题！C语言必须把所有的变量定义写在开头！  其次楼主要注意编码风格！ 看着很DT

楼主错误信息是什么？可否贴出错误信息让在下看下？

没分配内存怎么改动

char **outsaveptr=NULL;   //没有分配内存   在函数中 else 	{ 		*s='\0'; 		*saveptr=s+1;  //这里没有分配内存    对*saveptr必然崩溃  	}


Question: C 语言 sin(x)积分问题求助？

引用 3 楼 u011606329 的回复:但是即使是0到1.02积分，那么答案也应该是在1左右啊，但是，事实山好像这个不是真正的，致命的错误啊。怎么会是1呢？sinx在0到1上积分，是cos0-cos1，是1-0.54=0.46。 使用double类型精确一下，得到近似的结果：#include<stdio.h> #include<math.h> int main() { 	double num = 0.0, sum = 0.0; 	while (num <= 1.0) 	{ 		num += 0.02; 		sum += sin(num)*0.02; 	} 	printf("sum is %lf\n", sum);    //0.468097 }

引用 3 楼 u011606329 的回复:但是即使是0到1.02积分，那么答案也应该是在1左右啊，但是，事实山好像这个不是真正的，致命的错误啊。 所以说你高数得重修了，sin(x)从0到1的积分大约是0.45970

高数重修确定 另外你这是0到1.02的积分

sin每次乘0.02是什么意思


Question: 新手求教一个关于c语言的小问题，

这种语句相当于TVB的经典台词“你妈逼的！”  不同的编译器有不同的理解  另外，别看这些屎语句了，毛意义都没有

对于这种未定义的行为， 不同的编译器结果不一样， 楼主只需记住前++是先改变本身在计算， 后++先计算在自增。   实际开发中是不会写出这种代码的，  只有考二级会有这种。。。。

楼主还不明白吗， i = i++ + ++i; 这样的语句，不同的编译器有不同的解释。  比如下面这句话： “我爱上你了！”  不同的人的理解就完全不同嘛！

引用 9 楼 Eazil3 的回复:我现在纠结的是，这个计算的步骤到底有没有一个正规的步骤，现在就两个版本，1+3 和 2+2+1 这两种算法都算对吗？根据不同编译器的规则来看的花 没有正规的步骤，标准压根就没规定正规步骤。所以，这种代码压根就不该出现在程序里。  这个问题，等你对C有了比较深刻的了解再来研究也不迟。

楼主，不要纠结于这种无聊的问题上。 这跟小学生的那种“一边灌水一边排水，什么时候把水灌满”的问题没有什么区别

引用 5 楼 jacksonfan 的回复:VS08输出2,5 i = i++ + ++i; 1、++i，i = 2； 2、i++，i = 3； 3、i++ + ++i，i = （2 + 1）+ 2  对于你这个步骤我是不怎么赞同的 我觉得是i = 1                 ++i   i = 2                i = 2 + 2                i++  i= i+1

未定义行为，各种编译器编译出来的结果不同，导致运行结果不一样，实际使用中，不应该写出这种代码。

自己顶一下，求帮忙，谢谢

才疏学浅没怎么看懂，现在的问题就是  到底是2+2+1 还是1+3   现在就是这两个版本，是不是不同编译器不一样？


Question: C语言读取键盘代码分享

楼主威武霸气

推荐使用NCURSES库。


Question: 统计字符个数

引用 1 楼 user-3 的回复:#include <stdio.h> /* count characters in input; 1st version */ int main() { 	long nc; 	nc = 0; 	while (getchar() != EOF) 		++nc; 	printf("%ld\n", nc); } 谢谢啊，明白了。  引用 2 楼 TJF331311545 的回复:输入还没有结束 按了回车也不等于结束  谢谢啊，现在明白了。  引用 3 楼 robertbo 的回复:getchar()!= EOF, EOF 是终止符，不同的系统终止符不同·· Windows的控制台里面可以通过Ctrl   +   Z来表示终止 Linux/Unix的Shell里面可以通过Ctrl   +   D来表示终止 谢谢啊~

输入还没有结束 按了回车也不等于结束


Question: 求解如何把数组中的unsigned char 转16进制数输出

恩，谢谢，我已经知道怎么做了，是要做为界面控件输出的，用sprintf循环实现。

for(int i = 0; i != 16;i++) printf("%x" ,ivec[i]);


Question: 菜鸟求助关于指示灯的问题

引用 1 楼 shangyu0801 的回复:外部中断进入的后，状态转换的时机的控制问题吧。比如如果下次为全亮，此次必须要执行1HZ的由灭转亮后，再常亮。而不能当前还是灭呢，马上就让灯亮。  +1   从先全灭了  然后在点亮要点亮的！


Question: 1.生成1-99范围内的99个随机数，并删除重复数 2.若要补充齐全1-99位数，标记处补充内容

.生成1-99范围内的99个随机数，并删除重复数 和 .生成1-99范围内的99个不重复的随机数 不是一回事！

洗牌就行了，仅供参考 srand((unsigned)time(0));  // 设置随机种子 int n[99]; // 初始化为1~99的值 for(int i = 0; i != 99; i++) n[i] = i+1;  // 洗牌，打乱顺序 for(int i = 0; i != 99; i++) {     int ntmp = n[i];     int nIndex = rand()%99;     n[i] = n[nIndex];     n[nIndex] = ntmp; }

本质上是1-99的洗牌算法，参考http://blog.csdn.net/microchenhong/article/details/6456625


Question: hdoj1003，很多测试用例都通过了，但还是提示wa，求大神指导一下

如下修改可AC:  #include"stdio.h" int main() //改 main() {   int cases , amount , i , p , q , temp1 , temp2 , max_temp , a[100000] ;   int max , start , end ;   scanf("%d" , &cases) ;   if(cases < 1 || cases > 20)     return ;   for(temp1 = 0 ; temp1 < cases ; temp1++)   {     scanf("%d" , &amount) ;      for(temp2 = 0 ; temp2 < amount ; temp2++)       scanf("%d" , a + temp2) ;      max = a[0] ;     p = 1 ;     q = 1 ;     start = 1 ;     end = 1 ;      for(i = 1 , max_temp = a[0] ; i < amount ; i++) //改 for(i = 0 , max_temp = 0 ; i < amount ; i++)     {       max_temp += a[i] ;       q = i + 1 ;       if(max_temp < a[i]) //加       {         max_temp = a[i] ; //加         p = i + 1;        //加       }       if(max_temp > max)       {         max = max_temp ;         start = p ;         end = q ;       }       /*删       else if(max_temp < 0)       {         max_temp = 0 ;         p = i + 2 ;         q = i + 2 ;       }*/     }       printf("Case %d:\n%d %d %d\n" , temp1 + 1 , max , start , end) ;     if(temp1 < cases - 1)       printf("\n") ;   }    return 0; //加 }

之前做过，贴下代码，a是数组，len是数组长度  void max_sum(int *a, long len) {     long i,p = 0;     int curSum = 0;      int maxSum = -1000;      long start = 0,end = 0;      for(i = 0;i < len;i++)     {         if(curSum < 0)         {             curSum = *(a+i);             p = i ;         }         else             curSum += *(a+i);         if(curSum > maxSum )         {             maxSum = curSum;             start = p;             end = i;         }     }     printf("%d %ld %ld",maxSum,start+1,end+1);  }

这是你的程序输出结果，正确结果应该是-1。

看下面这组测试。


Question: 关于用C语言实现图像处理

就是opencv了， 及其强大的图像处理功能， 还有模式识别， 非常厉害， 我也在学。

参考 MSDN98\SAMPLES\VC98\SDK\GRAPHICS\GDI\SHOWDIB\*.* MSDN98_1.ISO http://pan.baidu.com/s/1dDF41ix,  MSDN98_2.ISO http://pan.baidu.com/s/1bnGo0Vl

参考我的博文 http://blog.csdn.net/turingo/article/details/8131057  引用 楼主 csdnqxh1 的回复:各位大神，请问一下，能不能推荐一些关于“用C语言实现图像处理功能的软件”的资料啊，谢谢谢谢

楼主有兴趣的话可以研究研究 GTK3  这个是C的！

下载研究OpenCV 《学习OpenCV（中文版）》

老师说是只要实现作图以及一些类似翻转，平移等的功能就行，要用纯C编，为什么我随便写了一个小程序在VC里面有错误呢，是不是一定要在turboC里面编啊，但是电脑又没办法装turboC

你好，我是在做毕业论文，原来学过C语言，不过都是一些基础知识，看到这个题目感觉无从着手，所以在找点资料看看，谢谢回答

下载研究OpenCV 《学习OpenCV（中文版）》


Question: float类型不定参数的问题

引用 1 楼 user-1 的回复:因为有个默认的类型提升。float-->double 根据您的提示，我搜到了这编文章，也解决了我的问题。 http://blog.csdn.net/astrotycoon/article/details/8284501

因为有个默认的类型提升。float-->double


Question: getchar 在程序中的用途？？

在这里没用作用纯多余 有和没有都不影响程序正常运行

#include<stdio.h> main() { 	char a[101],l,m; 	while(scanf("%s",a)!=EOF) 		{ 			l=getchar(); 			printf("%d\n",l); 			a[0]-=32; 			printf("%s",a); 			if(l=='\n') 			printf("\n"); 			else 			printf(" "); 		} 			  	m=getch();  	printf("%d",m);  	return 0; }你可以试一下这个程序，至于getchar是一般是10和32，表示换行和空格符，对于getch（）是13，说明返回的是回车符的值，当然，没有这一句，输入流还是在缓冲中， 不影响程序的本次执行

你可以设个变量c=getchar，然后看看c是什么就知道为啥要有了。


Question: 急！求帮忙，又谁做过这几种课程设计~~~

谁帮忙看一下可不可以

#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct stu { 	char sz_Name[20]; 	char sz_ID[11]; 	char sz_Class[10]; 	float r_Score[3]; }student; #define STU_MAXSIZE 60 int i_stuSize; student stu[STU_MAXSIZE]; /*==========显示主菜单=============*/ void Dis_Main_Menu() { 	printf("\n 学生成绩管理系统   \n"); 	printf("-----------------------\n"); 	printf("1:新录入书生成绩       \n"); 	printf("2:修改学生成绩         \n"); 	printf("3：学生成绩查寻        \n"); 	printf("4:平均成绩和排序       \n"); 	printf("5:显示班级成绩单       \n"); 	printf("6:追加学生成绩         \n"); 	printf("0：退出                \n"); 	printf("-----------------------\n"); } /*=============录入学生成绩============*/ void Input_Stu_Information(student stu[]) { 	int i; 	printf("请依次输入学生成绩信息（姓名 学号 班级 数学 语文 化学）:\n"); 	for (i = 0; i<i_stuSize; i++) 	{ 		printf("Student %d:", i + 1); 		scanf_s("%s%s%s", stu[i].sz_Name, stu[i].sz_ID, stu[i].sz_Class); 		scanf_s("%f%f%f", &stu[i].r_Score[0], &stu[i].r_Score[1], &stu[i].r_Score[2]); 	} } /*==============将信息存入scorefile.dat文件===========*/ void Save_File(student stu[]) { 	FILE *fp; 	int i; 	if ((fp = fopen("c:\\scorefile.dat", "wb")) == NULL) 	{ 		printf("Save_File函数打开文件c:\\scorefile.dat!失败，按任意键退出！\n"); 		exit(1); 	} 	for (i = 0; i<i_stuSize; i++) 		if (fwrite(&stu[i], sizeof(student), 1, fp) != 1) 		{ 		printf("Writer file error!\n"); 		exit(1); 		} 	fclose(fp); } /*===============主菜单第一项：新录入成绩==========*/ int Input_Data() { 	printf("\n请输入学生实际人数:"); 	scanf("%d", &i_stuSize); 	Input_Stu_Information(stu); 	Save_File(stu); 	return(i_stuSize); } /*=================学生成绩查询菜单=============*/ void Dis_Search_Menu() { 	printf("\n学生成绩查询       \n"); 	printf("\n-------------------\n"); 	printf("\n   1:按学号查询    \n"); 	printf("\n   2:按科目查询    \n"); 	printf("\n   0:退出          \n"); 	printf("\n-------------------\n"); } /*===============按学号查询===========*/ int Search_ID(char sz_ID[11]) { 	int i; 	for (i = 0; i<i_stuSize; i++) 	{ 		if (!strcmp(sz_ID, stu[i].sz_ID)) 		{ 			printf("姓名\t学号\t班级\t数学\t\t语文\t\t化学\n"); 			printf("--------------------------------------\n"); 			printf("%S\t%s\t%s", stu[i].sz_Name, stu[i].sz_ID, stu[i].sz_Class); 			printf("\t%-8.1f\t%-8.1f\t%-8.1f\n", stu[i].r_Score[0], stu[i].r_Score[1], 				stu[i].r_Score[2]); 			break; 		} 	} 	if (i == i_stuSize)printf("学号输入有误！没有该学生！\n"); 	return(i); } /*=============按科目查询==========*/ void Search_Course(int course) { 	int i; 	switch (course) 	{ 	case 1:printf("\n姓名\t学号\t班级\t数学\n"); break; 	case 2:printf("\n姓名\t学号\t班级\t语文\n"); break; 	case 3:printf("\n姓名\t学号\t班级\t化学\n"); break; 	default:printf("\n课程号错误！\n"); return; 	} 	printf("-------------------------------\n"); 	for (i = 0; i<i_stuSize; i++) 	{ 		printf("%s\t%s\t%s", stu[i].sz_Name, stu[i].sz_ID, stu[i].sz_Class); 		printf("\t%-8.1f\n", stu[i].r_Score[course - 1]); 	} 	printf("---------------------------------------\n"); } /*=================主页第二项：修改学生成绩==============*/ void Modify_Data() { 	int i = 0; 	char s_ID[11]; 	FILE *fp; 	if ((fp = fopen("c:\\scorefile.dat", "wb")) == NULL) 	{ 		printf("Modify_Data函数打开文件c:\\scorefile.dat!失败，按任意键退出!"); 		return; 	} 	printf("请输入要修改的学生学号："); 	scanf("%s", s_ID); 	i = Search_ID(s_ID); 	printf("请按【数学 语文 化学】顺序输入成绩："); 	scanf("%f%f%f", &stu[i].r_Score[0], &stu[i].r_Score[1], &stu[i].r_Score[2]); 	fwrite(&stu[i], sizeof(student), i_stuSize, fp); 	fclose(fp); } /*=============主菜单第三项：学生成绩查询============*/ void Search_Data() { 	int Select, flag = 1; 	int course; 	char s_id[11]; 	while (flag) 	{ 		Dis_Search_Menu(); 		printf("请输入所选查询功能号："); 		scanf("%d", &Select); 		switch (Select) 		{ 		case 1:printf("请输入查询学号:"); 			scanf("%s", s_id); 			Search_ID(s_id); 			break; 		case 2:printf("请输入查询科目号:1 数学，2语文 3化学\n"); 			scanf("%d", &course); 			Search_Course(course); 			break; 		default:printf("输入有错误，重新选择！\n"); 			break; 		} 		if (Select == 0) 			flag = 0; 		else 			flag = 1; 	} } /*===============成绩排序==============*/ void Sort(float average[STU_MAXSIZE]) { 	int i, j, k; 	student stemp; 	float ave; 	for (i = 0; i<i_stuSize - 1; i++) 	{ 		k = i; 		for (j = i; j<i_stuSize; j++) 			if (average[j]<average[k])k = j; 		if (k != i) 		{ 			stemp = stu[i]; 			stu[i] = stu[k]; 			stu[k] = stemp; 			ave = average[i]; 			average[i] = average[k]; 			average[k] = ave; 		} 	} } /*===============主菜单第四项：计算平均成绩和排序=========*/ void Average_Sort() { 	int i; 	float sum, average[STU_MAXSIZE]; 	for (i = 0; i<i_stuSize; i++) 	{ 		sum = stu[i].r_Score[0] + stu[i].r_Score[1] + stu[i].r_Score[2]; 		average[i] = sum / 3; 	} 	Sort(average); 	printf("\n\t\t\t按平均成绩升序先是成绩\n"); 	printf("\t\t\t=========================\n"); 	printf("姓名\t学号\t班级\t数学\t\t语文\t\t化学\t\t平均成绩\n"); 	printf("--------------------------------\n"); 	for (i = 0; i<i_stuSize; i++) 	{ 		printf("%s\t%s\t%s", stu[i].sz_Name, stu[i].sz_ID, stu[i].sz_Class); 		printf("\t%-8.1f\t%-8.1f\t%-8.1f", stu[i].r_Score[0], stu[i].r_Score[1], stu[i].r_Score[2]); 		printf("\t%-8.1f\n", average[i]); 	} 	printf("--------------------------------------------\n"); } /*=================主菜单第五项：显示班级成绩单========*/ void Display_Data() { 	char sz_Class[10]; 	int i = 0; 	printf("情输入班级名称:"); 	scanf("%s", sz_Class); 	printf("\n\t\t\t%s班成绩单\n", sz_Class); 	printf("\t\t\t===============\n"); 	printf("姓名\t学号\t数学\t\t语文\t\t化学\n"); 	printf("-----------------------------------------\n"); 	for (; i<i_stuSize; i++) 	{ 		if (!strcmp(sz_Class, stu[i].sz_Class)) 		{ 			printf("%s\t%s", stu[i].sz_Name, stu[i].sz_ID); 			printf("\t%-8.1f\t%-8.1f\t%-8.1f\n", stu[i].r_Score[0], stu[i].r_Score[1], stu[i].r_Score[2]); 		} 	} 	printf("---------------------------------------\n"); } /*===================主菜单第六项：追加学生成绩====================*/ void Insert_Data() { 	student st; 	FILE *fp; 	printf("轻按下列顺序输入要插入学生的成绩（姓名 学号 班级 数学 语文 化学）:\n"); 	scanf("%s%s%s", st.sz_Name, st.sz_ID, st.sz_Class); 	scanf("%f%f%f", &st.r_Score[0], &st.r_Score[1], &st.r_Score[2]); 	if ((fp = fopen("c:\\scorefile.dat", "ab")) == NULL) 	{ 		printf("Insert_stu函数打开文件scorefile.dat!失败，按任意键退出!"); 		return; 	} 	fwrite(&st, sizeof(student), 1, fp); 	fclose(fp); } /*==============初始化数组函数==========*/ int Init_Arr() { 	FILE *fp; 	int i = 0; 	if ((fp = fopen("c:\\scorefile.dat", "rb")) == NULL) 	{ 		printf("Init_Arr函数打开文件c:\\scorefile.dat!失败，按任意键退出！"); 		return(0); 	} 	while (!feof(fp)) 	{ 		fread(&stu[i], sizeof(student), 1, fp); 		i++; 	} 	i_stuSize = i - 1; 	fclose(fp); 	return(1); } /*==========主程序=======*/ void main() { 	int iSelectNum, flag = 1; 	while (flag) 	{ 		Dis_Main_Menu(); 		printf("情输入所选功能号0-6:"); 		scanf("%d", &iSelectNum); 		switch (iSelectNum) 		{ 		case 1:Input_Data(); 			break; 		case 2: 			if (Init_Arr())Modify_Data(); 			break; 		case 3: 			if (Init_Arr()) Search_Data(); 			break; 		case 4: 			if (Init_Arr()) Average_Sort(); 			break; 		case 5: 			if (Init_Arr()) Display_Data(); 			break; 		case 6: 			if (Init_Arr()) Insert_Data(); 			break; 		default:printf("输入有误，重新输入!\n"); 			break; 		} 		if (iSelectNum == 0) 			flag = 0; 		else 			flag = 1; 	} }

引用 9 楼 xihu1364 的回复:[quote=引用 7 楼 qq_25043793 的回复:] [quote=引用 3 楼 xihu1364 的回复:] 楼猪想干嘛？   我可以考虑帮你做，只要价格合适 ==多少是合适，，，，只用C语言的[/quote]  还以为你帮学校做呢，自己的课程设计，那就算了吧  自己动手，丰衣足食[/quote] 怎么可能啦

引用 7 楼 qq_25043793 的回复:[quote=引用 3 楼 xihu1364 的回复:] 楼猪想干嘛？   我可以考虑帮你做，只要价格合适 ==多少是合适，，，，只用C语言的[/quote]  还以为你帮学校做呢，自己的课程设计，那就算了吧  自己动手，丰衣足食

引用 4 楼 zxh707wk 的回复:每个课设做一个做一个思维导图，把模块分清，数据结构设计好，然后设计算法，再编写代码实现。tai 太渣了，，，，只能抄网上的码

引用 3 楼 xihu1364 的回复:楼猪想干嘛？   我可以考虑帮你做，只要价格合适 ==多少是合适，，，，只用C语言的

大一的啥也不会，百度的话，又有好多错误，，改有的时候都不会改。。。。

比如这个

楼猪想干嘛？   我可以考虑帮你做，只要价格合适

网上有好多这个方面的源码

求助啊


Question: 魔术师猜数问题

上面ans>1000应该为 ans>=1000

引用 1 楼 user-3 的回复:不就是 input = 122a + 212b + 221c，实在不行穷举法算出a，b，c 请问穷举怎么编代码，基本功不是很扎实。。。

#include <stdio.h>  //      sum              ans     = 222* k // 122a+212b+221c + 100a +10b+10 = 222*(a+b+c) int guess(int sum) {     int k = (sum+221)/222;     int ans =k *222- sum;     for(;k<9*3+1;k++,ans+=222){         if(ans>1000) return 0;         if(ans<100) continue;         if(ans/100+ans%100/10+ans%10 == k) return ans;     }     return 0; }  int main() {     int n;     while(1)     {         scanf("%d",&n);         if(!n) break;         n = guess(n);         n ? printf("%d\n",n) : puts("Error.");     }     return 0; }

和为 122a+212b+221c， 如果加上原数 100a+10b+10c，就刚好是222(a+b+c),可以此处想办法去解，然后穷举一下满足这个条件的数

穷举。。。 。


Question: 定义一个求两个整数最大值的函数max(int a,int b)，从键盘上输入4个整数u,v,w,x,通过调用max(int a,int b)求出它们的最大数并输

++  引用 1 楼 user-3 的回复: #include <stdio.h>  int max(int a,int b) { 	return a > b?a:b; }  void main() { 	int a,b,c,d; 	int r = 0; 	scanf("%d %d %d %d",&a,&b,&c,&d); 	r = max(max(max(a,b),c),d); 	printf("%d",r); }

int MyMax(int _a ,int _b) { 	return ((_a > _b)?_a:_b); }   int main() { 	int a,b,c,d; 	scanf("%d %d %d %d" ,&a,&b,&c,&d); 	int k = MyMax(a,b); 	int h = MyMax(c,d); 	int j = MyMax(k,h); 	printf("最大的数是%d\n" ,j); }


Question: 为什么下面这段代码debug时一切正常，运行的时候就崩掉。

引用 28 楼 zhao4zhong1 的回复:13楼最后应选第二行。 纠正：最后应点按钮“中断”进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。

13楼最后应选第二行。

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

学习了，谢谢各位大神了。

还是sizeof好

引用 23 楼 zhao4zhong1 的回复:8191+1=8192=默认tcp缓冲区大小的两倍。  strncpy, wcsncpy, _mbsncpy Copy characters of one string to another.  char *strncpy( char *strDest, const char *strSource, size_t count );  wchar_t *wcsncpy( wchar_t *strDest, const wchar_t *strSource, size_t count );  unsigned char *_mbsncpy( unsigned char *strDest, const unsigned char *strSource, size_t count );  Routine Required Header Compatibility  strncpy <string.h> ANSI, Win 95, Win NT  wcsncpy <string.h> or <wchar.h> ANSI, Win 95, Win NT  _mbsncpy <mbstring.h> Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns strDest. No return value is reserved to indicate an error.  Parameters  strDest  Destination string  strSource  Source string  count  Number of characters to be copied  Remarks  The strncpy function copies the initial count characters of strSource to strDest and returns strDest. If count is less than or equal to the length of strSource, a null character is not appended automatically to the copied string. If count is greater than the length of strSource, the destination string is padded with null characters up to length count. The behavior of strncpy is undefined if the source and destination strings overlap.  wcsncpy and _mbsncpy are wide-character and multibyte-character versions of strncpy. The arguments and return value of wcsncpy and _mbsncpy vary accordingly. These three functions behave identically otherwise.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tcsncpy strncpy _mbsnbcpy  wcsncpy     Example  /* STRNCPY.C */  #include <string.h> #include <stdio.h>  void main( void ) {    char string[100] = "Cats are nice usually";    printf ( "Before: %s\n", string );    strncpy( string, "Dogs", 4 );    strncpy( string + 9, "mean", 4 );    printf ( "After:  %s\n", string ); }   Output  Before: Cats are nice usually After:  Dogs are mean usually   String Manipulation Routines  See Also   _mbsnbcpy, strcat, strcmp, strcpy, strncat, strncmp, _strnicmp, strrchr, _strset, strspn 大概明白了，谢谢！ 是不是strncpy(ptchar, item,L-1);ptchar[L-1]=0这种表达方式是为了防止长度大于8191的时候才设计的？ 当长度小于等于8191的时候它和strncpy(ptchar, item,L);等价。 另外请您看一下在13楼我问您的问题，谢谢！

引用 21 楼 zhao4zhong1 的回复:[quote=引用 20 楼 qq_21909183 的回复:] [quote=引用 19 楼 zhao4zhong1 的回复:] [quote=引用 2 楼 user-5 的回复:] char *StringCopy(const char *item) { 	char *ptchar = (char *)malloc(strlen(item)+1);//看看这句吧 	strcpy(ptchar, item); 	return ptchar; } char *StringCopy(const char *item) { int L=__min(8191,strlen(item))+1; char *ptchar = (char *)malloc(L);//看看这句吧 strncpy(ptchar, item,L-1);ptchar[L-1]=0; return ptchar; }[/quote] 您的程序我有两点不太明白： 一是__min里的8191是什么意思 二是为什么不直接用strncpy(ptchar, item,L); 请您指教，谢谢！[/quote] 如果strlen(item)比8191大，只取item前8191个字节，多出来的忽略。 strncpy在处理刚好L-1个字节时，后面不加'\0',为确保ptchar的末尾有'\0',ptchar[L-1]=0;  __min Returns the smaller of two values.  type __min( type a, type b );  Routine Required Header Compatibility  __min <stdlib.h> Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  The smaller of the two arguments  Parameters  type  Any numeric data type  a, b  Values of any numeric type to be compared  Remarks  The __min macro compares two values and returns the value of the smaller one. The arguments can be of any numeric data type, signed or unsigned. Both arguments and the return value must be of the same data type.  Example  /* MINMAX.C */  #include <stdlib.h> #include <stdio.h>  void main( void ) {    int a = 10;    int b = 21;     printf( "The larger of %d and %d is %d\n",  a, b, __max( a, b ) );    printf( "The smaller of %d and %d is %d\n", a, b, __min( a, b ) ); }   Output  The larger of 10 and 21 is 21 The smaller of 10 and 21 is 10   Floating-Point Support Routines  See Also   __max [/quote] 8191是某个具有特殊意义的值吗？ 为什么不是8192,8193？ 当item的长度不超过8191的时候，L正好是字符串长度加一，这时候用strncpy(ptchar, item,L);的话不是正好可以将结尾的\0也复制进去么，为什么还要分开处理？

引用 20 楼 qq_21909183 的回复:[quote=引用 19 楼 zhao4zhong1 的回复:] [quote=引用 2 楼 user-5 的回复:] char *StringCopy(const char *item) { 	char *ptchar = (char *)malloc(strlen(item)+1);//看看这句吧 	strcpy(ptchar, item); 	return ptchar; } char *StringCopy(const char *item) { int L=__min(8191,strlen(item))+1; char *ptchar = (char *)malloc(L);//看看这句吧 strncpy(ptchar, item,L-1);ptchar[L-1]=0; return ptchar; }[/quote] 您的程序我有两点不太明白： 一是__min里的8191是什么意思 二是为什么不直接用strncpy(ptchar, item,L); 请您指教，谢谢！[/quote] 如果strlen(item)比8191大，只取item前8191个字节，多出来的忽略。 strncpy在处理刚好L-1个字节时，后面不加'\0',为确保ptchar的末尾有'\0',ptchar[L-1]=0;  __min Returns the smaller of two values.  type __min( type a, type b );  Routine Required Header Compatibility  __min <stdlib.h> Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  The smaller of the two arguments  Parameters  type  Any numeric data type  a, b  Values of any numeric type to be compared  Remarks  The __min macro compares two values and returns the value of the smaller one. The arguments can be of any numeric data type, signed or unsigned. Both arguments and the return value must be of the same data type.  Example  /* MINMAX.C */  #include <stdlib.h> #include <stdio.h>  void main( void ) {    int a = 10;    int b = 21;     printf( "The larger of %d and %d is %d\n",  a, b, __max( a, b ) );    printf( "The smaller of %d and %d is %d\n", a, b, __min( a, b ) ); }   Output  The larger of 10 and 21 is 21 The smaller of 10 and 21 is 10   Floating-Point Support Routines  See Also   __max

引用 19 楼 zhao4zhong1 的回复:[quote=引用 2 楼 user-5 的回复:] char *StringCopy(const char *item) { 	char *ptchar = (char *)malloc(strlen(item)+1);//看看这句吧 	strcpy(ptchar, item); 	return ptchar; } char *StringCopy(const char *item) { int L=__min(8191,strlen(item))+1; char *ptchar = (char *)malloc(L);//看看这句吧 strncpy(ptchar, item,L-1);ptchar[L-1]=0; return ptchar; }[/quote] 您的程序我有两点不太明白： 一是__min里的8191是什么意思 二是为什么不直接用strncpy(ptchar, item,L); 请您指教，谢谢！

引用 2 楼 user-5 的回复:char *StringCopy(const char *item) { 	char *ptchar = (char *)malloc(strlen(item)+1);//看看这句吧 	strcpy(ptchar, item); 	return ptchar; } char *StringCopy(const char *item) { int L=__min(8191,strlen(item))+1; char *ptchar = (char *)malloc(L);//看看这句吧 strncpy(ptchar, item,L-1);ptchar[L-1]=0; return ptchar; }

一看到这代码我立刻就知道我不会

引用 16 楼 user-5 的回复:你可以构造string的时候传递的字符串长点看看会不会调试的时候奔溃吧 已崩，谢谢提醒... 果然不崩是个巧合

你可以构造string的时候传递的字符串长点看看会不会调试的时候奔溃吧

引用 14 楼 user-5 的回复:这个不好说，只是调试时运气好，没破坏堆结构或者调试的时候有些额外的内存分配没有导致问题的产生 但这样的话有点奇怪，因为调试了很多次都没问题，运行的时候是次次都会崩掉，是调试和运行的原理不同？

引用 3 楼 zhao4zhong1 的回复:崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。 我不太明白调试方面的技巧，请您指教： 我开始的程序运行的时候会出现 几秒钟后变成 我点击调试会出现 我选择了第一个 就会跳出下面的界面 然后我就不知道怎么操作了，还请您说明一下，谢谢！

引用 11 楼 user-5 的回复:[quote=引用 10 楼 qq_21909183 的回复:] [quote=引用 8 楼 qq_21909183 的回复:] [quote=引用 2 楼 user-5 的回复:] char *StringCopy(const char *item) { 	char *ptchar = (char *)malloc(strlen(item)+1);//看看这句吧 	strcpy(ptchar, item); 	return ptchar; } 谢谢！ 改动这一句之后就可以了，不过这是为什么呢？ 还麻烦您解释一下，谢谢！[/quote] 是不是因为sizeof得到的是指针的大小...[/quote]是的[/quote] 那为什么在调试的时候这个错误不会引起程序崩溃呢...

引用 10 楼 qq_21909183 的回复:[quote=引用 8 楼 qq_21909183 的回复:] [quote=引用 2 楼 user-5 的回复:] char *StringCopy(const char *item) { 	char *ptchar = (char *)malloc(strlen(item)+1);//看看这句吧 	strcpy(ptchar, item); 	return ptchar; } 谢谢！ 改动这一句之后就可以了，不过这是为什么呢？ 还麻烦您解释一下，谢谢！[/quote] 是不是因为sizeof得到的是指针的大小...[/quote]是的

引用 8 楼 qq_21909183 的回复:[quote=引用 2 楼 user-5 的回复:] char *StringCopy(const char *item) { 	char *ptchar = (char *)malloc(strlen(item)+1);//看看这句吧 	strcpy(ptchar, item); 	return ptchar; } 谢谢！ 改动这一句之后就可以了，不过这是为什么呢？ 还麻烦您解释一下，谢谢！[/quote] 是不是因为sizeof得到的是指针的大小...


Question: 暖橘子程序

橘子暖透了，CPU烧坏了。

引用 8 楼 CharlesSimonyi 的回复:光CPU发热还不够，想办法把GPU调用起来

等我有时间了贴出我的暖菠萝程序

你这么吊。cpu愿意吗

都是大神啊~

光CPU发热还不够，想办法把GPU调用起来

引用 3 楼 u013163178 的回复:#include<unistd.h> #include<sys/types.h> int main() { 	for(;;) 	{ 		fork(); 	} 	return 0; } 你这不得把系统搞晕了啊。。。

引用 5 楼 luoxuechengbing 的回复:  我也来一发~！

我也来一发~！

LZ这是要干啥？？？贴出来程序的一部分，我们也没法体验暖橘子呀~~~~

放开那个橘子,给我吃


Question: 1.生成1-99范围内的99个随机数，并删除重复数 2.若要补充齐全1-99位数，标记处补充内容

.生成1-99范围内的99个随机数，并删除重复数 和 .生成1-99范围内的99个不重复的随机数 不是一回事！

第二个没弄明白意思

洗牌算法，不会重复，仅供参考 srand((unsigned)time(0));  // 设置随机种子 int n[99]; // 初始化为1~99的值 for(int i = 0; i != 99; i++) n[i] = i+1;  // 洗牌，打乱顺序 for(int i = 0; i != 99; i++) {     int ntmp = n[i];     int nIndex = rand()%99;     n[i] = n[nIndex];     n[nIndex] = ntmp; }

本质上是1-99的洗牌算法，参考http://blog.csdn.net/microchenhong/article/details/6456625

1比较好实现，2看不懂意思，说说下

仅供参考//文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; }

1很简单，2是什么意思？

第2个是在第一个基础上的意思


用整数保存电话号码是不可取的。

哥 temp 指针你给开空间了么？ 就malloc 或指向其它数据了么？

++  引用 1 楼 user-5 的回复:是%I64d，大写的i，不是小写的L

引用 1 楼 user-5 的回复:是%I64d，大写的i，不是小写的L  +1 scanf("%I64d",&phone );

是%I64d，大写的i，不是小写的L


Question: 程序与操作系统的问题，望高手赐教

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

引用 楼主 cumtwyc 的回复:一个程序调入内存开始执行时，它的堆的大小还有栈的大小是怎么确定的？ 还有既然虚拟存储空间可以很大，怎么感觉一个简单递归就经常出现堆栈溢出等问题呢？ 比如一个最简单的程序只有一条输出语句，操作系统还会为它分配堆空间吗？  堆大小是运行时才确定的，不然也不用判断malloc的返回值了。  栈大小虽然最终体现在运行上，不过从源码级别也能够判断，大小和源码息息相关。 递归搞挂了肯定是没归回来，查查代码吧。

《程序员的自我修养——链接、装载与库》

引用 6 楼 C0909 的回复:

不好意思 刚配图配错了

栈是有限制大小的,好像是2M左右,具体忘了 楼主可以试试 创建一个数组  VS会报栈溢出的

回答的都很好啊

不同平台栈的大小可能不一样！ Linux下，THREAD_SIZE_ORDER指定了栈的大小，通过alloc_thread_info进行分配。目前kernel-3.16源码THREAD_SIZE_ORDER值依旧为1，即进程分配的栈依旧是一页！至于页的大小有OS指定，可以是4k，1M等等

/STACK   (Stack Allocations) Home |  Overview |  How Do I |  Linker Options  The Stack Allocations (/STACK:reserve[,commit]) option sets the size of the stack in bytes.   To find this option in the development environment, click Settings on the Project menu. Then click the Link tab, and click Output in the Category box. The Reserve text box (or in the reserve argument on the command line) specifies the total stack allocation in virtual memory. The default stack size is 1 MB. The linker rounds up the specified value to the nearest 4 bytes.  The optional value specified in the Commit text box (or in the commit argument on the command line) is subject to interpretation by the operating system. In Windows NT, it specifies the amount of physical memory to allocate at a time. Committed virtual memory causes space to be reserved in the paging file. A higher commit value saves time when the application needs more stack space, but increases the memory requirements and possibly the startup time.  Specify the reserve and commit values in decimal or C-language notation.  Another way to set the size of the stack is with the STACKSIZE statement in a module-definition (.DEF) file. STACKSIZE overrides the Stack Allocations (/STACK) option if both are specified. You can change the stack after the .EXE file is built by using the EDITBIN tool.

栈的大小一般都是一页的样子，而且不能扩充，由OS指定，而堆则大的多。理论上，以32位系统的1:3比例划分，4G可用内存，有3G都可以作为堆来分配。

我看书写的是栈一般是向低字节分配的，一般有2M，也不是肯定的，还和系统有关。堆是向高字节分配的，所以理论来讲没有空间限制（还有硬盘空间呢！这个也可以拿来用）

栈有限，递归不结束肯定溢出。 输出语句会用到c库或c++库，库会申请堆空间

在Windows系统上程序运行起来后栈大小默认是1MB，当然这个值可以在编译程序的时候通过链接器命令来修改。 堆上内存空间需要程序向操作系统申请，比如malloc或new，不申请就不分配。


Question: c语言版数据结构图的一些基本操作函数如下，有三个地方不了解，请各位帮帮忙？

1. 使用函数指针，可以避免很多问题，在VisitFunc调用的地方，完全可控。现在是直接printf，将来如果是写入文件呢，只需要修改那个print函数就可以了 2. 不是很理解你问的意思 3. 在CreateGraph中传入的G是指针，而在调用LocalVex需要的参数实际是传值。因此在函数里调用的时候使用取值运算符*，目的是将G所指向的值传递给LocalVex

代码排版太烂，无意看下去  int i=0;

#include"string.h"  #include"stdio.h"  #include"stdlib.h"  typedef int InfoType;  #define MAX_NAME 3  typedef char VertexType[MAX_NAME]; #define MAX_VERTEX_NUM 20  typedef enum{DG,DN,AG,AN}GraphKind;   typedef struct ArcNode  {  	int adjvex;  	struct ArcNode *nextarc;  	InfoType *info; }ArcNode;  typedef struct  {  	VertexType data;  	ArcNode *firstarc; }VNode,AdjList[MAX_VERTEX_NUM];   typedef struct  {  	AdjList vertices;  	int vexnum,arcnum;  	int kind; }ALGraph;   int LocateVex(ALGraph G,VertexType u)  { 	int i;  	for(i=0;i<G.vexnum;++i)  		if(strcmp(u,G.vertices[i].data)==0)  			return i;  	return -1;  }  void CreateGraph(ALGraph *G)  {  	int i,j,k;  	int w;  	VertexType va,vb;  	ArcNode *p;   	scanf("%d",&(*G).kind);   	scanf("%d%d",&(*G).vexnum,&(*G).arcnum);  	for(i=0;i<(*G).vexnum;++i)  	{  		scanf("%s",(*G).vertices[i].data);  		(*G).vertices[i].firstarc=NULL;  	}   	for(k=0;k<(*G).arcnum;++k)  	{  		if((*G).kind==1||(*G).kind==3)  		scanf("%d%s%s",&w,va,vb);  		else   		scanf("%s%s",va,vb);  		i=LocateVex(*G,va);  		j=LocateVex(*G,vb);   		p=(ArcNode*)malloc(sizeof(ArcNode));  		p->adjvex=j;  		if((*G).kind==1||(*G).kind==3)  		{  			p->info=(int *)malloc(sizeof(int));  			*(p->info)=w;  		}  		else  		p->info=NULL;  		p->nextarc=(*G).vertices[i].firstarc; 		(*G).vertices[i].firstarc=p;  		if((*G).kind>=2)  		{  			p=(ArcNode*)malloc(sizeof(ArcNode));  			p->adjvex=i;  			if((*G).kind==3)  			{  				p->info=(int*)malloc(sizeof(int));  				*(p->info)=w;  			}  			else  			p->info=NULL;  			p->nextarc=(*G).vertices[j].firstarc; 			(*G).vertices[j].firstarc=p;  		}  	}	  }   VertexType* GetVex(ALGraph G,int v)  {  	if(v>=G.vexnum||v<0)  		exit(0);  	return &G.vertices[v].data;  }   int FirstAdjVex(ALGraph G,VertexType v)  { 	ArcNode *p;  	int v1;  	v1=LocateVex(G,v); 	p=G.vertices[v1].firstarc;  	if(p)  		return p->adjvex;  	else  		return -1;  }   int NextAdjVex(ALGraph G,VertexType v,VertexType w)  {  	ArcNode *p;  	int v1,w1;  	v1=LocateVex(G,v);  	w1=LocateVex(G,w); 	p=G.vertices[v1].firstarc;  	while(p&&p->adjvex!=w1)  		p=p->nextarc;  	if(!p||!p->nextarc)  		return -1;  	else 		return p->nextarc->adjvex; }  int visited[MAX_VERTEX_NUM]; void(*VisitFunc)(char* v);  void DFS(ALGraph G,int v)  {  	int w; 	visited[v]=1; 	VisitFunc(G.vertices[v].data); 	for(w=FirstAdjVex(G,G.vertices[v].data);w!=-1;w=NextAdjVex(G,G.vertices[v].data,G.vertices[w].data)) 		if(!visited[w])           DFS(G,w);  }  void DFSTraverse(ALGraph G,void(*print)(char*))   {  	int i;     VisitFunc=print; 	for(i=0;i<G.vexnum;i++) 		visited[i]=0; 	for(i=0;i<G.vexnum;i++) 		if(!visited[i]) 			DFS(G,i); 	printf("\n");  }   void print(char *i)  {  	printf("%s ",i);  }   int main()  {  	ALGraph g;  	CreateGraph(&g);  	DFSTraverse(g,print);  	return 1; }

C/C++ code ? 1 2 3 4 5 6 7 8 9 10 11 void DFSTraverse(ALGraph G,void(*print)(char*))   {      int i;     VisitFunc=print;     for(i=0;i<G.vexnum;i++)         visited[i]=0;     for(i=0;i<G.vexnum;i++)         if(!visited[i])             DFS(G,i);     printf("\n");  }   1、楼主的DFSTraverse函数的第二个参数在函数体没有用到，可以删掉。

同排版太烂。


Question: C语言, 数组sizeof的问题, 懂的人, 一分钟搞定, 求帮忙解惑一下

结果是4，也许是你看错结果了吧。

2楼是对的，你的编译器有问题。

引用 1 楼 kino_chen 的回复:a是数组地址，&a也是数组地址，编译器认为他们的类型是一样的，所以两者的sizeof输出是一样的。以上纯属自认为  我用的是VC6.0， 是编译器问题,


Question: 用long long 定义为什么会出错

C++98/03标准不支持 long long类型，C99标准支持long long类型的，后来C++11 又将 long long类型吸收进来了，新版的Visual Studi 支持long long类型了。

用11位整数保存电话号码是不可取的。

用__int64 ，输出时写scanf("%I64d",&temp.phone );

你直接用double类型就可以了，%.0f输出

VC里好像没有long long类型！long long最早由GCC扩展出来的，后来被纳入标准的；vc6.0比较早应该不支持此类型。新的VS估计支持。LZ可验证下

是%I64d，大写的i，不是小写的L

我用了_64int，用scanf("%l64d",&temp.phone );这个进行输入，调试的时候发现根本就没有录入进去，怎么办


Question: 二维数组列排序，代码测试总有问题，总有样例会出错，，求大神指导问题在哪？万分感谢

没有很多人有那么多时间。自己慢慢调试。顺便说一下你的排版  #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #include "oj.h"  // 功能：排列一个m行n列 大小的数组 // 输入： int * pArray 指向数组第一个元素的指针,m为行数， n为列数 ，请按第i列排列 // 输出：按第i, i+1, ..., n列优先级排序完成后的数组放到入参指定的地址中	(i的取值范围 1 - n)    void ArrCpy(int A[], int B[], int len); bool Arr1BiggerThanArr2(int *Arr1, int *Arr2, int len, int i);  void RangeArray(int * pArray, unsigned int  m, unsigned int  n,unsigned int  i) {	 unsigned int p,j; int Tmp[100] = {0};  if(NULL == pArray) return;  for(p = 1; p < m; p++)    // 插入排序法 { ArrCpy(Tmp, &pArray[p*n], n); for(j = p; j > 0 && Arr1BiggerThanArr2(&pArray[(j-1)*n], Tmp, n, i); j--) { ArrCpy(&pArray[j*n],&pArray[(j-1)*n],n); } ArrCpy(&pArray[j*n],Tmp,n); }  }  void ArrCpy(int *A, int *B, int len) { int i; for(i = 0; i < len; i++ ) { A[i] = B[i]; } }  //  判断Arr1从第i列开始是否大于Arr2 bool Arr1BiggerThanArr2(int *Arr1, int *Arr2, int len, int i) { int j; int EqCount = 0;  for(j = i-1; j < len; j++) { if(Arr1[j] < Arr2[j]) return false; else if(Arr1[j] == Arr2[j]) EqCount++; }  if(EqCount == (len+1-i)) return false;  return true; }

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。  崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处，看不懂时双击下一行，直到能看懂为止。


Question: 求助这是怎么回事，请问代码是否有错，（素数判断，原创），百度上查不到跟我一样的

而且没写跳出循环。。。

我改一下，就是判断那你写错了，而且写弄跳出循环 #include<stdio.h> #include<Windows.h> int main() { 	long int a;//8位及以下 	long int d; 	printf("请输入一个正整数,如果不是素数会显示，如果是素数那么会发生/错误/提示，最大八位1不是素数，请不要输入1\n"); 	scanf_s("%d",&a);//输入 	d=a+2-3;//a-1 	while(1) 	{ 		if(a%d==0&&d!=1&&d<a)//判断 		{ 			printf("这不是素数\n");//a都能被d整除了，它就不是素数了啊 			break;  		} 		if(d==1) 		{ 			printf("这是素数\n");//d=1，它就是素数了啊 			break;  		} 		//else//如果不是 			   d--;//d一直减，每次都循环，直到除开，如果没除开那就不是素数 			 	} 	system("pause"); 	return 0; }

你不加花括号，编译能通过？第一个if之后两条语句加花括号。亲，再说，你这个算法本身都有问题，素数你都没搞懂，除1和本身之外没有约数才是素数，你搞反了。。。

printf,d--,是不是应该加大括号

if(a%d==0&&d!=1&&d<a)//判断             printf("这是素数\n");             d--;//d一直减，每次都循环，直到除开，如果没除开那就不是素数         else//如果不是         printf("这不是素数");  这语法不死吗？

帮忙回答一下，谢谢


Question: 模拟语言语法分析器，这要怎么做啊，各位帮帮忙，谢了

看龙书，半年后，希望楼主有小成。

你的简单错误指的后面列的那些错误，倒简单了，栈数据结构就能解决。如果简单错误涉及C类型，语法，语义错误。那就大了去喽！

还可以参考Tiny C Compiler

仅供参考#include<stdio.h> #include<malloc.h> #include<string.h> #define STACK_INIT_SIZE 10 #define STACK_GROW_SIZE 5 #define ELEMTYPE char #define OK 1 #define ERROR 0 typedef struct { /*建立一个栈的首结点*/     ELEMTYPE * base;     ELEMTYPE * top;     int stacksize; } SpStack; int InitStack(SpStack *s) { /*建立空的栈并返回首地址*/     s->base=((ELEMTYPE*)malloc(STACK_INIT_SIZE*sizeof(ELEMTYPE)));     if (!s->base) return ERROR;     s->top=s->base;     s->stacksize=STACK_INIT_SIZE;     return OK; } int StackEmpty(SpStack *s) { /*判断栈是否为空*/     if (s->top==s->base) return OK;     else                 return ERROR; } int Push(SpStack *s,ELEMTYPE e) { /*往栈顶插入元素即进栈*/     if (s->top-s->base>=s->stacksize) { /*判断是否栈满*/         s->base=((ELEMTYPE*)realloc(s->base,(s->stacksize+STACK_GROW_SIZE)*sizeof(ELEMTYPE)));         if (!s->base) return ERROR;         s->stacksize+=STACK_GROW_SIZE;         s->top=s->base+s->stacksize;     }     *s->top++=e;     return OK; } int Pop(SpStack *s,ELEMTYPE *e) { /*让栈顶元素依次输出即出栈*/     if (StackEmpty(s)) return ERROR;     *e=*(--s->top);     return OK; } int Comp(ELEMTYPE a,ELEMTYPE b) {     if ((a=='('&&b!=')')       ||(a=='['&&b!=']')       ||(a=='{'&&b!='}')) {         return ERROR;     } else return OK; } int Count(SpStack *s) {     ELEMTYPE e[STACK_INIT_SIZE*2];     ELEMTYPE e1;     int i;      InitStack(s);     fgets(e,STACK_INIT_SIZE*2,stdin);     if ('\n'==e[strlen(e)-1]) e[strlen(e)-1]=0;     printf("%s\n",e);     for (i=0;e[i]!='\0';i++) {         switch (e[i]) {         case '(':         case '[':         case '{':             Push(s,e[i]);             break;         case ')':         case ']':         case '}':             if (StackEmpty(s)) {                 printf("%*s↖右括号多余\n",i+1,"");                 return(ERROR);             } else Pop(s,&e1);             if (!Comp(e1,e[i])) {                 printf("%*s↖左右匹配出错\n",i+1,"");                 return(ERROR);             }         }     }     if (!StackEmpty(s)) {         printf("%*s↖左括号多余\n",i,"");         return(ERROR);     } else {         printf("匹配正确\n");         return(OK);     } } void main() {     SpStack s;     Count(&s);     free(s.base); }

lex/yacc可以检测词法文法，再依据错误内容定位高亮行就可以。

汗，这个任务，恐怕一周都搞不完的东西啊。 楼主就糊弄糊弄就行啦。


Question: 实现库函数strncpy

C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\strncpy.c /*** *strncpy.c - copy at most n characters of string * *       Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *       defines strncpy() - copy at most n characters of string * *******************************************************************************/  #include <cruntime.h> #include <string.h>  /*** *char *strncpy(dest, source, count) - copy at most n characters * *Purpose: *       Copies count characters from the source string to the *       destination.  If count is less than the length of source, *       NO NULL CHARACTER is put onto the end of the copied string. *       If count is greater than the length of sources, dest is padded *       with null characters to length count. * * *Entry: *       char *dest - pointer to destination *       char *source - source string for copy *       unsigned count - max number of characters to copy * *Exit: *       returns dest * *Exceptions: * *******************************************************************************/  char * __cdecl strncpy (         char * dest,         const char * source,         size_t count         ) {         char *start = dest;          while (count && (*dest++ = *source++))    /* copy string */                 count--;          if (count)                              /* pad out with zeroes */                 while (--count)                         *dest++ = '\0';          return(start); }

楼主看了你的代码，你在用*tmp++  当执行n次后tmp早已不是s的初始地址，反回tmp，在去解引地址会出现不可预料的事

#include<stdio.h> #include<stdlib.h> #include<string.h>  char * my_strncpy(char *buffer, const char *targe, int n) { 	if(buffer == NULL) 	{ 		fprintf(stderr,"buffer is a nunn pointer!\n"); 		return buffer; 	} 	int i; 	for( i = 0; i < n && targe != NULL; ++i) 	{ 		buffer[i] = targe[i]; 	} 	buffer[i] = '\0'; 	return buffer; }  int main(int argv, char ** argc) { 	char buffer[100]; 	const char *p = "Hello World"; 	printf("%s\n",my_strncpy(buffer,p,20));  	exit(EXIT_FAILURE);  }

char *s = "hello world!"; char *t = "boys"; 你这里定义的是字符串串常量,处于常量去,是不可以写的,即使i可以写,你也没有给buffer啊, 在一个问题定义h指针h常量应该是 const char *s = "hello world!";  const  char *t = "boys";

看看库函数源码 /* Copyright (C) 1993-2014 Free Software Foundation, Inc.    This file is part of the GNU C Library.     The GNU C Library is free software; you can redistribute it and/or    modify it under the terms of the GNU Lesser General Public    License as published by the Free Software Foundation; either    version 2.1 of the License, or (at your option) any later version.     The GNU C Library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Lesser General Public License for more details.     You should have received a copy of the GNU Lesser General Public    License along with the GNU C Library; if not, see    <http://www.gnu.org/licenses/>.  */  /* This is almost copied from strncpy.c, written by Torbjorn Granlund.  */  #ifdef HAVE_CONFIG_H # include <config.h> #endif  #ifdef _LIBC # include <string.h> #else # include <sys/types.h> #endif  #ifndef STPNCPY # ifdef weak_alias #  define STPNCPY	__stpncpy weak_alias (__stpncpy, stpncpy) # else #  define STPNCPY	stpncpy # endif #endif  /* Copy no more than N characters of SRC to DEST, returning the address of    the terminating '\0' in DEST, if any, or else DEST + N.  */ char * STPNCPY (char *dest, const char *src, size_t n) {   char c;   char *s = dest;    if (n >= 4)     {       size_t n4 = n >> 2;        for (;;) 	{ 	  c = *src++; 	  *dest++ = c; 	  if (c == '\0') 	    break; 	  c = *src++; 	  *dest++ = c; 	  if (c == '\0') 	    break; 	  c = *src++; 	  *dest++ = c; 	  if (c == '\0') 	    break; 	  c = *src++; 	  *dest++ = c; 	  if (c == '\0') 	    break; 	  if (--n4 == 0) 	    goto last_chars; 	}       n -= dest - s;       goto zero_fill;     }   last_chars:   n &= 3;   if (n == 0)     return dest;    for (;;)     {       c = *src++;       --n;       *dest++ = c;       if (c == '\0') 	break;       if (n == 0) 	return dest;     }   zero_fill:   while (n-- > 0)     dest[n] = '\0';    return dest - 1; } #ifdef weak_alias libc_hidden_def (__stpncpy) #endif


Question: 实现库函数strncpy

你的问题挺不错的，代码写的还可以。面试时有时候就会考strcpy之类的。我照着一位大牛的写了一遍，跑通了。不知道对你有帮助没有，你看一下。#include <stdio.h> #define NDEBUG #include <assert.h> char*  my_strncpy(char *strDest,const char *strSrc,int n){   assert((strDest!=NULL)&&(strSrc!=NULL));     char *address=strDest;     for(int i=0;i<n;i++) 	   *strDest++=*strSrc++;   *strDest='\0';     return address; } int main(void){   char array1[]="sdsad";   char array2[]="hello world";   char *strDest=array1;   char *strSrc=array2;   int n=5;   my_strncpy(strDest,strSrc,8);   printf("%s",strDest);   return 0; } 代码在GCC上面跑了一遍没问题的。 但有几个细节要注意：const char ×strSrc 源地址是一个常量。第二个考点：assert断言，程序的安全性。第三个考点：为了保证链式操作 可以返回一个指针。 你比我要聪明。。我这是前几天刚看到这个问题。 还有，要注意代码的精简性，没事多看一下源码，代码应追求短小精悍。

照着源码多写几次你就记得了，我觉得源码的写的很好啊 下面几句是主要的。。 char *temp=dst; while((*dst++=*src++)!='\0'); *dst='\0'; return dst;

#include <stdio.h>    char *mystrncpy( char *des, const char *source, int n ) {     if( des == NULL || source == NULL )     return des;      char *tmp = des;      for( int i = 0; i < n; i++)     {         if( *source != '\0')         {             *tmp++ = *source++;         }     }     *tmp = '\0';     return des; }  int main() {     char s[] = "hello world!";     char *t = "boys";     printf( "%s\n", mystrncpy( s, t, 3 ) );     return 0; }

return tmp？ 你的tmp已经指向'\0'了吧？ char* tmp=s之后，不要动tmp，这个tmp只是记录s的初始位置而已，将s赋值为你想要的结果即可。

这个哪里错了   为什么运行不聊？谢谢


Question: C语言新手求助

仅供参考#include <iostream> #include <stack> #include <queue> #include <locale.h> using namespace std; typedef struct BiTNode {//二叉树结点     char data;                      //数据     struct BiTNode *lchild,*rchild; //左右孩子指针 } BiTNode,*BiTree; int CreateBiTree(BiTree &T) {//按先序序列创建二叉树     char data;     scanf("%c",&data);//按先序次序输入二叉树中结点的值（一个字符），‘#’表示空树     if (data == '#') {         T = NULL;     } else {         T = (BiTree)malloc(sizeof(BiTNode));         T->data = data;         //生成根结点         CreateBiTree(T->lchild);//构造左子树         CreateBiTree(T->rchild);//构造右子树     }     return 0; } void Visit(BiTree T) {//输出     if (T->data != '#') {         printf("%c ",T->data);     } } void PreOrder(BiTree T) {//先序遍历     if (T != NULL) {         Visit(T);               //访问根节点         PreOrder(T->lchild);    //访问左子结点         PreOrder(T->rchild);    //访问右子结点     } } void InOrder(BiTree T) {//中序遍历     if (T != NULL) {         InOrder(T->lchild);     //访问左子结点         Visit(T);               //访问根节点         InOrder(T->rchild);     //访问右子结点     } } void PostOrder(BiTree T) {//后序遍历     if (T != NULL) {         PostOrder(T->lchild);   //访问左子结点         PostOrder(T->rchild);   //访问右子结点         Visit(T);               //访问根节点     } } void PreOrder2(BiTree T) {//先序遍历(非递归) //访问T->data后，将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，再先序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             printf("%c ",p->data);  //访问根节点             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈             stack.pop();             p = p->rchild;          //访问右子树         }     } } void InOrder2(BiTree T) {//中序遍历(非递归) //T是要遍历树的根指针，中序遍历要求在遍历完左子树后，访问根，再遍历右子树。 //先将T入栈，遍历左子树；遍历完左子树返回时，栈顶元素应为T，出栈，访问T->data，再中序遍历T的右子树。     stack<BiTree> stack;     BiTree p = T;//p是遍历指针     while (p || !stack.empty()) {   //栈不空或者p不空时循环         if (p != NULL) {             stack.push(p);          //存入栈中             p = p->lchild;          //遍历左子树         } else {             p = stack.top();        //退栈，访问根节点             printf("%c ",p->data);             stack.pop();             p = p->rchild;          //访问右子树         }     } }  typedef struct BiTNodePost{     BiTree biTree;     char tag; } BiTNodePost,*BiTreePost; void PostOrder2(BiTree T) {//后序遍历(非递归)     stack<BiTreePost> stack;     BiTree p = T;//p是遍历指针     BiTreePost BT;     while (p != NULL || !stack.empty()) {//栈不空或者p不空时循环         while (p != NULL) {//遍历左子树             BT = (BiTreePost)malloc(sizeof(BiTNodePost));             BT->biTree = p;             BT->tag = 'L';//访问过左子树             stack.push(BT);             p = p->lchild;         }         while (!stack.empty() && (stack.top())->tag == 'R') {//左右子树访问完毕访问根节点             BT = stack.top();             stack.pop();//退栈             printf("%c ",BT->biTree->data);         }         if (!stack.empty()) {//遍历右子树             BT = stack.top();             BT->tag = 'R';//访问过右子树             p = BT->biTree;             p = p->rchild;         }     } }  void LevelOrder(BiTree T) {//层次遍历     if (T == NULL) return;     BiTree p = T;     queue<BiTree> queue;//队列     queue.push(p);//根节点入队     while (!queue.empty()) {    //队列不空循环         p = queue.front();      //对头元素出队         printf("%c ",p->data);  //访问p指向的结点         queue.pop();            //退出队列         if (p->lchild != NULL) {//左子树不空，将左子树入队             queue.push(p->lchild);         }         if (p->rchild != NULL) {//右子树不空，将右子树入队             queue.push(p->rchild);         }     } } int main() {     BiTree T;      setlocale(LC_ALL,"chs");     CreateBiTree(T);      printf("先序遍历        ：");PreOrder  (T);printf("\n");     printf("先序遍历(非递归)：");PreOrder2 (T);printf("\n");                                                printf("\n");     printf("中序遍历        ：");InOrder   (T);printf("\n");     printf("中序遍历(非递归)：");InOrder2  (T);printf("\n");                                                printf("\n");     printf("后序遍历        ：");PostOrder (T);printf("\n");     printf("后序遍历(非递归)：");PostOrder2(T);printf("\n");                                                printf("\n");     printf("层次遍历        ：");LevelOrder(T);printf("\n");      return 0; } //ABC##DE#G##F### //先序遍历        ：A B C D E G F //先序遍历(非递归)：A B C D E G F // //中序遍历        ：C B E G D F A //中序遍历(非递归)：C B E G D F A // //后序遍历        ：C G E F D B A //后序遍历(非递归)：C G E F D B A // //层次遍历        ：A B C D E F G //  ///       A ///      / ///     B ///    / \ ///   C   D ///      / \ ///     E   F ///      \ ///       G

递归回溯法。

印象里”数据结构“里面就有相关代码实现！自己查查


Question: 局部变量定义后初值怎么会是0？是编译器的问题吗

局部变量的初始化，语言标准里没规定编译器的行为，编译器的实现可以选择初始化或不初始化。一般都不会选初始化的，要做额外的工作。  另一方面，一个局部变量，在stack上分配了空间，这个空间就是个内存地址，不管编译器初始化还是不初始化，这个内存地址本身就有值，可能是0，可能不是0，依赖于之前被使用的情况。即使是0也不应该就理解成编译器初始化成0的，除非看到编译器确实生成了初始化局部变量的代码。

跟编译器有关系，vs2008运行出错，count初始化随机值 变量定义最好都初始化

初始值是随机的。。。 具体是多少，0？FF？还是乱码？看编译器心情


Question: 24点算法，大家都没有好的思路提点一下。。先谢谢了

题目说的不够清楚啊

不是一幅牌算24点吗?差不多都固定的

4个数 2^4个循环。。。

我说一个笨办法：先简化为2个数，四则运算遍历；那么三个数可以先选任意2个先四则，将结果和另一个数传入上述函数；四个数同理。

引用 3 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/380157851看到这个帖子我马上想到了赵老师的一个帖子

上面算错了，重来： 第一个数a，有10种可能，第一运算符&，有4种可能，两个结合有40种可能。结合进第2个数b，就有400种可能（因为a和b这两个集合是一样的），结合进第二个运算符，就有1600种可能，再结合进第三个数，有(a&b)&c和c&(a&b)两种方式（(a&b)和c这两个集合不一样），就有128000种可能。再结合第三个运算符、第四个数，就有1024万种可能。 另外考虑到(a&b)&(c&d)的形式，有400*400*4=64万种可能（(a&b)和(c&d)这两个集合是一样的） 总共有1024万+128万=1152万种可能

上面算错了，重来： 第一个数a，有10种可能，第一运算符&，有4种可能，两个结合有40种可能。结合进第2个数b，就有400种可能，结合进第二个运算符，就有1600种可能，再结合进第三个数，有(a&b)&c和c&(a&b)两种方式，就有128000种可能。再结合第三个运算符、第四个数，就有1024万种可能。 另外考虑到(a&b)&(c&d)的形式，有400*400*8=128万种可能 总共有1024万+128万=1152万种可能

第一个数a，有10种可能，第一运算符&，有4种可能，两个结合有40种可能。结合进第2个数b，就有400种可能，结合进第二个运算符，就有1600种可能，再结合进第三个数，有(a&b)&c和c&(a&b)两种方式，就有32000种可能。再结合第三个运算符、第四个数，就有256万种可能。 另外考虑到(a&b)&(c&d)的形式，有400*400*8=128万种可能 总共有256万+128万=384万种可能


Question: 由函数指针印引发的问题；

函数指针就是个指针，指向函数的地址。  你下面说的两个都是变量。和函数指针的用法不一样而已


Question: 刚学C就遇到这样的问题

引用 11 楼 sholber 的回复:[quote=引用 10 楼 PhycoKnight 的回复:] [quote=引用 9 楼 sholber 的回复:] void main ????? 我的建议是不要学C了。这样又不是不可以，直接main(){}都可以的。[/quote]  是啊，可以，可以，一定可以。非常可以。完全可以滴……[/quote]

引用 10 楼 PhycoKnight 的回复:[quote=引用 9 楼 sholber 的回复:] void main ????? 我的建议是不要学C了。这样又不是不可以，直接main(){}都可以的。[/quote]  是啊，可以，可以，一定可以。非常可以。完全可以滴……

引用 9 楼 sholber 的回复:void main ????? 我的建议是不要学C了。这样又不是不可以，直接main(){}都可以的。

void main ????? 我的建议是不要学C了。

没有初始化ch1和ch2的原因

优先级没问题，只是ch1,ch2没有初始化的缘故，当你输入a时，第一个条件运算符满足，ch1=a，第二个条件运算符不满足，就变成了ch2=ch2-1，ch2没有初始化，所以才会显示？

变量初始化，运算符优先级。这两个注意下，，再试一遍吧。

引用 1 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 你除了会拿这个忽悠一下人还会干什么，貌似不是第一次这样 打太极了 引用 1 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 引用 1 楼 zhao4zhong1 的回复:计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。 （Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 大神，我崇拜你好久了哦，这句话看见你说过好多次了，一直激励着我前进。。

我怎么回复不了你们呀？

调试时，你输入的字符是什么？ 把ch1,ch2先初始化一下，再看看输出，如： char ch1 = 'f'; char ch2 = 'f';

#include <stdio.h> #include <conio.h> void main() { 	char ch,ch1,ch2; 	ch=getche(); 	putchar('\n');  	ch1 = (ch == 'a')?'z':ch - 1; 	ch2 = (ch == 'z')?'a':ch + 1; 	printf("ch1=%c,ch2=%c\n",ch1,ch2); }


Question: C++大神求救课程设计

什么叫管理？无非就是记录谁谁谁在什么时候打电话进来，咨询什么事情，然后回复的内容是什么，是否解决了问题，需不需要后续跟进。  把需求分析清楚，然后就是设计了呗。简单的数据库设计，用户表，管理用户资料，名字，电话，ID之类的；事件表，记录一次通话的相关信息，就是上面说的什么事件，谁，问了什么，给他答复了什么，后续需要做什么。  然后就是数据库的增删改查。。。  界面部分的功能，展示，管理，用户权限


Question: 求助linux下getch问题

引用 7 楼 u013847126 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] 使用NCURSES库。 库我用过，不过我不太会，用的时候编译提示要向屏幕返回什么东西[/quote] 难道NCURSES库不自带例子代码或网上搜不到有例子代码的文章吗？

需要注意事项:   gcc test.h -o t1 -lcurses 编译的时候 后面加上 lcurses curses.h的用法看这里 http://www.maomao365.com/?p=256

引用 6 楼 zhao4zhong1 的回复:使用NCURSES库。 库我用过，不过我不太会，用的时候编译提示要向屏幕返回什么东西

使用NCURSES库。

支持1楼说的

引用 1 楼 zhouchongzxc 的回复:把 13 变成 10 试一下 13换成10的话回车就不管用了呀，而且就一直输入无法结束

13换成10的话回车就不管用了呀，而且就一直输入无法结束

把 13 变成 10 试一下


Question: sizeof()函数问题

很明显是把sizeof和strlen给混淆了，楼上各位都说得差不多了，我就来水水。。。

楼上已经给出解释了，不需要解释太多。 要知道   void fun(char* s)   与  void fun(char  s[ ])  对于编译器来说是一样的东西。

引用 15 楼 hxl199109 的回复: Quote: 引用 9 楼 Const_User 的回复:  函数定义中的数组参数，其实就是指针，就是一个存放地址的单元，我用的编译器定义的是4个字节。当你调用函数时，会自动创建参数列表中的变量，也就是函数定义中的参数列表，并不是在main函数里面的数组，调用时就会把main中的数组地址赋值给指针，这时指针就会指向数组，又不是复制数组，所以就会出现问题了。 +1  正解 +1

参数为指针。。。

int mystrcat(char str[], char sub[], int len, int sizestr) 这是误导性的，看起来像数组，其实没有任何数组的特性， 既然楼主发现sizeof了，就应该想到这不是数组……

引用 1 楼 u013163178 的回复:看到标题我就想进来说下,sizeof不是函数,是运算符,结果是在编译时候产生的,不是运行时候计算出来的,i所以楼主你该知道怎么错了的 吧 从C99开始变长数组的sizeof结果是在运行时计算的。

引用 15 楼 hxl199109 的回复:引用 9 楼 Const_User 的回复:函数定义中的数组参数，其实就是指针，就是一个存放地址的单元，我用的编译器定义的是4个字节。当你调用函数时，会自动创建参数列表中的变量，也就是函数定义中的参数列表，并不是在main函数里面的数组，调用时就会把main中的数组地址赋值给指针，这时指针就会指向数组，又不是复制数组，所以就会出现问题了。+1  正解 +1

以数组为参数，它会退化为指针

sizeof 好像是  501  而  strlen是500  因为  strlen  的长度不会包含  \0 而sizeof  会包含进去\0    楼主试试输出看看     sizeof是操作符而不是 函数

用sizeof运算符测数组名，不就是相当于将其退化成指针了，相当于 char * str；。。。。

楼主要要区分strlen和sizeof

引用 1 楼 u013163178 的回复:看到标题我就想进来说下,sizeof不是函数,是运算符,结果是在编译时候产生的,不是运行时候计算出来的,i所以楼主你该知道怎么错了的 吧 void f (int n) {     char a [n]     size_t v = sizeof a; } 你告诉我在编译的时候怎么产生的。

if ((len + strlen(sub)) >= sizestr) //如将此处的sizestr形参改为sizeof(str) 结果就会出错 因为数组作为参数传递后，传进来的就只是一个指针 其实你这个函数里的str是这样子的 char *str = str; 你可以把函数参数设成char **str试试

引用 1 楼 u013163178 的回复:看到标题我就想进来说下,sizeof不是函数,是运算符,结果是在编译时候产生的,不是运行时候计算出来的,i所以楼主你该知道怎么错了的 吧+1

引用 3 楼 user-18 的回复:[quote=引用 2 楼 user-18 的回复:] sizeof(str) 求得是数组（指针）的大小，总是4  不对啊，应该是数组总字节数，为什么我跟踪的一直是4呀[/quote]----- 正常情况下对数组进行 sizeof运算得到的是数组总字节数，但数组做参数时退化成指针，例如 在这个函数中mystrcat(char str[], char sub[], int len, int sizestr)中的str和sub，32为下，指针的大小为4字节

引用 2 楼 user-18 的回复:sizeof(str) 求得是数组（指针）的大小，总是4  不对啊，应该是数组总字节数，为什么我跟踪的一直是4呀


Question: c函数mkdir无法创建目录

使用perror查看错误码提示什么错误

引用 3 楼 u013163178 的回复:#include <sys/types.h> #include <sys/stat.h> #include <unistd.h>  struct stat st = {0};  if (stat("/some/directory", &st) == -1) {     mkdir("/some/directory", 0700); }  刚查了下，这个不能一次创建多级目录，是得循环创建的把。。。

You can see the manual of these functions with the man 2 stat and man 2 mkdir commands.

To use this function, your program should include the header file sys/stat.h.

if(IsHave<0)的话，用perror(”xxx")函数把错误信息打印出来，看看错误原因。  mkdir()可以直接创建多级目录？？忘了  也可以先看看path到底被sprintf成什么样子了      login_name = pwd->pw_name;        //获取当前用户名  这个写法不对，login_name之前malloc分配了内存了，这么一赋值，就内存泄露了，用strcpy


Question: 如何添加分数等级问题！

做对几个，做错几个统计？？这有啥不会的？做对了a++,做错了b++，最后的a,b不就是了？

从后面统计给分开始就不会了 什么意思？

统计给分部分，无非添加一个得分变量和一个等级变量，每次提示答对了之前就累加得分，并判断新的分数是否达到晋级分，达到了就累加等级变量；每次提示答错了之前就得分减少，并判断新的分数是否达到降级分，达到了就等级变量较小。很简单，楼主加油


Question: 求助  c程序

#pragma comment(linker,"/SECTION:.rdata,RW") //加这句可以让常量区可写，后果自负！

char *s = "xxxxxx",不能修改常量字符串s,改成字符数组就可以了

http://bbs.csdn.net/topics/390965077 这个帖子中2楼的回答能很好的解释为啥char *s = "abcdefg";不可以~~~

#include <stdio.h> #include <iostream> using namespace std; int main() { 	void reverse(char *s); 	char s[] = "abcdefg";//改动了这里 	cout<<s<<endl; 	reverse(s); 	cout<<s<<endl; 	return 0; }  void reverse(char *s) {  	char *end = s; 	char temp; 	while(*end){ 		end++; 	} 	end--; 	while(s < end) 	{ 		temp = *s; 		*s++ = *end; 		*end-- = temp; 	} }


Question: 自定义函数执行完毕后弹框

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

提示你了:发生溢出了

额。。这个，建议你还是先学习一下如何使用vs的调试技术

引用 3 楼 user-3 的回复:你在函数里面设断点进去看看  引用 2 楼 rct007 的回复:引用 1 楼 user-3 的回复:一般是访问地址除了问题。设断点调试，找出是那一句出的问题为什么他会运行完整段函数才会提示，而不是中途就弹窗提示呢设了断点之后，调试看什么

一般是访问地址除了问题。设断点调试，找出是那一句出的问题

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


Question: 两个while嵌套循环

LZ问这个问题是要干啥？？？ n1==2,n2==4的情况各只有一次，当n1=0时，内循环执行了四次，使得n2=4，此后n1自增执行外循环，内循环就不再执行了。当n1子等到2时，外循环也就执行完，程序就结束了……

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

其实这题目要看你说的外层循环是第几次了。 比如按你这个来： 外层第1次，内层循环就是4次。 接着外层第2次，内层不循环了（n2=4了）

先假设n1！=x1，n2！=x2，那总循环次数是x1+x2. ps：抢到沙发了


Question: 定义多个函数，函数被分配到的空间是连续的吗？

数组是一系列线性存储的相同类型元素的集合。无论数组中存储的是地址还是数值，它的大小都是确定的。如果想做个函数数组，那存储的元素就是地址了，如果想让它们连续，就必须知道每个函数的大小，即知道地址又知道大小，这样就可以使数组连续了，不过此时数组的类型最好是结构体了。如果这样分配的话，还有一个问题，如果你的函数足够多，又足够大，内存中是否存在这么一大块空间让你来存储连续函数，这样也不利于对内存的管理。总体来说看每个编译器的取舍了。

是不是连续的，是看编译器怎么分配。用户代码一般都不会依赖这个，否则的话可移植性肯定不好。  如果要确认自己写的这个特定应用的某几个函数是不是在一起，就把这几个函数的地址打印出来看看呗。我的经验，如果想让几个函数地址在一起，用static修饰一下函数，一般会在一起。不保证啊，可以这么试。

说穿了,函数不过是一些标号 函数调用,和函数返回,都是一种跳转 一个函数块 到底有多大, 和函数编译以后的指令 总长度有关系 至于函数会不会连续,简单的策略是会的 但是实际上,编译器因为种种原因, 并不一定会采取这种简单的办法. 高级语言的函数代码, 长度是不确定的 要在 C,C++中,通过标准C,C++行为, 直接生成,这种代码性质的数组,是不可能做到的 不过函数指针(函数地址)的长度, 很多时候是一致的,可以放到数组中

可以试一下emacs中的GDB调试器 。。这个可以让你查看程序机器级别的运行状态。 我刚刚用GDB看了一下，地址不是连续的。 po图：  4和7是两个函数的起始地址 函数体： void f1(){   return; } void f2(){  return; } 关于函数数组 问题，你自己google下 不过 我也谈一下我的理解，C中的函数名本身是一个地址，如果有函数数组，那怎么函数体中的代码怎么办？我的意思是函数名本身应该是函数执行的起点，应该是做不到函数地址递增的。额，，个人YY，，纯属TX

可以试一下emacs中的GDB调试器 。。这个可以让你查看程序额机器级别的运行状态。 关于函数数组 问题，你自己google下 不过 我也谈一下我的理解，C中的函数名本身是一个地址，如果有函数数组，那怎么函数体中的代码怎么办？我的意思是函数名本身应该是函数执行的起点，应该是做不到函数地址递增的。额，，个人YY，，纯属TX

为什么要连续的呢？应该是看编译器的吧

思索这个问题之前，你需要先弄搞清楚，你是如何确定它们是连续的，还是不连续的？ 还有连续有何好处，坏处 不连续有何好处，坏处


Question: 关于指针的问题

LinkList 是结构体指针定义吧，像下面这样你的代码就合理了。。。  struct stLinkList { ... stLinkList* next; }*LinkList;

显然LinkList是指针类型（LinkLIst p, q;这段代码看出来的），L 是指向指针的指针，当然要加*

说明LinkList是一个typedef类型，它也是指针类型

你这里LinkList本来就是某个结构体的指针了吧 再加个*就是指针的指针了 所以后面用的时候要加*  其实感觉直接传这个指针就可以了，不用传指针的指针

*L->next那意思是指*L指针指向的结构体的next，这没什么问题吧

帮帮我吧！！


Question: 【求助】结尾语法错误不知如何修改

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

不需要那么多“return 0；”吧，建议一个函数就一个return。确实main函数最后一行少了一个“}”，不知道是不是你拷贝的时候漏掉了。

引用 4 楼 ccnyou 的回复:最好换行再敲 } +1

最好换行再敲 }

return 0;}  你试试

请问具体在哪里呢？

main函数少了结尾的花括号


Question: 程序中如何把一个ANSI汉字字符串转换成UNICODE字符串?

MultiByteToWideChar The MultiByteToWideChar function maps a character string to a wide-character (Unicode) string. The character string mapped by this function is not necessarily from a multibyte character set.   int MultiByteToWideChar(   UINT CodePage,         // code page   DWORD dwFlags,         // character-type options   LPCSTR lpMultiByteStr, // address of string to map   int cchMultiByte,      // number of bytes in string   LPWSTR lpWideCharStr,  // address of wide-character buffer   int cchWideChar        // size of buffer );   Parameters CodePage  Specifies the code page to be used to perform the conversion. This parameter can be given the value of any code page that is installed or available in the system. You can also specify one of the following values: Value Meaning  CP_ACP ANSI code page  CP_MACCP Macintosh code page  CP_OEMCP OEM code page  CP_SYMBOL Symbol code page (42)  CP_THREAD_ACP The current thread's ANSI code page  CP_UTF7 Translate using UTF-7  CP_UTF8 Translate using UTF-8    dwFlags  A set of bit flags that indicate whether to translate to precomposed or composite wide characters (if a composite form exists), whether to use glyph characters in place of control characters, and how to deal with invalid characters. You can specify a combination of the following flag constants: Value Meaning  MB_PRECOMPOSED Always use precomposed characters — that is, characters in which a base character and a nonspacing character have a single character value. This is the default translation option. Cannot be used with MB_COMPOSITE.  MB_COMPOSITE Always use composite characters — that is, characters in which a base character and a nonspacing character have different character values. Cannot be used with MB_PRECOMPOSED.  MB_ERR_INVALID_CHARS If the function encounters an invalid input character, it fails and GetLastError returns ERROR_NO_UNICODE_TRANSLATION.   MB_USEGLYPHCHARS Use glyph characters instead of control characters.    A composite character consists of a base character and a nonspacing character, each having different character values. A precomposed character has a single character value for a base/non-spacing character combination. In the character è, the e is the base character and the accent grave mark is the nonspacing character.   The function's default behavior is to translate to the precomposed form. If a precomposed form does not exist, the function attempts to translate to a composite form.   The flags MB_PRECOMPOSED and MB_COMPOSITE are mutually exclusive. The MB_USEGLYPHCHARS flag and the MB_ERR_INVALID_CHARS can be set regardless of the state of the other flags.   lpMultiByteStr  Points to the character string to be converted.  cchMultiByte  Specifies the size in bytes of the string pointed to by the lpMultiByteStr parameter. If this value is –1, the string is assumed to be null terminated and the length is calculated automatically.  lpWideCharStr  Points to a buffer that receives the translated string.  cchWideChar  Specifies the size, in wide characters, of the buffer pointed to by the lpWideCharStr parameter. If this value is zero, the function returns the required buffer size, in wide characters, and makes no use of the lpWideCharStr buffer.  Return Values If the function succeeds, and cchWideChar is nonzero, the return value is the number of wide characters written to the buffer pointed to by lpWideCharStr.   If the function succeeds, and cchWideChar is zero, the return value is the required size, in wide characters, for a buffer that can receive the translated string.   If the function fails, the return value is zero. To get extended error information, call GetLastError. GetLastError may return one of the following error codes:  ERROR_INSUFFICIENT_BUFFER ERROR_INVALID_FLAGS ERROR_INVALID_PARAMETER ERROR_NO_UNICODE_TRANSLATION  Remarks The lpMultiByteStr and lpWideCharStr pointers must not be the same. If they are the same, the function fails, and GetLastError returns the value ERROR_INVALID_PARAMETER.   The function fails if MB_ERR_INVALID_CHARS is set and it encounters an invalid character in the source string. An invalid character is one that would translate to the default character if MB_ERR_INVALID_CHARS was not set, but is not the default character in the source string, or when a lead byte is found in a string and there is no valid trail byte for DBCS strings. When an invalid character is found, and MB_ERR_INVALID_CHARS is set, the function returns 0 and sets GetLastError with the error ERROR_NO_UNICODE_TRANSLATION.  Windows CE: Windows CE does not support the CP_UTF7 and CP_UTF8 values for the CodePage parameter.  QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Requires version 1.0 or later.   Header: Declared in winnls.h.   Import Library: Use kernel32.lib.  See Also Unicode and Character Sets Overview, Unicode and Character Set Functions, WideCharToMultiByte

//iconv_linux下字符集编码转换轻松实现 (1) iconv_t iconv_open(const char *tocode, const char *fromcode); //此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。 (2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft); //此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。 (3) int iconv_close(iconv_t cd); //此函数用于关闭转换句柄,释放资源。  //例子1: 用C语言实现的转换示例程序  /* f.c : 代码转换示例C程序 */ #include <iconv.h> #define OUTLEN 255 main() { char *in_utf8 = "姝ｅ?ㄥ??瑁?"; char *in_gb2312 = "正在安装"; char out[OUTLEN];  /*unicode码转为gb2312码*/ rc = u2g(in_utf8,strlen(in_utf8),out,OUTLEN); printf("unicode-->gb2312 out=%sn",out); //gb2312码转为unicode码  rc = g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN); printf("gb2312-->unicode out=%sn",out); } /*代码转换:从一种编码转为另一种编码*/ int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen) { iconv_t cd; int rc; char **pin = &inbuf; char **pout = &outbuf;  cd = iconv_open(to_charset,from_charset); if (cd==0) return -1; memset(outbuf,0,outlen); if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1; iconv_close(cd); return 0; } /*UNICODE码转为GB2312码*/ int u2g(char *inbuf,int inlen,char *outbuf,int outlen) { return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen); } /*GB2312码转为UNICODE码*/ int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen) { return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen); }  //例子2: 用C++语言实现的转换示例程序  /* f.cpp : 代码转换示例C++程序 */ #include <iconv.h> #include <iostream>  #define OUTLEN 255  using namespace std;  // 代码转换操作类  class CodeConverter {  private: iconv_t cd; public:  // 构造 CodeConverter(const char *from_charset,const char *to_charset) { cd = iconv_open(to_charset,from_charset); }   // 析构 ~CodeConverter() { iconv_close(cd); }   // 转换输出 int convert(char *inbuf,int inlen,char *outbuf,int outlen) { char **pin = &inbuf; char **pout = &outbuf;  memset(outbuf,0,outlen); return iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen); } };  int main(int argc, char **argv) { char *in_utf8 = "姝ｅ?ㄥ??瑁?"; char *in_gb2312 = "正在安装"; char out[OUTLEN];  // utf-8-->gb2312 CodeConverter cc = CodeConverter("utf-8","gb2312"); cc.convert(in_utf8,strlen(in_utf8),out,OUTLEN); cout << "utf-8-->gb2312 in=" << in_utf8 << ",out=" << out << endl;  // gb2312-->utf-8 CodeConverter cc2 = CodeConverter("gb2312","utf-8"); cc2.convert(in_gb2312,strlen(in_gb2312),out,OUTLEN); cout << "gb2312-->utf-8 in=" << in_gb2312 << ",out=" << out << endl; }    二、利用iconv命令进行编码转换  iconv命令用于转换指定文件的编码,默认输出到标准输出设备,亦可指定输出文件。  用法： iconv [选项...] [文件...]  有如下选项可用:  输入/输出格式规范： -f, --from-code=名称 原始文本编码 -t, --to-code=名称 输出编码  信息： -l, --list 列举所有已知的字符集  输出控制： -c 从输出中忽略无效的字符 -o, --output=FILE 输出文件 -s, --silent 关闭警告 --verbose 打印进度信息  -?, --help 给出该系统求助列表 --usage 给出简要的用法信息 -V, --version 打印程序版本号  例子: iconv -f utf-8 -t gb2312 aaa.txt >bbb.txt 这个命令读取aaa.txt文件，从utf-8编码转换为gb2312编码,其输出定向到bbb.txt文件。  小结: Linux为我们提供了强大的编码转换工具,给我们带来了方便。

Windows: MultiByteToWideChar  Linux:libiconv之类的库 如果你可以随时改全局local的话，可以用mbsrtowcs

你可以直接用C语言的宽字符类型存储，至于转换也有对应的函数 比如： wint_t btowc (int c);  Convert single byte character to wide character Returns the wide character representation of the byte value c if (and only if) c is a valid multibyte character with a length of a single byte in the initial state of a multibyte sequence.  Otherwise, it returns WEOF. 其他转换函数，请参阅标准的<wchar.h>库

C没有这么牛的函数。。。

手工方法我会：把该字符串存到ANSI格式的NOTEPAD.EXE文本txt文件中，然后双击打开此txt文件的窗口，然后在”文件-另存为-编码“中选择UNICODE后存盘，然后用程序从那个另存的文件中读出的就是UNICODE编码了。


Question: centos下的一些c语言问题

引用 5 楼 FightForProgrammer 的回复:hent = gethostbyname(si->host_ip_address);//这块崩溃了，为啥啊？ gethostbyname这个函数不该传入ip地址吧。应该是例如"www.google.cn"等等。 高手你知道为啥，codeblocks调试信息输不出来不？  就是我图片里显示的第一行，后面那些信息都是，程序卡一下才输出来的，啥情况啊

引用 2 楼 FightForProgrammer 的回复:先找到哪里除了问题吧。这个自己调试应该可以找出来啊      hent = gethostbyname(si->host_ip_address);//这块崩溃了，为啥啊？

引用 1 楼 coding_hello 的回复:崩溃的地方仔细看各个指针是否指向正确的内存数据      hent = gethostbyname(si->host_ip_address);//这块崩溃了，为啥啊？

先找到哪里除了问题吧。这个自己调试应该可以找出来啊

崩溃的地方仔细看各个指针是否指向正确的内存数据

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

codeblocks在linux下我也遇到很多奇怪的问题，这个应该是和软件相关，容易挂掉等。  怎么解决我也不知道，所以一般在linux下我就不用IDE了。直接vim+gcc+gdb


Question: 关于scanf缓冲的一个问题。

Format Specification Fields: scanf and wscanf Functions A format specification has the following form:  % [width] [{h | l | I64 | L}]type  The format argument specifies the interpretation of the input and can contain one or more of the following:   White-space characters: blank (' '); tab ('\t'); or newline ('\n'). A white-space character causes scanf to read, but not store, all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input.   Non–white-space characters, except for the percent sign (%). A non–white-space character causes scanf to read, but not store, a matching non–white-space character. If the next character in stdin does not match, scanf terminates.   Format specifications, introduced by the percent sign (%). A format specification causes scanf to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list.  The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in stdin; the matching characters in stdin are scanned but not stored. If a character in stdin conflicts with the format specification, scanf terminates, and the character is left in stdin as if it had not been read.  When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.  An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.  Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.   The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.  An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored.

看到原因了，第178行，少了%c

我看控制选项是用scanf("%d"，..)的，这也会自动跳过'\n'等空白符。我猜测是输入的时候多输入的别的字符。

引用 3 楼 kanoyami 的回复:使用了getchar()之后还是这样，是在scanf语句后面加一句吧。为什么用fflush不能刷掉这个呢？ 怎么会没用，你写个小程序测试一下就知道有用了，不加fflush(stdin)，那么程序直接退出，加了，需要再输入一次 int main() { 	char str[128] = {0}; 	scanf("%s",str); //	fflush(stdin); 	getchar();  	return 0; } 第60行的fflush(stdin)放错位置了，不知道是不是这个原因，应该放在scanf()之后，放在那也应该是fflush(stdout)。

引用 1 楼 coding_hello 的回复:因为用scanf输入，会等待回车确认。这个回车就是多出来的输入。  如果之后跟着另一个scanf，只要不是%c的scanf，都会吞掉之前的回车，不会有问题。但是最后一个scanf还是有一个回车。  对于最后一个回车的情况，就调用个getchar()吧 使用了getchar()之后还是这样，是在scanf语句后面加一句吧。为什么用fflush不能刷掉这个呢？

引用 1 楼 coding_hello 的回复:因为用scanf输入，会等待回车确认。这个回车就是多出来的输入。  如果之后跟着另一个scanf，只要不是%c的scanf，都会吞掉之前的回车，不会有问题。但是最后一个scanf还是有一个回车。  对于最后一个回车的情况，就调用个getchar()吧+1,原来写了一个类似的程序，然后让同学进行测试，修改了许多这种问题


Question: 关于文件的一个问题

楼主是读取一个不知道多大的文件么？那就判断EOF。要是创建一个不知道要写入多少数据的文件，那就随你了，最好是写入一定数据后，就分割文件。因为文件大小是有限制。

文本方式打开用EOF，二进制打开用feof函数。。。

没看懂LZ的意思。

如何判断写入结束？？没得写了就结束了呗  判断数据读入结束，可以用feof()

EOF  字数字数

只要磁盘还有可用空间，你高兴写到哪里结束就到哪里结束。

到底是要读取还是写入啊


Question: 数据结构算法设计

谢谢大家，我自己会试试的。

引用 1 楼 user-4 的回复:明天有空来写写。题目不难。。。。 Agree,自己试一下。逻辑上不难实现，删除可能有点难度，也需要一些指针和结构的基础知识。

当给出的结点值存在与二叉树时，删除该结点 //删除某个结点 int DeleteBST(BiTree *p) { 	BiTree q,s; 	if((*p)->rchild==NULL) //该结点右孩子为空时 	{ 		q=*p;*p=(*p)->lchild;free(q); 	} 	else if((*p)->lchild==NULL)//该结点左孩子为空时 	{ 		q=*p;*p=(*p)->rchild;free(q); 	} 	else  //该结点左右孩子都存在时 	{ 		q=*p;s=(*p)->lchild; 		while(s->rchild) 		{ 			q=s; 			s=s->rchild; 		} 		(*p)->data=s->data; 		if(q!=*p) 			q->rchild=s->lchild; 		else 			q->lchild=s->lchild; 		free(s); 	} 	return 1; } int Delete(BiTree *T,int key) { 	BiTree p; 	if(!*T) 		return 0; 	else 	{ 	 if(Search(*T,key,NULL,&p)) 	 {DeleteBST(&p);return 1;} 	 else return 0; 	} }

这里先给出构造排序二叉树的过程 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h>  typedef struct BiTNode { 	int data; 	struct BiTNode *lchild,*rchild; }BiTNode,*BiTree; //查找二叉树是否存在与key相同的值，若存在，则返回1，不存在，则另*p为 //查找的最后节点的指针 int Search(BiTree T,int key,BiTree f,BiTree *p) { 	if(!T) 	{ 		*p=f; 		return 0; 	} 	else if(key==T->data) 	{ 		*p=T; 		return 1; 	} 	else if(key<T->data) 			return Search(T->lchild,key,T,p); 	else 			return Search(T->rchild,key,T,p); } //依据查找结果，逐个插入key，构造排序二叉树 int Insert(BiTree *T,int key) { 	BiTree p,s; 	if(!Search(*T,key,NULL,&p)) 	{ 		s=(BiTree)malloc(sizeof(BiTNode)); 		s->data=key; 		s->lchild=NULL; 		s->rchild=NULL; 		if(!p) 		*T=s; 		else if(key<p->data) 			p->lchild=s; 		else 			p->rchild=s; 	} 	else 		return 1; } void main() { 	int i,j; 	BiTree T=NULL; 	int d[10]={62,88,58,47,35,73,51,99,37,93}; 	for(i=0;i<10;i++) 	{ 		Insert(&T,d[i]); 	} }

看着挺难的。好吧，我试试

拒绝直接的伸手党 你可以自己搜二叉排序数，参考这类代码，自己写简单的排序数的数据结构与逻辑方法。

明天有空来写写。题目不难。。。。


Question: 为什么说可能会导致内存访问错误

引用 7 楼 coding_hello 的回复:char *p1="sdkfsdsdg"; p1[0]='g';  这里的"sdkfsdsdg"是在只读属性的内存区，按说正确写法应该是const char* p1 = "sdkfsdsdg"; 但是编译器兼容了这个常量字符串赋值的写法。  乱说

"sdkfsdsdg"是字符串常量，在内存中的代码段，是不允许修改的，P[0]='g'是要改变‘S’，这样运行会产生段错误，

char *p1 = "sdkfsdsdg"; p1指向常量字符串，不允许修改。  char p2[] = "sdkfsdsdg"; p2[0] = 'g'; p2指向字符数组，可以通过指针或数组下标修改字符数组中的字符。 p2[0] = 'g';

#pragma comment(linker,"/SECTION:.rdata,RW") //加这句可以让常量区可写，后果自负！

指针p1指向的是一个常量字符串。你无法修改常量字符串的值。  若想修改，建议写如下代码： char p1[]="sdkfsdsdg";     p1[0]='g'; 这样会给p1在栈上分配内存，从而你可以修改其中的值。

char *p1="sdkfsdsdg";  p1[0]='g'; C语言是表达能力很强的语言，为什么写得这么傻？干嘛不这么写： "sdkfsdsdg" [0] = 'g'; 问题在于，不管怎么写，串字面值都被用于初始化一个静态数组，它可能位于一个受处理器硬件保护的只读页内。

一个是字符串常量，一个是字符数组，注意区分

内存是有属性的，读写，只读什么的。字符串常量保存的地方一般是只读，你往那写自然会引起段错误，内存是有保护机制的。

不知道c primer plus 里举的例子，说原因是在于编译器可能选择内存中的同一个单个的拷贝，来表示所有相同的字符串文字

直接这么写不会吧。除非你把p1指向了其他地方（比如null），然后又用p1【0】