Question: 关于数组和指针

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

&a 的类型是int (*)[5] , 数组指针

应该就是这个样子的。。。

其实这个问题可以通过打印一下数组的地址和ptr 的地址值来分析；ptr 已经指向了数组的末尾。

引用 1 楼 u012033027 的回复:如果你的语句是 int *ptr = (int *) (a+1); 在这种情况下，ptr = &(a[1]) 那么输出就是 2, 1. 这是正常的。  但是你的是(int *)(&a + 1) 在这种情况下 ptr = (&a + 1) a是数组名，可以理解为指向整数的指针。 但是&a就理解为指向一个包含五个元素的数组的指针，那么&a + 1，就是指向下五个数组（实际上未定义）。 那么ptr是指向未定义的位置。但是ptr在被转化为整形指针，在减1之后，就后退了一个整数的位置，也就是数组a的最末一个元素。  也许这样理解是合理的。 正解

引用 1 楼 u012033027 的回复:如果你的语句是 int *ptr = (int *) (a+1); 在这种情况下，ptr = &(a[1]) 那么输出就是 2, 1. 这是正常的。  但是你的是(int *)(&a + 1) 在这种情况下 ptr = (&a + 1) a是数组名，可以理解为指向整数的指针。 但是&a就理解为指向一个包含五个元素的数组的指针，那么&a + 1，就是指向下五个数组（实际上未定义）。 那么ptr是指向未定义的位置。但是ptr在被转化为整形指针，在减1之后，就后退了一个整数的位置，也就是数组a的最末一个元素。  也许这样理解是合理的。 合理

这个问题的根本，就是搞清楚数组名和对数组名取地址的意义。 可以参考下这个，看完应该就明白了 http://blog.csdn.net/tuzhutuzhu/article/details/19267833

同意楼上，跟我的猜想一样。

看输出就明白了吧

#include <iostream>  using namespace std;  int main() { 	int a[5] = {1,3,5,7,9}; 	int *ptr = (int*)(&a+1); 	 	cout << "a[0]:\t" << &a[0] << endl; 	cout << "a[1]:\t" << &a[1] << endl; 	cout << "a[2]:\t" << &a[2] << endl; 	cout << "a[3]:\t" << &a[3] << endl; 	cout << "a[4]:\t" << &a[4] << endl; 	cout << endl;  	cout << "a:\t" << a << endl; 	cout << "&a:\t" << &a << endl; 	cout << "&a[1]:\t" << &a[1] << endl; 	cout << "(&a+1):\t" << (&a +1) << endl; 	cout << "ptr:\t" << ptr << endl; 	cout << "*ptr:\t" << *ptr << endl; 	cout << *(a+1) << "," << *(ptr-1) << endl;  	/* 	OUTPUT: 	a[0]:	0x7fff87182620 	a[1]:	0x7fff87182624 	a[2]:	0x7fff87182628 	a[3]:	0x7fff8718262c 	a[4]:	0x7fff87182630  	a:	0x7fff87182620 	&a:	0x7fff87182620 	&a[1]:	0x7fff87182624 	(&a+1):	0x7fff87182634 	ptr:	0x7fff87182634 	*ptr:	0 	3,9 	*/ }


Question: 奇怪的指针声明

知识点： 数组->指针转换。

size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );  可以转化void*， 所以没有编译OK。

求送点分，我没分了，谢谢

part[1]的结构： part是一个指向数组的指针，所以如下 part-->{结构}，{结构} 但是数组只有一个元素，所以上图中实际上只有一个结构。 这样的话，你读的数据放在了用来保存结构的地址空间中。  *part[1] part-->{指针}-->{结构} 其中，结构要经malloc分配能合法使用。 但是你实际把数值写进了保存指针的空间，大小不一定符合可能会越界。之所以没有出错，是因为你程序太短了。

引用 9 楼 u012033027 的回复:Part *part[1] 这样应该是要出错的。 没出错是因为你没有执行到会出错的地方。 我执行完整个程序了啊，就是一开始的那个程序

引用 3 楼 turingo 的回复:碰巧而已，Part*的话需要先用malloc分配内存。  [quote=引用 2 楼 u014463229 的回复:] [quote=引用 1 楼 turingo 的回复:] Part part[1]完全符合语法啊，有什么疑问呢？  [quote=引用 楼主 u014463229 的回复:] #include <stdio.h> #include <stdlib.h> int main() {     FILE *file=fopen("rr","r");     typedef struct{         int i;         long a;     }Part;     Part part[1];      //这里改成Part *part[1];为什么也对？     fread(part,sizeof(Part),1,file); } [/quote] 看后面的注释啊，问题在注释里[/quote][/quote] 你说的这个碰巧而已实话说我听不懂什么意思

引用 5 楼 wang0635 的回复:fread的第一个参数只要是指针就行，第二个只要是size_t的就行，sizeof（）括号里什么都可以，编译器只管这些了，后果自负 但是运行也没错误啊

引用 4 楼 u012033027 的回复:也许指针和数组元素的大小刚好相等，对sizeof操作来说，他们的结果是相同的。 我的意思是fread第一个参数为什么没报错，和sizeof没关系

也许指针和数组元素的大小刚好相等，对sizeof操作来说，他们的结果是相同的。

碰巧而已，Part*的话需要先用malloc分配内存。  引用 2 楼 u014463229 的回复:[quote=引用 1 楼 turingo 的回复:] Part part[1]完全符合语法啊，有什么疑问呢？  [quote=引用 楼主 u014463229 的回复:] #include <stdio.h> #include <stdlib.h> int main() {     FILE *file=fopen("rr","r");     typedef struct{         int i;         long a;     }Part;     Part part[1];      //这里改成Part *part[1];为什么也对？     fread(part,sizeof(Part),1,file); } [/quote] 看后面的注释啊，问题在注释里[/quote]

引用 1 楼 turingo 的回复:Part part[1]完全符合语法啊，有什么疑问呢？  [quote=引用 楼主 u014463229 的回复:] #include <stdio.h> #include <stdlib.h> int main() {     FILE *file=fopen("rr","r");     typedef struct{         int i;         long a;     }Part;     Part part[1];      //这里改成Part *part[1];为什么也对？     fread(part,sizeof(Part),1,file); } [/quote] 看后面的注释啊，问题在注释里

Part part[1]完全符合语法啊，有什么疑问呢？  引用 楼主 u014463229 的回复:#include <stdio.h> #include <stdlib.h> int main() {     FILE *file=fopen("rr","r");     typedef struct{         int i;         long a;     }Part;     Part part[1];      //这里改成Part *part[1];为什么也对？     fread(part,sizeof(Part),1,file); }


Question: 求解释下面程序的结果

引用 3 楼 boxmanstan 的回复:return;+1 主函数要近回int型的！！

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

return;

什么结果都不会有，因为 for 循环里 i 初始化为4之后一开始就不满足循环条件，导致此 for 循环根本没有得到执行。

我知道了，查了一下书 ，原来for（表达式1，表达式2，表达式3）语句的执行过程是1.先求表达式1 。2.再求表达式2，若真执行语句，否则退出循环。3.求解表达式3 4转回步骤2


Question: 求教大家如何使用数据集呢？

通读ADO联机帮助中的RecordSet对象？

能否具体一点


Question: C语言中的 （无符号字符指针）unsigned char *pImage 对应JAVA的byte[]是吗？

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

还有继续补充的吗，就要接贴了。

大概是这个意思。  引用 4 楼 lgmsyy 的回复:也就是说JAVA读取图片信息保存在byte[]后，可以将byte[]作为参数传给C语言的 unsigned char *pImage;(当然，中间需要JNI) 而并不需要在意byte是有符号的，而unsigned char *pImage是无符号的，是这样吗？  [quote=引用 3 楼 turingo 的回复:] 直接转就可以了。  [quote=引用 楼主 lgmsyy 的回复:] 但是byte[]怎么让他也是无符号的呢。  是这样的，在C中读取图片保存到无符号的字符指针变量。当读取的时候打印出>0的数字  但是JAVA读取图片保存在byte[]中，读取的时候，发现有的数据是负数。我如何将JAVA的byte[]也保存成无符号的呢。  有点绕，可能做过的人明白我的意思。[/quote][/quote]

也就是说JAVA读取图片信息保存在byte[]后，可以将byte[]作为参数传给C语言的 unsigned char *pImage;(当然，中间需要JNI) 而并不需要在意byte是有符号的，而unsigned char *pImage是无符号的，是这样吗？  引用 3 楼 turingo 的回复:直接转就可以了。  [quote=引用 楼主 lgmsyy 的回复:] 但是byte[]怎么让他也是无符号的呢。  是这样的，在C中读取图片保存到无符号的字符指针变量。当读取的时候打印出>0的数字  但是JAVA读取图片保存在byte[]中，读取的时候，发现有的数据是负数。我如何将JAVA的byte[]也保存成无符号的呢。  有点绕，可能做过的人明白我的意思。[/quote]

直接转就可以了。  引用 楼主 lgmsyy 的回复:但是byte[]怎么让他也是无符号的呢。  是这样的，在C中读取图片保存到无符号的字符指针变量。当读取的时候打印出>0的数字  但是JAVA读取图片保存在byte[]中，读取的时候，发现有的数据是负数。我如何将JAVA的byte[]也保存成无符号的呢。  有点绕，可能做过的人明白我的意思。

引用 1 楼 user-3 的回复:为何要把二进制数据当作数字或者字符串打印，没有意义的事情。  打印出来是正是负完全取决于你用有符号还是无符号存储，可见java的byte是有符号的。  C语言对外提供的接口参数要求是无符号字符指针类型，这里保存的是图片信息。  而JAVA读取图片后保存在byte[]中，因为byte[]是带符号的，我不知道这样传给C的参数unsigned char *是否可以


Question: 对统一个文件进行读取图片，为什么C语言和JAVA的结果不一样呢。我如何才能让JAVA读取和C一样的结果呢？

1、数据本质上都是一样的，只是被理解为有符号数和无符号数而已； 2、用byte类型就好，不需要转换的，后续主要把它理解为无符号数即可； 3、如果应是想转换，那么可以这样： 正常情况下，Java提供的数据类型是有符号signed类型的，可以通过位运算的方式得到它们相对应的无符号值： public int getUnsignedByte (byte data) {     return data & 0x0FF;  }  引用 楼主 lgmsyy 的回复:C语言：	 	FILE *fpImageFile; 	long lBegin, lEnd; 	unsigned char *pImage; 	int  nImageSize; 	 	fpImageFile = fopen("a.bmp", "rb");//读取图片 	 	lBegin = ftell(fpImageFile); 	fseek(fpImageFile, 0L, SEEK_END); 	lEnd = ftell(fpImageFile); 	nImageSize = int(lEnd - lBegin); 	pImage = new unsigned char[nImageSize]; 		 	fseek(fpImageFile, 0L, SEEK_SET);	 	fread(pImage, sizeof(unsigned char), nImageSize, fpImageFile);	         	fclose(fpImageFile); 	         int k=0; 	for(k=0;k<10;k++){ 		printf("%d : %d\n",k,pImage[k]); 	} 打印字符，假设前10个 0 : 66 1 : 77 2 : 202 3 : 61 4 : 7 5 : 0 6 : 0 7 : 0 8 : 0 9 : 0  ------------------------------------------------- JAVA语言：      public  byte[] image2Bytes(String imagePath) throws Exception {                 	 BufferedImage bu=ImageIO.read(new File(imagePath));       	           ByteArrayOutputStream imageStream = new ByteArrayOutputStream();                      try {           	               ImageIO.write(bu, "bmp", imageStream);                          } catch (Exception e) {           	               e.printStackTrace();            }            imageStream.flush();                    return imageStream.toByteArray();      } -------------------- 	byte[] imgBuff = hello.image2Bytes("a.bmp");			 	int nImageSize = imgBuff.length;	  	for(int i=0;i<10;i++){ 		if(imgBuff[i]!=-1){ 			System.out.println(i+":"+imgBuff[i]); 		}				 	}   读取字符，假设前十个 0:66 1:77 2:-54 3:61 4:7 5:0 6:0 7:0 8:0 9:0 ------------------------------ 为什么第二个元素的内容不一样呢？ 真实的情况下，不仅仅读取是个元素，图片有多大就图去多大，这样。C和JAVA打印出来的数据就以后很大的不同。

引用 2 楼 lgmsyy 的回复:[quote=引用 1 楼 user-2 的回复:] 无符号和有符号数。 请问怎么让JAVA的byte[]也是无符号的呢。目的是与C语言的 unsigned char *pImage对应。  我实验了以下，但是不行         byte[] mybyte = bos.toByteArray();                 for(int i=0;i<mybyte.length;i++){         	mybyte[i] = mybyte[i] & 0xff;           }[/quote] java没有无符号的byte,可以用更长的类型存储，然后再截断吧。

引用 1 楼 user-2 的回复:无符号和有符号数。 请问怎么让JAVA的byte[]也是无符号的呢。目的是与C语言的 unsigned char *pImage对应。  我实验了以下，但是不行         byte[] mybyte = bos.toByteArray();                 for(int i=0;i<mybyte.length;i++){         	mybyte[i] = mybyte[i] & 0xff;           }

无符号和有符号数。


Question: setjmp（）的返回值和longjmp的第二个参数是不是同一个变量？

longjmp第二个参数就是setjmp的返回值，但不能传0，如果传0则被修正为1.  自己学会看man page：man longjmp

你的帮助文档似乎并没有说明我的问题啊，而且残缺不全

