Question: 请帮我解释一下这个程序，最后结果是咋得到的

@zjq9931,谢谢您的解答，我明白了

引用 5 楼 mongoose_tonny 的回复:您好，根据您的解答运行结果应为7,8 可是最终的运行结果为8,8，这个该如何解释 8,8啊。++ptr已经变成指向8了啊，

#include <stdio.h>  void main( )  {              int arr[]={6,7,8,9,10};            int *ptr=arr;  //指向6           *(ptr++)+=123;    //指向7+123           printf("%d,%d",*ptr,*++ptr); //从右向左的顺序都指向了8  }

引用 1 楼 qq_38204686 的回复:一开始指向6 +=123这句 运行完指针加一 指向7 最后一句输出 前++ 先加一后输出 指向8  分清 ++前后位置的不同意义就可以 详情可以百度 简单明了

建议对指针操作时，不要合并语句，难以理解不说还容易出错。 楼主，把握好前++和后++的执行顺序就很容易理解了，你的代码实际执行为如下：  #include <stdio.h> void main( ) {   	int arr[]={6,7,8,9,10}; 	int *ptr=arr;  	/* 此语句拆分：*(ptr++)+=123;  */ 	*ptr += 123; ptr++; 	/* 词语句拆分：printf("%d,%d",*ptr,*++ptr);*/ 	++ptr; printf("%d,%d",*ptr,*ptr); }


Question: c 的问题

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

static int callback_text(void *notused,int argc,char **argv,char **azcolname) {    char *item="NULL";     *((char *)notused=argv[0]?argv[0]:item;     if (argv[0])         strcpy(notused, argv[0]);     else         strcpy(notused, item);    printf("ss--->%p,%s\n",notused,*((char *)notused));     return 0; }

你参数是按值传递的，只能更改指针指向的内容，更改指针本身没有效果

首先在a.c里面的这一句 p="aaaa"; 已经改了p的值了。  这一句，也不用这么崎岖： *((char *)notused=argv[0]?argv[0]:item; 直接 notused = argv[0]?argv[0]:item;就好了。 用printf输出的时候，也只要这样就好了 printf("%s", (char*)notuse);

你把p又指向了一个常量的位置，函数返回当然出错了，你应该在修改p指向内存的值，不能p="aaaa"；这样做 可以这样  char *p=malloc(sizeof(char) * 32); strcpy(p, "aaaaaa");  但是要注意内存的释放，否则会造成内存泄露！


Question: 求助大神，一个简易的计算器，copy的百度上的逆波兰法但是最后出了点问题

引用 6 楼 null121 的回复:[quote=引用 1楼zjq9931 的回复:]原来的代码编译不过，一下是整理好的代码：  #include<stdlib.h> #include<stdio.h> #include<stack> #include<math.h> #include<string.h> #define max 100 using namespace std; char ex[max];/*存储后缀表达式*/  void trans() {/*将算术表达式转化为后缀表达式*/ 	char str[max];/*存储原算术表达式*/ 	char stack[max];/*作为栈使用*/ 	char ch; 	int sum, i, j, t, top = 0; 	printf("*****************************************\n"); 	printf("*输入一个求值的表达式，以#结束。*\n"); 	printf("******************************************\n"); 	printf("算数表达式："); 	i = 0;/*获取用户输入的表达式*/ 	do { 		i++; 		scanf("%c", &str[i]); 	} while (str[i] != '#'&&i != max); 	sum = i; 	t = 1;i = 1; 	ch = str[i];i++; 	// 	while (ch != '#') 	{ 		switch (ch) 		{ 		case'(':/*判定为左括号*/ 			top++;stack[top] = ch; 			break; 		case')':/*判定为右括号*/ 			while (stack[top] != '(') 			{ 				ex[t] = stack[top];top--;t++; 			} 			top--; 			break; 		case'+':/*判定为加减号*/ 		case'-': 			while (top != 0 && stack[top] != '(') 			{ 				ex[t] = stack[top]; 				top--; 				t++; 			} 			top++; 			stack[top] = ch; 			break; 		case'*':/*判定为乘除号*/ 		case'/': 			while (stack[top] == '*' || stack[top] == '/') 			{ 				ex[t] = stack[top]; 				top--; 				t++; 			} 			top++; 			stack[top] = ch; 			break; 		case' ':break; 		default: 			while (ch >= '0'&&ch <= '9') 			{/*判定为数字*/ 				ex[t] = ch;t++; 				ch = str[i];i++; 			} 			i--; 			ex[t] = ' ';t++; 		} 		ch = str[i];i++; 	} 	while (top != 0) 	{ 		ex[t] = stack[top]; 		t++;top--; 	} 	ex[t] = ' '; 	printf("\n\t原来表达式："); 	for (j = 1;j < sum;j++) 		printf("%c", str[j]); 	printf("\n\t逆波兰式：", ex); 	for (j = 1;j < t;j++) 		printf("%c", ex[j]); }  void compvalue() {/*计算后缀表达式的值*/ 	float stack[max], d;/*作为栈使用*/ 	char ch; 	int t = 1, top = 0;/*t为ex下标，top为stack下标*/ 	ch = ex[t];t++; 	while (ch != ' ') 	{ 		switch (ch) 		{ 		case'+': 			stack[top - 1] = stack[top - 1] + stack[top]; 			top--; 			break; 		case'-': 			stack[top - 1] = stack[top - 1] - stack[top]; 			top--; 			break; 		case'*': 			stack[top - 1] = stack[top - 1] * stack[top]; 			top--; 			break; 		case'/': 			if (stack[top] != 0)stack[top - 1] = stack[top - 1] / stack[top]; 			else 			{ 				printf("\n\t除零错误!\n"); 				exit(0);/*异常退出*/ 			} 			top--; 			break; 		default: 			d = 0; 			while (ch >= '0'&&ch <= '9') 			{ 				d = 10 * d + ch - '0';/*将数字字符转化为对应的数值*/ 				ch = ex[t];t++; 			} 			top++; 			stack[top] = d; 		} 		ch = ex[t]; 		t++; 	} 	printf("\n\t计算结果:%g\n", stack[top]); }  int main() { 	trans(); 	compvalue(); 	system("pause"); 	return 0; } 麻烦再问一下，如果我在输入中输入个含有X的数学表达式，怎样才能在程序中调用这个公式[/quote] 涉及未知数了，肯定得改程序啊。 各处switch处改改。

再供参考：http://www.codeproject.com/Articles/286121/Compiler-Patterns

引用 1楼zjq9931 的回复:原来的代码编译不过，一下是整理好的代码：  #include<stdlib.h> #include<stdio.h> #include<stack> #include<math.h> #include<string.h> #define max 100 using namespace std; char ex[max];/*存储后缀表达式*/  void trans() {/*将算术表达式转化为后缀表达式*/ 	char str[max];/*存储原算术表达式*/ 	char stack[max];/*作为栈使用*/ 	char ch; 	int sum, i, j, t, top = 0; 	printf("*****************************************\n"); 	printf("*输入一个求值的表达式，以#结束。*\n"); 	printf("******************************************\n"); 	printf("算数表达式："); 	i = 0;/*获取用户输入的表达式*/ 	do { 		i++; 		scanf("%c", &str[i]); 	} while (str[i] != '#'&&i != max); 	sum = i; 	t = 1;i = 1; 	ch = str[i];i++; 	// 	while (ch != '#') 	{ 		switch (ch) 		{ 		case'(':/*判定为左括号*/ 			top++;stack[top] = ch; 			break; 		case')':/*判定为右括号*/ 			while (stack[top] != '(') 			{ 				ex[t] = stack[top];top--;t++; 			} 			top--; 			break; 		case'+':/*判定为加减号*/ 		case'-': 			while (top != 0 && stack[top] != '(') 			{ 				ex[t] = stack[top]; 				top--; 				t++; 			} 			top++; 			stack[top] = ch; 			break; 		case'*':/*判定为乘除号*/ 		case'/': 			while (stack[top] == '*' || stack[top] == '/') 			{ 				ex[t] = stack[top]; 				top--; 				t++; 			} 			top++; 			stack[top] = ch; 			break; 		case' ':break; 		default: 			while (ch >= '0'&&ch <= '9') 			{/*判定为数字*/ 				ex[t] = ch;t++; 				ch = str[i];i++; 			} 			i--; 			ex[t] = ' ';t++; 		} 		ch = str[i];i++; 	} 	while (top != 0) 	{ 		ex[t] = stack[top]; 		t++;top--; 	} 	ex[t] = ' '; 	printf("\n\t原来表达式："); 	for (j = 1;j < sum;j++) 		printf("%c", str[j]); 	printf("\n\t逆波兰式：", ex); 	for (j = 1;j < t;j++) 		printf("%c", ex[j]); }  void compvalue() {/*计算后缀表达式的值*/ 	float stack[max], d;/*作为栈使用*/ 	char ch; 	int t = 1, top = 0;/*t为ex下标，top为stack下标*/ 	ch = ex[t];t++; 	while (ch != ' ') 	{ 		switch (ch) 		{ 		case'+': 			stack[top - 1] = stack[top - 1] + stack[top]; 			top--; 			break; 		case'-': 			stack[top - 1] = stack[top - 1] - stack[top]; 			top--; 			break; 		case'*': 			stack[top - 1] = stack[top - 1] * stack[top]; 			top--; 			break; 		case'/': 			if (stack[top] != 0)stack[top - 1] = stack[top - 1] / stack[top]; 			else 			{ 				printf("\n\t除零错误!\n"); 				exit(0);/*异常退出*/ 			} 			top--; 			break; 		default: 			d = 0; 			while (ch >= '0'&&ch <= '9') 			{ 				d = 10 * d + ch - '0';/*将数字字符转化为对应的数值*/ 				ch = ex[t];t++; 			} 			top++; 			stack[top] = d; 		} 		ch = ex[t]; 		t++; 	} 	printf("\n\t计算结果:%g\n", stack[top]); }  int main() { 	trans(); 	compvalue(); 	system("pause"); 	return 0; } 麻烦再问一下，如果我在输入中输入个含有X的数学表达式，怎样才能在程序中调用这个公式

引用 1楼zjq9931 的回复:原来的代码编译不过，一下是整理好的代码：  #include<stdlib.h> #include<stdio.h> #include<stack> #include<math.h> #include<string.h> #define max 100 using namespace std; char ex[max];/*存储后缀表达式*/  void trans() {/*将算术表达式转化为后缀表达式*/ 	char str[max];/*存储原算术表达式*/ 	char stack[max];/*作为栈使用*/ 	char ch; 	int sum, i, j, t, top = 0; 	printf("*****************************************\n"); 	printf("*输入一个求值的表达式，以#结束。*\n"); 	printf("******************************************\n"); 	printf("算数表达式："); 	i = 0;/*获取用户输入的表达式*/ 	do { 		i++; 		scanf("%c", &str[i]); 	} while (str[i] != '#'&&i != max); 	sum = i; 	t = 1;i = 1; 	ch = str[i];i++; 	// 	while (ch != '#') 	{ 		switch (ch) 		{ 		case'(':/*判定为左括号*/ 			top++;stack[top] = ch; 			break; 		case')':/*判定为右括号*/ 			while (stack[top] != '(') 			{ 				ex[t] = stack[top];top--;t++; 			} 			top--; 			break; 		case'+':/*判定为加减号*/ 		case'-': 			while (top != 0 && stack[top] != '(') 			{ 				ex[t] = stack[top]; 				top--; 				t++; 			} 			top++; 			stack[top] = ch; 			break; 		case'*':/*判定为乘除号*/ 		case'/': 			while (stack[top] == '*' || stack[top] == '/') 			{ 				ex[t] = stack[top]; 				top--; 				t++; 			} 			top++; 			stack[top] = ch; 			break; 		case' ':break; 		default: 			while (ch >= '0'&&ch <= '9') 			{/*判定为数字*/ 				ex[t] = ch;t++; 				ch = str[i];i++; 			} 			i--; 			ex[t] = ' ';t++; 		} 		ch = str[i];i++; 	} 	while (top != 0) 	{ 		ex[t] = stack[top]; 		t++;top--; 	} 	ex[t] = ' '; 	printf("\n\t原来表达式："); 	for (j = 1;j < sum;j++) 		printf("%c", str[j]); 	printf("\n\t逆波兰式：", ex); 	for (j = 1;j < t;j++) 		printf("%c", ex[j]); }  void compvalue() {/*计算后缀表达式的值*/ 	float stack[max], d;/*作为栈使用*/ 	char ch; 	int t = 1, top = 0;/*t为ex下标，top为stack下标*/ 	ch = ex[t];t++; 	while (ch != ' ') 	{ 		switch (ch) 		{ 		case'+': 			stack[top - 1] = stack[top - 1] + stack[top]; 			top--; 			break; 		case'-': 			stack[top - 1] = stack[top - 1] - stack[top]; 			top--; 			break; 		case'*': 			stack[top - 1] = stack[top - 1] * stack[top]; 			top--; 			break; 		case'/': 			if (stack[top] != 0)stack[top - 1] = stack[top - 1] / stack[top]; 			else 			{ 				printf("\n\t除零错误!\n"); 				exit(0);/*异常退出*/ 			} 			top--; 			break; 		default: 			d = 0; 			while (ch >= '0'&&ch <= '9') 			{ 				d = 10 * d + ch - '0';/*将数字字符转化为对应的数值*/ 				ch = ex[t];t++; 			} 			top++; 			stack[top] = d; 		} 		ch = ex[t]; 		t++; 	} 	printf("\n\t计算结果:%g\n", stack[top]); }  int main() { 	trans(); 	compvalue(); 	system("pause"); 	return 0; } 谢谢

引用 2楼赵4老师 的回复:仅供参考：/*--------------------------------------- 函数型计算器(VC++6.0,Win32 Console) 功能： 目前提供了10多个常用数学函数:     ⑴正弦sin     ⑵余弦cos     ⑶正切tan     ⑷开平方sqrt     ⑸反正弦arcsin     ⑹反余弦arccos     ⑺反正切arctan     ⑻常用对数lg     ⑼自然对数ln     ⑽ｅ指数exp     ⑾乘幂函数^     ⑿向上取整ceil     ⒀向下取整floor     ⒁四舍五入取整round 用法： 如果要求2的32次幂，可以打入2^32<回车> 如果要求30度角的正切可键入tan(Pi/6)<回车> 注意不能打入：tan(30)<Enter> 如果要求1.23弧度的正弦，有几种方法都有效： sin(1.23)<Enter> sin 1.23 <Enter> sin1.23  <Enter> 如果验证正余弦的平方和公式,可打入sin(1.23)^2+cos(1.23)^2 <Enter>或sin1.23^2+cos1.23^2 <Enter> 此外两函数表达式连在一起,自动理解为相乘如：sin1.23cos0.77+cos1.23sin0.77就等价于sin(1.23)*cos(0.77)+cos(1.23)*sin(0.77) 当然你还可以依据三角变换，再用sin(1.23+0.77)也即sin2验证一下。 本计算器充分考虑了运算符的优先级因此诸如：2+3*4^2 实际上相当于：2+(3*(4*4)) 另外函数名前面如果是数字,那么自动认为二者相乘. 同理，如果某数的右侧是左括号，则自动认为该数与括弧项之间隐含一乘号。 如：3sin1.2^2+5cos2.1^2 相当于3*sin2(1.2)+5*cos2(2.1) 又如：4(3-2(sqrt5-1)+ln2)+lg5 相当于4*(3-2*(√5 -1)+loge(2))+log10(5) 此外，本计算器提供了圆周率 Pi键入字母时不区分大小写,以方便使用。 ----------------------------------------*/ #include <iostream> #include <iomanip> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <stdio.h> #include <string.h> #include <windows.h> using namespace std; const char Tab=0x9; const int  DIGIT=1; const int MAXLEN=16384; char s[MAXLEN],*endss; int pcs=15; double round(double dVal, short iPlaces) {//iPlaces>=0     char s[30];     double dRetval;      sprintf(s,"%.*lf",iPlaces,dVal);     sscanf(s,"%lf",&dRetval);     return (dRetval); } double fun(double x,char op[],int *iop) {     while (op[*iop-1]<32) //本行使得函数嵌套调用时不必加括号,如 arc sin(sin(1.234)) 只需键入arc sin sin 1.234<Enter>         switch (op[*iop-1]) {         case  7: x=sin(x);    (*iop)--;break;         case  8: x=cos(x);    (*iop)--;break;         case  9: x=tan(x);    (*iop)--;break;         case 10: x=sqrt(x);   (*iop)--;break;         case 11: x=asin(x);   (*iop)--;break;         case 12: x=acos(x);   (*iop)--;break;         case 13: x=atan(x);   (*iop)--;break;         case 14: x=log10(x);  (*iop)--;break;         case 15: x=log(x);    (*iop)--;break;         case 16: x=exp(x);    (*iop)--;break;         case 17: x=ceil(x);   (*iop)--;break;         case 18: x=floor(x);  (*iop)--;break;         case 19: x=round(x,0);(*iop)--;break;         }     return x; } double calc(char *expr,char **addr) {     static int deep; //递归深度     static char *fname[]={"sin","cos","tan","sqrt","arcsin","arccos","arctan","lg","ln","exp","ceil","floor","round",NULL};     double ST[10]={0.0}; //数字栈     char op[10]={'+'}; //运算符栈     char c,*rexp,*pp,*pf;     int ist=1,iop=1,last,i;      if (!deep) {         pp=pf=expr;         do {             c = *pp++;             if (c!=' '&& c!=Tab)                 *pf++ = c;         } while (c!='\0');     }     pp=expr;     if ((c=*pp)=='-'||c=='+') {         op[0] = c;         pp++;     }     last = !DIGIT;     while ((c=*pp)!='\0') {         if (c=='(') {//左圆括弧             deep++;             ST[ist++]=calc(++pp,addr);             deep--;             ST[ist-1]=fun(ST[ist-1],op,&iop);             pp = *addr;             last = DIGIT;             if (*pp == '('||isalpha(*pp) && strnicmp(pp,"Pi",2)) {//目的是：当右圆括弧的右恻为左圆括弧或函数名字时，默认其为乘法                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }         else if (c==')') {//右圆括弧             pp++;             break;         } else if (isalpha(c)) {             if (!strnicmp(pp,"Pi",2)) {                 if (last==DIGIT) {                     cout<< "π左侧遇）" <<endl;exit(1);                 }                 ST[ist++]=3.14159265358979323846264338328;                 ST[ist-1]=fun(ST[ist-1],op,&iop);                 pp += 2;                 last = DIGIT;                 if (!strnicmp(pp,"Pi",2)) {                     cout<< "两个π相连" <<endl;exit(2);                 }                 if (*pp=='(') {                     cout<< "π右侧遇（" <<endl;exit(3);                 }             } else {                 for (i=0; (pf=fname[i])!=NULL; i++)                     if (!strnicmp(pp,pf,strlen(pf))) break;                 if (pf!=NULL) {                     op[iop++] = 07+i;                     pp += strlen(pf);                 } else {                     cout<< "陌生函数名" <<endl;exit(4);                 }             }         } else if (c=='+'||c=='-'||c=='*'||c=='/'||c=='%'||c=='^') {             char cc;             if (last != DIGIT) {                 cout<< "运算符粘连" <<endl;exit(5);             }             pp++;             if (c=='+'||c=='-') {                 do {                     cc = op[--iop];                     --ist;                     switch (cc) {                     case '+':  ST[ist-1] += ST[ist];break;                     case '-':  ST[ist-1] -= ST[ist];break;                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 } while (iop);                 op[iop++] = c;             } else if (c=='*'||c=='/'||c=='%') { operate:        cc = op[iop-1];                 if (cc=='+'||cc=='-') {                     op[iop++] = c;                 } else {                     --ist;                     op[iop-1] = c;                     switch (cc) {                     case '*':  ST[ist-1] *= ST[ist];break;                     case '/':  ST[ist-1] /= ST[ist];break;                     case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;                     case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;                     }                 }             } else {                 cc = op[iop-1];                 if (cc=='^') {                     cout<< "乘幂符连用" <<endl;exit(6);                 }                 op[iop++] = c;             }             last = !DIGIT;         } else {             if (last == DIGIT) {                 cout<< "两数字粘连" <<endl;exit(7);             }             ST[ist++]=strtod(pp,&rexp);             ST[ist-1]=fun(ST[ist-1],op,&iop);             if (pp == rexp) {                 cout<< "非法字符" <<endl;exit(8);             }             pp = rexp;             last = DIGIT;             if (*pp == '('||isalpha(*pp)) {                 op[iop++]='*';                 last = !DIGIT;                 c = op[--iop];                 goto operate ;             }         }     }     *addr=pp;     if (iop>=ist) {         cout<< "表达式有误" <<endl;exit(9);     }     while (iop) {         --ist;         switch (op[--iop]) {         case '+':  ST[ist-1] += ST[ist];break;         case '-':  ST[ist-1] -= ST[ist];break;         case '*':  ST[ist-1] *= ST[ist];break;         case '/':  ST[ist-1] /= ST[ist];break;         case '%':  ST[ist-1] = fmod(ST[ist-1],ST[ist]);break;         case '^':  ST[ist-1] = pow(ST[ist-1],ST[ist]);break;         }     }     return ST[0]; } int main(int argc,char **argv) {     int a;      if (argc<2) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算函数表达式的值。"<<endl<<"支持(),+,-,*,/,%,^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;         while (1) {             cout << "请输入表达式：";             gets(s);             if (s[0]==0) break;//             cout << s <<"=";             cout << setprecision(15) << calc(s,&endss) << endl;         }     } else if (argc==2 && 0==strcmp(argv[1],"/?")) {         if (GetConsoleOutputCP()!=936) system("chcp 936>NUL");//中文代码页         cout << "计算由≥1个命令行参数给出的函数表达式的值。最后一个参数是.0～.15表示将计算结果保留小数0～15位"<<endl<<"支持(),+,-,*,/,%,^^,Pi,sin,cos,tan,sqrt,arcsin,arccos,arctan,lg,ln,exp,ceil,floor,round"<<endl;     } else {         strncpy(s,argv[1],MAXLEN-1);s[MAXLEN-1]=0;         if (argc>2) {             for (a=2;a<argc-1;a++) strncat(s,argv[a],MAXLEN-1);//将空格间隔的各参数连接到s             if (1==sscanf(argv[a],".%d",&pcs) && 0<=pcs && pcs<=15) {//最后一个参数是.0～.15表示将计算结果保留小数0～15位                 printf("%.*lf\n",pcs,calc(s,&endss));             } else {                 strncat(s,argv[a],MAXLEN-1);                 printf("%.15lg\n",calc(s,&endss));             }         } else {             printf("%.15lg\n",calc(s,&endss));         }     }     return 0; } 谢谢


Question: 从记事本里按行读取字符串问题

引用 1 楼 zjq9931 的回复:上代码。  #include<stdio.h> #include<stdlib.h> #include<time.h> #define length 10  char *creat(char *str) {  	int i;  	for (i = 0; i < length; i++) 	{ 		switch (rand() % 3) 		{ 		case 0: 			str[i] = rand() % 26 + 'a'; 			break; 		case 1: 			str[i] = rand() % 26 + 'A'; 			break; 		case 2: 			str[i] = rand() % 10 + '0'; 			break; 		} 	}   	FILE *fp; 	if ((fp = fopen("ggg.txt", "a")) == NULL) 		printf("ERROR"); 	fprintf(fp, "%s\n", str); 	puts(str);	// 输出一下，看存入文件的是什么顺序 	fclose(fp);  	return str; }  void main() { 	srand((unsigned)time(0));  	char str[length + 1] = { 0 }; 	char str1[length + 1] = { 0 }; 	char str2[length + 1] = { 0 };  	FILE *fp; 	if ((fp = fopen("ggg.txt", "w")) == NULL) 		printf("ERROR");  	fclose(fp);   	puts("生成顺序："); 	creat(str); 	creat(str1); 	creat(str2);  	char s1[length+1] = { 0 }; 	char s2[length + 1] = { 0 }; 	char s3[length + 1] = { 0 };  	int i = 0, j, k, r = 0, t = 0, y = 0; 	 	puts("读取顺序1："); 	FILE *pfl; 	pfl = fopen("ggg.txt", "rb"); 	fgets(s1, 10, pfl); 	while(!feof(pfl)) { 		printf("%s", s1); 		fgets(s1, 11, pfl); 	} 	fclose(pfl);   	puts("读取顺序2："); 	FILE *fp3; 	fp3 = fopen("ggg.txt", "r"); 	for (i; i < 11; i++)	//读取11个字符？ 	{ 		fscanf(fp3, "%c", &s1[i]); 		printf("%c", s1[i]); 	} 	//for (j = i; j < 22; j++)	// 在读取22个字符？ 	//{ 	//	fscanf(fp3, "%c", &s2[j]); //s2只有11个字符的空间限制的j已经大于11了会越界访问，下面的s3也一样，所以才会出错，从0开始才对 	//	printf("%c", s2[j]); 	//} 	//for (k = j; k < 33; k++)	//上面已经把文件读完了，还要读取？ 	//{ 	//	fscanf(fp3, "%c", &s3[k]); 	//	printf("%c", s3[k]);  	//}  	fclose(fp3); } 我想读出来的字符串能用三个数组分别存着


Question: 我认为结果为a=5,b=0 哪位大神能给解释一下吗，谢谢！

引用 6 楼 zhao4zhong1 的回复:不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！哈哈，跟你们讲有时候我都觉得赵四老师疯了，可是一想呢，又觉得说的很有道理

引用 7 楼 Rocco01 的回复:[quote=引用 6 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！哈哈，跟你们讲有时候我都觉得赵四老师疯了，可是一想呢，又觉得说的很有道理[/quote] 实践是检验真理的唯一标准。

do while循环只会执行一次，因为b--<0条件决定的。 执行完do while体后，a = 2, b = 9; 然后执行判断条件，b-- < 0即判断9 < 0吗？，然后再执行b--；即b = b -1; 所以结果是a = 2, b = 8;

建议你单步跟踪程序运行，观察每一步执行后变量变化情况，比给你解释你更容易理解

建议楼主学会设置断点调试

你循环条件错了，改成b-->0就是你的答案了

你是怎么认为出来的...  首先这个循环体只会执行一次, 所以等价于  int a=1,b=10; b−=a;  // b = 9 a++;    // a = 2 b−−;    // b = 8


Question: 链表崩溃的问题 大神来帮帮忙啊！输入字符就崩溃，无语。

引用 2 楼 zjq9931 的回复:1.输入字符串，会导致scanf返回0你的循环体就结束了，要处理好这种情况。    我这里有个示例代码，供你参考。  #include<stdio.h> int main() { 	int i; 	int iRet = 1; 	while(1) { 		iRet = scanf("%d*s", &i); 		printf("%d, %d", iRet, i); 		if (iRet == 0) { //没有输入数字，输入的是字符串 			//输入字符串后怎么处理，代码卸载这里。 		} 	} 	return 0; }   2.第二个问题printf("%3d", temp->net->name)，从变量名上看name应当是个字符型的变量，用数值的方式输出确实不太好。  我是为了图省事 结点定义的是struct node{ int name；struct node * next} 。。sancf是读入要搜索的链表中的第几个元素。

报错信息


Question: 有没有好的推荐的C语言书籍？

C prime plus，找最新版本的PDF格式的，可以边学习，边看敲代码练习

C语言教程（附带C语言100例）http://download.csdn.net/detail/zhao4zhong1/8830817

!(TanHaoqiang)

http://bbs.csdn.net/topics/391890488 资料不少 百度也有很多


Question: 接口设计问题

我觉得接口类不是只是一个规定吗？ 就是接口只是规定有哪些方法，具体的实现交由子类来做。 都说了是接口，肯定是只调用接口规定的方法啊，为什么要调用子类的，如果需要调用子类方法，那就定义子类对象呗 不知道说的对不对

那你需要的是两个接口类，而不是一个。


Question: 文档

是的,  我用了 rename , 但那是把  旧文件中的 “换” 字删除之后的新文件改名 ，改成原来的名字 。 所以名字上是相同的，但是内容 应该不能是相同的， 但运行结果确还是相同 ？

第1个问题可能是编码不一致，确保文本文件也用ASCII保存 第2个问题你remove后不是还rename了吗


Question: ARM64 structure 对齐问题

source code:   11 __attribute__ ((__section__(".init.data"))) uint32_t fw_ver = 0;    20 struct spinlock {                                                  21         uint32_t lock;                                                22 }__attribute__((packed));        78 __attribute__ ((__section__(".init.data"))) spinlock_t dbg_lock = {.lock = 0};  79 __attribute__ ((__section__(".init.data"))) uint32_t dbg_rd_idx = 0;   ldscript: 153 SECTIONS { 154 .init.data : { 155     156 } > INIT_DATA 157 }  system.map: 482  .init.data     0x000000000003fc00       0x10  483                 0x000000000003fc00                fw_ver 484                 0x000000000003fc08                dbg_lock 485                 0x000000000003fc0c                dbg_rd_idx  我想LZ想问的是为什么dbg_lock的地址是08而不是04，对吧。毕竟fw_ver的大小是4字节，那么04就可以了。  其实我倒不奇怪dbg_lock的地址是08。因为总的来说，不管计算机是怎样的架构，访问word是最快最有效的，这点LZ应该赞同吧。64位机器字长8字节，那么比8字节小的4字节整数，自然都是对其到8的倍数地址上访问时最有效的。  我更好奇的是，为什么dbg_rd_idx的地址是0c。按照上述的推理，dbg_rd_idx的地址应该是10，这样才更有效。仔细想想，觉得是__attribute__((packed))起了作用。  我有个想法，给fw_ver加上__attribute__((aligned (4)))，不知LZ能否帮忙试试，告诉我结果是怎样的。

提醒：gcc是开源的。

问了gcc的工程师，他的回复是：  aarch64固定了 struct/union/array的地址对齐到8字节，为了性能的优化。任何属性的设置都被忽略了。  他建议我在这种use case下避免使用struct。  如果这个编译器特性确实影响很大，可以向aarch64开发方报bug。

引用 69 楼 leslielg 的回复:[quote=引用 67 楼 DelphiGuy 的回复:] [quote=引用 54 楼 leslielg 的回复:] [quote=引用 46 楼 DelphiGuy 的回复:] [quote=引用 44 楼 leslielg 的回复:] [quote=引用 43 楼 DelphiGuy 的回复:] leslielg，瞧你这傻缺紧张的，连续引用两次。 要说逻辑错误么，某个傻缺说的“int在任何编译器都是32位 ”就是典型，逻辑智力不够啊。 至于你的所谓“问题”，我已经明确告诉你了，变量首地址对齐要用__attribute__((aligned(n))); 这是gcc文档中明确写了的，也是经过实践检验的，你的“问题”很可能是人品问题。  你这弱智跑来说一堆都是前面回帖里重复过的话，你看不懂前面写的字？__attribute__ aligned在之前就说过了，你跑来重提一遍还以为就是要害，你要么瞎要么智力不足。 int在任何编译器都是32位这个问题，我也明确回复过你让你说一个int不是32位的编译器出来，你又说不出来。你凭想象发言？  谈技术就谈技术，技术说不清了就扯出人品道德之类，你当什么程序员。劝你赶紧转行。[/quote]  你这傻缺果然是逻辑智力不够啊，且不说以前大把的dos、win16编译器int是16位的，就说现在，intel C++、Fortran也支持ilp64和lp64两种模型，ilp64模型的int就是64位的，见：https://software.intel.com/en-us/node/528863 多学着点吧，傻缺。 [/quote]  以前还有8位的编译器，任天堂的游戏机用的它，但是这种曾经存在过的编译器跟_现在的编译器_什么关联？拿过去的编译器来讨论现在的标准？你是哪里有毛病？  C语言的int长度是C的标准，跟Fortran什么关联？？？？？  说你傻缺不冤枉，找不到任何逻辑。[/quote]  傻缺你又跳出来表演你的智商。 1. intel C++、Fortran就是现在的编译器，你这狗脑子看不懂人话。 2. 你这狗脑子忘记你自己说的是“我也明确回复过你让你说一个int不是32位的编译器出来”，就在你的引用中不还有么。 3. 那么大的intel C++没看见么。 你继续跳好了，就让你继续表演，让大家好好欣赏你的嘴脸。 [/quote]  你这么傻逼，还如此三番五次的来秀你那进水的脑。难道是读不懂骂你的点？换个有点羞耻心的人早回炉重造去了。 [/quote]   继续回，回一次我就曹尼玛一次。尼玛不爽的话，就用辣椒曹尼玛，曹到尼玛叫到死为止。

引用 69 楼 leslielg 的回复:[quote=引用 67 楼 DelphiGuy 的回复:] [quote=引用 54 楼 leslielg 的回复:] [quote=引用 46 楼 DelphiGuy 的回复:] [quote=引用 44 楼 leslielg 的回复:] [quote=引用 43 楼 DelphiGuy 的回复:] leslielg，瞧你这傻缺紧张的，连续引用两次。 要说逻辑错误么，某个傻缺说的“int在任何编译器都是32位 ”就是典型，逻辑智力不够啊。 至于你的所谓“问题”，我已经明确告诉你了，变量首地址对齐要用__attribute__((aligned(n))); 这是gcc文档中明确写了的，也是经过实践检验的，你的“问题”很可能是人品问题。  你这弱智跑来说一堆都是前面回帖里重复过的话，你看不懂前面写的字？__attribute__ aligned在之前就说过了，你跑来重提一遍还以为就是要害，你要么瞎要么智力不足。 int在任何编译器都是32位这个问题，我也明确回复过你让你说一个int不是32位的编译器出来，你又说不出来。你凭想象发言？  谈技术就谈技术，技术说不清了就扯出人品道德之类，你当什么程序员。劝你赶紧转行。[/quote]  你这傻缺果然是逻辑智力不够啊，且不说以前大把的dos、win16编译器int是16位的，就说现在，intel C++、Fortran也支持ilp64和lp64两种模型，ilp64模型的int就是64位的，见：https://software.intel.com/en-us/node/528863 多学着点吧，傻缺。 [/quote]  以前还有8位的编译器，任天堂的游戏机用的它，但是这种曾经存在过的编译器跟_现在的编译器_什么关联？拿过去的编译器来讨论现在的标准？你是哪里有毛病？  C语言的int长度是C的标准，跟Fortran什么关联？？？？？  说你傻缺不冤枉，找不到任何逻辑。[/quote]  傻缺你又跳出来表演你的智商。 1. intel C++、Fortran就是现在的编译器，你这狗脑子看不懂人话。 2. 你这狗脑子忘记你自己说的是“我也明确回复过你让你说一个int不是32位的编译器出来”，就在你的引用中不还有么。 3. 那么大的intel C++没看见么。 你继续跳好了，就让你继续表演，让大家好好欣赏你的嘴脸。 [/quote]  你这么傻逼，还如此三番五次的来秀你那进水的脑。难道是读不懂骂你的点？换个有点羞耻心的人早回炉重造去了。 [/quote]  "换个有点羞耻心的人早回炉重造去了" 这话说得太好了，你咋这么有自知之明呢，你的那些笑料在这贴子里一直存在，你能让它们消失么？你是不是以为自己继续嘴硬就没有闹笑话？认清现实吧，傻缺。

引用 67 楼 DelphiGuy 的回复:[quote=引用 54 楼 leslielg 的回复:] [quote=引用 46 楼 DelphiGuy 的回复:] [quote=引用 44 楼 leslielg 的回复:] [quote=引用 43 楼 DelphiGuy 的回复:] leslielg，瞧你这傻缺紧张的，连续引用两次。 要说逻辑错误么，某个傻缺说的“int在任何编译器都是32位 ”就是典型，逻辑智力不够啊。 至于你的所谓“问题”，我已经明确告诉你了，变量首地址对齐要用__attribute__((aligned(n))); 这是gcc文档中明确写了的，也是经过实践检验的，你的“问题”很可能是人品问题。  你这弱智跑来说一堆都是前面回帖里重复过的话，你看不懂前面写的字？__attribute__ aligned在之前就说过了，你跑来重提一遍还以为就是要害，你要么瞎要么智力不足。 int在任何编译器都是32位这个问题，我也明确回复过你让你说一个int不是32位的编译器出来，你又说不出来。你凭想象发言？  谈技术就谈技术，技术说不清了就扯出人品道德之类，你当什么程序员。劝你赶紧转行。[/quote]  你这傻缺果然是逻辑智力不够啊，且不说以前大把的dos、win16编译器int是16位的，就说现在，intel C++、Fortran也支持ilp64和lp64两种模型，ilp64模型的int就是64位的，见：https://software.intel.com/en-us/node/528863 多学着点吧，傻缺。 [/quote]  以前还有8位的编译器，任天堂的游戏机用的它，但是这种曾经存在过的编译器跟_现在的编译器_什么关联？拿过去的编译器来讨论现在的标准？你是哪里有毛病？  C语言的int长度是C的标准，跟Fortran什么关联？？？？？  说你傻缺不冤枉，找不到任何逻辑。[/quote]  傻缺你又跳出来表演你的智商。 1. intel C++、Fortran就是现在的编译器，你这狗脑子看不懂人话。 2. 你这狗脑子忘记你自己说的是“我也明确回复过你让你说一个int不是32位的编译器出来”，就在你的引用中不还有么。 3. 那么大的intel C++没看见么。 你继续跳好了，就让你继续表演，让大家好好欣赏你的嘴脸。 [/quote]  你这么傻逼，还如此三番五次的来秀你那进水的脑。难道是读不懂骂你的点？换个有点羞耻心的人早回炉重造去了。

引用 54 楼 leslielg 的回复:[quote=引用 46 楼 DelphiGuy 的回复:] [quote=引用 44 楼 leslielg 的回复:] [quote=引用 43 楼 DelphiGuy 的回复:] leslielg，瞧你这傻缺紧张的，连续引用两次。 要说逻辑错误么，某个傻缺说的“int在任何编译器都是32位 ”就是典型，逻辑智力不够啊。 至于你的所谓“问题”，我已经明确告诉你了，变量首地址对齐要用__attribute__((aligned(n))); 这是gcc文档中明确写了的，也是经过实践检验的，你的“问题”很可能是人品问题。  你这弱智跑来说一堆都是前面回帖里重复过的话，你看不懂前面写的字？__attribute__ aligned在之前就说过了，你跑来重提一遍还以为就是要害，你要么瞎要么智力不足。 int在任何编译器都是32位这个问题，我也明确回复过你让你说一个int不是32位的编译器出来，你又说不出来。你凭想象发言？  谈技术就谈技术，技术说不清了就扯出人品道德之类，你当什么程序员。劝你赶紧转行。[/quote]  你这傻缺果然是逻辑智力不够啊，且不说以前大把的dos、win16编译器int是16位的，就说现在，intel C++、Fortran也支持ilp64和lp64两种模型，ilp64模型的int就是64位的，见：https://software.intel.com/en-us/node/528863 多学着点吧，傻缺。 [/quote]  以前还有8位的编译器，任天堂的游戏机用的它，但是这种曾经存在过的编译器跟_现在的编译器_什么关联？拿过去的编译器来讨论现在的标准？你是哪里有毛病？  C语言的int长度是C的标准，跟Fortran什么关联？？？？？  说你傻缺不冤枉，找不到任何逻辑。[/quote]  傻缺你又跳出来表演你的智商。 1. intel C++、Fortran就是现在的编译器，你这狗脑子看不懂人话。 2. 你这狗脑子忘记你自己说的是“我也明确回复过你让你说一个int不是32位的编译器出来”，就在你的引用中不还有么。 3. 那么大的intel C++没看见么。 你继续跳好了，就让你继续表演，让大家好好欣赏你的嘴脸。

引用 65 楼 zhao4zhong1 的回复:提醒：gcc是开源的。  这里讨论了这个问题。据他们工程师说在6月份release的版本里修复了这个问题。使用-Os可以取消 8字节对齐这个限制。  https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00073.html  但是我还是希望用attribute来设置对齐，比较灵活，不想用-Os。 好在问题明确了。

引用 27 楼 leslielg 的回复:[quote=引用 21 楼 zhao4zhong1 的回复:] 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素  能直接说明你的观点和建议么？[/quote] 学会使用调试窗口、内存窗口查看内存对齐的实际情况。 http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

引用 21 楼 zhao4zhong1 的回复:不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素  能直接说明你的观点和建议么？

引用 24 楼 lonelyhacker 的回复:uint32_t这个本身在gcc中是4字节对齐的。并不是8字节对齐的。  单字节 -> 地址是偶数地址 双字节 -> 地址是被4整除的地址 四字节 -> 地址是被8整除的地址  你这又是在胡说八道了  uint32_t占的长度是4字节，*并不代表它的地址是4字节对齐*，在可以非对齐访问的机器上(比如arm cortex A), uin32_t变量可以放到任何非对齐的地址上访问。  以下3句完全不明白在说什么，单字节必须是偶数地址那奇数地址放的是啥？  单字节 -> 地址是偶数地址 双字节 -> 地址是被4整除的地址 四字节 -> 地址是被8整除的地址

引用 23 楼 lonelyhacker 的回复:int在任何编译器都是32位？？？？？？  这个说法有点屌。。 第一次看到有人这样说的。  现在有int不是32位的编译器？你说个出来看看

引用 59 楼 leslielg 的回复:[quote=引用 51 楼 lonelyhacker 的回复:] [quote=引用 26 楼 leslielg 的回复:] [quote=引用 24 楼 lonelyhacker 的回复:] uint32_t这个本身在gcc中是4字节对齐的。并不是8字节对齐的。  单字节 -> 地址是偶数地址 双字节 -> 地址是被4整除的地址 四字节 -> 地址是被8整除的地址  你这又是在胡说八道了  uint32_t占的长度是4字节，*并不代表它的地址是4字节对齐*，在可以非对齐访问的机器上(比如arm cortex A), uin32_t变量可以放到任何非对齐的地址上访问。  以下3句完全不明白在说什么，单字节必须是偶数地址那奇数地址放的是啥？  单字节 -> 地址是偶数地址 双字节 -> 地址是被4整除的地址 四字节 -> 地址是被8整除的地址[/quote]   你现在讨论的是非对齐的吗？你现在所说的是arm cortex A吗？起始地址是偶数，奇数拿来干嘛？你猜拿来干嘛。 你的智力不适合当程序员。其他工作也不适合你，因为你装逼，而且装得很失败。 [/quote]  傻逼你概念都是错的。后面还讨论什么。还什么起始地址必须是偶数，一个地址就表示一个单字节。偶数奇数都是一个字节地址。 uint32_t这是个变量类型，跟对齐毫无关系。而且aarch64编译器就是给arm cortex A用的。  你要抬扛，要指出技术上的硬伤，是你能站住脚的基础。你说出错这么远的概念，还来跟我扯，不骂你傻逼对不起程序员这3个字。  你个傻逼还是算了吧，教不了你。[/quote]   怪不得这么多人在骂你傻逼。说了技术和智商都是你的硬伤。别做了。听爹的。该死那就死哪里去吧。

引用 51 楼 lonelyhacker 的回复:[quote=引用 26 楼 leslielg 的回复:] [quote=引用 24 楼 lonelyhacker 的回复:] uint32_t这个本身在gcc中是4字节对齐的。并不是8字节对齐的。  单字节 -> 地址是偶数地址 双字节 -> 地址是被4整除的地址 四字节 -> 地址是被8整除的地址  你这又是在胡说八道了  uint32_t占的长度是4字节，*并不代表它的地址是4字节对齐*，在可以非对齐访问的机器上(比如arm cortex A), uin32_t变量可以放到任何非对齐的地址上访问。  以下3句完全不明白在说什么，单字节必须是偶数地址那奇数地址放的是啥？  单字节 -> 地址是偶数地址 双字节 -> 地址是被4整除的地址 四字节 -> 地址是被8整除的地址[/quote]   你现在讨论的是非对齐的吗？你现在所说的是arm cortex A吗？起始地址是偶数，奇数拿来干嘛？你猜拿来干嘛。 你的智力不适合当程序员。其他工作也不适合你，因为你装逼，而且装得很失败。 [/quote]  傻逼你概念都是错的。后面还讨论什么。还什么起始地址必须是偶数，一个地址就表示一个单字节。偶数奇数都是一个字节地址。 uint32_t这是个变量类型，跟对齐毫无关系。而且aarch64编译器就是给arm cortex A用的。  你要抬扛，要指出技术上的硬伤，是你能站住脚的基础。你说出错这么远的概念，还来跟我扯，不骂你傻逼对不起程序员这3个字。  你个傻逼还是算了吧，教不了你。

引用 56 楼 lonelyhacker 的回复:楼主傻比。。。你上面说的是  有int不是32位的编译器。。。现在加了个“现在”两个字，你现在不用，表示别人没用吗？智障玩意。  智力正常的都不会非要去把8位时代的编译器扯出来，跟现在的讨论毫无关联。这种计算机发展史的讨论你跟你认识的傻逼们说去。

引用 46 楼 DelphiGuy 的回复:[quote=引用 44 楼 leslielg 的回复:] [quote=引用 43 楼 DelphiGuy 的回复:] leslielg，瞧你这傻缺紧张的，连续引用两次。 要说逻辑错误么，某个傻缺说的“int在任何编译器都是32位 ”就是典型，逻辑智力不够啊。 至于你的所谓“问题”，我已经明确告诉你了，变量首地址对齐要用__attribute__((aligned(n))); 这是gcc文档中明确写了的，也是经过实践检验的，你的“问题”很可能是人品问题。  你这弱智跑来说一堆都是前面回帖里重复过的话，你看不懂前面写的字？__attribute__ aligned在之前就说过了，你跑来重提一遍还以为就是要害，你要么瞎要么智力不足。 int在任何编译器都是32位这个问题，我也明确回复过你让你说一个int不是32位的编译器出来，你又说不出来。你凭想象发言？  谈技术就谈技术，技术说不清了就扯出人品道德之类，你当什么程序员。劝你赶紧转行。[/quote]  你这傻缺果然是逻辑智力不够啊，且不说以前大把的dos、win16编译器int是16位的，就说现在，intel C++、Fortran也支持ilp64和lp64两种模型，ilp64模型的int就是64位的，见：https://software.intel.com/en-us/node/528863 多学着点吧，傻缺。 [/quote]  以前还有8位的编译器，任天堂的游戏机用的它，但是这种曾经存在过的编译器跟_现在的编译器_什么关联？拿过去的编译器来讨论现在的标准？你是哪里有毛病？  C语言的int长度是C的标准，跟Fortran什么关联？？？？？  说你傻缺不冤枉，找不到任何逻辑。

引用 26 楼 leslielg 的回复:[quote=引用 24 楼 lonelyhacker 的回复:] uint32_t这个本身在gcc中是4字节对齐的。并不是8字节对齐的。  单字节 -> 地址是偶数地址 双字节 -> 地址是被4整除的地址 四字节 -> 地址是被8整除的地址  你这又是在胡说八道了  uint32_t占的长度是4字节，*并不代表它的地址是4字节对齐*，在可以非对齐访问的机器上(比如arm cortex A), uin32_t变量可以放到任何非对齐的地址上访问。  以下3句完全不明白在说什么，单字节必须是偶数地址那奇数地址放的是啥？  单字节 -> 地址是偶数地址 双字节 -> 地址是被4整除的地址 四字节 -> 地址是被8整除的地址[/quote]   你现在讨论的是非对齐的吗？你现在所说的是arm cortex A吗？起始地址是偶数，奇数拿来干嘛？你猜拿来干嘛。 你的智力不适合当程序员。其他工作也不适合你，因为你装逼，而且装得很失败。

引用 48 楼 DelphiGuy 的回复:[quote=引用 45 楼 leslielg 的回复:] [quote=引用 43 楼 DelphiGuy 的回复:] leslielg，瞧你这傻缺紧张的，连续引用两次。 要说逻辑错误么，某个傻缺说的“int在任何编译器都是32位 ”就是典型，逻辑智力不够啊。 至于你的所谓“问题”，我已经明确告诉你了，变量首地址对齐要用__attribute__((aligned(n))); 这是gcc文档中明确写了的，也是经过实践检验的，你的“问题”很可能是人品问题。  而且 __attribute__((aligned(n)))要怎么用你知道么？你还看了文档，一知半解就跑来发言，我写__attribute__((packed)))的地方能替换成aligned？还实践检验。 你写的这些东西基本上都是错的，引人耻笑。[/quote]  你这傻缺果然是一脑子浆糊，看看你在#15说了些啥？  引用 15 楼 leslielg 的回复:[quote=引用 11 楼 bravery36 的回复:] 另外，还可以用 __attribute__((packed))来取消填充。  你说的这个是结构体的内部对齐和填充，我问的是结构体被编译到的首地址。  另外你觉得我写这个结构体会产生8字节对齐？唯一一个成员就是4字节[/quote]  别人告诉你__attribute__((packed))，你说“这个是结构体的内部对齐和填充，我问的是结构体被编译到的首地址”，结果你代码你还用__attribute__((packed))，我告诉你了变量首地址对齐要用__attribute__((aligned(n)));  你又跑出来说“我写__attribute__((packed)))的地方能替换成aligned”，你说说你是不是傻缺、人品有问题？ [/quote]  这里的这个packed是用来pack结构体内部的对齐的，这个结构体本来内容不止这一个变量，所以需要pack，我删除了其它内容方便说明问题。你非要以为是用来对齐首地址的，而且还是在我前面说过了pack是用来内部对齐的情况下，不说你弱智说你啥？  而且要写aligned也不是在这个位置，这个位置跟aligned 毫无关系，是你看不懂非要把这个packed扯进来。说你半天都想不明白，你个傻缺。

引用 45 楼 leslielg 的回复:[quote=引用 43 楼 DelphiGuy 的回复:] leslielg，瞧你这傻缺紧张的，连续引用两次。 要说逻辑错误么，某个傻缺说的“int在任何编译器都是32位 ”就是典型，逻辑智力不够啊。 至于你的所谓“问题”，我已经明确告诉你了，变量首地址对齐要用__attribute__((aligned(n))); 这是gcc文档中明确写了的，也是经过实践检验的，你的“问题”很可能是人品问题。  而且 __attribute__((aligned(n)))要怎么用你知道么？你还看了文档，一知半解就跑来发言，我写__attribute__((packed)))的地方能替换成aligned？还实践检验。 你写的这些东西基本上都是错的，引人耻笑。[/quote]  你这傻缺果然是一脑子浆糊，看看你在#15说了些啥？  引用 15 楼 leslielg 的回复:[quote=引用 11 楼 bravery36 的回复:] 另外，还可以用 __attribute__((packed))来取消填充。  你说的这个是结构体的内部对齐和填充，我问的是结构体被编译到的首地址。  另外你觉得我写这个结构体会产生8字节对齐？唯一一个成员就是4字节[/quote]  别人告诉你__attribute__((packed))，你说“这个是结构体的内部对齐和填充，我问的是结构体被编译到的首地址”，结果你代码你还用__attribute__((packed))，我告诉你了变量首地址对齐要用__attribute__((aligned(n)));  你又跑出来说“我写__attribute__((packed)))的地方能替换成aligned”，你说说你是不是傻缺、人品有问题？


Question: 数据库、C语言

没事，谢谢你，给我提供了思路

引用 2 楼 summer_b 的回复:楼上的大神，第一个问题代码是这样的 void luying::on_pushButton_2_clicked() {           connect(ui->tableView,SIGNAL(clicked(QModelIndex)),this,SLOT(ShowSupplyclick())); } void luying::ShowSupplyclick() {         static QSqlQueryModel model(ui->tableView);         model.setQuery(QString("select * from Supply;"));         int row = ui->tableView->currentIndex().row();         QSqlRecord record = model.record(row);         ui->lineEdit->setText(record.value(0).toString());  } 但是显示QSqlQuery::exec: database not open，为什么呢 看来是QT代码，数据库没有打开，我不知道QT里面怎么用数据库的，抱歉了，这方面没有回答你了。

1.增加tableview的点击事件处理函数，在函数里面设置lineedit的内容 2.lineedit的文本，用GetWindowText来获取； 3.逆序输出的意思是，先输出的数据放到下面吧？在另一个窗口得到新的数据的时候插入到数据列的最前面。 因为没有具体代码，所以只能这么笼统的说了。


Question: 求大佬帮看这个程序 casse7这个功能怎么改下能实现

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

这是大学生课程设计?

建议多加些注释，方便观看

另外，把功能不要都写到main函数里，多自定义一些功能函数放到main函数之外，然后在main函数里调用。这样代码会更有条例，代码可读性就更高。

学生的数据结构建议总结一下，不建议分开；可以考虑使用如下的数据结构： struct stu_info {     char no[15];     char name[50];     float math, chinese, english;     float sum; }; struct stu_info stu[student_count];

你单步跑一下你这个程序，里面很多地方都是跳过的，没法运行，全是一些定义数据类型的时候的随机值，怎么比较大小交换。


Question: C语言单链表逆置

数据结构对单链表进行数据排序 http://bbs.csdn.net/topics/392201633

我认为问题并不像你所说的那样，因为你在创建链表的时候每次添加一个节点，节点的next指针就已经指向了NULL。其实是你的逆转函数有问题的，我同意2楼的逆转函数和观点。另外我觉得你创建链表的那个函数中for循环里边那个while(i == n)的循环和判断是没有什么实际意义的（因为进入for循环的条件就是i < n ,在循环里边 i == n 这种情况应该是不会出现的）。

#include<stdio.h> #include <malloc.h>  typedef struct Node {     int element;     struct Node *next; }Node;  Node * Create(int n) {     Node *head,*p,*tail,*q;     int i,x;      head = NULL;     tail = NULL;     q = NULL;     for(i=0;i<n;i++)     {         p=(Node *)malloc(sizeof(Node));         printf("输入一个数:  \n");         scanf("%d", &x);         p->element = x;         p->next = NULL;         if(NULL==head)             head = p;         else             tail->next = p;         tail = p;          if (i == n)             p->next = q;     }     return head;  } void print(Node * head) {     Node *p;     p = head;     if(!head) {         printf("链表为空！\n");     } else {         printf("如下所示：\n");         while(p) {             printf("%d ",p->element);             p = p->next;         }     }     putchar(10); }  Node * Inverse(Node * head) {     Node *p, *q, *s;      if(!head)         return NULL;      p = head;     s = head->next;     head->next = NULL;      while (s) {         q = s->next;         s->next = p;         p = s;         s = q; /*  *      Node *r;         r = p;         while (r) {             printf("%d\t", r->element);             r = r->next;         }         putchar(10);         */     }      return p;  /*     q = head->next;     while(q->next!=NULL)     {         p=q->next;         q->next=p->next;         p->next=head->next;         head->next=p;     }     return head; */ } int main() {     Node *head;     int x;     printf("链表内有几个数： \n");     scanf("%d",&x);     head = Create(x);     print(head);     head = Inverse(head);     printf("逆转后的链表为：");     print(head);     return 0; } 参考一下吧。 逆转之后的头结点需要返回，但是你没有使用返回的头结点。另外，你的逆转逻辑有问题。

输入 1 2 3 4 但是输出1 4 3 2  我想问题主要出在初始化的时候最后一个结点的next没有指向一个NULL 但如何加 敢问大佬们


Question: 为什么会有这样的打印

第一个问题: i<0这个条件在这里恒为false,所以while里的语句不会执行。  第二个问题: memset是按字节进行初始化的，因此你这个表达式实际上只初始化了前10个字节。然后，每个字节按照1的二进制位初始化，均为00000001，输出的时候，int又是一次取4个字节，即00000001000000010000000100000001，所以第0个和第1个元素均为16843009，第2个元素实际上只初始化了两个字节，所以为257，再后面都没有初始化。

引用 3 楼 user-5 的回复:你只填了10个字节，每个字节为1，而一个int有32字节 一个int有32位，而不是32个字节的。并且是在32为系统里。   while(i < 0)   /*条件不满足，不能进入循环，所以无打印。天剑改成i >= 0*/ {     printf(" %d ", DFBE[i]); i--; }

1 为什么第三种情况 memset(DFBE, 0, sizeof(DFBE) / sizeof(int)); 时输出都是0？ 其原因并不是应为这一行代码将DFBE中的所有元素都设置成0，而是在于 在函数体外定义的内置数组，其元素均初始化为0 也就是说，即使没有这一行代码，因为DFBE是全局变量，所以默认初始化为0，实际上 memset(DFBE, 0, sizeof(DFBE) / sizeof(int)); 只是将DFBE前10个字节设置成了0。 2 sizeof(DFBE) / sizeof(int)的作用是什么？ sizeof(DFBE) / sizeof(int)的作用是获取数组中元素的个数，而不是数组的大小，即 sizeof(DFBE) / sizeof(int)的值是10，数组的大小为sizeof(DFBE) 3 如果想将DFBE的初始值都设置为1，怎么办？ 因为memset操作的内存，以字节位单位，而DFBE是int的数组，以int为单位。所以要想将DFBE的初始值都设置为1，可以在定义DFBE时使用数组初始化，即 int DFBE[10] = {1, 1, 1, 1, 1, 1, 1, 1, 1,1}; 或者在main()函数中 for(int i=0; i<9; ++i) {    DFBE[i] = 1; }

2打印的是DFBE[9]-DFBE[1]，而 sizeof(DFBE) / sizeof(int)的值是10，memset(DFBE, 1, sizeof(DFBE) / sizeof(int));只是将DFBE前10个字节设置成了0x01

1 当条件为真时，while 语句反复执行目标语句。它的语法形式如下： while (condition) statement 只要条件 condition 的值为 true，执行语句 statement（通常是一个块语句）。condition 不能为空。如果第一次求解 condition 就产生 false 值，则不执行 statement。 你的while语句的条件是i<0，因为i的值是9，所以条件是false，不执行statement，所以就不会打印。

i==9,不满足while的条件i<0，所以没有执行循环体内内容

此外，就算你32字节全填为1，他的值也不是1

你只填了10个字节，每个字节为1，而一个int有32字节

相当于IDE帮你调用了system("pause")最后暂停下来，方便你查看结果，实际运行这个程序执行完就自动退出了


Question: 请大神帮我拍看一下错在哪？为什么谭浩强的代码写出来不行

#include<stdio.h> int main() {     int max(int x,int y);     int a,b,c;     scanf("%d%d",&a,&b);     c=max(a,b);     a=5;     b=8;     ptintf("max=%d\n",c);   // 改成 printf("max=%d\n",c); // 拼写错误     return 0; ;}  // 多了个分号，不过不影响 int max(int x,int y) {     int z;     if(x>y)z=x;     else z=y;     return(z); }

引用 1 楼 qq_38204686 的回复:;}  前面多了个; 删掉楼下正解。只有;是空语句，在这里并不会有影响的，话说楼主的IDE都没有提示么？一般都有语法错误提示的。这里printf打错，会提示未定义的函数的；