Platform Builder for Microsoft Windows CE 5.0      setjmpSee Also longjmp | _fpreset  Requirements OS Versions: Windows CE 2.0 and later. Header: stdlib.h. Link Library: coredll.dll. Saves the current state of the program.  int setjmp(    jmp_buf env  ); Parameters env  Variable in which environment is stored.  Libraries All versions of the C run-time libraries.  Return Values setjmp returns 0 after saving the stack environment. If setjmp returns as a result of a longjmp call, it returns the value argument of longjmp, or if the value argument of longjmp is 0, setjmp returns 1. There is no error return.  Remarks The setjmp function saves a stack environment, which you can subsequently restore using longjmp. When used together, setjmp and longjmp provide a way to execute a non-local goto. They are typically used to pass execution control to error-handling or recovery code in a previously called routine without using the normal calling or return conventions.  A call to setjmp saves the current stack environment in env. A subsequent call to longjmp restores the saved environment and returns control to the point just after the corresponding setjmp call. All variables (except register variables) accessible to the routine receiving control contain the values they had when longjmp was called.  setjmp and longjmp do not support C++ object semantics. In C++ programs, use the C++ exception-handling mechanism. Using the longjmp or setjmp run-time routines in a C++ program will generate a link error if C++ exceptions are enabled using the /GX-Enable Exception Handling compiler option.  Requirements OS Versions: Windows CE 2.0 and later. Header: stdlib.h. Link Library: coredll.dll.  See Also longjmp | _fpreset     --------------------------------------------------------------------------------  Last updated on Wednesday, September 14, 2005  © 2005 Microsoft Corporation. All rights reserved.    Platform Builder for Microsoft Windows CE 5.0      longjmpSee Also setjmp  Requirements OS Versions: Windows CE 2.0 and later. Header: stdlib.h. Link Library: coredll.dll. Restores stack environment and execution locale.  void longjmp(     jmp_buf env,     int value  ); Parameters env  Variable in which environment is stored.  value  Value to be returned to setjmp call.  Return Values None.  Remarks The longjmp function restores a stack environment and execution locale previously saved in env by setjmp.   setjmp and longjmp provide a way to execute a nonlocal goto; they are typically used to pass execution control to error-handling or recovery code in a previously called routine without using the normal call and return conventions.  A call to setjmp causes the current stack environment to be saved in env. A subsequent call to longjmp restores the saved environment and returns control to the point immediately following the corresponding setjmp call. Execution resumes as if value had just been returned by the setjmp call.   The values of all variables (except register variables) that are accessible to the routine receiving control contain the values they had when longjmp was called.   The values of register variables are unpredictable. The value returned by setjmp must be nonzero. If value is passed as 0, the value 1 is substituted in the actual return.  Call longjmp before the function that called setjmp returns; otherwise the results are unpredictable.  Observe the following restrictions when using longjmp:   Do not assume that the values of the register variables will remain the same. The values of register variables in the routine calling setjmp may not be restored to the proper values after longjmp is executed.  Do not use longjmp to transfer control out of an interrupt-handling routine unless the interrupt is caused by a floating-point exception. In this case, a program may return from an interrupt handler via longjmp if it first reinitializes the floating-point math package by calling _fpreset.  Be careful when using setjmp and longjmp in C++ programs. Because these functions do not support C++ object semantics, it is safer to use the C++ exception-handling mechanism.  Using the longjmp or setjmp C runtime routines in a C++ file will generate a link error if C++ exceptions are enabled by using the /GX - Enable Exception Handling compiler option. This behavior is by design in Windows CE.  Requirements OS Versions: Windows CE 2.0 and later. Header: stdlib.h. Link Library: coredll.dll.  See Also setjmp     --------------------------------------------------------------------------------  Last updated on Wednesday, September 14, 2005  © 2005 Microsoft Corporation. All rights reserved.    我想帮助文档总比我的描述更妥当。希望对LZ有所帮助。


Question: clock_t实际是什么类型 ？怎么打出clock（）返回值？

clock()的粒度比较粗，各大平台的clib实现基本都保持在10ms左右的粒度上。需要更细粒度的你不能用clock()。

这个问题还没解决那： 我把lu换成ld格式码，为什么输出还是0？

顶上去累了乐乐

我把lu换成ld格式码，为什么输出还是0？

C:\Program Files\Microsoft Visual Studio 10.0\VC\include\time.h      82: typedef long clock_t;

clock_t是个长整型数。 #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { long i = 10000000L; clock_t start, finish; double duration; /* 测量一个事件持续的时间*/ printf( "Time to do %ld empty loops is ", i) ; start = clock(); while( i-- ); finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; printf( "%f seconds\n", duration ); system("pause"); }

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


Question: 全局变量如何定义

现在编辑器  生成.h的时候  会自动生成防止重复链接的关键字吧

zhao 专家的没错。。。都这么弄的， .h 里面 extern 在某个 .c文件中 声明了之后  其他 .c 文件都可以用  关键 还是防止重编译的问题

引用 10 楼 xunfeng0862 的回复:谢谢各位牛的回复。赵老师说的方法不对，我已经试过，会有重复包含的问题。  可能同我的工作有关吧，我做嵌入式的，公司所有的全局变量都是定义在相对应的.h里面，如果别的文件要用，所有的文件都可以使用。  9楼的回复 我的第二点，第三点是不一样的，第二点最起码我在IAR上用是通不过的， 第三点可以，9楼可以试下。  我现在的做法是，在一个.h里面用extern int a, 其他的头文件里面直接int a.这样做行的通。  全局变量的定义到底同编译器有么有关系，欢迎各位畅所欲言，提供宝贵的意见，谢谢！ 我觉着zhao专家的说法没有什么问题。关键就是你怎么防止重复定义，也就是判断是否已经定义过。 多年之前使用C语言都是这样定义全局变量。 或者你可以参考一下系统的头文件定义，一般都会有几个全局变量之类的定义，比如windows.h之流。 仔细检查对比一下，应该能发现自己错误的原因。 至于你现在采取的.h里面用extern，然后在.c里面定义，只是绕开重复定义的一种方法，即只在一个地方定义，其它都是extern。 至于不美观的方法，应该是个人风格的原因。 你已经在.h里面extern定义了变量，其它.c文件只需要include这个.h文件就可以了，为什么还要extren定义呢

头文件extern int g; 对应cpp,int g;

嗯，可以这么说，一个.c或.h文件中，在函数以外定义的变量，就是全局变量。

引用 10 楼 xunfeng0862 的回复: 最佳方式就是一个头文件，比如  /** x.h ***/   extern int x; 一个C文件 比如 /*** x.c ***/ int x = 0; 任何C文件  #include “x.h” 因为 extern int x; 是声明，不怕重复，可以在任何文件里重复任意次  如果非要一次定义，并定义在头文件里 那就学学μOS2 的方法 /***x.h ***/ #ifdef XXXX #define EXTERN_XXXX  #else  #define EXTERN_XXXX extern #endif   EXTERN_XXXX  int x; /**** x.c *****/ #define XXXX #include "x.h" /** 其它实现文件 **/ /*** y.c**/ #include "x.h"  也可以这么做 /****x.h *****/ #ifdef XXXXX int  x =0; #else extern int x; #endif  这样定义 在某个.C 中  例如 x.c  #define XXXXX #include "x.h" 其他.C /** y.c  **/ #include "x.h"  头文件加保护，防止重复包含 主要是某些声明定义和顺序有关的，比如结构 枚举，宏定义等等 重复包含就会出错  象函数原型声明，外部变量声明，类型的前置声明;这种只，只要形式一致，不论包含多少次，声明几次，都不会出现重复定义错误。  重复定义，包括重复包含，之所以会出现错误，主要是因为多处定义问题，多处声明并不会有问题。  函数，外部变量，类型的多处定义，一些宏定义，enum 定义，可能会导致重复定义错误。

#include就是原原本本把另一个文件的内容放到include的位置。  在一个C文件里定义变量，其他C文件里面extern变量 一个C文件里定义变量，H文件extern变量，其他C文件include这个H文件 这两个方式是一样的  LZ说通不过，发出错误警告和报错的代码看看

不在任何函数里面定义的变量就是全局变量

引用 楼主 xunfeng0862 的回复:1. 要在.h里面定义全局变量。所有文件都可以使用。  我用GCC， vc, keil编译器都没有问题，最近用IAR出现重复定义问题。  这种用法是错误的。除非你的这个头文件只用了一次。  引用 楼主 xunfeng0862 的回复:2. 不要说什么在.h里面用extern int a, 在.c里面用int a这样就可以，我试了行不通。  为什么不说，这是最常规的用法。  引用 楼主 xunfeng0862 的回复:3. 目前我的方法是在.c文件里面定义，其他文件要用的话用extern，但是这样做不美观。  这和 2 的用法是完全等价的。

在头文件定义，然后其他源文件需要使用的时候直接#include 此头文件就好了！

IAR 肯定重包含文件了

我是dsp， 我的全局变量是在一个C中定义，别的C extern

1，理解头文件是什么，#Include做了什么事情。 2，理解编译和链接是干嘛的。

在.c文件里定义 int xxx;在头文件里声明extern同时注意头文件要用宏包起来，防止重复包含，在需要用这个变量的.c里包含头文件

引用2. 不要说什么在.h里面用extern int a, 在.c里面用int a这样就可以，我试了行不通。  把你所谓的不行的代码贴出来  我怀疑你自己写错了

1.在.h文件中定义变量是大忌。 首先为什么要用.h文件？头文件提供的是接口，是被其他程序引用的。你在.h中定义了变量，其他程序include之后，在编译的时候会将.h文件展开。这时候，就会出现两个.c文件中定义了同名的变量。这样就会出现重复定义的问题。 2.因为1的原因，所以全局变量要在.c文件中定义。其他引用的地方使用extern声明。LZ说这么做不可以，还是贴代码看看吧。 3.这种做法为什么不美观了。。。

在.h里面定义，并在.h文件 前面加 #ifndef _INC_THISFILE #define _INC_THISFILE 最后加 #endif  或者  前面加 #pragma once


Question: 如何将mac地址转换成6字节的字符数组

16进制转字节表示。

第6行maxhex[i]=(char)v; 纠正为machex[i]=(char)v;

char macstr[18] = "00:0f:2a:d2:fe:ef"; char machex[6]; int v,i; for (i=0;i<6;i++) {     sscanf(macstr+3*i,"%2x",&v);     maxhex[i]=(char)v; }  作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。

嗯，谢谢了，实验了，没有问题！！！

要这个效果吗？     char mac[] = "00:0f:2a:d2:fe:ef";     unsigned char addr[6];     sscanf(mac,"%2x:%2x:%2x:%2x:%2x:%2x",addr,addr+1,addr+2,addr+3,addr+4,addr+5);


Question: 刚下的c-free，怎么会这样啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

无聊路过看看。  zhao4zhong1  就是CSDN的佑哥

把源代码的后缀名.cpp改成.c

推荐使用vc或者vs。如果是win8的系统的话，vc不怎么兼容，只有用vs。win8以下的应该两种都兼容。具体下载地址你可以去百度。

stdio.h找不到！

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

#include<stdio.h> void main() { 	printf("运行不了"); }


Question: 不在数组正常坐标的值是什么值？

int a[] = {1,2,3}   对数组的访问, 其实就是以数组的首地址为基地址, 然后以索引为偏移取地址访问数据.  按int为4字节为例 比如 a数组首地址为 0x12340000  那么 a[-1] 即相当于访问  0x12340000 - 4  =  0x1233FFFC  其它类似.

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

引用 楼主 u012421069 的回复:int a[] = {1,2,3}  a[-1] a[188] a[11123]  这些值代表的是什么？在内存中吗？ 就你上面几个例子，都在内存中. a是数组，也就是一个分配的地址 a[-1]表示a的地址减去int个字节 a[188]表示a的地址加上188个int字节。

其实电脑开机后物理内存的每个字节都是可读写的，区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。


Question: proc问题

你的sql语句在那里执行的？

你没有执行SQL语句怎么可能获取到值.

EXEC SQL EXECUTE IMMEDIATE :sqlstr; 以上这句不是执行吗？


Question: 结构体大小的计算中嵌套结构体的情况

谢谢各位的解释，借用了zhao4zhong1大牛的代码测试了一下，编译器设置仍然是默认8，结果如图，是我那个理解

打印两个变量的内存地址看一下就知道了。

#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 // //A1.a 0 //A1.b 4 //A1.c 17 // //A2.a 0 //A2.b 4 //A2.c 18 // //A4.a 0 //A4.b 4 //A4.c 20 // //A8.a 0 //A8.b 4 //A8.c 24 // //A16.a 0 //A16.b 4 //A16.c 24 // //

输出它们的指针, 应该会有所发现.

你的理解应该是对的，你同学的错了 首先要搞清楚为什么需要字节对齐。如果是你同学的那种方式，那么cpu在读取stB的时候，需要做两次读操作。这样很耗时的


Question: 将十进制整数转换为字符串的printd函数看不明白

明白了，有一种顿悟的感觉！！！！higxin

用gcc测试通过，不过puchar是不是写错了，是不是putchar。。。。。。

唉，还是不懂啊，

引用 6 楼 u014082409 的回复:哥们，我没有理解，你就解释下呗。我要是理解了就不会上来问了。  主要是一开始你就把这个排除了  引用 1 楼 u014082409 的回复:当然每一语句都没问题，还有递归的调用。问题在于  .

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

引用 3 楼 u014082409 的回复:测试能通过，我的意思是这个函数的逻辑没有弄清楚。123这个数，经过 两次的 /，最后剩下  1（十进制的1），然后 % 10 + ‘0’，就得到字符串的‘1’，但是貌似这个函数就没有然后了。另外，第一个 if（n / 10）后，再到printd（n / 10），这里面的两个n的值是一样的吗？ 建议： 1. step into 2. 打印输出运行信息。  供参考。

哥们，我没有理解，你就解释下呗。我要是理解了就不会上来问了。

引用 3 楼 u014082409 的回复:测试能通过，我的意思是这个函数的逻辑没有弄清楚。123这个数，经过 两次的 /，最后剩下  1（十进制的1），然后 % 10 + ‘0’，就得到字符串的‘1’，但是貌似这个函数就没有然后了。另外，第一个 if（n / 10）后，再到printd（n / 10），这里面的两个n的值是一样的吗？ 之所以你弄不清楚，你因为你没理解递归

同样测试过，输入123，输出123。 只是发现puchar写错了，应该是putchar。

vs2005测试通过，结果 123

数字加 ‘0’ 之后就成对应ascii的字符数字了！ 递归取每一位数字


Question: 新手刚学C语言getchar函数，有个问题想问问

和编译器有关，VC6的变异器不是你这种情况，你用的什么编译器？ 如果你的代码想避免这种情况可以在printf之后加上这句：fflush(stdout);应当就可以了。 引用 楼主 weiryou10 的回复: #include<stdio.h> int main() { 	int c; 	printf("hello\n"); 	while ((c = getchar()) != EOF && c != '\n') { 		printf("%c", c); 	} 	return 0; }  我的打印hello的语句在getchar函数前面，为什么运行的时候，还是等待我输入后，才打印hello

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


Question: 一个软件是单机版的，怎么限制它的安装数量

软件是可以写自己的，弄个计数器，装一次就+1.

开源时代，再说在中国市场上，反盗版你是做不到的

不绑定安装主机的相关信息,   什么作用也没有. 一般限制安装的做法, 都是绑定目标机器的一些硬件信息. 符合则能运行安装, 不符合则不安装. 但是你能这样限制, 别人肯定也有方法破解. 现在都是软件免费, 服务收费的年代了.

在 神 朝 ，讲究 分享 与 和平；当然如果是卖到国外，有些国家可以直接在授权声明里面 做好授权即可

这个只能找逆向大神帮你加壳了。

一般的思路都是不限制安装，但是控制运行（比如注册码的形式）

奉劝楼主不要把有限的生命浪费在无限的加密解密死循环中！  现在是开源时代。

用个usb key，记录安装数量，每次安装必须要插入key，安装完成后更新对应的数值


Question: C语言串口通信

google下吧，应该有很多例子吧！

另外：推荐使用portmon软件辅助调试串口通讯程序。

引用 2 楼 z_jzhao 的回复:哪里有下载的？ 搜MSDN98或MSDN 6.0

哪里有下载的？

MSDN98\SAMPLES\VC98\SDK\WINBASE\IO\SERIAL\*.*


Question: 大神来教一教。感激不尽

建议楼主还是抽时间学习一下T-SQL语句。

哪里有问题？