ptintf("max=%d\n",c); 修改为 printf("max=%d\n",c);   打错单词了吧

;}  前面多了个; 删掉

#include<stdio.h>     int max(int x,int y); int main() {     int a,b,c;     scanf("%d%d", &a, &b);     c = max(a,b);     a=5;     b=8;     printf("max=%d\n",c);     return 0;  } int max(int x,int y) {     int z;     if(x > y)         z = x;     else         z = y;     return(z); }  printf单词拼写错误。


Question: 归并排序递归调用

引用 7 楼 a645328869 的回复:[quote=引用 6 楼 for_grasp 的回复:] @幻夢之葉 @OldHello  我能理解这个意思，但是a[]一开始并没有排好序啊，对它不断分半的在作用和直接用岂不是一样嘛 分半以后再比较 然后排序 然后合并，合并后仍然有序,直到全部合并完。 合并两个有序序列，是比较两个有序序列的第一个元素，谁小把谁放进最终序列的结尾，并把它从原来的队列里面删掉直到有个序列为空。 比如[1 4 3 2 ] ->  [1 4] [3 2] ->比较两次 -> [1 4] [2 3] -> 取出1 和 2 比较 1小 进最后序列 [1] 然后比较4和2 2小 就是[1 2 3 4]  因为[2 3]本来就是有序的 所以1 4 3 2 比较两次 ->[1 2 3 4]，直接用的话，你看比较要多少次。分离和合并是很快的。[/quote]  引用 8 楼 for_grasp 的回复:@OldHello  1. merge_sort(r,t,m,p);           /  /递归调用，将r[m]~r[p]归并成有序的t[m]~t[p]                               2.merge_sort(r,t,p+1,n);       /  /类似上步骤，归并后半部分                        3.merge(t ,s,m,p,n);}      是不是在1中递归分半到不能再分之后，就进入3.进行排序合并吗，还是进入2，又直到2分半完，再一起进入3？

不懂你在说什么，每次递归时分为左、右，然后再让两边合并  http://blog.csdn.net/morewindows/article/details/6678165/

就比如一副扑克牌，你整副牌一起进行排序（方块A~K，然后梅花A~K......）假设除去大小王共52张 你先进行一次对分每部分26，再对分13......一直到每部分只有一张（无需排序）或两张（对其进行一次排序） 之后选两组何在一起，再进行一次排序（因为两组都是有序的，所以排序相对简单些，只需要不断向前比较） 继续上述过程，直到全部的牌合为一组

任务进行分解成小块，最后再合并求解结果！ 不断调用递归函数，任务会不会被划分，直到满足条件，之后原路返回（由深到浅的函数退出）即为合并求解结果

嵌套运行，满足条件出来，执行下一句。 一定是先执行完第一句， merge_sort(r,t,m,p);  不管里面递归了几次，p=(m+n)/2，最后P一定会和m相等。等于是你想把一块柴砍的很细，首先你把S柴砍成了两半A B，然后你把其中一半A又砍了一半A1 A2，你把A1这一半又砍了一半A11 A12，A11可以了，下一步砍A12.A12也可以了,那么A1就砍完了.接下来砍A2，A2也慢慢的砍完了，那么A就砍完了。接下来砍柴火B，一样的一个一个砍完了，那么柴火B就砍完了。也就意味着S柴砍完了。 我是这样理解的^_^

引用 6 楼 for_grasp 的回复:@幻夢之葉 @OldHello  我能理解这个意思，但是a[]一开始并没有排好序啊，对它不断分半的在作用和直接用岂不是一样嘛 分半以后再比较 然后排序 然后合并，合并后仍然有序,直到全部合并完。 合并两个有序序列，是比较两个有序序列的第一个元素，谁小把谁放进最终序列的结尾，并把它从原来的队列里面删掉直到有个序列为空。 比如[1 4 3 2 ] ->  [1 4] [3 2] ->比较两次 -> [1 4] [2 3] -> 取出1 和 2 比较 1小 进最后序列 [1] 然后比较4和2 2小 就是[1 2 3 4]  因为[2 3]本来就是有序的 所以1 4 3 2 比较两次 ->[1 2 3 4]，直接用的话，你看比较要多少次。分离和合并是很快的。

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

这是一个顺序执行的过程，递归则会悬置当前的代码。递归的首要就是划分规模或者计算难度的，到达最深的调用完整执行函数代码，退出之后运行上一次调用函数自身（递归函数），再完整执行，一直回退到达第一次的调用，整个过程结束。


Question: 一个程序用SendMessage和keybd_event模拟按键,两种打开方式结果不同,求教

又用按键精灵不挂句柄模拟按键 应当是这个原因了。 就是两种打开方式，窗口的句柄是不同的。 用SPY++看看是不是这样。

检查函数返回值，判断失败原因，再作分析


Question: 求教递归问题

可以单步跟踪程序运行，观察程序流程及变量变化情况

我也是个萌新，个人平常是 递归就先简化。从最简单的举例开始，比如s="01（或者abc）",，然后跟着调试或者Printf输出，不太会就用记事本记一下，不过一定要学会调试，监控值的变化。发现好像没有变化，那就s="012"，递归关键看如何终结的条件，根据其来举例。

能否简单分析说明一下

新手是不可能快速看出代码的意图的，如果你不是天才，只有靠积累

就是看代码逻辑，熟悉编程技巧； 对于递归的代码，建议你分步调试和打印对应递归变量的值。

判断是否为回文字符串


Question: 在一个程序中计算出给定误差小于0.1,0.01,0.001,0.0001,0.00001 这题这样解算正确吗？来个人帮忙看看！

#include<stdio.h> #include<math.h>  int main() { 	double dx; 	double precision1 = 0.1; 	double precision2 = 0.01; 	double precision3 = 0.001; 	double precision4 = 0.0001; 	double precision5 = 0.00001;  	double denominator = 0; 	double numerator = 0; 	double dRes = 1; 	double dPreRes = 0; 	double precision = 0;  	for(dx = 1; ; dx++) { 		denominator = (2 * dx + 1)*(2 * dx + 1); 		numerator = 2 * dx*(2 * dx + 2); 		dRes *= numerator / denominator; 		precision = dPreRes - dRes;  		printf("%f\n", dRes); 		printf("------\n"); 		if (fabs(precision) < precision1) { 			printf("%3.1f\n", dRes); 		}  		if (fabs(precision) < precision2) { 			printf("%4.2f\n", dRes); 		}  		if (fabs(precision) < precision3) { 			printf("%5.3f\n", dRes); 		}  		if (fabs(precision) < precision4) { 			printf("%6.4f\n", dRes); 		}  		if (fabs(precision) < precision5) { 			printf("%7.5f\n", dRes); 			break; 		} 		dPreRes = dRes; 	}  	return 0; }

浮点数格式 http://bbs.csdn.net/topics/390676437

精度误差，使用double更精确