Question: c语言des 解密问题！！！

引用 9 楼 zjq9931 的回复:[quote=引用 8 楼 newcdl3 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。 你想气死我啊？？？我是弄java的，c我也不会，我要是会，我就不用你了，现在就差c的解密了，就不能帮帮我，我这不没办法了吗！！！[/quote] 这个算法似乎和标准的DES有些区别。估计是翻译问题。 这样你把你的java的代码发上来，我来翻译成C的，应当就可以了。[/quote] 谢谢了，弄出来了，好累啊！！弄了一个星期。

引用 5 楼 zhao4zhong1 的回复:/***************************************************************************** *                                                                            * *  --------------------------------- bit.h --------------------------------  * *                                                                            * *****************************************************************************/  #ifndef BIT_H #define BIT_H  /***************************************************************************** *                                                                            * *  --------------------------- Public Interface ---------------------------  * *                                                                            * *****************************************************************************/  int bit_get(const unsigned char *bits, int pos);  void bit_set(unsigned char *bits, int pos, int state);  void bit_xor(const unsigned char *bits1, const unsigned char *bits2, unsigned    char *bitsx, int size);  void bit_rot_left(unsigned char *bits, int size, int count);  #endif  /***************************************************************************** *                                                                            * *  ------------------------------- encrypt.h ------------------------------  * *                                                                            * *****************************************************************************/  #ifndef ENCRYPT_H #define ENCRYPT_H  /***************************************************************************** *                                                                            * *  In a secure implementation, Huge should be at least 400 decimal digits,   * *  instead of the 10 below (ULONG_MAX = 4294967295).                         * *                                                                            * *****************************************************************************/  typedef unsigned long Huge;  /***************************************************************************** *                                                                            * *  Define a structure for RSA public keys.                                   * *                                                                            * *****************************************************************************/  typedef struct RsaPubKey_ {  Huge               e; Huge               n;  } RsaPubKey;  /***************************************************************************** *                                                                            * *  Define a structure for RSA private keys.                                  * *                                                                            * *****************************************************************************/  typedef struct RsaPriKey_ {  Huge               d; Huge               n;  } RsaPriKey;  /***************************************************************************** *                                                                            * *  --------------------------- Public Interface ---------------------------  * *                                                                            * *****************************************************************************/  void des_encipher(const unsigned char *plaintext, unsigned char *ciphertext,    const unsigned char *key);  void des_decipher(const unsigned char *ciphertext, unsigned char *plaintext,    const unsigned char *key);  void rsa_encipher(Huge plaintext, Huge *ciphertext, RsaPubKey pubkey);  void rsa_decipher(Huge ciphertext, Huge *plaintext, RsaPriKey prikey);  #endif  哥哥你能不能把我的那个解密弄弄，我现在就差解密了，因为是和java联通的，现在java和我的那个c程序加密的密文一样的，但是这个c程序解密有问题，帮我看看

《算法精解（C语言实现）》  #include <math.h> #include <stdlib.h> #include <string.h>  #include "bit.h" #include "encrypt.h"  static const int DesTransform[56] = {     57, 49, 41, 33, 25, 17,  9,  1, 58, 50, 42, 34, 26, 18,    10,  2, 59, 51, 43, 35, 27, 19, 11,  3, 60, 52, 44, 36,    63, 55, 47, 39, 31, 23, 15,  7, 62, 54, 46, 38, 30, 22,    14,  6, 61, 53, 45, 37, 29, 21, 13,  5, 28, 20, 12,  4  };  static const int DesRotations[16] = {     1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1  };  static const int DesPermuted[48] = {     14, 17, 11, 24,  1,  5,  3, 28, 15,  6, 21, 10,    23, 19, 12,  4, 26,  8, 16,  7, 27, 20, 13,  2,    41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,    44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32  };  static const int DesInitial[64] = {     58, 50, 42, 34, 26, 18, 10,  2, 60, 52, 44, 36, 28, 20, 12,  4,    62, 54, 46, 38, 30, 22, 14,  6, 64, 56, 48, 40, 32, 24, 16,  8,    57, 49, 41, 33, 25, 17,  9,  1, 59, 51, 43, 35, 27, 19, 11,  3,    61, 53, 45, 37, 29, 21, 13,  5, 63, 55, 47, 39, 31, 23, 15,  7  };  static const int DesExpansion[48] = {     32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,     8,  9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,    16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,    24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32,  1  };  static const int DesSbox[8][4][16] = {     {    {14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7},    { 0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8},    { 4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0},    {15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13},    },     {    {15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10},    { 3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5},    { 0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15},    {13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9},    },     {    {10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8},    {13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1},    {13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7},    { 1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12},    },     {    { 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15},    {13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9},    {10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4},    { 3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14},    },     {    { 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9},    {14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6},    { 4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14},    {11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3},    },     {    {12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11},    {10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8},    { 9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6},    { 4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13},    },     {    { 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1},    {13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6},    { 1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2},    { 6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12},    },     {    {13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7},    { 1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2},    { 7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8},    { 2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11},    },  };  static const int DesPbox[32] = {     16,  7, 20, 21, 29, 12, 28, 17,  1, 15, 23, 26,  5, 18, 31, 10,     2,  8, 24, 14, 32, 27,  3,  9, 19, 13, 30,  6, 22, 11,  4, 25  };  static const int DesFinal[64] = {     40,  8, 48, 16, 56, 24, 64, 32, 39,  7, 47, 15, 55, 23, 63, 31,    38,  6, 46, 14, 54, 22, 62, 30, 37,  5, 45, 13, 53, 21, 61, 29,    36,  4, 44, 12, 52, 20, 60, 28, 35,  3, 43, 11, 51, 19, 59, 27,    34,  2, 42, 10, 50, 18, 58, 26, 33,  1, 41,  9, 49, 17, 57, 25  };  typedef enum DesEorD_ {encipher, decipher} DesEorD;  static void permute(unsigned char *bits, const int *mapping, int n) {  unsigned char      temp[8];  int                i;  memset(temp, 0, (int)ceil(n  8));  for (i = 0; i < n; i++)    bit_set(temp, i, bit_get(bits, mapping[i] - 1));  memcpy(bits, temp, (int)ceil(n  8));  return;  }  static int des_main(const unsigned char *source, unsigned char *target, const    unsigned char *key, DesEorD direction) {  static unsigned char subkeys[16][7];  unsigned char        temp[8],                      lkey[4],                      rkey[4],                      lblk[6],                      rblk[6],                      fblk[6],                      xblk[6],                      sblk;  int                  row,                      col,                      i,                      j,                      k,                      p;  if (key != NULL) {     *    *  Make a local copy of the key.    *     memcpy(temp, key, 8);     *    *  Permute and compress the key into 56 bits.    *     permute(temp, DesTransform, 56);     *    *  Split the key into two 28-bit blocks.    *     memset(lkey, 0, 4);    memset(rkey, 0, 4);     for (j = 0; j < 28; j++)       bit_set(lkey, j, bit_get(temp, j));     for (j = 0; j < 28; j++)       bit_set(rkey, j, bit_get(temp, j + 28));     *    *  Compute the subkeys for each round.    *     for (i = 0; i < 16; i++) {        *       *  Rotate each block according to its round.       *        bit_rot_left(lkey, 28, DesRotations[i]);       bit_rot_left(rkey, 28, DesRotations[i]);        *       *  Concatenate the blocks into a single subkey.       *        for (j = 0; j < 28; j++)          bit_set(subkeys[i], j, bit_get(lkey, j));        for (j = 0; j < 28; j++)          bit_set(subkeys[i], j + 28, bit_get(rkey, j));        *       *  Do the permuted choice permutation.       *        permute(subkeys[i], DesPermuted, 48);     }  }  memcpy(temp, source, 8);  permute(temp, DesInitial, 64);  memcpy(lblk, &temp[0], 4); memcpy(rblk, &temp[4], 4);  for (i = 0; i < 16; i++) {     *    *  Begin the computation of f.    *     memcpy(fblk, rblk, 4);     *    *  Permute and expand the copy of the right block into 48 bits.    *     permute(fblk, DesExpansion, 48);     *    *  Apply the appropriate subkey for the round.    *     if (direction == encipher) {        *       *  For enciphering, subkeys are applied in increasing order.       *        bit_xor(fblk, subkeys[i], xblk, 48);       memcpy(fblk, xblk, 6);        }     else {        *       *  For deciphering, subkeys are applied in decreasing order.       *        bit_xor(fblk, subkeys[15 - i], xblk, 48);       memcpy(fblk, xblk, 6);     }     *    *  Do the S-box substitutions.    *     p = 0;     for (j = 0; j < 8; j++) {        *       *  Compute a row and column into the S-box tables.       *        row = (bit_get(fblk, (j * 6)+0) * 2) + (bit_get(fblk, (j * 6)+5) * 1);       col = (bit_get(fblk, (j * 6)+1) * 8) + (bit_get(fblk, (j * 6)+2) * 4) +             (bit_get(fblk, (j * 6)+3) * 2) + (bit_get(fblk, (j * 6)+4) * 1);        *       *  Do the S-box substitution for the current six-bit block.       *        sblk = (unsigned char)DesSbox[j][row][col];        for (k = 4; k < 8; k++) {           bit_set(fblk, p, bit_get(&sblk, k));          p++;        }     }     *    *  Do the P-box permutation to complete f.    *     permute(fblk, DesPbox, 32);     *    *  Compute the XOR of the left block and f.    *     bit_xor(lblk, fblk, xblk, 32);     *    *  Set the left block for the round.    *     memcpy(lblk, rblk, 4);     *    *  Set the right block for the round.    *     memcpy(rblk, xblk, 4);  }  memcpy(&target[0], rblk, 4); memcpy(&target[4], lblk, 4);  permute(target, DesFinal, 64);  return 0;  }  void des_encipher(const unsigned char *plaintext, unsigned char *ciphertext,    const unsigned char *key) {  des_main(plaintext, ciphertext, key, encipher);  return;  }  void des_decipher(const unsigned char *ciphertext, unsigned char *plaintext,    const unsigned char *key) {  des_main(ciphertext, plaintext, key, decipher);  return;  }

引用 1 楼 zjq9931 的回复:这个里面没有解密代码。。。 有的// 执行加密解密操作 void Encrypt(int timeData[], int flag, int keyarray[][48],byte encrypt[])  { 	int i; 	int flags = flag; 	int M[64]={0}; 	int MIP_1[64]={0}; 	// 特别注意：xxx[IP[i]-1]等类似变换 	for (i = 0; i < 64; i++) { 		M[i] = timeData[IP[i] - 1]; // 明文IP变换 	} 	if (flags == 1) { // 加密 		for (i = 0; i < 16; i++) { 			LoopF(M, i, flags, keyarray); 		} 	} else if (flags == 0) { // 解密 		for (i = 15; i > -1; i--) { 			LoopF(M, i, flags, keyarray); 		} 	} 	for (i = 0; i < 64; i++) { 		MIP_1[i] = M[IP_1[i] - 1]; // 进行IP-1运算 	} 	GetEncryptResultOfByteArray(MIP_1, encrypt); }是根据1是加密，0是解密，但是这个程序哪个有点小问题，我没找到。

这里的这个应当可用。 http://download.csdn.net/download/wwww5500/7117269

这个里面没有解密代码。。。

引用 9 楼 zjq9931 的回复:[quote=引用 8 楼 newcdl3 的回复:] [quote=引用 7 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。 你想气死我啊？？？我是弄java的，c我也不会，我要是会，我就不用你了，现在就差c的解密了，就不能帮帮我，我这不没办法了吗！！！[/quote] 这个算法似乎和标准的DES有些区别。估计是翻译问题。 这样你把你的java的代码发上来，我来翻译成C的，应当就可以了。[/quote] 路过，学习学习。

引用 8 楼 newcdl3 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。 你想气死我啊？？？我是弄java的，c我也不会，我要是会，我就不用你了，现在就差c的解密了，就不能帮帮我，我这不没办法了吗！！！[/quote] 对我来说，给你张网比给你一条刚好对你胃口的鱼容易得多。

引用 8 楼 newcdl3 的回复:[quote=引用 7 楼 zhao4zhong1 的回复:] 代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。 你想气死我啊？？？我是弄java的，c我也不会，我要是会，我就不用你了，现在就差c的解密了，就不能帮帮我，我这不没办法了吗！！！[/quote] 这个算法似乎和标准的DES有些区别。估计是翻译问题。 这样你把你的java的代码发上来，我来翻译成C的，应当就可以了。

引用 7 楼 zhao4zhong1 的回复:代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。 你想气死我啊？？？我是弄java的，c我也不会，我要是会，我就不用你了，现在就差c的解密了，就不能帮帮我，我这不没办法了吗！！！


Question: 栈空间的生长方式为从高地址到低地址 但是在栈空间申请一个数组 地址生长方式为递增  我也知道数组名是数组地址 +1为下一个元素

C，C++堆栈有这么几种用途，很多其它语言也这么用 1）为局部变量，包括数组，分配内存，以及初始化他们（如果需要） 2）某些临时数据暂存在堆栈，  3）由于寄存器数量有限，一些中间结果要及时压栈处理 4）函数调用时，存放将来函数返回时候，要执行的下一条指令的地址。 以及函数返回的退栈处理。包括。函数入口 ,函数出口的ebp,esp调整。 这个其实本来是自动执行的，不过C,C++会利用这个机制做些安排。  5）当用堆栈传递参数的时候（参数可能用寄存器传递，不一定都是堆栈传递），        复制参数到堆栈中（就是初始化函数的形式参数） 6）异常处理中的堆栈操作 7）longjmp 函数的堆栈操作  8）其他用途，和C,C++这种具体的编程语言无关， 中断时候的状态寄存器自动入栈处理， 中断位置的自动记录处理，以及中断返回的自动处理。 以及操作系统的堆栈切换处理 例如，线程上下文切换等等。

函数调用通常会有数据压栈 但不是总是如此 最重要的是，数组的内容，通常不会压栈，而是仅仅传递一个指针 struct 倒是会压栈的，struct 内部的数组，也会压栈的 不过所谓压栈其实也就是数据复制，可能用 压栈指令， 也可能只是直接的复制，例如使用memcpy 函数或者说，rep movs 指令 像 float,double 入栈， 则是把数据，装载到浮点寄存器中，然后写入堆栈 一般整型数据，采用压栈指令 其它数据跟类型有关， 总之，就是在堆栈中，分配个位置给所有非寄存器参数，然后一一装入堆栈中。 一些参数用寄存器传递，此时跟堆栈无关 寄存器传递的参数，没啥好说的，按照位置，以及某种约定，直接传入寄存器中

引用 16 楼 lm_whales 的回复:[quote=引用 15 楼 u010956619 的回复:] 一年多过去了，今天我搜到了这个帖子。正好我看到的一本书里面是这样说的： 默认的函数内部变量的压栈操作为：从上到下、从左到右，采用4字节对齐。数组的压栈方法略有不同，即从最后一个元素开始，直到起始元素为止，即采用从右向左的方法压栈。 书名是 《C语言进阶：重点、难点与疑点》 内部变量，只是空间安排，不需要压栈，只有初始化的问题。 初始化未必是压栈操作，实际上只需要向这个地址空间，填入初始化的数据，就可以了 初始化函数内部的数组，要么是个填充操作,典型的如 int a[]=｛0｝； 要么是个复制操作例如： int a[]={1,2,3,4,5,6,7,8,9,10} 而函数参数，数组只需要传递地址，不需要数据压栈。所以并不需要特殊处理。 所以，你看到的这个，可能只是某个具体的实现。未必都是如此 [/quote] 忘了说了，这段话是在函数调用的章节中提到的，函数调用的时候会有压栈操作

所谓 栈空间的生长方式由高到低，指的是（以 X86 体系结构为例），一些默认使用 sp (stack pointer)寄存器的指令，如 push, pop, call, ret 等，在入栈的时候 sp 会减小，出栈的时候 sp 增加。  其实栈空间也是一段普通的内存，可以任意的方式访问；sp 也可以不通过 push pop 直接操作。  以上是机器语言实现层面的问题。在这里，没有所谓数组的概念。  在访问函数参数与局部变量的时候，几乎一定是不会用 push 和 pop 的。 开辟空间的时候，参数入栈经常不使用 push ，局部变量开辟空间几乎一定不会用 push （而是直接 sub sp）。  编译器生成代码用 sub sp 预留一段空间给局部变量用，然后把那一段给那个变量用，编译器就可以自行决定了。 由于这只是一段普通的内存，当然怎么用都可以。  以下说 C 语言。  然而 C 语言本身并没有栈的概念。 C 语言只规定了一些特殊情况下的指针比较结果，如在两个指针指向同一数组中的元素时（序号大的大于序号小的），指向同一个结构体对象的成员时（后定义的成员大于先定义的成员），等等。但是对于指向同一个函数的不同局部变量的指针之间的比较结果并没有规定。也就是说，编译器可以随便安排他们的顺序。  =================== 这里应该是将不同层面的问题混淆在了一起。

引用 15 楼 u010956619 的回复:一年多过去了，今天我搜到了这个帖子。正好我看到的一本书里面是这样说的： 默认的函数内部变量的压栈操作为：从上到下、从左到右，采用4字节对齐。数组的压栈方法略有不同，即从最后一个元素开始，直到起始元素为止，即采用从右向左的方法压栈。 书名是 《C语言进阶：重点、难点与疑点》 内部变量，只是空间安排，不需要压栈，只有初始化的问题。 初始化未必是压栈操作，实际上只需要向这个地址空间，填入初始化的数据，就可以了 初始化函数内部的数组，要么是个填充操作,典型的如 int a[]=｛0｝； 要么是个复制操作例如： int a[]={1,2,3,4,5,6,7,8,9,10} 而函数参数，数组只需要传递地址，不需要数据压栈。所以并不需要特殊处理。 所以，你看到的这个，可能只是某个具体的实现。未必都是如此

引用 13 楼 aa2650 的回复:[quote=引用 9 楼 yusiguyuan 的回复:] [quote=引用 7 楼 aa2650 的回复:] 就像4楼说的, 数组的方向和栈的方向为什么要相同呢？ 因为栈是用数组实现的, 所以lz产生了数组增长方向一定得和栈方向一致的下意识的错觉吧 这种错觉就好比, 物理内存增长方向还是从低地址向高地址的呢, 那么堆的方向对了, 栈的方向错啦, 怎么能开口向上呢?(这么比喻是不是感觉到你的那种错觉很无理了?) 数组无非是连续的char而已, 一个int其实也是4个连续的char, 如果必须按栈的方向来, 就没有大小端的问题存在了.我是这么想的，首先申请地 数组属于栈空间内，既然这个变量在栈空间内，那么就总得符合栈空间的一些规范吧，比如栈空间的生长方式是由从高地址到低地址，但是数组中的元素地址并非这样，但是申请别的变量又符合这种规范，就觉得有什么蹊跷不懂的地方[/quote] 啥叫栈空间的规范? 就是栈的"后进先出"特性而已. 你所谓的"申请别的变量符合", 那是因为你把别的变量当作一个整体看了; 你所谓的"数组不符合", 那是因为你把其它变量都从整体看, 却偏偏"歧视性"地把数组变量从微观去看.(为啥int是4个字节你把这4个字节从整体来看, 数组是n个字节你却不把这n个字节当成一个整体看???)  从整体看, "别的变量"和数组变量, 都是符合栈的LIFO规范(从整体看!!! 整个数组是一个变量, 别一看数组又从微观去看) 从微观看, 数组增长方向和栈开头方向没必要一致; 你所谓的"别的变量", 比如一个int是4个字节, 也不一定和栈的开口方向一致(大小端总有一种情况是不一样的吧?)  我觉得解释的够细了, 你还不理解的话, 只能说你钻牛角尖没真正看进去大家的回复.[/quote] 首先，谢谢，说句你懂我，你真的懂我的意思，我可能就是钻到那个牛角尖了----从整体来看（把数组当做一个变量而不是多个变量）确实符合栈的规范。 但是，数组也是多个4字节组成的，为啥就没按照栈的规范呢（可能我有牛角尖了，呵呵呵），你所说的除最后一句话 我都很清楚，但是有一句不是很明白。      从微观看, 数组增长方向和栈开头方向没必要一致; 你所谓的"别的变量", 比如一个int是4个字节, 也不一定和栈的开口方向一致(大小端总有一种情况是不一样的吧?)     这句该咋想呢？谢谢啊！！！

引用 9 楼 yusiguyuan 的回复:[quote=引用 7 楼 aa2650 的回复:] 就像4楼说的, 数组的方向和栈的方向为什么要相同呢？ 因为栈是用数组实现的, 所以lz产生了数组增长方向一定得和栈方向一致的下意识的错觉吧 这种错觉就好比, 物理内存增长方向还是从低地址向高地址的呢, 那么堆的方向对了, 栈的方向错啦, 怎么能开口向上呢?(这么比喻是不是感觉到你的那种错觉很无理了?) 数组无非是连续的char而已, 一个int其实也是4个连续的char, 如果必须按栈的方向来, 就没有大小端的问题存在了.我是这么想的，首先申请地 数组属于栈空间内，既然这个变量在栈空间内，那么就总得符合栈空间的一些规范吧，比如栈空间的生长方式是由从高地址到低地址，但是数组中的元素地址并非这样，但是申请别的变量又符合这种规范，就觉得有什么蹊跷不懂的地方[/quote] 啥叫栈空间的规范? 就是栈的"后进先出"特性而已. 你所谓的"申请别的变量符合", 那是因为你把别的变量当作一个整体看了; 你所谓的"数组不符合", 那是因为你把其它变量都从整体看, 却偏偏"歧视性"地把数组变量从微观去看.(为啥int是4个字节你把这4个字节从整体来看, 数组是n个字节你却不把这n个字节当成一个整体看???)  从整体看, "别的变量"和数组变量, 都是符合栈的LIFO规范(从整体看!!! 整个数组是一个变量, 别一看数组又从微观去看) 从微观看, 数组增长方向和栈开头方向没必要一致; 你所谓的"别的变量", 比如一个int是4个字节, 也不一定和栈的开口方向一致(大小端总有一种情况是不一样的吧?)  我觉得解释的够细了, 你还不理解的话, 只能说你钻牛角尖没真正看进去大家的回复.

引用 11 楼 yusiguyuan 的回复:[quote=引用 10 楼 my_live_123 的回复:] 和栈的增长方向没有关系 谁给你说的a》b》c？估计你没有仔细看跑的结果吧？！  这是我在UNBUNTU下的结果，其实栈的增长方式是我提前假设的，在unbuntu下这个结果页很让我好奇，最起码咱两的规律就不一样，你的是一只递增，我的并不是[/quote] 这是我在VC6.0下的结果，这个结果就是我想讨论的依据，暂且依据这个讨论，a b c 的地址按照栈的生长方式来，但是到了数据的内部元素就不再按照这种原则了，就怀疑编译器做了什么  就想搞明白怎么回事

引用 10 楼 my_live_123 的回复:和栈的增长方向没有关系 谁给你说的a》b》c？估计你没有仔细看跑的结果吧？！  这是我在UNBUNTU下的结果，其实栈的增长方式是我提前假设的，在unbuntu下这个结果页很让我好奇，最起码咱两的规律就不一样，你的是一只递增，我的并不是

和栈的增长方向没有关系 谁给你说的a》b》c？估计你没有仔细看跑的结果吧？！

引用 7 楼 aa2650 的回复:就像4楼说的, 数组的方向和栈的方向为什么要相同呢？ 因为栈是用数组实现的, 所以lz产生了数组增长方向一定得和栈方向一致的下意识的错觉吧 这种错觉就好比, 物理内存增长方向还是从低地址向高地址的呢, 那么堆的方向对了, 栈的方向错啦, 怎么能开口向上呢?(这么比喻是不是感觉到你的那种错觉很无理了?) 数组无非是连续的char而已, 一个int其实也是4个连续的char, 如果必须按栈的方向来, 就没有大小端的问题存在了.我是这么想的，首先申请地 数组属于栈空间内，既然这个变量在栈空间内，那么就总得符合栈空间的一些规范吧，比如栈空间的生长方式是由从高地址到低地址，但是数组中的元素地址并非这样，但是申请别的变量又符合这种规范，就觉得有什么蹊跷不懂的地方

数组的方向和栈的方向为什么要相同？

引用 楼主 yusiguyuan 的回复:int main()   {       int a;       int b;       int c;       int p[5];           printf("a  %p\n",&a);       printf("b  %p\n",&b);       printf("c  %p\n",&c);       printf("p0    %p\n",&p[0]);       printf("p1    %p\n",&p[1]);       printf("p2    %p\n",&p[2]);       printf("p3    %p\n",&p[3]);       printf("p4    %p\n",&p[4]);  	return 0; 	} 在上述代码中，a的地址比b的地址大 b低地址比c的地址大， 这正好说明了栈的生长方式是从高地址到低地址 但是数组内的元素却是依次递增 这样好像违背了栈的生长方式    这是为什么？ 编译器做了什么？ 编译器怎么处理定长数组？ 数组在内存中如何分配的 其解释！！谢谢 空增/减栈 满增/减栈  说实在这还得看编译器怎么玩

1 C语言保证 数组中 下标小的元素必然在下标大是元素前面  2 "栈的生长方式"和变量内存分配布局 没有必然联系

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

看看反汇编就知道了， 1）分配内存空间的动作，(X86,Win32 MSVC,就是对SP，esp 这样的堆栈指针寄存器，做一下减法)。 2）为变量确定地址，每个变量，根据需要安排一个位置 。 (X86,Win32 MSVC，一般是相对ebp 的位置偏移量，如果做了栈帧优化，则可能会是相对esp 的置偏移量） 编译器就做了这些 至于数组，只需要最低地址，和数组空间大小，两个数据就可以了 空间大小，就是第一步要减去的数值，地址，其实只是相对偏移量由于每个函数的某一次调用中，ebp,esp 尤其是 ebp 内容是确定的，所以 ebp 的内容加上相对偏移量，就是地址了。  PS： 编译后的代码中，不必存在变量名字。

高端的问题，没有考虑过呵呵


Question: linux中运行程序如何得到 "^D" ?

搜NCURSES库。

Ctrl+D在Linux下代表EOF ？

本题不用答了，我把号换了

本体作废。。。

引用 4 楼 user-3 的回复:puts("^D");//... 不实用程序实现，是在终端运行程序时按下CTRL+D

puts("^D");//...

引用 1 楼 zhao4zhong1 的回复:Ctrl+D在Linux下代表EOF ？ 我的意思是，我想让终端显示成这样： root  # ./a.out abc ^D abc  可实际上却是这样的： root  # ./.a.out abc abc  我忘了^D这字符是在哪种情况下显示出来的


Question: 能否说C语言指针存在的意义是为了简化向某地址传值的代码？

C语言指针存在的意义好比大脑神经元突触存在的意义。


Question: 各位大神帮我找找那有问题

在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。

/*华氏温度转换为摄氏温度和绝对温度*/ #include<stdio.h> void Temperatures(double);//函数声明 int main(void) { 	/*变量声明*/ 	double a;  	printf("请输人华氏温度："); 	while(scanf("%lf",&a) == 1)//当输入非数字值时结束循环 	{  		Temperatures(a);//调用函数 		printf("请输人华氏温度："); 	}  	getchar(); 	getchar(); 	return 0;  }    /*温度的转换*/ void Temperatures(double Fahrenheit) { 	double Celsius, Kelvin;     const float n = 1.8; 	const float m = 32.0; 	const float t = 273.16;  	Celsius = n * Fahrenheit + m;//摄氏温度 	Kelvin = Celsius + t;//绝对温度  	printf("\n华氏温度：%.2f\n", Fahrenheit); 	printf("摄氏温度：%.2f\n", Celsius); 	printf("绝对温度：%.2f\n", Kelvin);  }

这种问题有过不少讨论了，scanf 把以前缓冲的字符读取了。可以先清一下缓冲或者就用 u=getchar()

#include<stdio.h> void Temperatures(double Fahrenheit);  int main(void) { 	double b; 	char u;  	printf("请输入u的值："); 	scanf("%c", &u);  	while (u != 'Q') 	{ 		printf("请输人华氏温度："); 		scanf("%f", &b); 		Temperatures(b); 		getchar();    //吃掉输出流中的那个'\n'  		printf("请输入u的值："); 		scanf("%c", &u); 	}  	getchar(); 	return 0; }  void Temperatures(double Fahrenheit) { 	double Celsius, Kelvin; 	const float a = 1.8; 	const float b = 32.0; 	const float c = 273.16;  	Celsius = a * Fahrenheit + b; 	Kelvin = Celsius + c;  	printf("\t      华氏温度为：%.2e", Fahrenheit); 	printf("\n华氏温度转换为摄氏温度为：%.2e\n", Celsius); 	printf("摄氏温度转换为绝对温度为：%.2e\n", Kelvin); }

b是double型的，所以： scanf("%f", &b),->scanf("%lf", &b),


Question: C语言是不是汇编语言写出来的？

蛋生鸡，，然后开始滚动发展，就是这样

borland TC2.0 是的，是使用汇编语言直接写出来的，包括他的IDE界面，都是用汇编写的； 早期的编译器，甚至和全部的源代码一起发行。  这个编译器的库里，甚至有库的初始化代码的，汇编源代码。 使用时，可能还需要自己汇编出来，生成.obj，不过提供了一个 build.bat 专门做这个。  另外，borland 早期的 pascal 也是用汇编写的。

C语言是不是汇编语言写出来的？  应该是“C的编译器是不是汇编语言写出来的？”  答案是，早期是。那时没有任何现成的语言的编译器，只有汇编语言及其汇编器。人们用汇编写了一个简单语法的编译器，然后由这个编译器及其简单语法，去写更复杂语法的编译器，直到语言和编译器都成熟。 先在有很多语言及其实现了，所以，用Java也可以写C的编译器，用Python也可以写编译器。  C语言写的程序不同的CPU是否要翻译成不同的机器语言？（例如有intel和amd的CPU是否要分别编译）  是，但是LZ举的例子不太好，AMD和intel的CPU是兼容的，都是x86的架构，所以“目标代码”是兼容的，不需要另外翻译。 举x86和mips或者arm就比较好，这种情况下，一份代码，多处编译。  自己想写一个不同语法风格的C语言是不是要实现各个不同的CPU的汇编代码？   首先，“语法风格”都不同了，那还是C么？所以其实就是LZ自行开发一个语言而已。 至于CPU不同，那么目标代码一定是不一样的。

你是问C语言的编译器吧

蛋生鸡，和鸡生蛋的问题！ 其实在计算机世界里，是先有的汇编，然后有汇编写成的编译器，然后再有高级语言编译器。C的第一版编译器肯定是汇编写成的，而后就可以有C语言写成的编译器。。。越来越多的语言以及编译器。。。

一般不能用自身编译自己编译器的语言都是流氓.   编译器实现自举编译的版本都是要大书特书一把的.

参考Tiny C源代码。

C语言是自编译语言，我的理解是自身滚动发展，不是鸡生蛋、蛋生鸡。

最早是，后来就不是了。 现在GCC好像是用C++开发的。

c语言在编译是时候会进行汇编，转换为机器指令，才可以运行。。。。

C语言写的程序不同的CPU是否要翻译成不同的机器语言？（例如有intel和amd的CPU是否要分别编译）  准确的说，应该是不同指令集的CPU需要编译成不同的机器语言。 目前PC机的CPU的指令集都是一样的，所以，你在你的PC上编译了一份可执行文件，复制到你同学的PC里面，也可以用，但是复制到平板电脑里，就无法使用了。

引用 楼主 tiwenid0 的回复:C语言是不是汇编语言写出来的？  嗯？lz这话不对吧

引用 楼主 tiwenid0 的回复:C语言是不是汇编语言写出来的？ C语言写的程序不同的CPU是否要翻译成不同的机器语言？（例如有intel和amd的CPU是否要分别编译） 自己想写一个不同语法风格的C语言是不是要实现各个不同的CPU的汇编代码？  感觉你把C语言和C编译器搞混了

C语言是不是汇编语言写出来的？ 可以是，也可以不是。理论上，任何语言都可以写c语言编译器。  C语言写的程序不同的CPU是否要翻译成不同的机器语言？（例如有intel和amd的CPU是否要分别编译） 是的。  自己想写一个不同语法风格的C语言是不是要实现各个不同的CPU的汇编代码？  对的。不过既然是c语言，就要满足c语言规范定义的内容，否则就不叫c语言了。


Question: ++运算符的问题

不客气，不要纠结这种问题了，正像我上面说的，你看——    上面是C-Free 5  ，下面是VC6.0的结果

引用 1 楼 u012421456 的回复:这样的问题很多人问过了，自加或自减这种事不同的机器不同的编译器就可能出现不同的结果，lz可以看置顶帖——http://bbs.csdn.net/topics/370153775 看了一下 thank you

代码是错的 结果没有意义

我觉得纠结于这种问题没意义


Question: 段错误为何称为 段 ？

内存实际上还是分页管理吧，分段只是另一种形式体现和程序员吧。分页是按照固定大小分配的，这对于程序员来说很不好用，因为程序员所需要的内存都不是固定的，这样可能造成程序员分配得到的内存是不连续的。所以操作系统以分段的形式呈现给程序员，这对程序员来说分配得到的内存是连续的。

举个常见的例子 char *p = "hello"; strcpy(p, "world");  上面的例子会产生段错误，原因在于指针p指向的是只读存储区。 只读区自然不能修改，因此strcpy访问了不该访问的内存段，所以出现段错误

是的。因为内存分段，然后程序中访问了不能访问的段，所以称为段错误


Question: 栈

这个思想就是“可以先进一个，出一个；或者进多个，出多个”

懂了谢谢。。

入栈顺序是123 那出栈不就唯一是321吗

第一道的结果是怎么出来的解释下可以吗

引用 6 楼 u014462801 的回复:进栈是123，出栈可能是：123、321、213、231、132 进栈是123456，出栈则不可能是435612（根据先进后出的原则，1不能先于2出栈）                                出战顺序可能是135426（1进，1出、2进、3进，3出、4进、5进，5出、4出、2出、6进，6出）  正确

设无序表的关键字序列为：13,26,20,24,23,31,19,23,12,37。取中间位置元素的键值做基准值，应用快速排序算法，第一次分组后得到的序列为  A.13,12,20,19,23,31,26,23,24,37  B.12,19,13,20,23,37,26,24,23,31  C.19,12,20,13,23,23,37,31,24,26  D.20,19,13,12,23,23,24,31,26,37 顺便问一下这道题。我没有分了。不好意思

lz是打算让火车掉头啊？一个个车厢调换位置，栈是后进先出的

栈是后进先出的（也可以说先进后出）——http://www.weixueyuan.net/view/5864.html 进去123，出则321

按123进栈，如果3先出栈，1，2一定还在栈中，出栈一定是2、1，以此类推。。。

lz了解栈吗

那结果是什么，怎么分析的

先进后出。进栈的倒序。


Question: DHCP 网络通信

void proc_dhcp_renew(tEthpkt* pkthdr, tIp* pIp, tUser* pUser) {     tUdp*   pudp;     tDhcp*  pdhcp;     UINT4   rip;     tTlv*   pTlv = NULL;     UINT4   yaddr;      pudp = (tUdp*)pIp->data;     if(!pudp)         return ;      pdhcp = (tDhcp*)pudp->data;     if(!pdhcp)         return ;      if(pdhcp->cipaddr == 0)     {         rip = GetOptionInt((char*)pdhcp->data, 50);     }     else     {         rip = pdhcp->cipaddr;     }     if(rip != 0)     {         if((ntohl(rip) & 0xffffff00) != (ntohl(dhcp_config.gateway)& 0xffffff00))  //不在同一网段         {             proc_dhcp_nak(pkthdr, pIp, pUser);             return ;         }     }     if(rip)     {         yaddr = rip;     }     else     {         if(pUser->dhcp_flag)         {             yaddr = pUser->ip;         }         else         {             yaddr = get_dhcp_request_ip(pUser->mac);             pUser->dhcp_flag = TRUE;             pUser->ip = yaddr;         }     }     memcpy(pkthdr->pEth->dest, pkthdr->pEth->src, MAC_ALEN);     memcpy(pkthdr->pEth->src,  dhcp_config.mac,   MAC_ALEN);      pIp->dest = yaddr;     pIp->src = dhcp_config.gateway;      pudp->dport = htons(68);     pudp->sport = htons(67);      if(pdhcp->opt == 0x01)         pdhcp->opt = 0x02;      if(pdhcp->htype != 0x01)         pdhcp->htype = 0x01;      pdhcp->hlen = 0x06;     pdhcp->hops = 1;     pdhcp->xid  = htonl(rand());     pdhcp->secd = 0;     pdhcp->flg = 0;     pdhcp->cipaddr = 0;     pdhcp->yipaddr = yaddr;     pdhcp->sipaddr = 0;     pdhcp->gipaddr = 0;     memcpy(pdhcp->cmcaddr, pkthdr->pEth->dest, MAC_ALEN);     pdhcp->hostname[0] = 0xff;     memset(pdhcp->filename, 0, 128);     pdhcp->sname = htonl(0x63825363);      //dhcp ack     pTlv = (tTlv *)pdhcp->data;     pTlv->type = 0x35;     pTlv->len  = 0x01;     pTlv->data[0] = 0x05;              //server ip address     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x36;     pTlv->len  = 0x04;         memcpy(pTlv->data, &dhcp_config.gateway, 4);          //time     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x33;     pTlv->len  = 0x04;     pTlv->data[0] = 0x00;     pTlv->data[1] = 0x01;     pTlv->data[2] = 0x51;     pTlv->data[3] = 0x80;          //net mask     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x01;     pTlv->len  = 0x04;     pTlv->data[0]=0xff;     pTlv->data[1]=0xff;     pTlv->data[2]=0xff;     pTlv->data[3]=0x00;      //gateway     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x03;     pTlv->len  = 0x04;     memcpy(pTlv->data, &dhcp_config.gateway, 4);      //dns     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x06;     pTlv->len  = 0x04;     //pTlv->len  = 0x08;     memcpy(pTlv->data, &dhcp_config.main_dns, 4);     memcpy(pTlv->data + 4, &dhcp_config.back_dns, 4);      #if 0     //netbios     pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0x2e;     pTlv->len  = 0x01;     pTlv->data[0] = 0x08;     #endif      pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0xff;     pTlv->len  = 0xff;     memset(pTlv->data, 0 , 10);      pIp->cksum = 0;     pIp->cksum = IpCksum(pIp, IP_HLEN(pIp));      pudp->cksum = 0;     pudp->cksum = UdpCksum(pIp, ntohs(pIp->len) - 20);      xmit_packet(pkthdr->ifindex, pkthdr->pid, pkthdr); }  void proc_dhcp_nak(tEthpkt* pkthdr, tIp* pIp, tUser* pUser) {     tUdp*   pudp;     tDhcp*  pdhcp;     tTlv*   pTlv = NULL;      memcpy(pkthdr->pEth->dest, pkthdr->pEth->src, MAC_ALEN);     memcpy(pkthdr->pEth->src, dhcp_config.mac, MAC_ALEN);      pudp = (tUdp*)pIp->data;     if(!pudp)         return ;      pudp->dport = htons(68);     pudp->sport = htons(67);      pdhcp = (tDhcp *)pudp->data;      if (!pdhcp)         return ;         pIp->dest = htonl(0xffffffff);     pIp->src = dhcp_config.gateway;      if(pdhcp->opt == 0x01)         pdhcp->opt = 0x02;      if(pdhcp->htype != 0x01)         pdhcp->htype = 0x01;      pdhcp->hlen = 0x06;     pdhcp->cipaddr = htonl(0x00);     memcpy(pdhcp->cmcaddr, pkthdr->pEth->dest, MAC_ALEN);      pTlv = (tTlv*)pdhcp->data;     pTlv->type = 0x35;     pTlv->len = 0x01;     pTlv->data[0] = 0x06;      pTlv = (tTlv*)(pTlv->data + pTlv->len);     pTlv->type = 0x36;     pTlv->len = 0x04;     memcpy(pTlv->data, &dhcp_config.gateway, 4);      pTlv = (tTlv *)(pTlv->data + pTlv->len);     pTlv->type = 0xff;     pTlv->len  = 0xff;     memset(pTlv->data, 0 , 10);      pIp->cksum = 0;     pIp->cksum = IpCksum(pIp, IP_HLEN(pIp));      pudp->cksum = 0;     pudp->cksum = UdpCksum(pIp, ntohs(pIp->len) - 20);      xmit_packet(pkthdr->ifindex, pkthdr->pid, pkthdr);  }  void proc_dhcp_decline(tUser* pUser) {     int         i = 0;      for (i=0;i<0xfff;i++)     {         if (memcmp(dnode[i].mac, pUser->mac, MAC_ALEN) == 0)         {             memset(dnode[i].mac, 0xff, MAC_ALEN);               pUser->dhcp_flag = FALSE;             break;         }     }      for (i=0; i<0xfff; i++)     {         if (dnode[i].isused == FALSE)         {             dnode[i].isused     = TRUE;             dnode[i].renew_time = time(NULL);             memcpy(dnode[i].mac, pUser->mac, MAC_ALEN);             pUser->dhcp_flag = FALSE;             break;         }     } }  UINT4 GetOptionInt(char* data, UINT1 type) {     tTlv*  ptlv;     UINT4  result = 0;      ptlv = (tTlv*)data;     while(ptlv)     {         if(!ptlv)             break;         if(ptlv->len == 0)             break;         if(ptlv->type == 0xff ||            ptlv->type == 0)             break;         if(ptlv->type== type && ptlv->len == 4)         {             memcpy(&result, ptlv->data, 4);             break;         }         ptlv = (tTlv*)(ptlv->data + ptlv->len);     }     return result; }  static UINT4 get_dhcp_request_ip(UINT1* mac) {     int i = 0;     for (i = 0; i < DHCP_NODE_MAX; i++)     {         if(memcmp(dnode[i].mac, mac, MAC_ALEN) == 0)         {             dnode[i].isused = TRUE;             dnode[i].renew_time = time(NULL);             if(dnode[i].ipaddr)             {                 return dnode[i].ipaddr;             }         }     }      for(i = 0; i < DHCP_NODE_MAX; i++)     {         if(dnode[i].isused == FALSE)         {             dnode[i].isused = TRUE;             memcpy(dnode[i].mac, mac, MAC_ALEN);             dnode[i].renew_time = time(NULL);             return dnode[i].ipaddr;         }     }     return 0; }

void dhcp_server(tEthpkt* pkthdr) {     tEther*  pEth;     tIp*     pIp;      pEth = (tEther*)pkthdr->pEth;     pIp = (tIp*)pEth->data;      proc_dhcp_pkt(pkthdr,  pIp); }  inline tUser*  CheckUserExit(UINT1*  mac) {     tUser*  pUser = NULL;     int     hsindex = 0;      mutex_lock(UserTable.mutex);     hsindex = MacHash(mac, UserTable.capcity);     while(pUser)     {         if(!pUser)             break;         if(pUser->mac[5] == mac[5] &&            pUser->mac[4] == mac[4] &&            pUser->mac[3] == mac[3])         {             if(pUser->mac[2] == mac[2] &&                pUser->mac[1] == mac[1] &&                pUser->mac[0] == mac[0])             {                 mutex_unlock(UserTable.mutex);                 return pUser;             }         }           pUser = pUser->next;     }     mutex_unlock(UserTable.mutex);      return NULL; } void User_Tm_out(void* para, tTimer* tid) {     tUser*  pUser;      pUser = (tUser*)para;     if(!pUser)     {         kill_timer(tid);     }      if(time_now - pUser->time > 86400)     {        pUser->clear_flag = TRUE;     } } inline tUser* add_newuser_toTb(tUser* pUser) {     tUser*  pTmpScan = NULL;     int     uindex = 0;      uindex = MacHash(pUser->mac, UserTable.capcity);     pTmpScan = UserTable.user_arr[uindex];      mutex_lock(UserTable.mutex);     if(pTmpScan)     {         while(pTmpScan)         {             if(pTmpScan->mac[5] == pUser->mac[5] &&                pTmpScan->mac[4] == pUser->mac[4] &&                pTmpScan->mac[3] == pUser->mac[3])             {                 if(pTmpScan->mac[2] == pUser->mac[2] &&                    pTmpScan->mac[1] == pUser->mac[1] &&                    pTmpScan->mac[0] == pUser->mac[0])                 {                     ReleaseMemToPool(UserTable.pool, (char*)pUser);                     pUser = pTmpScan;                     break;                 }             }                 pTmpScan = pTmpScan->next;         }         if(!pTmpScan)         {             create_ctimer(UserTable.timerID, 5, pUser, &pUser->time_id, User_Tm_out);             pUser->next = UserTable.user_arr[uindex];             UserTable.user_arr[uindex] = pUser;         }     }     else     {         create_ctimer(UserTable.timerID, 5, pUser, &pUser->time_id, User_Tm_out);         pUser->next = UserTable.user_arr[uindex];         UserTable.user_arr[uindex] = pUser;     }     mutex_unlock(UserTable.mutex);     return pUser; } void proc_dhcp_pkt(tEthpkt* pkthdr, tIp*  pIp) {     tDhcp*  pdhcp;     tUser*  pUser;     tUdp*   pudp;     tTlv*   ptlv;      pUser = CheckUserExit(pkthdr->pEth->src);     if(!pUser)     {         pUser = (tUser*)GetMemFromPool(UserTable.pool);         if(pUser)         {             pUser->ip = pIp->src;    //  ip: 0:0:0:0             memcpy(pUser->mac, pkthdr->pEth->src, MAC_ALEN);             pUser->time = time_now;             add_newuser_toTb(pUser);         }         else         {             return ;         }     }      pudp = (tUdp*)pIp->data;     if(!pudp)         return ;      pdhcp = (tDhcp*)pudp->data;     if(!pdhcp)         return ;      if(pdhcp->opt == 0x01)     {         ptlv = (tTlv*)pdhcp->data;         if(ptlv->type == 0x35)         {             if(ptlv->data[0] == 0x01)//dhcp discovery             {                 printf("bootp offer!\n");                 proc_dhcp_offer(pkthdr, pIp, pUser);             }             else if (ptlv->data[0] == 0x03)//dhcp request/renew             {                 printf("bootp request\n");                 proc_dhcp_renew(pkthdr, pIp, pUser);             }             else if (ptlv->data[0] == 0x04)//dhcp decline             {                 printf("bootp decline\n");                 proc_dhcp_decline(pUser);             }             else if (ptlv->data[0] == 0x07)// dhcp release             {                 printf("bootp release\n");             }         }     } } void proc_dhcp_offer(tEthpkt* pkthdr, tIp* pIp, tUser* pUser) {     tUdp*  pudp;     tDhcp* pdhcp;     tTlv*  ptlv = NULL;     UINT4  yaddr;      memcpy(pkthdr->pEth->dest, pkthdr->pEth->src, MAC_ALEN);     memcpy(pkthdr->pEth->src, dhcp_config.mac, MAC_ALEN);      pudp = (tUdp*)pIp->data;     if(!pudp)         return ;      pudp->dport = htons(68);     pudp->sport = htons(67);      pdhcp = (tDhcp*)pudp->data;      if(!pdhcp)         return ;      if(pUser->dhcp_flag)     {         yaddr = pUser->ip;     }     else     {         yaddr = get_dhcp_request_ip(pUser->mac);         pUser->dhcp_flag = TRUE;         pUser->ip = yaddr;     }         pIp->dest = yaddr;     pIp->src = dhcp_config.gateway;      if(pdhcp->opt == 0x01)         pdhcp->opt = 0x02;      if(pdhcp->htype != 0x01)         pdhcp->htype == 0x01;      pdhcp->hlen = 0x06;     pdhcp->hops = 1;     //dhcp报文经过的dhcp中继的数目，dhcp请求报文每经过一个dhcp中继，该字段就会加1     pdhcp->xid  = htonl(rand());     pdhcp->secd = htons(0x00);     pdhcp->flg = htons(0x00);     pdhcp->cipaddr = 0;     pdhcp->yipaddr = yaddr;     pdhcp->sipaddr = 0;     pdhcp->gipaddr = 0;     memcpy(pdhcp->cmcaddr, pkthdr->pEth->dest, MAC_ALEN);     pdhcp->hostname[0] = 0xff;     memset(pdhcp->filename, 0, 128);     pdhcp->sname = htonl(0x63825363);      ptlv = (tTlv *)pdhcp->data;     ptlv->type = 0x35;     ptlv->len  = 0x01;     ptlv->data[0] = 0x02;              //server ip address     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x36;     ptlv->len  = 0x04;         memcpy(ptlv->data, &dhcp_config.gateway, 4);          //time     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x33;     ptlv->len  = 0x04;     ptlv->data[0] = 0x00;     ptlv->data[1] = 0x01;     ptlv->data[2] = 0x51;     ptlv->data[3] = 0x80;          //net mask     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x01;     ptlv->len  = 0x04;     ptlv->data[0]=0xff;     ptlv->data[1]=0xff;     ptlv->data[2]=0xff;     ptlv->data[3]=0x00;      //gateway     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x03;     ptlv->len  = 0x04;     memcpy(ptlv->data, &dhcp_config.gateway, 4);      //dns     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x06;     ptlv->len  = 0x04;     //ptlv->len  = 0x08;     memcpy(ptlv->data,  &dhcp_config.main_dns, 4);     //memcpy(ptlv->data + 4, &dhcp_config.back_dns, 4);      #if 0     //netbios     ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0x2e;     ptlv->len  = 0x01;     ptlv->data[0] = 0x08;     #endif          ptlv = (tTlv *)(ptlv->data + ptlv->len);     ptlv->type = 0xff;     ptlv->len  = 0xff;     memset(ptlv->data, 0 , 10);      pIp->cksum = 0;     pIp->cksum = IpCksum(pIp, IP_HLEN(pIp));      pudp->cksum = 0;     pudp->cksum = UdpCksum(pIp, ntohs(pIp->len) - 20);      xmit_packet(pkthdr->ifindex, pkthdr->pid, pkthdr);     }


Question: fread第一个参数的疑问

part没有初始化

你们说我的part指针没有初始化，因为我认为fread把读到的数据的地址赋给了part指针。 那么按照你们的意思，fread这个函数是把数据的值赋给了指针所指的地址，而不是把数据的地址赋给指针？？？

引用 楼主 u014463229 的回复:程序如下,我看到fread的第一个参数是void *buffer，所以我就这样写了 #include <stdio.h> int main() {        FILE *file;     int *part;     file=fopen("ff","rb");     fread(part,sizeof(int),1,file); }  而正确用法应该是： int part； fread（&part，........); 我不知怎么总结我的错误，请各位帮忙了 int *part; 是指针，没有初始化。 初始化要指向一个对象。即指向一个实例、实体。否则就是野指针。可以把指针可以当成一本书的目录。没有指向实体的指针就像目录没有页码。根本没有办法是用。

引用 楼主 u014463229 的回复:程序如下,我看到fread的第一个参数是void *buffer，所以我就这样写了 #include <stdio.h> int main() {        FILE *file;     int *part;     file=fopen("ff","rb");     fread(part,sizeof(int),1,file); }  而正确用法应该是： int part； fread（&part，........); 我不知怎么总结我的错误，请各位帮忙了  int *part;  这个指针没有赋值  可以按楼上说的在堆上申请内存，也可以 int nPart = 0； int* pPart = &nPart； file=fopen("ff","rb"); fread(pPart ,sizeof(int),1,file);

你没有为part申请空间 int *part; part = (int *)malloc(sizoef(int)); 这样也可以


Question: ACM题目：素数求和问题

试试这个算法 “sieve of eratosthenes”

引用 2 楼 oYinGui1 的回复:还有main没返回值这种写法，早过时了。。。书上这么写就把书扔了吧。。。 请教一下，为什么main要int，然后最后还要return 0？？

引用 4 楼 alexbem 的回复:[quote=引用 2 楼 oYinGui1 的回复:] 还有main没返回值这种写法，早过时了。。。书上这么写就把书扔了吧。。。 请教一下，为什么main要int，然后最后还要return 0？？[/quote] 返回个值判断一下执行的情况呗。。0是表示正确执行，其它值就是系统定义的了，代表不同含义。

题目说：0<M<10；0<N<1000，每个数都小于1000 假如系统测试用例m=9 切每个N都为999个数每个数都为999那样你的程序很吃力了。还有你的循环怎么不从0开始。边界问题值得思考一下。附上修改了的代码。 #include <stdio.h> #include <math.h>  int prm[1001]={0};//0表示是素数，1表示不是   void prime()	 {	//if Num is a prime number, return 1 	int i,Num=2; 	prm[1]=1; 	prm[0]=1;		 	while(Num<=1000) 	{for (i = 2; i <= sqrt(Num); i++) 		if (Num%i == 0) 			{prm[Num]=1; 			break;}  	Num++; 	}	 }  main() {	 	int Qty, QtyLtl, Num;	//quantity 	int j, k, Sum[10] = { 0 }; 	scanf("%d", &Qty); 	prime(); 	for (k=0; k<Qty; k++) 	{ 		scanf("%d", &QtyLtl); 		for (j=0; j<QtyLtl; j++) 		{ 			scanf("%d", &Num); 			if (prm[Num]==0)    //只需查表prm中是不是素数直接判断就可以了。  				Sum[k]=Sum[k]+Num; 		} 	} 	for (k=0; k<Qty; k++) 	{ 		printf("%d\n", Sum[k]); 	}  }

我想问一下楼主   你的提交结果是wa 还是运行超时。我觉得应该是超时吧。我觉得这题应该打表。你先回复到底是哪种错误类型。然后我再看看

int main(void)    	return 0; 改成这种的，不要再直接main（）了

还有main没返回值这种写法，早过时了。。。书上这么写就把书扔了吧。。。

一般都要求个多次输入吧。。。搞个可以输入多次的就差不多了。


Question: 链表求并集问题，学习中，求大大解答

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

代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试是程序员必须掌握的技能之一。


Question: strxfrm中的x什么意思？

楼主不觉得 t和x形似吗？

引用 2 楼 u014463229 的回复:上面这位大哥说了这么多，还是没回答我的问题啊 我个人觉得，你可以理解为转换和未知长度两个意思的结合。 一般转换用2，或者to，长度用n。 这里是两种意思都有，用x.

transform简写为xfrm

上面这位大哥说了这么多，还是没回答我的问题啊

strxfrm, wcsxfrm Transform a string based on locale-specific information.  size_t strxfrm( char *strDest, const char *strSource, size_t count );  size_t wcsxfrm( wchar_t *strDest, const wchar_t *strSource, size_t count );  Routine Required Header Compatibility  strxfrm <string.h> ANSI, Win 95, Win NT  wcsxfrm <string.h> or <wchar.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns the length of the transformed string, not counting the terminating null character. If the return value is greater than or equal to count, the content of strDest is unpredictable. On an error, each of the functions sets errno and returns (size_t) – 1.  Parameters  strDest  Destination string  strSource  Source string  count  Maximum number of characters to place in strDest  Remarks  The strxfrm function transforms the string pointed to by strSource into a new collated form that is stored in strDest. No more than count characters, including the null character, are transformed and placed into the resulting string. The transformation is made using the current locale’s LC_COLLATE category setting. For more information on LC_COLLATE, see setlocale.  After the transformation, a call to strcmp with the two transformed strings yields results identical to those of a call to strcoll applied to the original two strings. As with strcoll and stricoll, strxfrm automatically handles multibyte-character strings as appropriate.  wcsxfrm is a wide-character version of strxfrm; the string arguments of wcsxfrm are wide-character pointers. For wcsxfrm, after the string transformation, a call to wcscmp with the two transformed strings yields results identical to those of a call to wcscoll applied to the original two strings. wcsxfrm and strxfrm behave identically otherwise.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tcsxfrm strxfrm strxfrm wcsxfrm    In the “C” locale, the order of the characters in the character set (ASCII character set) is the same as the lexicographic order of the characters. However, in other locales, the order of characters in the character set may differ from the lexicographic character order. For example, in certain European locales, the character 'a' (value 0x61) precedes the character 'ä' (value 0xE4) in the character set, but the character 'ä' precedes the character 'a' lexicographically.  In locales for which the character set and the lexicographic character order differ, use strxfrm on the original strings and then strcmp on the resulting strings to produce a lexicographic string comparison according to the current locale’s LC_COLLATE category setting. Thus, to compare two strings lexicographically in the above locale, use strxfrm on the original strings, then strcmp on the resulting strings. Alternatively, you can use strcoll rather than strcmp on the original strings.  The value of the following expression is the size of the array needed to hold the strxfrm transformation of the source string:  1 + strxfrm( NULL, string, 0 )  In the “C” locale only, strxfrm is equivalent to the following:  strncpy( _string1, _string2, _count ); return( strlen( _string1 ) );  Data Conversion Routines, Locale Routines, String Manipulation |  strcoll Functions  See Also   localeconv, setlocale, strcmp, strncmp


Question: 货币格式化参数char *frac_digits中的frac是什么的缩写？

fractile


Question: localeconv的conv是什么意思？

convert  英语也是一门计算机语言的说。  http://translate.google.cn/?hl=zh-cn&tab=wT#


Question: 多行宏定义的代码

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

return语句出现在宏里不太好吧！！ 这样的程序，程序运行流程被宏替换遮住了，看不清楚。 这是不准备让人看懂得代码么？？？  宏替换，应该是比较独立的代码，像 return ,goto 这样的语句，最好不出现。  if else，switch 语句也最好不要拆分 for,while do while 同样最好不要拆分 拆分了以后。控制流程支离破碎，代码就很难看懂了，这个宏也就不好使用了。

没明白什么意思


Question: 并行的三个种群+各自循环400次之后交互一次，再循环交互，出现第一个种群循环完，第二个还没有循环完，无法交互 怎么办

这东西已经不是c语言范畴了

1. 可以創建一個調度器，提供各個循環的狀態查詢接口 2. 交互通過異步消息，每個循環自己管自己循環，定期/不定期 發送/查詢交互消息。


Question: 初学指针变了程序三个warnings求助!!!!

引用 4 楼 u013107295 的回复:调用时错了   maxAndmin(a[10],gpt); 不对 是 maxAndmin(a,gpt);

调用时错了   maxAndmin(a[10],gpt);

是函数没有声明罢了

你的maxAndmin函数应这样写 void maxAndmin(int a, int b);

改成这样： #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> void maxAndmin(int a[10],int*gpt); int main() {     int a[10];     int* gpt ;     int i=0 ;     gpt=&a[0];     printf("press 10 numbers:\n");     for(i=0;i<=9;i++)     {         scanf("%d",&*(a+i));     }     maxAndmin(a,gpt);     return 0 ; } void maxAndmin(int a[10],int* gpt) {     int max=*(a+0);     int min=*(a+9);     int i=0;     for(;i<=9;i++)     {         if(*(a+i)>=*(a+0))         *(a+0)=*(a+i);         else if(*(a+i)<=*(a+9))         *(a+9)=*(a+i);     }     printf("max is%d\n min is%d\n",*(a+0),*(a+9));      }  运行截图：


Question: 问个关于结构体指针的问题

#include <iostream> using namespace std;  struct LNode; typedef struct LNode *ptrLNode; typedef ptrLNode LinkList; struct LNode{ 	struct LNode *next; 	int date; }; int creatList(LinkList H, int n) { 	if (!H) 	{ 		return false; 	} 	LinkList p = (LinkList)malloc(sizeof(LNode)); 	p = H; 	while (n--) 	{ 		LinkList newLnode = (LinkList)malloc(sizeof(LNode)); 		if (!newLnode) 		{ 			return false; 		} 		cin >> newLnode->date; 		p->next = newLnode; 		p = p->next; 	} 	p->next = NULL; 	return true; }  void putoutAll(LinkList H) { 	LinkList p = H->next; 	while (p) 	{ 		cout << p->date << endl; 		p = p->next; 	} }  void unionList1(LinkList LA, LinkList LB, LinkList LC) { 	LinkList pa, pb, pc;  	pa = LA->next; 	pb = LB->next; 	pc = LC; 	//LC = LA; 	//pc = LA; #if 1 	while (pa && pb) 	{ 		if (pa->date <= pb->date) 		{ 			pc = pc->next = pa; 			pa = pa->next; 		} 		else 		{ 			pc = pc->next = pb; 			pb = pb->next; 		} 	} #else 	while (pa&&pb) 	{ 		if (pa->date<pb->date) 		{ 			pc->next = pa; 			pa = pa->next; 			pc = pc->next; 		} 		else if (pa->date>pb->date) 		{ 			pc->next = pb; 			pb = pb->next; 			pc = pc->next; 		} 		else if (pa->date == pb->date) 		{ 			pc->next = pa; 			pa = pa->next; 			pb = pb->next; 			pc = pc->next; 		} 	} #endif 	if (pa) 	{ 		pc->next = pa; 	} 	if (pb) 	{ 		pc->next = pb; 	} }  void main() { 	LinkList LA = (LinkList)malloc(sizeof(LNode)); 	creatList(LA, 3); 	//putoutAll(LA); 	LinkList LB = (LinkList)malloc(sizeof(LNode)); 	creatList(LB, 3); 	//putoutAll(LB); 	LinkList LC = (LinkList)malloc(sizeof(LNode)); 	unionList1(LA, LB, LC); 	putoutAll(LC); }  稍微修改了LZ的代码，在输入 1 2 3 4 5 6的情况下可以正常运行。  不过LZ本身的代码还存在严重的逻辑问题： 1. 合并的链表真正拥有的空间只有头结点，换句话说，就是共享了LA,LB的其他结点空间。 2. 也正是因为第一个逻辑问题，所以造成在合并的修改LA,LB结点的next域-----合并操作不应该修改LA,LB. 3. LZ的代码兼有排序逻辑，那么应该基于LA,Lb有序的情况下才可以。


Question: [swu]fscanf函数

ret 是 fscanf 的返回值，即能够从文件中 成功读取的 整形 数据的个数，u是字符型数据，所以无法读取，能读取的数据个数为0，所以返回0赋予ret ，故你输出的结果是0

请判断fscanf的返回值！

fscanf(p, "%d", &n); 哦，有错误， fscanf，scanf 的格式化串以后的参数（...），即省略号部分， 除了 *星号格式对应的参数，是个整型数据外，其他参数。。全部形参都是指针，实参应该是地址，指针。

fscanf(p, "%d", &n); fscanf，scanf 的格式化串以后的参数（...），即省略号部分，全部形参都是指针，实参应该是地址，指针。

文件管理这章都忘记完了。。

你从文本中读取%d，只会读取文本中的数字，而不会读取字符的

还有就是你输入的是一个u字符，但是要读取一个int值，所以没有读取到，所以返回0，如果你想读取u的ASC2码，要改是使用%c来读取，然后打印的时候使用%d。

引用 楼主 u012789847 的回复:1 #include <stdio.h>   2   3 int main()   4 {   5         FILE *p;   6         int n, ret;   7         p       = fopen("data.in", "r");   8         ret     = fscanf(p, "%d", n);   9         printf("%d\n", ret);  10 } 我在data.in的文件中输入的数据是u  ，运行的结果是0  请问我该如何买书这种错误情况？ 使用fscanf时一定谨记取地址符&要加上  ret     = fscanf(p, "%d", &n);

和scanf一样，如果你%d期待一个整数，你输入一个u，也会是0. 把%d改成%c


Question: 刚学c新手求教，为什么一运行程序就停止

单步调试下，另外可以再程序中加一些异常打印的函数，这样也好定位问题

引用 1 楼 user-4 的回复:s数组越界：s[j] = t[i]; 为什么初始化t的时候，我删除一个'\t'或者'\n'，程序就正确执行了？

引用 楼主 weiryou10 的回复: /*编写一个函数escape(s,t)，将字符串t复制到字符串s中，并在复制过程中将换行符、制表符等不可见字符分别转换为  * \n,\t等相应的可见的转义字符序列。要求使用switch语句。再编写一个具有相反功能的函数，在复制过程中将转义字符序列  * 转换为实际字符*/ #include<stdio.h> void escape(char[], char[]);  int main() { 	char t[] = { '1', '2', '3', '4', '\n', '\t', '5', '\0' }; 	char s[] = { '\0' }; 	escape(s, t); 	return 0; }  void escape(char s[], char t[]) { 	int i, j,c; 	for (i = 0; t[i] != '\0'; i++) { 		printf("%c", t[i]); 	} 	printf("\n"); 	for (i = j = 0; t[i] != '\0'; i++, j++) { 		c = t[i]; 		printf("%c",c); 		switch (c) { 		case '\n': 			s[j++] = '\\'; 			s[j] = 'n'; 			break; 		case '\t': 			s[j++] = '\\'; 			s[j] = 't'; 			break; 		default: 			s[j] = t[i]; 			break; 		} 	} 	s[j] = '\0'; 	for (i = 0; s[i] != '\0'; i++) { 		printf("%c ", s[i]); 	} } 为什么一运行程序就停止 首先程序存在写缓冲越界的问题，这个#1已经指出。 另外，如果LZ的“一运行就停止”指的是控制台窗口一闪即过，那就是是没加“暂停功能”。  修改了下LZ的代码，所有带“// added"的行都是添加的，带”// changed“的行是做出了改变的，供参考：  /*编写一个函数escape(s,t)，将字符串t复制到字符串s中，并在复制过程中将换行符、制表符等不可见字符分别转换为 * \n,\t等相应的可见的转义字符序列。要求使用switch语句。再编写一个具有相反功能的函数，在复制过程中将转义字符序列 * 转换为实际字符*/ #include <stdio.h>  void escape(char[], char[]);  #define N 8 // added  int main() { 	char t[N] = { '1', '2', '3', '4', '\n', '\t', '5', '\0' }; // changed 	char s[N*2 + 1] = { '\0' }; // changed 	escape(s, t);  	getchar(); // added 	return 0; }  void escape(char s[], char t[]) { 	int i, j, c; 	for (i = 0; t[i] != '\0'; i++) { 		printf("%c", t[i]); 	} 	printf("\n"); 	for (i = j = 0; t[i] != '\0'; i++, j++) { 		c = t[i]; 		printf("%c", c); 		switch (c) { 		case '\n': 			s[j++] = '\\'; 			s[j] = 'n'; 			break; 		case '\t': 			s[j++] = '\\'; 			s[j] = 't'; 			break; 		default: 			s[j] = t[i]; 			break; 		} 	} 	s[j] = '\0'; 	for (i = 0; s[i] != '\0'; i++) { 		printf("%c ", s[i]); 	} }

s数组越界：s[j] = t[i];


Question: Linux下ＧＣＣ编译ＨＥＬＬＯ　ＷＯＲＬＤ失败。。。

引用 1 楼 user-2 的回复:首先，不能写在同一行中，其次，哪个$ 是干嘛用的？  换行，，，

#include <stdio.h> int main(void){printf("hello world!");return 0;} 预处理的内容，写在同一行上，会把该行所有的内容都当作预处理的内容，这样程序已经没有main函数入口了，会有链接错误，因为程序默认需要一个main入口函数。

首先，不能写在同一行中  其次，哪个$ 是干嘛用的？

首先，不能写在同一行中，其次，哪个$ 是干嘛用的？


Question: 超小程序问题，如何使用fread？

引用 2 楼 tuzhutuzhu 的回复:第6行定义了一个指针，但是指针指向哪里呢？到底指向哪里，谁都不知道 这种情况下最好定义一个字符指针 不好意思，说错了。最好定义一个字符数组

int *part; fread(part,sizeof(int),1,file); --〉 int part; fread(&part,sizeof(int),1,file);


Question: 双向循环链表

引用 4 楼 u010328107 的回复:空间为什么为O(1)呢？ 因为节点全部没有改变。不用占用任何空间。 双向链表，任何一个节点，可以找到前向和后向节点。 双向链表从任何一个节点，都可以遍历链表。 双向循环链表，任何一个节点都可以当作头结点。    画个图就可以理解了      +---------------------<--------------------------------------------------------------------+      |           1                      2                                           n-1                 n                 |      + ---> [ next  ] ----> [ next  ]  ---->   ............-----> [ next  ] ----> [ next  ]  --->-+                 [ data  ]         [ data ]              ............         [ data ]         +<----[  pre  ] <---- [ pre   ] <-----    .............<---[   pre   ] <---- [ pre   ] <——— +        |                                                                                |       +-------------------------------------------------------->---------------------------------------+          每次插入尾部就可以了，初始化 r = h->pre，q=h,p=q->next; 当 p 或者q =r 即结束p=r 要做一次插入。                                         h(1)   q(3)                           r(n)      r->next =p ( 2), p->next =r=next            第一次    2 取下插入尾部  1345.。。。。。。。n 2        h=1 ,q=5                          r=n                               r (n)      r->next =p ( 4), p->next =r->next(2)               第二次     4 取下插入尾部  1345.。。。。。。。n  4 2                                  插入结束，就得到奇数正序，偶数反序的链表了     当节点数为奇数的时候，查找到奇数节点是原尾节点，即可结束     当节点数为奇数的时候，查找到偶数节点是原尾节点，做一次插入，即可结束。     总之只要查到原尾节点，就可以结束操作了。     整个过程中，没有占用额外空间,用于储存节点和节点数据。仅仅使用了一些指针。    所以空间为 O(1)

可以分成两个函数做 1）每隔一个节点 取出，反向插入另一个链表时间 O(N)空间O(1)  2） 连接两个链表 时间 2=O(1)  空间 0  =O(1) 当你分成两个函数可以写好的时候，合并成一个函数也不成问题。

我是菜鸟。。。

这个会很难吗

空间为什么为O(1)呢？

恩是的只要求时间

没有空间复杂度的要求么，那最简单的就是牺牲空间了~


Question: 基于openssl开发的c语言程序可以移植到keil里么？

看看这个 http://topicideas.net/ppt/how-to-run-opengl-program-in-keil


Question: 关于结构体   请大家指导

引用 21 楼 sholber 的回复:[quote=引用 19 楼 my_live_123 的回复:] [quote=引用 15 楼 sholber 的回复:] [quote=引用 14 楼 my_live_123 的回复:] 结构体后面没有分号结束！记住，结构体声明一种数据类型，它是语句！要用分号结尾 声明是声明，语句是语句，结构体声明是数据类型，而且又是语句，真是荒谬之极！[/quote] 以分号结尾的一字符串怎么称呼？我说它是语句，你不赞同，你来说称呼它什么？[/quote]  C中的语句分类： statement:      labeled-statement      compound-statement      expression-statement      selection-statement      iteration-statement      jump-statement[/quote] 从C文法上来看，Phrase structure grammar下分支：Expressions，Declarations，Statements，External definitions。结构体文法在Declarations范畴。如果从文法细节扣，我的陈述“结构体是语句”是错的，我承认。但是放到自然语言的角度，我认为说的过去。比如声明语句，表达式语句，递归语句等等语言性描述，我不觉的是什么了不起或者致命的错误！或许你只站在C规则上说事，那我就无话可说喽！

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

引用 19 楼 my_live_123 的回复:[quote=引用 15 楼 sholber 的回复:] [quote=引用 14 楼 my_live_123 的回复:] 结构体后面没有分号结束！记住，结构体声明一种数据类型，它是语句！要用分号结尾 声明是声明，语句是语句，结构体声明是数据类型，而且又是语句，真是荒谬之极！[/quote] 以分号结尾的一字符串怎么称呼？我说它是语句，你不赞同，你来说称呼它什么？[/quote]  C中的语句分类： statement:      labeled-statement      compound-statement      expression-statement      selection-statement      iteration-statement      jump-statement

引用 19 楼 my_live_123 的回复:[quote=引用 15 楼 sholber 的回复:] [quote=引用 14 楼 my_live_123 的回复:] 结构体后面没有分号结束！记住，结构体声明一种数据类型，它是语句！要用分号结尾 声明是声明，语句是语句，结构体声明是数据类型，而且又是语句，真是荒谬之极！[/quote] 以分号结尾的一字符串怎么称呼？我说它是语句，你不赞同，你来说称呼它什么？[/quote]  如果以分号结尾的字符串是独立存在的，如： "my_live 123"; 则它是表达式语句。表达式语句是一个表达式，跟着一个分号。

引用 15 楼 sholber 的回复:[quote=引用 14 楼 my_live_123 的回复:] 结构体后面没有分号结束！记住，结构体声明一种数据类型，它是语句！要用分号结尾 声明是声明，语句是语句，结构体声明是数据类型，而且又是语句，真是荒谬之极！[/quote] 以分号结尾的一字符串怎么称呼？我说它是语句，你不赞同，你来说称呼它什么？

#include<stdio.h> struct student { char name[20]; int age; float score[5],ave;  } ;//注意这里有一个";" int main() { struct student stu; stu.ave=0;     int i=0; printf("input name,age: \n"); scanf("%s %d",stu.name,&stu.age); printf("inout score :\n"); for(i=0;i<5;i++) { scanf("%f",&stu.score[i]); stu.ave=stu.ave+stu.score[i]/5.0; } printf("%s %d\n",stu.name,stu.age); printf("the average is :\n"); printf("%f\n",stu.ave);  }楼主编程的时候注意看编译器给你的错误提示啊，不然一辈子都不知道哪里错了

有的时候，错误提示不一定会指向真正的错误。若只是纠正语法错误，那么可能有好几种纠正方式，也就是说对错误有好几种解释方法，所以，看到错误提示，要是在他所指位置看不到错误，那你就要找找前面的地方是否有错误。

可以点击错误信息，会跳到错误行的

引用 14 楼 my_live_123 的回复:结构体后面没有分号结束！记住，结构体声明一种数据类型，它是语句！要用分号结尾 声明是声明，语句是语句，结构体声明是数据类型，而且又是语句，真是荒谬之极！

结构体后面没有分号结束！记住，结构体声明一种数据类型，它是语句！要用分号结尾

引用 8 楼 zhao4zhong1 的回复:偶遇到类似问题都是用 “每次用/*...*/注释掉不同部分再重新编译，直到定位到具体语法出错的位置。” 的方法解决的。  用CLANG，语法加亮，定位比较准确，很适合你的哟。

引用 7 楼 spaceman10 的回复:或者把main的返回值改为void  这是在往歪路上引。

引用 6 楼 xunfeng0862 的回复:楼主应该是个新手，碰到问题先看报的是什么错，报错的英文不懂直接翻译下就明白了。 main函数要有返回值，四楼最后要加上一个return 0;  当main函数的执行流到达组成函数体的}时，等效于return 0; 就算是老的编译器，这也不算什么大毛病。

struct student { char name[20]; int age; float score[5],ave;  };//结构体定义和函数体定义不同，边界除了用{}区分，结尾}后面还要加“；”号

结构体定义后大括号外面要有分号的。

或者把main的返回值改为void

注意加分号....


Question: 用文本模式和二进制模式打开一个二进制文件有区别吗？

对，csdn 那段时间把我blog中的几乎所有的“\”都转了个方向

引用 2 楼 user-1 的回复:可以看看这个：小小换行符乱谈(文本文件vs二进制文件) http://blog.csdn.net/user-1/article/details/6430280 我有个问题，你文章中的/r/n什么的我认为应该是\r \n吧？

在传统的unix系统下没有区别。


Question: 什么时候要用到二进制I/O函数（fread,fwrite)？

很多文件本身就是二进制的，只能用二进制I/O去读 ， 比如说我写过一个工具，对exe文件进行处理，你就不可能用fscanf去读文件


Question: 文本模式与二进制模式

引用 楼主 u014320490 的回复:具体资料我已经查过，但还想确认一些事 另外，我的问题都是建立在排除这两个模式的存储空间以及执行速度的差别上的，回答时就不用考虑了！~~~~~~~~ 本来就和这两个没多大关系吧？  引用 楼主 u014320490 的回复:在UNIX中，用文本模式和二进制模式打开文件没区别吗？这两个模式与文本I/O函数（fscanf,fprintf)以及二进制I/O函数（fread，fwrite）没有联系吗？ 对，没有联系  引用 楼主 u014320490 的回复:在WINDOWS中，用文本和二进制模式打开文件会产生不同的显示结果吗？  取决于你的文件内有没有换行。


Question: 锯齿数组

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

哇，更期待代码或上图了

引用 2 楼 zhangbencheng 的回复:你的画张图说明下，长什么样哦！要不然，怎么搞啊！你意象啊有点像二维数组，但是每一行的长度都不同

你的画张图说明下，长什么样哦！要不然，怎么搞啊！你意象啊

这个名词比较新颖啊，以前怎么没听过。


Question: C语言  readLine函数   处理大于缓存区字节的问题

引用 5 楼 duqi_2009 的回复:[quote=引用 4 楼 richyhuang 的回复:] 如果那么没把握，建立一个链表数组也是可以的 不用担心会越界，除非系统内存不够  建立链表数组？？不是太明白您的意思  另外，这个问题，由于read系统调用会记录上次读的位置，所以，我想采取不丢弃的策略，然后当发现有没有完整接收的一行时就再次读取即可[/quote]  链表数组就是节点只有1个元素的数组啊, 不然你用list模板也可以 ,反正你这个长度不确定的情况下,就使用动态数据结构就好了.

引用 3 楼 zhao4zhong1 的回复:仅供参考#include <stdio.h> #include <string.h> #define MAXLEN 1000 char ln[MAXLEN]; FILE *f; int i,z; int b,n,L; int main(int argc,char **argv) {     if (argc<2) {         printf("Usage:%s fullpathfilename.ext\nget total blank/non-blank/total linenumbers.\n",argv[0]);         return 1;     }     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not open file [%s]!\n",argv[1]);         return 2;     }     z=0;     b=0;     n=0;     L=0;     while (1) {         if (NULL==fgets(ln,MAXLEN,f)) break;         L=strlen(ln);         if ('\n'==ln[L-1]) {             if (0==z) {                 for (i=0;i<L-1;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L-1) z=1;//当前行不是空行             }             if (0==z) b++; else n++;             z=0;         } else {             if (0==z) {                 for (i=0;i<L;i++) {                     if (!(' '==ln[i] || '\t'==ln[i])) break;                 }                 if (i<L) z=1;//当前行不是空行             }         }     }     fclose(f);     if (L>0 && '\n'!=ln[L-1]) {         if (0==z) b++; else n++;//最后一行末尾无'\n'也计算     }     printf("File:[%s] total blank/non-blank/total linenumbers is %d/%d/%d\n",argv[1],b,n,b+n);     return 0; }   赵老师。 话说 这个代码能不能规范点， int。。abcdefg 然后不够了 就aabbccdd 不要贪图快就随便abcd的。容易误导人啊 心急吃不了热豆腐

引用 4 楼 richyhuang 的回复:如果那么没把握，建立一个链表数组也是可以的 不用担心会越界，除非系统内存不够  建立链表数组？？不是太明白您的意思  另外，这个问题，由于read系统调用会记录上次读的位置，所以，我想采取不丢弃的策略，然后当发现有没有完整接收的一行时就再次读取即可

看你是做什么用的 如果是文本编辑器，要强制换行，并且记录这个超长行被分成几行。 如果是数据处理，并且可以便读取边处理，那么先处理已经读进来的部分， 剩下的接着继续，可以采用双缓冲循环技术，也可以缓存几个字符，在这几个字符没处理完之前，不处理缓冲中的字符。 当然，如果是控制台输入输出处理，还可以unget 已经读取的字符，文件似乎也是可以的。

如果那么没把握，建立一个链表数组也是可以的 不用担心会越界，除非系统内存不够

#include <unistd.h> #include <errno.h> #include "read_line.h"  ssize_t read_line(int fd, void *buffer, size_t n) { 	ssize_t numRead;	/* # of bytes fetched by last read()*/ 	size_t 	totRead;	/* Total bytes read so far*/ 	char *buf; 	char ch;  	if (n <= 0 || buffer == NULL){ 		errno = EINVAL; 		return -1; 	}  	buf = buffer; 	totRead = 0; 	for(;;){ 		numRead = read(fd, &ch, 1); 		if (numRead == -1){ 			if (errno == EINTR)     /*Interrupted ----> restart read()*/ 				continue; 			else 				return -1;			/* some other error*/ 		}else if (numRead == 0){	/* EOF*/ 			if (totRead == 0)		/* No bytes read so far, return 0*/ 				return 0; 			else					/* Some bytes read so far, add '\0'*/ 				break; 		}else{						 			if (totRead < n-1){		/* Discard > (n-1) bytes */ 				totRead++; 				if (totRead == n-2)   /* 让readLine最多能读取n-1个字符，不包括null字符，并且不丢弃字节*/ 					break; 				*buf++=ch; 			}  			if (ch == '\n') 				break; 		} 	}  	*buf = '\0'; 	return totRead; }   但是，调用者又是如何处理读取部分行的情况呢？？？？


Question: 读取串口程序--老是提示这个错误--已解决 【但（不想每次打开都加hid.lib）】

将错误信息中出现的标识符放在google里面搜一下，看其在哪个.lib中，然后在本地硬盘上搜索该.lib,如果没有，在网上搜索相关库或模块下载安装，然后将其所在目录填写到“附加依赖库所在目录”中，将其名字添加到“附加依赖库”中，重新连接。 VC6： 工程、设置、Link、分类：Input、附加库路径：填写附加依赖库所在目录 分号间隔多项 工程、设置、Link、分类：Input、对象/库模块：填写附加依赖库的名字.lib 空格间隔多项 VS20xx： 项目、属性、链接器、常规、附加库目录：填写附加依赖库所在目录 分号间隔多项 项目、属性、链接器、输入、附加依赖项：填写附加依赖库的名字.lib 空格或分号间隔多项

引用 2 楼 iamkconghua 的回复:#pragma comment(lib, "hid.lib")正确！

#pragma comment(lib, "hid.lib")

#include


Question: 请问，如何画出哥德巴赫猜想这个程序的N-S流程图？


Question: 关于链栈的问题。为什么输入数据后，输出错误啊？求教。

好长，没耐性看呐

引用 9 楼 u013429409 的回复:哦，终于知道了。我刚才那个懂了，Pop没改过来。pop函数出栈了，我还是指向那个。谢谢你啊。 不客气不客气。请点击上方“结贴”按钮，谢谢

引用 7 楼 u013429409 的回复:是啊。我把输出函数放到前面是可以。但我想最后输出栈中的元素。为什么输出放在最后不可以啊？ 之前让你改的内容，你还是没明白啊。 Push函数，为什么让你把返回值改成StackNode *，然后把top返回？ 是因为你把top作为参数穿进去，传递的是一个指针。函数中可以变更指针指向的地址的内容，但是不能更改指针的值啊。 因为实参是指针变量的一个拷贝，所以指针变量自身的值是不能变更的。所以必须通过将top返回，才能改变指针的值。  基于这个愿意，增加Pop操作之后，Pop函数也要增加同Push一样的变更。也就是把返回值改成StackNode *，然后把top返回

上面的格式乱了，重新贴一个。改动的地方就是1、2楼说的，你自己diff一下  #include<stdio.h> #include<malloc.h> #define N 6 typedef int elemtype; typedef struct stacknode{    elemtype data;    struct stacknode *next; }StackNode; StackNode *InitStack(StackNode *top){     top=(StackNode *)malloc(sizeof(StackNode));     top->next=NULL;     return top; } int Judge(StackNode *top){     if(top->next==NULL)        {            printf("建栈成功...\n");            return 1;        }     else        {             printf("建栈失败!\n");             return 0;        } } StackNode *Push(StackNode *top){     StackNode *p;     int i,item;     for(i=0;i<N;i++)         {             printf("请输入第%d个值item\n",i+1);             scanf("%d",&item);             p=(StackNode *)malloc(sizeof(StackNode));             p->next=NULL;             p->data=item;             p->next=top;             top=p;         }     return top; } int Output(StackNode *top){     int i;     for(i=0;i<N;i++)         {             printf("%d ",top->data);             top=top->next;         }     return 1; } int main() {     StackNode *top;     top=InitStack(top);     Judge(top);     top = Push(top);     printf("链式栈的输出（从栈顶到栈底）\n");     Output(top);     return 0; }

引用 3 楼 u013429409 的回复:恩恩  是的。我改了一下是可以了。但我还是不知道为什么输出还是出错，能再帮我看看吗。谢谢！ #include<stdio.h> #include<malloc.h> #define N 6 typedef int elemtype; typedef struct stacknode{    elemtype data;    struct stacknode *next; }StackNode; //链式栈的初始化 StackNode *InitStack(StackNode *top){     top=(StackNode *)malloc(sizeof(StackNode));     top=NULL;     return top; } //判断是否建栈成功 int Judge(StackNode *top){     if(top==NULL)        {            printf("建栈成功...\n");            return 1;        }     else        {             printf("建栈失败!\n");             return 0;        } } //链式栈入栈操作 StackNode *Push(StackNode *top){     StackNode *p;     int i,item;     for(i=0;i<N;i++)         {             printf("请输入第%d个值item:",i+1);             scanf("%d",&item);             p=(StackNode *)malloc(sizeof(StackNode));             p->next=NULL;             p->data=item;             p->next=top;             top=p;         }     return top; } //取栈顶元素的值 int StackTop(StackNode *top){     int item;     if(top==NULL)     {         printf("栈空.\n");         return 0;     }     else       {           item=top->data;           printf("栈顶的元素为%d\n",item);       }     return 1; } //链式栈的出栈操作 int Pop(StackNode *top){     int item;     StackNode *p;     p=top;     if(top==NULL)         {             printf("栈空.\n");             return 0;         }     else     {         item=p->data;         top=p->next;         free(p);         printf("出栈的元素为%d\n",item);         return 1;     } } //链式栈的输出（从栈顶到栈底） int Output(StackNode *top){     int i;     for(i=0;i<N-1;i++)         {             printf("%d ",top->data);             top=top->next;         }     printf("\n");     return 1; } int main() {     StackNode *top;     top=InitStack(top);     Judge(top);     printf("链式栈入栈操作\n");     top=Push(top);     printf("取栈顶元素的值\n");     StackTop(top);     printf("链式栈的出栈操作\n");     Pop(top);     printf("链式栈的输出（从栈顶到栈底）\n");     Output(top);     return 0; } 你开始的代码，稍微改下就行了  #include<stdio.h> #include<malloc.h> #define N 6 typedef int elemtype; typedef struct stacknode{    elemtype data;    struct stacknode *next; }StackNode; StackNode *InitStack(StackNode *top){     top=(StackNode *)malloc(sizeof(StackNode));     top->next=NULL;     return top; } int Judge(StackNode *top){     if(top->next==NULL)        {            printf("建栈成功...\n");            return 1;        }     else        {             printf("建栈失败!\n");             return 0;        } } StackNode *Push(StackNode *top){     StackNode *p;     int i,item;     for(i=0;i<N;i++)         {             printf("请输入第%d个值item\n",i+1);             scanf("%d",&item);             p=(StackNode *)malloc(sizeof(StackNode));             p->next=NULL;             p->data=item;             p->next=top;             top=p;         }     return top; } int Output(StackNode *top){     int i;     for(i=0;i<N;i++)         {             printf("%d ",top->data);             top=top->next;         }     return 1; } int main() {     StackNode *top;     top=InitStack(top);     Judge(top);     top = Push(top);     printf("链式栈的输出（从栈顶到栈底）\n");     Output(top);     return 0; }

同时Push这个函数的返回值类型改成StackNode *，然后在函数中返回top

scanf("%d",item);->scanf("%d",&item);


Question: 一段简单的C程序的疑问

实在是对人， 非常感谢！

((unsigned long)addr % 2048) < 2048  --->不是恒成立吗？

(((unsigned long)addr % 2048) < 2048) 这个不是必然成立的吗？


Question: 为什么能用NULL但不能用NUL

标准库里面，所有控制字符，都没有定义成 宏常量，或者枚举常量 NUL DEL ESC CR LF ...... 都没有定义


Question: 请教gViim问题

引用 7 楼 u014311679 的回复:[quote=引用 4 楼 my_live_123 的回复:] 和vim差不多 ：！gcc 。。。不就妥了 ：help 帮助文档 但显示的是“！gcc...”不是外部命令或内部命令，还有别的指令吗？ [/quote] 我是省略的写的 比如编译main.c gcc -o main main.c 生成可执行文件main gcc 是在终端编译程序的命令，前提是你已经安装了gcc。

不能。win里安心用gvim写程序然后开个visual studio cmd窗口用vc编译

和vim差不多 ：！gcc 。。。不就妥了 ：help 帮助文档

gvim是个编辑器。你需要的是 编译器，链接器，调试器

就是windows下的gVim7.4运行vi用的，现在就是变写完程序不知道如何运行

gdb吧，gvim只是GUI界面的一个文本编辑工具

引用 4 楼 my_live_123 的回复:和vim差不多 ：！gcc 。。。不就妥了 ：help 帮助文档 但显示的是“！gcc...”不是外部命令或内部命令，还有别的指令吗？

请问cmd可以模拟linux里的终端吗？

gvim是个类vim的文本编辑器。如此而已，即便在linux里面，你还不得用gcc,g++等编译器来编译么？