单精度和双精度的区别。 题目要求应该是让你给出类似这种答案： printf("%.1f, %.2f, .3f%);//逗号后面的数字依次增加

没人帮忙看看吗！


Question: realloc内存重新分配地址变化问题

realloc若是申请的大小比之前的小，是将原来的内存（可用）减少了。 至于申请过大，而之前所在的块不足，则拷贝数组至更大的块里。这些对我们使用者来讲是透明的，即看不到，也不需要注意。它如果申请成功，则会返回一个更大块的内存首地址。

你要问什么？  http://en.cppreference.com/w/c/memory/realloc  If there is not enough memory, the old memory block is not freed and null pointer is returned. If ptr is NULL, the behavior is the same as calling malloc(new_size). If new_size is zero, the behavior is implementation defined (null pointer may be returned (in which case the old memory block may or may not be freed), or some non-null pointer may be returned that may not be used to access storage).

没看到你想表达什么，是给大家科普？

MSDN官方文档里面是这么说的 The size argument gives the new size of the block, in bytes. The contents of the block are unchanged up to the shorter of the new and old sizes, although the new block can be in a different location. Because the new block can be in a new memory location, the pointer returned by realloc is not guaranteed to be the pointer passed through the memblock argument. realloc does not zero newly allocated memory in the case of buffer growth.


Question: 求指导C Primer Plus上的一道题目

引用 4楼自信男孩 的回复:printf ("\n"); 这句可以直接用 putchar(10); 代替是哦，谢谢哈！又学到了~

引用 2楼kuangbao9 的回复:你这应该任何个字符最后都会有个10;，这个是\n回车符的ASCII。你的程序是以#结束的，你按回车之后并没有结束，而是把内容刷新到控制台上显示，换行符也在其中。如果你每次以#结束，就没有这个问题了嗯嗯，谢谢，我把回车的asc2码记错了

引用 1楼user-3 的回复:10 就是回车符号的 ASCII 码, 没什么问题呀是诶！谢谢~~

printf ("\n"); 这句可以直接用 putchar(10); 代替

'\n'就是回车符，对应的ASCII值就是10.

10 就是回车符号的 ASCII 码, 没什么问题呀


Question: 动态分配内存问题

sizeof(jock)的长度是固定的，4. malloc没问题，问题出在sizeof(jock)，因为jock是指针变量，所以sizeof(jock) = 4  #include<stdio.h> #include<string.h> #include<stdlib.h>  int main(void) {     char str1[] = "The jock is:\n\n";     char str2[][80] = {         "Include one or more other config files here.This is useful if you\n",         "have a standard template that goes to all Redis servers but also need\n",         "to customize a few per - server settings.Include files can include\n",         "other files, so use this wisely\n"     };     int strcount = sizeof(str2) / sizeof(str2[0]);     unsigned int length = 0;     for (int i = 0; i < strcount; i++)     {         length += strnlen_s(str2[i], sizeof(str2[i]));      }     unsigned int newsize= length + strnlen_s(str1, sizeof(str1)) + 1;     char *jock=(char *)malloc(newsize);     if (strncpy_s(jock, newsize, str1, sizeof(str1)))     {         printf("ERROR!\n");         return 1;     }     for (int i = 0; i < strcount; i++)     {         if (strncpy_s(jock + strnlen_s(jock, newsize), newsize, str2[i], sizeof(str2[i])))         {             printf("ERROR!\n");             return 2;         }     }     printf("%s", jock);     free(jock);     jock = NULL;     return 0;   }

if (strncpy_s(jock, sizeof(jock), str1, sizeof(str1)))  注意 sizeof(jock) 取得的是指针的大小 4, 而不是你分配的内存大小. 把所有的 sizeof(jock) 改成  newsize 吧


Question: 怎么将unsigned char数组转换成16进制的unsigned char

引用 8 楼 adlay 的回复:直接追加就行了, 不用做转换 只有显示给人看的时候才有十进制和十六进制的说法, 对一个整数来说, 你把它写成十进制还是十六进制, 这个数还是这个数, 没有变化的. ok ok ，直接追加进去就可以了

我要转换成16进制追加到unsigned char 的数组中发送到串口

我要转换成16进制追加到unsigned char 的数组中发送到串口

引用 3 楼 user-3 的回复:你是想把  44 77 88 99  这样的16进制数值, 转换字符串吗?  还是要如何.  因为数值本身是没有10进制, 16进制之分的.   除非你要转换成字符串来显示, 才有区别. 同意见解。 十进制和十六进制只是输出的格式不一样，比如0x10和16是相等的。如果用%d输出的就是10进制，用%x或%X输出的就是16进制数。

unsigned char data[4] = { 44,55,66,77 }; 	char ch[32] = { 0 };  	for (int i = 0; i < 4; i++) 	{ 		sprintf(&ch[2 * i], "%02X", data[i]); 	}

请大家帮忙，谢谢


Question: c版本的正则表达式

谢谢  引用 1 楼 user-1 的回复:\\d*  表示匹配0个或者多个数字的字符串.  这样就会匹配多次. A前面有0个数字, 这是第一次匹配 然后A后面的数据123456是第二次匹配 然后B后面有0个数字, 这是第三次匹配  至于你说的\\d+为什么不能匹配, 这就不好解释了. 至少在我使用的正则表达式工具中, \\d+是能唯一匹配123456的.  只能说明你用的那个库, 可能存在bug, 或者你输入错误


Question: 求大神，为什么会这样？

你这是比较对象错了吧？？  应该这样吧   if(stu[i].sum < stu[j].sum)

调试一下吧.  你这个排序都是有问题的.


Question: 用return返回一个数值

前面改的差不多了，我再说一个问题，这个程序有点问题吧.count真的能统计字符数吗？ 每一次执行函数count都被赋值0，count的值永远不会大于1啊 把count定义成全局变量吧

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; //自动跳过一个或多个空格或Tab字符或回车换行，读取下一个字符。

scanf("%c",c)   改成  scanf("%c",&c)  其次先把count初始化为0

count 没有初始化。

#include<stdio.h> int ch(char); int main(void) {   char c;   while(scanf("%c", &c)==1)    //scanf,第二个参数是地址。           printf("that is %d chars\n",ch (c));         return 0; }   int ch(char a)   {     int count = 0;    //初始化。     if (isalpha(a))       count++;     return count;   }

int count = 0; //记得初始化


Question: c语言 怎么将字符串中的地址取出其内存输出

恩 那么知道了这个unsigned int 型的地址以后，怎么取得这个地址的内存呢  我想到的*(int *)addr会报错

那就是需要将字符串转换成地址值。   unsigned int addr;  sscanf(str, "%x", &addr); printf("%#x\n", addr);   这里addr的值就是0x100000；

请在DosBox下使用TC运行。


Question: 各变量在内存中的存储空间

引用 2 楼 a1qwertyuiop1 的回复:引用 1 楼 paschen 的回复:你指针变量本身是在栈中存储，函数返回值通过复制传递而指针指向的内存前者在常量区，后者在栈上，由于后者函数结束后，栈上内容被销毁，所以输出的是乱码既然栈的内容要销毁，为何还能输出00336B30和004DFBF8,不是应该也要被销毁吗  上面不是回答你了，函数返回值通过复制传递，销毁前已经进行了复制

引用 1 楼 paschen 的回复:你指针变量本身是在栈中存储，函数返回值通过复制传递  而指针指向的内存前者在常量区，后者在栈上，由于后者函数结束后，栈上内容被销毁，所以输出的是乱码 既然栈的内容要销毁，为何还能输出00336B30和004DFBF8,不是应该也要被销毁吗

a，b两个变量都是临时变量，因为它们都定义在函数内。对于临时变量是存放在函数栈上的。临时变量的生命周期是从定义开始到函数调用结束；所以'b', 'c'字符无法输出，也有可能可以输出，这个主要是函数返回临时变量是未定义的行为，即有可能能正确输出也可能不能正确输出，取决于释放的空间有没有被再次申请（栈的释放和申请是很频繁的），存放'b', 'c'的内存位置会被会被覆盖。 “psa”是字符串常量，存放在数据段（只读数据段），其生命周期是从定义的开始到整个程序结束； function();函数为什么可以正常输出，就是因为该函数返回的是数据段的字符串的首地址，它的生命周期是整个程序有效；所以，返回该字符串的地址就可以找到该字符串。 堆上的空间，一般是通过malloc， calloc，realloc函数申请的，并且需要手动释放free，C++还有一个new和delete 这类问题主要是分清变量在内存中存放的位置，即它们的生命周期。对于理解变量会有很大帮助。

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

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

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素


Question: 一个宽字符用wprintf输出正常，putwchar不能正常输出

统一改成Use Multi-Byte Character Set算了

引用 9 楼 SL091210 的回复:[quote=引用 4 楼 zjq9931 的回复:] [quote=引用 2 楼 lwj7423 的回复:] 还是不行，感觉应该是IDE有所更改；主要问题应该还是在VS2015上面 我用VS2015也是可以的啊。[/quote]  我用2015也是不行啊，气死我了[/quote] 应当是源文件编码的问题，另存成ANSI编码的源文件，然后再编译就可以了。

引用 4 楼 zjq9931 的回复:[quote=引用 2 楼 lwj7423 的回复:] 还是不行，感觉应该是IDE有所更改；主要问题应该还是在VS2015上面 我用VS2015也是可以的啊。[/quote]  我用2015也是不行啊，气死我了

引用 7 楼 zhao4zhong1 的回复:估计是楼主的Win10该升级或重装一个稳定版本了。  老师你好，我也和楼主一样的情况，我粘贴您的代码也是putwchar无法显示，wprintf可以显示，请问原因有可能是什么呢

估计是楼主的Win10该升级或重装一个稳定版本了。

vs2015，VC++编译器19.00.24210，用32位和64位编译器编译楼主的代码，结果均正常。

引用 2 楼 lwj7423 的回复:还是不行，感觉应该是IDE有所更改；主要问题应该还是在VS2015上面 如果还是不行，有可能是你的.cpp文件用的是其他编码的。 你可以用记事本打开以下，然后另存成ANSI编码，然后用另存的这个文件编译输出试试。

引用 2 楼 lwj7423 的回复:还是不行，感觉应该是IDE有所更改；主要问题应该还是在VS2015上面 我用VS2015也是可以的啊。

反正我用WinXP＋VC6是行的。

还是不行，感觉应该是IDE有所更改；主要问题应该还是在VS2015上面

#include<stdio.h> #include<locale.h> #include<stdlib.h>  void main() { setlocale(LC_ALL, "chs");  wchar_t chs ; chs = L'我'; putwchar(chs); wprintf(L"%c", chs); fflush(stdout);  system("pause"); }


Question: 二叉树建立里的scanf为啥不运行呢 ？？

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。 //请今后要用 char c; scanf("%c",&c); //时，都改为 char s[2]; char c; scanf("%1s",s); c=s[0]; //自动跳过一个或多个空格或Tab字符或回车换行，读取下一个字符。

scanf %c 会读取回车 注意一下

晕倒，手机里发的，排版怎么成这样呢

/*2017年9月12日13:46:02 建立二叉树，并遍历。 01（上个程序）：静态建立（即不需要用户输入数据，程序员已经设定好了各个树的数据域） 02（本程序）：尝试动态建立二叉树（即用户自己输入各个子树的数据域，程序接收） */  # include <stdio.h> # include <malloc.h>  struct BTNode { 	char data; 	struct BTNode * pLchild; 	struct BTNode * pRchild; };  struct BTNode * CreateBTree(); void Fuzhi(struct BTNode * pA); void PreTraverseBTree(struct BTNode * pT);  int main(void) { 	struct BTNode * pT = CreateBTree(); 	PreTraverseBTree(pT);/7oid PreTraverseBTree(struct BTNode * pT);这行原来是这样写的，也不报错，就是无输出结果。 	//pT本身已经是地址，前面再加struct BTNode *是啥意思呢，不懂！可以试试去掉或加上，运行看看。 	 	return 0; }   struct BTNode * CreateBTree(void) { 	struct BTNode * pA = (struct BTNode *)malloc(sizeof(struct BTNode)); 	struct BTNode * pB = (struct BTNode *)malloc(sizeof(struct BTNode)); 	struct BTNode * pC = (struct BTNode *)malloc(sizeof(struct BTNode)); 	struct BTNode * pD = (struct BTNode *)malloc(sizeof(struct BTNode)); 	struct BTNode * pE = (struct BTNode *)malloc(sizeof(struct BTNode)); 	 	pA->data = 'A'; 	pB->data = 'B'; 	pC->data = 'C'; 	pD->data = 'D'; 	pE->data = 'E'; 	 	pA->pLchild = pB; 	pA->pRchild = pC; 	pB->pLchild = pB->pRchild = NULL; 	pC->pLchild = pD; 	pC->pRchild = NULL; 	pD->pLchild = NULL; 	pD->pRchild = pE; 	pE->pLchild = pE->pRchild = NULL;  	Fuzhi(pA); 	 	 	return pA; }   void Fuzhi(struct BTNode * pA) { 	if(NULL != pA) 	{ 		printf("请输入子树%c的数据域值(字符型)：", pA->data); 		scanf("%c", pA); 		printf("哈哈"); 		printf("\n"); 		if(NULL != pA->pLchild) 		{ 			Fuzhi(pA->pLchild); 		} 		 		if (NULL != pA->pRchild) 		{ 			Fuzhi(pA->pRchild); 		} 	} 	 }   void PreTraverseBTree(struct BTNode * pT) { 	if(NULL != pT) 	{ 		printf("%c\n", pT->data); 		if(NULL != pT->pLchild) 		{ 			PreTraverseBTree(pT->pLchild); 		} 		if(NULL != pT->pRchild) 		{ 			PreTraverseBTree(pT->pRchild); 		} 	} 	 }  /* 2017年9月12日20:12:46  输出结果为(不懂啊，为啥B和D的scanf没有执行 ？)：  请输入子树A的数据域值(字符型)：k 哈哈 请输入子树B的数据域值(字符型)：哈哈 请输入子树C的数据域值(字符型)：m 哈哈 请输入子树D的数据域值(字符型)：哈哈 请输入子树E的数据域值(字符型)：n 哈哈 k   m   n Press any key to continue  */

/*2017年9月12日13:46:02   建立二叉树，并遍历。   01（上个程序）：静态建立（即不需要用户输入数据，程序员已经设定好了各个树的数据域）   02（本程序）：尝试动态建立二叉树（即用户自己输入各个子树的数据域，程序接收）   */  # include <stdio.h> # include <malloc.h>  struct BTNode {     char data;     struct BTNode * pLchild;     struct BTNode * pRchild; };  struct BTNode * CreateBTree(); void Fuzhi(struct BTNode * pA); void PreTraverseBTree(struct BTNode * pT);  int main(void) {     struct BTNode * pT = CreateBTree();     PreTraverseBTree(pT);          return 0; }   struct BTNode * CreateBTree(void) {     struct BTNode * pA = (struct BTNode *)malloc(sizeof(struct BTNode));     struct BTNode * pB = (struct BTNode *)malloc(sizeof(struct BTNode));     struct BTNode * pC = (struct BTNode *)malloc(sizeof(struct BTNode));     struct BTNode * pD = (struct BTNode *)malloc(sizeof(struct BTNode));     struct BTNode * pE = (struct BTNode *)malloc(sizeof(struct BTNode));      pA->data = 'A';     pB->data = 'B';     pC->data = 'C';     pD->data = 'D';     pE->data = 'E';      pA->pLchild = pB;     pA->pRchild = pC;     pB->pLchild = pB->pRchild = NULL;     pC->pLchild = pD;     pC->pRchild = NULL;     pD->pLchild = NULL;     pD->pRchild = pE;     pE->pLchild = pE->pRchild = NULL;      Fuzhi(pA);       return pA; }   void Fuzhi(struct BTNode * pA) {     if(NULL != pA)     {         printf("请输入子树%c的数据域值(字符型)：", pA->data);         scanf("%c", &pA->data);         getchar();         printf("哈哈");         printf("\n");         if(NULL != pA->pLchild)         {             Fuzhi(pA->pLchild);         }          if (NULL != pA->pRchild)         {             Fuzhi(pA->pRchild);         }     }  }   void PreTraverseBTree(struct BTNode * pT) {     if(NULL != pT)     {         printf("%c\n", pT->data);         if(NULL != pT->pLchild)         {             PreTraverseBTree(pT->pLchild);         }         if(NULL != pT->pRchild)         {             PreTraverseBTree(pT->pRchild);         }     }  }  注意scanf("%c", &pA->data); 另外，对于%c输入比较特殊，因为上次输入的回车符残留在输入缓存里，加一个getchar()就是为了接收这个回车符。


Question: 内存地址无法释放

只用free(p)就行。

不能两次free一块内存，clloc时p[0]p[1]的的内存其实就是p所指向的，就是说p其实是p0与p1和一样，所以要么你就只free掉p，要么你就不能free p然后你可以free其他两个

p[0]=strtok(a," ");     p[1]=strtok(NULL," "); 这两个操作已经修改了p[0], p[1]的地址了。即上面calloc申请的内存地址的首地址被覆盖了。这样会造成内存泄露。 这样改一下：  #include <stdio.h> #include <stdlib.h> #include <string.h>  int main() {     char a[]="Ti Al V";     char **p, *tmp;     p = (char **)calloc(2,sizeof(char *));     p[0] = (char *)calloc(4,sizeof(char));     p[1] = (char *)calloc(4,sizeof(char));      tmp = strtok(a," ");     strcpy(p[0], tmp);     tmp = strtok(NULL," ");     strcpy(p[1], tmp);     printf("%s\n",p[0]);     printf("%s\n",p[1]);     free(p[0]);     free(p[1]);     free(p);     return 0; }

p[0] = strtok(a, " "); p[1] = strtok(NULL, " "); 这两句你重新对p0 p1赋值了


Question: 求大神，为什么会这样？

第一个scanf需要按下回车键才能读入，但是读入后，这个回车键还在输入流里，所以，如果下一个还是读入字符，就会把这个回车键读进去。 getchar()在输入缓冲区顺序读入一个字符(包括空格、回车和Tab). 第一次getchar()时，需要人工的输入，但是如果你输了多个字符，以后的getchar()再执行时就会直接从缓冲区中读取。

应该在scanf("%d", &n);后面在加一句getchar();若不加这句getchar();下面的b获得就是回车符；

getchar(); b = getchar(); getchar();  上一次读取还遗留了一个换行符


Question: 关键路径算法，运行以下程序有问题，大神帮忙看看原因？

scanf_s %c %s时还需要一个参数，或者换成scanf

scanf_s(" %c %c %d",&v1,1,&v2,1,&w);


Question: 关于指针分配内存和超出内存空间的问题

多一个星和少一个星，对于这个结构体而言，申请的字节数不一样。 多一个星的，申请的是一个指针的长度，对于32为系统，一个指针占4个字节，即申请的是4个字节。 少一个星的，申请的是一个结构体的长度，即8个字节长度；  对于char *p而言，区别也是申请的长度不一样，带星的是4个字节，不带的是1个字节。 记住sizeof是计算类型长度的，或者是变量类型长度。 后果很严重，越界访问会造成数据不正确或者直接非法地址访问，提示段错误。

student *  是指针类型，32位机中占4个字节 student  是结构体类型，占8个字节

多线程需要加锁。 使用realloc的正确姿势参考下面： //输出PROG中有但LIST中没有的文本行，即集合PROG-LIST #include <stdio.h> #include <string.h> #include <stdlib.h> #include <search.h> #define MAXCHARS 512 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; char PROG[256]="PROG";//程序Program需要的文件列表 char LIST[256]="LIST";//dir /b /s生成的实际文件列表List FILE *fp,*fl; int i,c,n,L,hh; int ignore_case=0; char ln[MAXCHARS]; 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>1) strcpy(PROG,argv[1]);//命令行参数1覆盖PROG     if (argc>2) strcpy(LIST,argv[2]);//命令行参数2覆盖LIST     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     if ((fl=fopen(LIST,"rt"))==NULL) {         fprintf(stderr,"Can not open %s\n",LIST);         fprintf(stderr,"Usage: %s [PROG] [LIST] [-i]\n",argv[0]);         return 1;     }     if ((fp=fopen(PROG,"rt"))==NULL) {         fclose(fl);         fprintf(stderr,"Can not open %s\n",PROG);         fprintf(stderr,"Usage: %s [PROG] [LIST] [-i]\n",argv[0]);         return 2;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(fl);         fclose(fp);         fprintf(stderr,"Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 4;     }     n=0;     hh=0;     i=0;     while (1) {         if (fgets(ln,MAXCHARS,fl)==NULL) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             fprintf(stderr,"%s Line %d too long(>%d),spilth ignored.\n",LIST,hh,MAXCHARS);             while (1) {                 c=fgetc(fl);                 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) {                     free(buf);                     fclose(fl);                     fclose(fp);                     fprintf(stderr,"Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     return 5;                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(fl);     if (ignore_case) qsort(buf,n,MAXCHARS,icompare);     else qsort(buf,n,MAXCHARS,compare);     hh=0;     while (1) {         if (fgets(ln,MAXCHARS,fp)==NULL) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             fprintf(stderr,"%s Line %d too long(>%d),spilth ignored.\n",PROG,hh,MAXCHARS);             while (1) {                 c=fgetc(fp);                 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) {             if (ignore_case) {                 if (NULL==bsearch(ln,buf,n,MAXCHARS,icompare)) printf("%s\n",ln);             } else {                 if (NULL==bsearch(ln,buf,n,MAXCHARS,compare)) printf("%s\n",ln);             }         }     }     fclose(fp);     free(buf);     return 0; }

引用 2 楼 zhao4zhong1 的回复:其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。 最近在Linux系统上看Redis源码，在字典操作涉及到散列表的实现的时候使用的是一个二级指针存储键值对结构体，在一开始的时候只给二级指针分配了4个字节的内存空间，然后会因为键值对的key进行哈希得到的数字作为二级指针第二维的下标，在其过程中不排除会有下标是越过二级指针的内存空间的情况，在后续过程中才会不定时地对二级指针进行remalloc操作，请问这种操作方式也是合法安全的吗？会不会有其他程序操作导致说刚好二级指针的内存空间还没重新扩容，但是二级指针内存空间范围外的本来已存储好的数据被刷掉的情况？

记住，在32位系统下，所有的指针对象都是4个字节的。 p = (char *)malloc(sizeof(char *));申请了4个字节的内存大小 p = (char *)malloc(sizeof(char ));申请了1个字节的内存大小。


Question: 假设有N个数，找出第K大的数，K很大（c语言）

我的第一反应也是排序 取第k-1个数

你需要一个高效的排序算法

百度搜相关关键字。

引用 2 楼 qq_39251122 的回复:排序50万个在编译器上会停止运行 具体把你的代码提出来看看，能让编译器停止运行的电脑性能该多不好呀。 我看是因为你的代码优化的不够好吧，或者排序算法不够优吧。 你用快排试一试

引用 2 楼 qq_39251122的回复:排序50万个在编译器上会停止运行 你可以百度 排序一亿个数据

排序50万个在编译器上会停止运行

排序 相同合并 取出第k个


Question: 出不来结猴子吃桃问题。猴子第一天摘下若干个桃子，当即吃了一半，好不过瘾，又多吃了一个.  第二天早上又吃了剩下的桃子的一半，又多吃了一个。以后每天都吃了前一天剩

#include<stdio.h> #include<stdlib.h>  int f(int day,int result);  int main(void) {     int result = 1, day = 1;     printf("%d",f(1,1));     system("pause");     return 0; } int f(int day,int result) {     printf("day = %d\n", day);     return day == 9 ? result:f(day++, (result+1)*2);  } 用这个程序看一下原因。你会发现day输出的都是1； 问题就出在后加1上，如果换成前增1就可以，或者直接f(day+1, (result+1) *2)也行。  #include<stdio.h> #include<stdlib.h>  int f(int day,int result);  int main(void) {     int result = 1, day = 1;     printf("%d\n",f(1,1));     system("pause");     return 0; } int f(int day,int result) {     printf("day = %d\n", day);     return day == 9 ? result:f(++day, (result+1)*2);     //return day == 9 ? result:f(day+1, (result+1)*2);  }

#include<stdio.h>   int main()   {       int x=1,i;       for (i=1;i<=10;i++)       {           x=(x+1)*2;       }       printf("猴子第一天摘了%d个桃子\n",x);       return 0;   } 这个其实更简单，但是我的为什么出不来呢。小白求解啊


Question: 【小程序 文件读写】VS2010未经处理的异常 0xc0000005写入位置时发生访问冲突

我也遇到了这个问题，好像在x86下运行就不会报错，不知道为什么，但是我有一段x86的代码有一段x64的代码，想把他们合在一起用不知道怎么搞了。

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

引用 10 楼 cfjtaishan 的回复:那就缩小了范围，是文件指针的问题，你能确定fopen函数返回的文件指针不是指向NULL吗？你看我6楼的回复 我增加了判断指针的语句 同时将GMP库里用到fp的语句全注释掉了 用的基本的fputs 结果正常 说明文件指针也是正常的呀

引用 8 楼 cfjtaishan 的回复:[quote=引用 7 楼 qq_37401326 的回复:] [quote=引用 5 楼 cfjtaishan 的回复:] 建议先检查一下fopen的返回值是否为NULL； 然后看一下gmp_fprintf的参数是否有问题。 int gmp_fprintf (FILE *fp, const char *fmt, ...)这个是函数的定义[/quote] %Zd这个会不会有问题，使用%d试试，或者你查一下mpz_t类型，%Zd会导致越界了吗？！[/quote]应该不存在这个问题，问题还应该在文件指针 我换了几个gmp库里使用文件指针的函数也是同样的错误

引用 7 楼 qq_37401326 的回复:[quote=引用 5 楼 cfjtaishan 的回复:] 建议先检查一下fopen的返回值是否为NULL； 然后看一下gmp_fprintf的参数是否有问题。 int gmp_fprintf (FILE *fp, const char *fmt, ...)这个是函数的定义[/quote] %Zd这个会不会有问题，使用%d试试，或者你查一下mpz_t类型，%Zd会导致越界了吗？！

引用 5 楼 cfjtaishan 的回复:建议先检查一下fopen的返回值是否为NULL； 然后看一下gmp_fprintf的参数是否有问题。 int gmp_fprintf (FILE *fp, const char *fmt, ...)这个是函数的定义

引用 5 楼 cfjtaishan 的回复:建议先检查一下fopen的返回值是否为NULL； 然后看一下gmp_fprintf的参数是否有问题。不用gmp_fprintf的话是没问题的

引用 3 楼 qq_38204686 的回复:fopen返回值为null?并没有...

fopen返回值为null?

gmp是大数库

查看是否test文件夹是否存在，调用fopen("D:\\test\\RSA111.txt","wb+")，文件不存在会创建,但是文件夹不存在不会创建，试试fprintf();


Question: 神马鬼，一道算是物理题的编程题

你是对的，非常感谢回答。

如果有一条支路短路，整条电路都是短路的啊，电阻为0了，不是说整个电路就等于另一支路的电阻了。

那好吧，我现在才知道........... 你这道题会吗？

高考都已经取消物理了


Question: C语言，如何动态创建线程？

引用 14 楼 zhanggongjkl 的回复:[quote=引用 13 楼 zhao4zhong1 的回复:] 《Windows核心编程》 有没有Linux的推荐的书？。。Windows好多感觉方法不太一样[/quote] 鄙人没看过讲Linux多线程的书。

引用 6 楼 zhanggongjkl 的回复:引用 3 楼 user-5 的回复:频繁创建销毁线程性能差，同意2楼换个思路，使用线程池吧让引用 4 楼 paschen 的回复:1、可以让线程执行完后线程自己释放这片空间这种情况的话这个malloc的空间是不是得把指针传到线程里，结束的时候free？要是这样的话是不是只能传结构体类型的指针？是的 你不是已经把该参数作为参数传递到了线程，传递的是void*类型的

因为线程量不多，就没用线程池，并且创建销毁的频率也不高，所以最后用了指针数组，5个指针存放最大5个线程的信息，线程销毁时指针放空，新线程找空闲指针创建。主要还是线程池略有点复杂……

引用 13 楼 zhao4zhong1 的回复:《Windows核心编程》 有没有Linux的推荐的书？。。Windows好多感觉方法不太一样

不清楚，膜拜一下

《Windows核心编程》

引用 2 楼 cfjtaishan 的回复:用线程池，需要的时候创建，不需要的时候回收。 看一下这个楼主的博客： http://www.cnblogs.com/venow/archive/2012/11/22/2779667.html 这个帖子不错，在仔细研究。。

引用 4 楼 paschen 的回复:1、可以让线程执行完后线程自己释放这片空间 这种情况的话这个malloc的空间是不是得把指针传到线程里，结束的时候free？要是这样的话是不是只能传结构体类型的指针？[/quote] 需要，如果定义的指针是全局，那就不需要传进去了。否则是需要的。 如果需要判断或者使用的变量较多，多余2个。那么建议传递结构体指针进去。[/quote] 感谢，基本上解决了

引用 6 楼 zhanggongjkl 的回复:[quote=引用 3 楼 user-5 的回复:] 频繁创建销毁线程性能差，同意2楼 换个思路，使用线程池吧 让  引用 4 楼 paschen 的回复:1、可以让线程执行完后线程自己释放这片空间 这种情况的话这个malloc的空间是不是得把指针传到线程里，结束的时候free？要是这样的话是不是只能传结构体类型的指针？[/quote] 需要，如果定义的指针是全局，那就不需要传进去了。否则是需要的。 如果需要判断或者使用的变量较多，多余2个。那么建议传递结构体指针进去。

引用 3 楼 user-5 的回复:频繁创建销毁线程性能差，同意2楼 换个思路，使用线程池吧 让  引用 4 楼 paschen 的回复:1、可以让线程执行完后线程自己释放这片空间 这种情况的话这个malloc的空间是不是得把指针传到线程里，结束的时候free？要是这样的话是不是只能传结构体类型的指针？

2、这属于线程间通讯问题，你可以设置一个标志变量，线程结束前自动设置标志变量，外部判断该变量

1、可以让线程执行完后线程自己释放这片空间

频繁创建销毁线程性能差，同意2楼 换个思路，使用线程池吧

device_IP_info 结构体就是底下赋值的那三个变量


Question: 为什么VC编译错误的代码也能AC

引用 10 楼 zihui0459 的回复:引用 9 楼 paschen 的回复:引用 6 楼 zihui0459 的回复:引用 4 楼 paschen 的回复:在C语言中，stdio.h 头文件是主要的。而在后来的C++语言中，C只是C++的一个子集，且C++中，已不推荐再用C的类库，但为了对已有代码的保护，还是对原来的头文件支持。   cstdio是c++从C的stdio.h继承来的，在前面加C同时不要H后缀，在C++环境当然是选用前者，两者内容都一样，只是cstdio头文件中定义的名字被定义在命名空间std中那给链表分配空间的时候include <stdlib.h>还要写吗要不要写不是取决于做什么，而是取决于你需不需要用到里面提供的函数需要用malloc来分配空间呢  malloc需要<stdlib.h>

引用 8 楼 cfjtaishan 的回复:[quote=引用 7 楼 zihui0459 的回复:] [quote=引用 1 楼 cfjtaishan 的回复:] using namespace std;  这是C++的语法。用VC编译器是不识别C++的语法的。所以，建议用VC++编译这部分代码； C++编译器是能够识别C语言的语法的，所以用C++可以编译C语言的代码。  Visual C++6.0不可以吗？[/quote] 当然可以呢。它是C++编译器嘛[/quote]可是还是出错std does not exist

引用 1 楼 cfjtaishan 的回复:using namespace std;  这是C++的语法。用VC编译器是不识别C++的语法的。所以，建议用VC++编译这部分代码； C++编译器是能够识别C语言的语法的，所以用C++可以编译C语言的代码。 你是来搞笑的吗？VC不能识别C++代码？你试过吗？

引用 7 楼 zihui0459 的回复:[quote=引用 1 楼 cfjtaishan 的回复:] using namespace std;  这是C++的语法。用VC编译器是不识别C++的语法的。所以，建议用VC++编译这部分代码； C++编译器是能够识别C语言的语法的，所以用C++可以编译C语言的代码。  Visual C++6.0不可以吗？[/quote] 当然可以呢。它是C++编译器嘛

引用 1 楼 cfjtaishan 的回复:using namespace std;  这是C++的语法。用VC编译器是不识别C++的语法的。所以，建议用VC++编译这部分代码； C++编译器是能够识别C语言的语法的，所以用C++可以编译C语言的代码。  Visual C++6.0不可以吗？

那给分配空间的时候include <stdlib.h>还要写吗

感觉像是声明了一个永远不会被使用的变量 编译器优化能力还是可以的

Visual C++6.0不可以吗？


Question: linux c epoll_wait监听管道写事件，子进程退出，仍有事件发生。这是为什么呀。

提醒：Linux下的fork是开源的。

fork()会备份一份数据等给子进程，fork会返回两个数，分别执行子进程和父进程，子进程结束，但是父进程不一定结束。

百度搜相关关键字。 或者添加详细的写日志到文件辅助调试。 写日志到文件参考下面：//循环向a函数每次发送200个字节长度（这个是固定的）的buffer, //a函数中需要将循环传进来的buffer，组成240字节（也是固定的）的新buffer进行处理， //在处理的时候每次从新buffer中取两个字节打印 #ifdef _MSC_VER     #pragma warning(disable:4996) #endif #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef _MSC_VER     #include <windows.h>     #include <process.h>     #include <io.h>     #define  MYVOID             void     #define  vsnprintf          _vsnprintf #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  MYVOID             void * #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef _MSC_VER void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } void sleep_ms(int ms) {     Sleep(ms); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } void sleep_ms(int ms) {     usleep(ms*1000); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} #define ASIZE    200 #define BSIZE    240 #define CSIZE      2 char Abuf[ASIZE]; char Cbuf[CSIZE]; CRITICAL_SECTION cs_HEX; CRITICAL_SECTION cs_BBB; struct FIFO_BUFFER {     int  head;     int  tail;     int  size;     char data[BSIZE]; } BBB; int No_Loop=0; void HexDump(int cn,char *buf,int len) {     int i,j,k;     char binstr[80];      Lock(&cs_HEX);     for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%03d %04x -",cn,i);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             Log("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         Log("%s\n",binstr);     }     Unlock(&cs_HEX); } int GetFromRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      lent=0;     Lock(cs);     if (fbuf->size>=len) {         lent=len;         if (fbuf->head+lent>BSIZE) {             len1=BSIZE-fbuf->head;             memcpy(buf     ,fbuf->data+fbuf->head,len1);             len2=lent-len1;             memcpy(buf+len1,fbuf->data           ,len2);             fbuf->head=len2;         } else {             memcpy(buf     ,fbuf->data+fbuf->head,lent);             fbuf->head+=lent;         }         fbuf->size-=lent;     }     Unlock(cs);     return lent; } MYVOID thdB(void *pcn) {     char        *recv_buf;     int          recv_nbytes;     int          cn;     int          wc;     int          pb;      cn=(int)pcn;     Log("%03d thdB              thread begin...\n",cn);     while (1) {         sleep_ms(10);         recv_buf=(char *)Cbuf;         recv_nbytes=CSIZE;         wc=0;         while (1) {             pb=GetFromRBuf(cn,&cs_BBB,&BBB,recv_buf,recv_nbytes);             if (pb) {                 Log("%03d recv %d bytes\n",cn,pb);                 HexDump(cn,recv_buf,pb);                 sleep_ms(1);             } else {                 sleep_ms(1000);             }             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef _MSC_VER     pthread_exit(NULL); #endif } int PutToRBuf(int cn,CRITICAL_SECTION *cs,struct FIFO_BUFFER *fbuf,char *buf,int len) {     int lent,len1,len2;      Lock(cs);     lent=len;     if (fbuf->size+lent>BSIZE) {         lent=BSIZE-fbuf->size;     }     if (fbuf->tail+lent>BSIZE) {         len1=BSIZE-fbuf->tail;         memcpy(fbuf->data+fbuf->tail,buf     ,len1);         len2=lent-len1;         memcpy(fbuf->data           ,buf+len1,len2);         fbuf->tail=len2;     } else {         memcpy(fbuf->data+fbuf->tail,buf     ,lent);         fbuf->tail+=lent;     }     fbuf->size+=lent;     Unlock(cs);     return lent; } MYVOID thdA(void *pcn) {     char        *send_buf;     int          send_nbytes;     int          cn;     int          wc;     int           a;     int          pa;      cn=(int)pcn;     Log("%03d thdA              thread begin...\n",cn);     a=0;     while (1) {         sleep_ms(100);         memset(Abuf,a,ASIZE);         a=(a+1)%256;         if (16==a) {No_Loop=1;break;}//去掉这句可以让程序一直循环直到按Ctrl+C或Ctrl+Break或当前目录下存在文件No_Loop         send_buf=(char *)Abuf;         send_nbytes=ASIZE;         Log("%03d sending %d bytes\n",cn,send_nbytes);         HexDump(cn,send_buf,send_nbytes);         wc=0;         while (1) {             pa=PutToRBuf(cn,&cs_BBB,&BBB,send_buf,send_nbytes);             Log("%03d sent %d bytes\n",cn,pa);             HexDump(cn,send_buf,pa);             send_buf+=pa;             send_nbytes-=pa;             if (send_nbytes<=0) break;//             sleep_ms(1000);             if (No_Loop) break;//             wc++;             if (wc>3600) Log("%03d %d==wc>3600!\n",cn,wc);         }         if (No_Loop) break;//     } #ifndef _MSC_VER     pthread_exit(NULL); #endif } int main() { #ifdef _MSC_VER     InitializeCriticalSection(&cs_log);     InitializeCriticalSection(&cs_HEX);     InitializeCriticalSection(&cs_BBB); #else     pthread_t threads[2];     int threadsN;     int rc;     pthread_mutex_init(&cs_log,NULL);     pthread_mutex_init(&cs_HEX,NULL);     pthread_mutex_init(&cs_BBB,NULL); #endif     Log("Start===========================================================\n");      BBB.head=0;     BBB.tail=0;     BBB.size=0;  #ifdef _MSC_VER     _beginthread((void(__cdecl *)(void *))thdA,0,(void *)1);     _beginthread((void(__cdecl *)(void *))thdB,0,(void *)2); #else     threadsN=0;     rc=pthread_create(&(threads[threadsN++]),NULL,thdA,(void *)1);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1);     rc=pthread_create(&(threads[threadsN++]),NULL,thdB,(void *)2);if (rc) Log("%d=pthread_create %d error!\n",rc,threadsN-1); #endif      if (!access("No_Loop",0)) {         remove("No_Loop");         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     while (1) {         sleep_ms(1000);         if (No_Loop) break;//         if (!access("No_Loop",0)) {             No_Loop=1;         }     }     sleep_ms(3000);     Log("End=============================================================\n"); #ifdef _MSC_VER     DeleteCriticalSection(&cs_BBB);     DeleteCriticalSection(&cs_HEX);     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_BBB);     pthread_mutex_destroy(&cs_HEX);     pthread_mutex_destroy(&cs_log); #endif     return 0; }


Question: 一道练习题不会做，求助大家啦！

strcmp((s[i], "$$$$$") == 0 判断字符串相等  另外还有strncmp，strcpy，strstr等函数也是对字符串的一些操作，你可以搜索相关的资料来提高对字符串操作的认识

太感谢你们了！！

#include <stdio.h> #include <string.h>  #define ROW     10 #define COL     128  int main(void) {     char s[ROW][COL];     int i, j;      for (i = 0; i < ROW; i++) {         scanf("%s", s[i]);         if (strncmp(s[i], "$$$$$", 5) == 0)             break;     }      for (j = 0; j < i; j++)         puts(s[j]);     return 0; } 或者用strncmp

#include <stdio.h> #include <string.h>  #define ROW     10 #define COL     128  int main(void) {     char s[ROW][COL];     int i, j;      for (i = 0; i < ROW; i++) {         scanf("%s", s[i]);         if (strcmp(s[i], "$$$$$") == 0)             break;     }      for (j = 0; j < i; j++)         puts(s[j]);     return 0; }


Question: 关于scanf，sprintf，fread，fwrite函数的疑惑

不要把 fopen("...","...");fscanf,fprintf,fgets,fgetc,fclose //读时把\r\n替换成\n，写时把\n替换成\r\n;读到\x1a就设置EOF;读写的内容当字符看待 和 fopen("...","...b");fseek,ftell,fread,fwrite,fgetc,fclose //不作以上替换，遇到\x1a仍继续读;读写的内容当字节看待 弄混了

请判断fscanf函数的返回值！

while(fscanf(fp,"%d %d %f %f\n",&number, &last, &points,&extras) ==4)     {         printf("%d,%d,%f,%f\n", number, last, points,extras);     } 改一下这儿，用空格代替逗号；因为fscanf和fprintf是格式化读写，并且这两个函数正好是一对，即怎么写入文件的，就怎么从文件里读取，即格式要一样。所以要根据文件的内容和格式来确定读写的格式。 fscanf的返回值和scanf的返回值一样，根据读取的成功的个数作为返回值，比如这个读取是4个数据，如果能正确读取4个则返回4，正确读取3个则返回3.建议看一下这个函数的定义和返回值。 fread和fwrite则是二进制形式的读写。也是一对，用fwrite写的，可以用fread读。

fscanf忽略换行，fread会把换行读到内存中。

你写出时并没有逗号分隔  while(fscanf(fp,"%d,%d,%f,%f\n",&number, &last, &points,&extras) ==1)  改成：  while(fscanf(fp,"%d %d %f %f\n",&number, &last, &points,&extras) ==4)


Question: 求大神，为什么会这样

引用 3 楼 qq_40197340 的回复:可是我删了fclose（）；也不行 此时的流的位置是在最末尾，根本就没有数据，理论上是读取失败的 你可以重新打开文件，或者把流的位置重新定位到文件开始处

int main() { 	int x,y; 	FILE *file,*file2; 	file = fopen("a.txt","w+"); 	file2 = fopen("b.txt","w+"); 	fprintf(file,"%d",5); 	fseek(file,0,SEEK_SET); 	fscanf_s(file,"%d",&x); 	fclose(file); 	printf("%d\n",x);  	fprintf(file2,"%d",x); 	fclose(file2);    	system("pause"); 	return 0; }   这个代码在vs2012上面运行出来的结果和文件a.txt ，b.txt里面保存的内容都是5，楼上说的对，在用到文件指针的时候需要时刻注意当前的指向和文件是否有关闭。你试试看，应该是没什么问题了。

删除fclose()；之后，用rewind(file);替换，或者fseek(file, 0, SEEK_SET); 这样做的目的就是让文件指针（重新）指向文件的开头。 每次读之后，文件指针都会向文件尾部便宜一定的距离，所以，一旦读取一次，文件指针已经不指向文件开头了，这样就不能把上次读到的位置再次读取了。当然用rewind和fseek可以修改文件指针的位置。

文件流指针偏移

可是我删了fclose（）；也不行

close 以后以只读方式打开


Question: 求解最大值最小值min max的条件运算符?:为什么这样写就能选出最大最小值

引用 3 楼 coding_ing 的回复:大神们 我知道这个运算符的意思 我就是针对这道题不知道为什么那样写就能是min 和max读出最大值 每输入一个成绩，都跟当前的最大最小分值进行对比，如果较大/较小则重新设置最大最小分值

建议查一下条件运算符。?:这个是基本的语法。 c = a > b ？ a : b;这个是若a > b，则将a赋值给c，否则将b赋值给c；即将a和b中较大的值赋值给c； c = a > b ? b : a;  //或者  c = a < b ? a : b;这个是将较小值赋值给c

?:这个运算符的意思就是如果问号前的表达式成立，则返回问号后的表达式的结果，否则返回冒号后的表达式的结果


Question: 关于结构体的柔性数组

array[0]    不占空间

是的，编译器不会，因为他根本不知道要申请多大

必需用          。

typedef struct my_test { int number; char array[0]; }test,*test_p; 结构体中的char array[0];就是一个指针变量，定义一个这样的结构体变量，array元素就是一个野指针，所以需要给其分配空间。

typedef struct my_test { int number; char array[0]; }test,*test_p; //应该是这个地方报错吧？你把typedef删掉就没问题了，但是会出现另一个错误 test test,test1; //就是这里，你需要改成 struct my_test test, test1; 其他地方并没有错误，针对你给出的代码来说。

柔性数组本质就是指针访问


Question: 用C写彩色图转灰度图时转换后的图像打不开

引用 3 楼 qq_36763031 的回复:[quote=引用 1 楼 user-1的回复:]BMP 文件格式要求图像中每一行的数据要对齐到 32 位的, 你根本没有做这个处理 可是我在第25行后加上bin.biWidth=（bih.biWidth*8+31）/32*4后还是不对，求助[/quote] 不要直接改图像的宽度, 而是遍历图像数据的时候做处理, 输出的时候也是一样

引用 1 楼 user-1的回复:BMP 文件格式要求图像中每一行的数据要对齐到 32 位的, 你根本没有做这个处理 可是我在第25行后加上bin.biWidth=（bih.biWidth*8+31）/32*4后还是不对，求助

引用 1 楼 user-1的回复:BMP 文件格式要求图像中每一行的数据要对齐到 32 位的, 你根本没有做这个处理 真的谢谢你您，我试试


Question: 为什么第一个函数调用不了

你这删除输入的字符有个BUG，如果你需要删除的字符在数组里面出现两次或者以上，在删除完之后，在数组后面会有残留的字符，如果无意访问到的话应该会对程序运行结果或者判断有影响。例如str[20]="abcdefgabcd",删除字符a之后bcdefgbcd'\0'd,d还残留在数组里面。

学习了,很想学习

把你delete_string函数里面的for循环条件改下就好了 for(i=j=0;i!='\0';i++)改成for(i=j=0;str[i]!='\0';i++) 改完这个试下应该就OK了，我在vs2012里面试着是没问题的。

错啦，你就没调用啊

你舅没吊用啊

注意函数声明，定义与调用的区别。 #include<stdio.h> #include<string.h> #include<stdlib.h>  /*函数声明*/ void enter_string(char str[20]); void delete_string(char str[20],char a);  int main() {     char a;     char str[20];     /*函数调用*/     enter_string(str);     printf("输入一个要删除的字符：");     scanf("%c", &a);     /*函数调用*/     delete_string(str, a);     puts(str);     printf("\n\n");     return 0; } /*函数定义*/ void enter_string(char str[20]) {     gets(str); } /*函数定义*/ void delete_string(char str[20],char ch) {     int i,j;      for(i = 0; str[i];)         if(str[i] == ch) {             for (j = i; str[j]; j++)                 str[j] = str[j+1];         } else {             i++;         } }  详见上面的代码； 注意删除某个字符的函数逻辑有问题，建议对照一下看看逻辑问题出在哪。

把void删了，加上就是函数声明了。

那个问题已经解决了  再在的问题是怎么输出时那个数组str[[0]始终是'\0'这个是为什么   上面一位说得我不太懂   str[j]='\0';这行代码不是就最后 就执行一次吗    他不是循环里面的啊

楼主说的第一个函数调用不了，具体指的是那个函数呢？ str[j]='\0'; 这个是只执行一次，因为楼主的for循环只作用于 if(str[i]!=a) str[j++]=str[i]; 这个语句。

str[j]='\0'; 这个他不是只执行一次吗

//你那个绝对不是空格，应该是字符'\0'才对 void delete_string(char str[],char a) { int i,j; for(i=j=0;i!='\0';i++)//你的循环条件有问题 if(str[i]!=a) str[j++]=str[i]; str[j]='\0';//在这里如果你的字符变量a所代表的字符如果不是str的第一个字符，就会被改变成'\0'，而且总是改变str的第一个字符。 }

这个为什么输出不对啊 总是str[0]输出的是空格

#include<stdio.h> #include<string.h> #include<stdlib.h> void enter_string(char str[20]); void delete_string(char str[20],char a); void print_string(char str[20]); int main() { 	char a; 	char str[20]; 	enter_string(str); 	printf("输入一个要删除的字符："); 	scanf("%c",&a); 	delete_string(str,a); 	print_string(str); 	scanf("\n\n"); 	return 0; }  	 void enter_string(char str[20]) { 	printf("输入一串字符："); 	gets(str); } void delete_string(char str[],char a) { 	int i,j; 	for(i=j=0;i!='\0';i++) 	if(str[i]!=a) 	str[j++]=str[i]; 	str[j]='\0';	 	 }  void print_string(char str[20]) { 	int k; 	int i; 	printf("删除后的字符数组为：\n"); 	for(i=0;i<20;i++) 	printf("%c\n",str[i]); }

void enter_string(char str[20]); 你难道是想说这个是你的函数调用的地方？ 这里只是一个函数声明，并没有调用这个函数。


Question: 计算输入数字上限与下限的平方和的程序

如果不加{}的话，只执行x=I*i这句话；但是sum+=x是需要循环的啊！

2#楼的朋友你好，谢谢你的指点，因为我是自学，所以有些地方确实不大明白，能麻烦你帮我指出我的程序循环逻辑问题主要是什么问题吗？以后好避免，谢谢

楼主，我来解释一下你的这一段while循环，首先他是在x值小于y值的条件下，一直保持循环， 进入到for循环后，i=x初始值=5，且i<y初始值=9；一次for循环后，i=6，x=25，sum=25，y不变； 二次for，i=7，x=36，sum=61，y不变；直到四次for循环后，i=9，跳出for循环， 此时i=9，x=64，sum=25+36+49+64=174；然后继续for循环后面的语句，y=81；z=174+81=255； 所以这就是你输出时，x=64，y=81，z=255的原因，然后就是scanf的阻塞啦

引用 4 楼 daijunyiluoshiyong 的回复: for(i=x,sum=0;i<y;i++)   {     x1=i*i; sum+=x1;   }这是计算平方和的。你程序中for后边没有括号，然后只执行了一遍。建议你多看书（谭浩强的C和C++）,看看别人代码，上网搜怎么调试 你说这里呀，因为我在编程过程中发现，for循环后面如果不用{}，紧跟其后的循环声明部分是以分号来结束该循环的，我看循环声明这里的表达式不多，我就没有用{}，而是用的分号。谢谢指点

#include<stdio.h> int main() {    int x,y;    int i,z;    int sum;    int x1;    printf("Enter lower and upper integer limits:");   // scanf("%d %d",&x,&y);    x=5;    y=9;    while(x<y)    {       for(i=x,sum=0;i<y;i++) 	  { 	    x1=i*i; 		sum+=x1; 	  }       y=y*y; 	  z=sum+y; 	  printf("The sums of the squares from %d to %d is %d\n",x*x,y,z); 	  printf("Enter next set of limits':"); 	  scanf("%d %d",&x,&y);    }    printf("Done!Bye-Bye!\n");    return 0; } 你主要的问题不会调试，看每个值等于多少，而且循环逻辑有问题，你对比一下我基于你的代码改的部分

# include <stdio.h> long long sum; int main(){    int X,Y,T; do{  sum=0; scanf("%d %d",&X,&Y); T=X;   while(X<=Y){   sum+=X*X; X++; } printf("%d to %d is %lld\n",T,Y,sum); }while(1);     return 0; }


Question: C语言新手求助！！

#include<stdio.h> #include<string.h>  //定义学生结构体 struct student {     char id[20];     char name[20];     char grade[20];     char class[20];     char zhuanye[20];     float mark1;     float mark2;     float mark3;     float average;     float total; }; struct student number[1000];//定义学生结构体数量组 int num = 0;  void student_add()//添加学生信息 {     while (1)     {         printf("请输入学号:");         gets(number[num].id);         getchar();         printf("请输入姓名:");         gets(number[num].name);         getchar();         printf("请输入年级:");         gets(number[num].grade);         getchar();         printf("请输入班级:");         gets(number[num].class);         getchar();         printf("请输入专业:");         gets(number[num].zhuanye);         getchar();         printf("请输入成绩1:");         scanf_s("%f", &number[num].mark1);         //getchar();         printf("请输入成绩2:");         scanf_s("%f", &number[num].mark2);         //getchar();         printf("请输入成绩3:");         scanf_s("%f", &number[num].mark3);         getchar();         num++;         printf("是否进行其他操作?(y/n)");         if (getchar() == 'n')         {             break;         }     } } 试一下上面的代码； 不建议使用gets，可以用fgets替换，也可以用scanf_s

那么多的gets，getchar，你认真数一下是不是敲多了

#include<stdio.h> #include<string.h> # define N 20 //定义学生结构体 struct student { 	char S[5][N+1]; //0 ID   1  NAME 2 GRADE   3 CLASS   4 ZHUANYE 	double mark[5];  //mark1    mark2    mark3   average   total }; struct student number[1000];//定义学生结构体数量组 void student_add(); double gaindouble(double *p,int a,int b);//输入int *p直至满足[a,b]输入结束，返回*p int gainchar(char *A,int min,int max);//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度       int main(){ 	student_add(); 	return 0; } void student_add()//添加学生信息 { 	char F='Y',A[][5]={"学号","姓名","年级","班级","专业","语文","数学","英语"}; 	int  i,j,B[2][8]={{8,4,4,4,8,1,1,1},{10,8,8,8,N,100,100,100}};     for(i=0;i<1000&&(F=='Y'||F=='y');i++) 	{ 		for(j=0;j<8;j++) 		{ 			if(j<5) 			{ 				printf("请输入第%d个学生%s--[%d,%d]个字节:",i+1,A[j],B[0][j],B[1][j]); 				gainchar(number[i].S[j],B[0][j],B[1][j]); 			} 			else{ 				printf("请输入第%d个学生的%s成绩--[%d.00,%d.00]:",i+1,A[j],B[0][j],B[1][j]); 				number[i].mark[4]+=gaindouble(&number[i].mark[j-5],B[0][j],B[1][j]); 			} 		} 		printf("是否进行继续录入？(Y/N):"); 		F=getchar(); 	} }    double gaindouble(double *p,int a,int b)//输入int *p直至满足[a,b]输入结束，返回*p       {            do{               *p=a-1;             scanf("%lf",p);               while(getchar()!='\n');               if(*p>b||*p<a)                   printf("输入有误,请重新输入--[%d,%d]:\n",a,b);           }while(*p>b||*p<a);           return *p;       }       int gainchar(char *A,int min,int max)//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度             {                 int B,C;           	do{                     A[max]=B=C=0;                 while((A[B++]=getchar())!='\n'&&B<max);                 if(A[B-1]!='\n')while(getchar()!='\n'&&++C);                     else A[--B]=0;          		if(C||B&&B<min)         			printf("您录入的字符串长度:%d字节\n只录入[%d,%d]个字节!\n",B+C,min,max);                 }while(C||B<min);                 return B;           }

#include<stdio.h> #include<string.h> # define N 20 //定义学生结构体 struct student { 	char S[5][N+1]; //0 ID   1  NAME 2 GRADE   3 CLASS   4 ZHUANYE 	double mark[5];  //mark1    mark2    mark3   average   total }; struct student number[1000];//定义学生结构体数量组 void student_add(); double gaindouble(double *p,int a,int b);//输入int *p直至满足[a,b]输入结束，返回*p int gainchar(char *A,int min,int max);//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度       int main(){ 	student_add(); 	return 0; } void student_add()//添加学生信息 { 	char F='Y',A[][5]={"学号","姓名","年级","班级","专业","语文","数学","英语"}; 	int  i,j,B[2][8]={{8,4,4,4,8,1,1,1},{10,8,8,8,N,100,100,100}};     for(i=0;i<1000&&(F=='Y'||F=='y');i++) 	{ 		for(j=0;j<8;j++) 		{ 			if(j<5) 			{ 				printf("请输入%s--[%d,%d]个字节:",A[j],B[0][j],B[1][j]); 				gainchar(number[i].S[j],B[0][j],B[1][j]); 			} 			else{ 				printf("请输入%s的成绩--[%d.00,%d.00]:",A[j],B[0][j],B[1][j]); 				number[i].mark[4]+=gaindouble(&number[i].mark[j-5],B[0][j],B[1][j]); 			} 		} 		printf("是否进行其他操作？(Y/N):"); 		F=getchar(); 	} }    double gaindouble(double *p,int a,int b)//输入int *p直至满足[a,b]输入结束，返回*p       {            do{               *p=a-1;             scanf("%lf",p);               while(getchar()!='\n');               if(*p>b||*p<a)                   printf("输入有误,请重新输入--[%d,%d]:\n",a,b);           }while(*p>b||*p<a);           return *p;       }       int gainchar(char *A,int min,int max)//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度             {                 int B,C;           	do{                     A[max]=B=C=0;                 while((A[B++]=getchar())!='\n'&&B<max);                 if(A[B-1]!='\n')while(getchar()!='\n'&&++C);                     else A[--B]=0;          		if(C||B&&B<min)         			printf("您录入的字符串长度:%d字节\n只录入[%d,%d]个字节!\n",B+C,min,max);                 }while(C||B<min);                 return B;           }      希望能帮到你  我的QQ2423824433

建议使用 fgets(number[num].id, 20, stdin)读取字符串 然后getchar()语句统统删除


Question: 求教，求教

应该是分配内存时候出的问题，但也不能个说是个问题。 在第二次调用这个函数进行链表创建的时候，会顺着第一个链表创建结束的位置处继续分配内存空间。 差不多类似这张图：

http://blog.csdn.net/zhagoodwell/article/details/59230474 里面有你想要的

看不出来 建议设置断点调试

LIST2* creat_number(LIST2 * head, int number1)        {   	LIST2 *new_=NULL;                       	LIST2 *end=NULL;                      	int i;                                    	srand((int)time(0));  	for (i = 0; i < number1; i++) 	{ 		 		new_ = (LIST2 *)malloc(sizeof(LIST2)); 		if (new_ == NULL) 		{ 			printf("there is no please\n"); 			exit(1); 		}  		new_->number = (rand()%(10*number1));  		 		if (head == NULL) 		{ 		   head = new_; 			end =head;  		} 		else 		{ 			end->next = new_; 			end = new_; 		} 	} 	end->next = NULL;         ｝  我就是调用这个函数 可以生成的第一个链表正常，在调用的话 就出现上面的情况了

我感觉是你代码的问题


Question: C语言中Scanf函数的问题。新手求教，在线等。

引用 4 楼 khxu10234 的回复:[quote=引用 2 楼 jianwen0529 的回复:] scanf_s("%s", student[i].name, 20); 劳烦可以解释一下吗，谢谢[/quote] scanf 是标准库的函数，scanf_s是微软vc的函数，你百度scanf_s的用法就清楚了，字符串后面加一个表示缓存的大小，保证读取不会发生越界行为

引用 2 楼 jianwen0529 的回复:scanf_s("%s", student[i].name, 20); 劳烦可以解释一下吗，谢谢

scanf_s("%s", student[i].name, 20);

name 后面再加一个参数试试


谢谢回复，不过跟这个无关，重写了一遍，就通过了 #include <stdio.h> #include <stdlib.h>  int main() {     char a[3];     char t,i,j;     while(scanf("%s",a)!=EOF)     {         for(i=0;i<3;i++)             for(j=0;j<2-i;j++)                 if(a[j]>a[j+1])                 {                     t=a[j];                     a[j]=a[j+1];                     a[j+1]=t;                 }         printf("%c %c %c\n",a[0],a[1],a[2]);         }      return 0; }

char a[4]; char t, i, j; while (scanf_s("%s", a, 4))


Question: 关于局部静态变量

静态变量可以被再次赋值，但是在只能初始化一次！！！

其实电脑开机后物理内存的每个字节中都有值且都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。  栈中的变量通常包括函数参数和函数里声明的临时变量。 栈中的基本变量退出其作用域时，没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时，会自动执行其析构函数，……  在占用内存空间较大的局部数组声明的前面加static将其从堆栈数据段挪到全局数据段即可避开因局部数组大小超过默认堆栈大小1MB造成程序不能正常运行的问题。

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  对学习编程者的忠告： 多用小脑和手，少用大脑、眼睛和嘴，会更快地学会编程！ 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！ 不会单步Release版对应汇编？在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有，然后在IDE中运行。（一般人我不告诉他！）  VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 对VC来说，所谓‘调试时’就是编译连接通过以后，按F10或F11键单步执行一步以后的时候，或者在某行按F9设了断点后按F5执行停在该断点处的时候。  VMMap 是进程虚拟和物理内存分析实用工具。http://technet.microsoft.com/zh-cn/sysinternals/dd535533

这个涉及到进程空间模型。  进程空间的栈空间是变化最多的地方；函数调用都在这里发生，所有非静态局部变量、入参副本都在栈空间。 函数调用结束，栈空间被释放；  静态局部变量之所以是个例外，是因为它存放的位置和普通全局变量一样，都在全局数据区。 与auto局部变量不同，函数退出后它的空间不被释放，因此它具有记忆功能，这是与普通局部变量最大的区别。  此外，它还是局部变量，只在函数内部可见。这是因为它在符号表不可见（或者是符号表里面根本就没有它），因此在所属函数之外无法访问

静态变量具有永久存储区，是变量本身被赋予了永久存储区。赋初值后，这个变量还可以自我循环运算，所以静态变量初值并不是最终值，只是每次调用函数的时候，上次调用产生的结果是固定不变的，比如该例，下次调用的时候a的值就直接是9，a=6这个步骤是不再重复运行的。运用静态变量的函数其实是产生了一个特殊固定函数功能，该功能有一个固定不变的结果提供给用户。

你把静态变量看成普通变量就好理解了，其实静态变量就是普通变量呀，只是静态变量的生命周期是在整个程序运行期间的，而普通产量出了其所在的程序块中就会消亡。所以他们的区别只是谁可以存活的时间更长，其他一样的。

你只不过是在主函数里用的它而已， 你可以在循环里使用它， 也可以在其它函数里声明定义并使用然后在主函数里循环调用函数。 你还可以将局部静态变量的指针传出去，任意访问。

静态变量只是不被销毁 在程序运行期间可以一直用 作用域不会变 但是值可以被改变 其还是一个变量 详情百度 静态变量

静态局部变量是可以再次赋值的，又不是const类型，只是只能被初始化一次，估计你对初始化概念不太清晰

const不能再赋值，但是static可以再赋值的。

如果你搞过嵌入式，学过bin程序文件的文件格式，亲自上手写从flash芯片，导入Ram芯片（内存），然后调用main函数的整过流程，你会很明白，全局变量，和静态变量，堆栈，局部变量到底是啥东西。

static有两大作用：             1.   声明静态存储             2.   限定作用域      static int a=6; 中这据代码，根本从来就没有翻译成机器码过，根本没有任何一条指令执行了a=6这个表达式，全局变量中的      int  a=6也是一样，根本没有一条指令是用来执行a=6的，很意外吧。。。静态变量和局部赋初值变量是不同的，却和全局付初值变量相同，没有任何代码给他们付初值，赋初值的是程序文件导入器。。。他们的初始值都是通过文件流一口气复制到内存的（此时main函数还没有运行）。。他和全局有初值变量的区别，仅仅是作用域不同，被限定到函数体内使用。        当然这是实际情况，但老师的介绍情况，通常不是这样，老师会告诉你在初次调用时会被赋值一次，其实有点想当然，但这么理解对于编程没有坏处，反而有助于新手理解，否则新手会认每次调用，这个数都是6，其实不是初次调用被赋初值，而是每次调用都没有赋初值，初值在程序没运行就赋值过了。程序就是个死代码，他怎么会区分是不是第一次调用呢，要想区分就要有计标志变量和代码，来统计是不是第一次，这样的运行效率降低，不仅麻烦，而且很傻。当然C#.net就不一样了，他确实是按照这个逻辑做的，初次调用才赋值，这个很容易跟踪到，但C你设断点，是走不到的，因为根本不存在这句代码，C从来不是按照他想表达的逻辑在做。       static 其实最大的作用，除了声明静态存储外，还有一个目的是限定作用域。。如果不是为了这个目的，它写在函数外和函数内根本没分别，编译器最多检测一下语法正确性，编译代码时，写在函数内外机器码是相同的。       全局变量本身就是静态存储，为什么也用 static ，  前面说过，他的第二个作用是限定作用域， 他可以告诉连接器这个变量仅源文件内部有效，类似于C++ 的  private的作用。


Question: 打印机驱动怎么在word里增加双面长边和双面短边的选项

和横向纵向是打印方向不一样，这个是装订的位置，类似于说是竖着翻页还是横着翻页

Word是Word； 打印机驱动是打印机驱动。

就是在word2010，打印选项下有个设置，debugview看应该是从devicecapabilities中获取了写的纸张大小等信息，但是在其中dc_duplex设为ture，选项中只有单面和手动双面，从哪能加入双面打印的短边和长边选项呢


Question: C语言中为什么使用指针能节省内存？

指针最基本也是最重要的用处就是提供一层间接。

减少数据拷贝，直接告诉对方存放数据的地址，通过地址访问一个数据，比把数据拷贝一份给你，两个代价是不一样的

http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素

建立一个错误的理论，再来问为什么这样

这个前提不对。指针不是用来是省内存的，可以用来操作内存，不过作为函数参数传递时，会减少拷贝操作，变相的节省了内存，但是这不是目的

指针节省内存还是主要体现在参数传递上，比如传递一个结构体指针变量和传递一个结构体变量，若结构体占用内存越大，传递指针变量约节省内存的

这样的目的可能是不想修改str的地址，通过p可以做到遍历str字符串。

引用 7 楼 paschen 的回复:char str = "abcd";   这句应该是   char* str = "abcd";  str和p都是指针，确实使用str就可以了  这里和节省内存没任何关系 应该是减少不必要的数据复制

可能是说内存可以动态按需分配，如果用静态的数组，事先可能无法确定需要多大的数组，只能定义较大的数组，造成浪费。

推荐：《深入理解C指针》

然后你的房子太大了  交换起来不方便 不是还有房产证吗 这时候 房产证就是指针 房产证换了 房子就换了

补充 好像还是和节省内存有关系的 呵呵  比如你的一间房子里放一堆黄金 放着放着放不下了 但是用纸币 可以放个几亿

和节省内存没关系 和交换内存有关系 就好像纸币代表一堆黄金 就是指针代表一堆内存 交换一吨一吨的黄金很麻烦 不如用纸币代替黄金 交换一堆堆的内存很没有效率 不如直接交换指向他们的指针  并且使用指针代表他们

还有就是用指针可以是程序的灵活性更好： http://blog.csdn.net/zhagoodwell/article/details/53512140

用指针节省内存一般是 calloc 或者malloc 还有就是字符数组排序的时候 如果用指针指向每个字符地址 交换的时候不用交换，每个字符串 直接交换字符指针即可“ EG： # include <stdio.h>   # include <string.h>   # define N 100   //如果想录入x个字节那么就把N的数值改成x    int gainchar(char *A,int min,int max);  int gainint(int *p,int a,int b); void paixu(char *a[],int n,int F);  void main(){       int n,F,i;       char B[N][N+1],*P[N],S[][3]={"升","降"};   	do{   		printf("输入要录入的字符串个数[2,%d]:",N); 		gainint(&n,2,N); 		for(i=0;i<n;i++) 		{ 			printf("第%d个字符串,字节--[1,%d]:",N); 			gainchar(B[i],1,N); 			P[i]=B[i];//让每个指针指向每个字符数组 		} 		printf("升序请按0:降序请按1--[0,1]:");           gainint(&F,0,1); 		paixu(P,n,F); 		printf("%s后:\n",S[F]); 		for(i=0;i<n;i++) 			printf("%s\n",P[i]); 	}while(1);   }    int gainint(int *p,int a,int b)//输入int *p直至满足[a,b]输入结束，返回*p       {            do{               *p=a-1;             scanf("%d",p);               while(getchar()!='\n');               if(*p>b||*p<a)                   printf("输入有误,请重新输入(%d--%d):\n",a,b);           }while(*p>b||*p<a);           return *p;       }   int gainchar(char *A,int min,int max)//长度在[min,max]  <闭区间>  之间时 函数结束 返回字符串A的长度       {           int B,C;      do{               A[max]=B=C=0;           while((A[B++]=getchar())!='\n'&&B<max);           if(A[B-1]!='\n')               while(getchar()!='\n'&&++C);           else A[--B]=0;        if(C||B&&B<min)          printf("您录入的字符串长度:%d字节\n只录入(%d--%d)个字节!\n",B+C,min,max);           }while(C||B<min);           return B;     } void paixu(char *a[],int n,int F)  {       int i,j,k,Y;   	char *temp; 	for(i=0;i<n-1;i++)   	{   		k=i;   		for(j=i+1;j<n;j++)   		{             Y=strcmp(a[j],a[k]);  			if(F?Y<0:Y>0)   //b=0升序  b为其他降序   				k=j;   		} 			if(k!=i)   			{   				temp=a[k];   				a[k]=a[i];   				a[i]=temp;   			}   	}   }    这样能节省交换的运行内存和时间 希望能帮到你

char str = "abcd"; 这是定义字符的  指针只是指向内存的首地址，与节省内存没关系。 指针对比其他语言，能直接访问内存地址空间，所以效率会高点。当然使用汇编会更高。 学习C/C++，使用指针是不可避免的。

这两个语句都有问题，你让别人怎么回答你？指针不是更省内存，而是减少内存拷贝。

https://zhidao.baidu.com/question/362521628.html 来自百度  仅供参考

char str = "abcd"; 这句话不报错？  总之使用指针跟节省内存没有半毛钱关系


Question: vs 2012 设置/MD 可以编译，设置 /MT,就会有几个无法解析的外部符号

把所有依赖的.lib、.dll库加上/MT重新编译一下

链接不到标准库的lib文件，看下库目录等设置有没问题

libcmt.lib 有的，如果没有就不只这几个错误了。

这得看你的VS安装目录比如C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\lib里没有libcmt.lib库


Question: 有关二级指针的一些疑问和猜想

仅供参考：//在堆中开辟一个3×4×5的3维int数组 #include <stdio.h> #include <malloc.h> int ***p; int i,j,k; void main() {     p=(int ***)malloc(3*sizeof(int **));     if (NULL==p) return;     for (i=0;i<3;i++) {         p[i]=(int **)malloc(4*sizeof(int *));         if (NULL==p[i]) return;         for (j=0;j<4;j++) {             p[i][j]=(int *)malloc(5*sizeof(int));             if (NULL==p[i][j]) return;         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 p[i][j][k]=i*20+j*5+k;             }         }     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             for (k=0;k<5;k++) {                 printf(" %2d",p[i][j][k]);             }             printf("\n");         }         printf("---------------\n");     }     for (i=0;i<3;i++) {         for (j=0;j<4;j++) {             free(p[i][j]);         }         free(p[i]);     }     free(p); } //  0  1  2  3  4 //  5  6  7  8  9 // 10 11 12 13 14 // 15 16 17 18 19 //--------------- // 20 21 22 23 24 // 25 26 27 28 29 // 30 31 32 33 34 // 35 36 37 38 39 //--------------- // 40 41 42 43 44 // 45 46 47 48 49 // 50 51 52 53 54 // 55 56 57 58 59 //---------------  //在堆中开辟一个2×3×4×5的4维int数组 #include <stdio.h> #include <malloc.h> int ****p; int h,i,j,k; void main() {     p=(int ****)malloc(2*sizeof(int ***));     if (NULL==p) return;     for (h=0;h<2;h++) {         p[h]=(int ***)malloc(3*sizeof(int **));         if (NULL==p[h]) return;         for (i=0;i<3;i++) {             p[h][i]=(int **)malloc(4*sizeof(int *));             if (NULL==p[h][i]) return;             for (j=0;j<4;j++) {                 p[h][i][j]=(int *)malloc(5*sizeof(int));                 if (NULL==p[h][i][j]) return;             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     p[h][i][j][k]=h*60+i*20+j*5+k;                 }             }         }     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 for (k=0;k<5;k++) {                     printf(" %3d",p[h][i][j][k]);                 }                 printf("\n");             }             printf("--------------------\n");         }         printf("=======================\n");     }     for (h=0;h<2;h++) {         for (i=0;i<3;i++) {             for (j=0;j<4;j++) {                 free(p[h][i][j]);             }             free(p[h][i]);         }         free(p[h]);     }     free(p); } //   0   1   2   3   4 //   5   6   7   8   9 //  10  11  12  13  14 //  15  16  17  18  19 //-------------------- //  20  21  22  23  24 //  25  26  27  28  29 //  30  31  32  33  34 //  35  36  37  38  39 //-------------------- //  40  41  42  43  44 //  45  46  47  48  49 //  50  51  52  53  54 //  55  56  57  58  59 //-------------------- //======================= //  60  61  62  63  64 //  65  66  67  68  69 //  70  71  72  73  74 //  75  76  77  78  79 //-------------------- //  80  81  82  83  84 //  85  86  87  88  89 //  90  91  92  93  94 //  95  96  97  98  99 //-------------------- // 100 101 102 103 104 // 105 106 107 108 109 // 110 111 112 113 114 // 115 116 117 118 119 //-------------------- //======================= //

引用 1 楼 user-3 的回复:p、b、c分别指向了3块内存，  p是一个地址数组，它本身指向的内存块肯定是连续的5个指针大小的内存，但是它的各元素值可能是离散的，p[0]与c一样指向了第2 次申请的堆内存，p[1]跟b一样指向了第3次申请的堆内存。  32位程序，一个指针大小也就4字节，p指向的堆内存就是20字节，p[0]跟p[1]肯定是连续的，就相差4字节。也就是说二级指针p的内存空间只是用来存储元素中的地址 而不是b和c的值 因此分配的空间不用范围大到包括指针b和指针c的地址?

引用 4 楼 zhao4zhong1 的回复:http://edu.csdn.net/course/detail/2344 C语言指针与汇编内存地址-一.代码要素 http://edu.csdn.net/course/detail/2455 C语言指针与汇编内存地址-二.函数 http://edu.csdn.net/course/detail/2516 C语言指针与汇编内存地址-三.数组和二维数组 http://edu.csdn.net/course/detail/2517 C语言指针与汇编内存地址-四.三维数组谢谢 我去认真学习一下

谢谢各位大神的回答，是我表达不清楚 我想问得是在一维数组中地址是连续的 那么二维数组呢？ 上述的二级指针如果我们是当作一个二维数组看待 指针c和指针b记录的是一个字符 但同时可以看作是一个二维数组中的第一维数组 那么它们的地址是连续的没错 那么二维数组的内存空间是否连续的?二级指针的地址是否跟二维数组一样是连续的?如果不连续 那么给二级指针分配的内存空间又是指什么?

首先，你打印p的地址有问题 printf( "%p,%p\n", p, p+1 );这个才是p的地址，b和c的地址只是赋值给 *p 和 *(p+1)   举一个简明的例子。 有五个并排的格子，编号即为p+0, p+1, p+2... 有两个不知道什么东西的东西b和c，只知道它们所处的位置  此刻在前格子里面记录它们所在的地址 *p = c; *(p+1) = b;  地址是变量在内存中的位置（格子所在的地址），指向的内存其实就是记录在这个内存中的一个值（格子内所记录的地址）


Question: 指针常量与常量指针问题

代码内指针p1，p2，p3均未初始化地址，其中p2为指针变量，其地址可以更改，但指向的值不能修改；p3为指针常量，指向地址不能修改，但内部存储值可以修改。由于代码中p3=p1，地址均为初始化，直接指向常量区，所以*p3 = a出错，将两者语序调换即可，即p3 = a；*p3 = 'A'，则允许没有问题。前面的问题根据定义你自己修改下，比修改p3这两行代码容易~~

不要纠结各种常量了，这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢！

指针常量是指针变量本身的内容不可以修改，比如数组名，不可以做左值； 常量指针，是指向的内容不可以修改。

你可以运行一遍，出来错误原因，然后修改，有利于理解。 常量不能赋值和类型不能转换。

指针常量与常量指针:  顾名思义, const char* p:   const 描述的是char*,char*是字符串嘛，等价于字符串是常量，不能改，就不要妄图通过指针引用去修改字符串咯。一改动编译器在编译代码时就可以检查出来. 但是p可不是哟，可以随时再指向其他字符串。  char* const p:  const 描述的是p,p是指针哟，等价于指针是常量，指针不能指别人咯。指别人编译器在编译代码时就可以检查出来


Question: 对于c语言用文本txt文件存储数据  我百度了很多书也翻了很多  究竟我哪里错了...

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

引用 1 楼 user-3 的回复:读的时候不要用模式at+打开，这个是按文本增加方式打开， 打开的时候读写指针在末尾，所以你读不到数据，还是可以写的方式，这样也不太好 应该用 rt 模式打开就可以了 然后我刚刚试了一下打开之后用rewind()函数用在第86行将指针移到了文件的开头也还是不行...

第一个创建信息那个Cre_Goods函数没有问题 可以成功创建也可以往文件中输入信息 但是第二个函数Run_Purchase这个函数还是有问题   我按楼上的各位大神的方法修改了一下子还是不可以...void Run_Purchase(struct Purchase *head1,struct Goods *head2) {     char x;     struct Goods *g1,*g2;     struct Purchase *p1;     FILE *rs;     if((rs=fopen("货物信息.txt","at+"))==NULL)   //此处用at+是为了匹配到后将进货的重量输入到货物信息中      {      	printf("打开失败!按任意键返回主菜单。\n");       	scanf("%s",x);         menu();     } 	g1=(struct Goods *)malloc(sizeof(struct Goods)); 	g2=(struct Goods *)malloc(sizeof(struct Goods)); 	rewind(rs);     //将文件中的指针移到文件开头  	g2=head2; 	fscanf(rs,"%s %d%d%f%d%d",g1->gname,&g1->allweight,&g1->sellweight,&g1->money,&g1->Unit_price,&g1->Unit_sell); 	while(feof(rs)==0) 	{ 		g2->next=g1; 		g2=g1; 		g1=(struct Goods *)malloc(sizeof(struct Goods)); 		fscanf(rs,"%s %d%d%f%d%d",g1->gname,&g1->allweight,&g1->sellweight,&g1->money,&g1->Unit_price,&g1->Unit_sell); 	} 	g2->next=0; 	p1=(struct Purchase *)malloc(sizeof(struct Purchase)); 	if(p1==0) 	{ 		printf("添加失败！返回主菜单\n"); 		menu(); 	} 	printf("输入进货的货物的名字："); 	scanf("%s",p1->gname); 	printf("输入该货物的此次进货重量："); 	scanf("%d",&p1->weight); 	printf("输入此次购买该货物所花费的总金额："); 	scanf("%f",&p1->money); 	FILE *rw; 	if((rw=fopen("进货信息.txt","a"))==NULL) 	{ 		printf("信息存储失败!按任意键返回主菜单。\n"); 		scanf("%s",x); 		menu(); 	} 	fprintf(rw,"%s%d%f",p1->gname,&p1->weight,&p1->money);   //此处往新文件中输入信息不成功，文件中没信息  	while(head2->next) 	{ 		if(head2->next->gname==p1->gname) 		{ 			head2->next->allweight+=p1->weight; 			fprintf(rs,"%s%d%d%f%d%d",head2->next->gname,&head2->next->allweight,&head2->next->sellweight,&head2->next->money,&head2->next->Unit_price,&head2->next->Unit_sell); 			break; 		} 		else 			head2->next=head2->next->next; 	} 	if(head2->next==0) 	{ 		printf("请先添加该货物的信息！\n"); 		printf("添加请按1\n返回主菜单请按0\n"); 		scanf("%d",&x); 		if(x==1) 		Cre_Goods(g1); 		else 			menu();  	} 	else 	{ 	printf("继续添加请按1\n"); 		printf("返回主菜单请按0\n"); 	if(x==1) 			Run_Purchase(p1,g1); 	else 		menu(); 	} 	fclose(rw); 	fclose(rs); }  然后现在发现一个问题就是程序运行要先用Cre_Goods输入货物信息才能用Run_Purchase函数，否则就会程序停止运行，即便之前输入过数据也不行 拜托各位大神再仔细看看

引用 4 楼 zhao4zhong1 的回复:printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  请检查fscanf的返回值。想问一下是不是读取货物名字的字符串的问题  就是那个%s的问题，但是不用%s  不知道用什么来读取货物的名字

引用 3 楼 whut_lcy 的回复:问题出在这里： fscanf(rs,"%s%d%.2f%d%d",g1->gname,&g1->allweight,&g1->money,&g1->Unit_price,&g1->Unit_sell);  原因是  scanf家族(scanf,fscanf,sscanf等), 在提取浮点数据的时候，不能指定数据精度.  这一点与printf家族有所不同  你把%.2f改成%f就可以了 更改了还是不行....