Question: 求问，c编译器有什么版本，怎么看是什么版本？

提醒：不一定版本越高越好用。

引用 4 楼 caiwei_cs 的回复:[quote=引用 3 楼 user-2 的回复:] [quote=引用 2 楼 caiwei_cs 的回复:] [quote=引用 1 楼 user-2 的回复:] gcc -v 那我经常用的古老的vc6呢？ 这个gcc版本和vc的版本是不是都是遵照一个什么国际c标准[/quote] vc呢，是一个集成开发环境，准确来讲，不是一个编译器，是包含编译器而已。 vc6有些实现不符合c标准。 gcc有很多版本，是否每个实现都符合c标准，我没有每个都去测试过，所以也无法下结论。 不过以我个人的经验来讲，gcc编译器是最贴近标准的。 据我所知，目前存在的才语言标准有：c89(被规范为iso90)，c99，c0x，c1x。[/quote] 谢谢啦，是不是我有条件的话用gcc是最好的吧。[/quote] 没有这样的限制啦，看你打算在哪个平台做开发，做什么样的开发。 各种编译器存在，都有其不可替代的用途。

引用 3 楼 user-2 的回复:[quote=引用 2 楼 caiwei_cs 的回复:] [quote=引用 1 楼 user-2 的回复:] gcc -v 那我经常用的古老的vc6呢？ 这个gcc版本和vc的版本是不是都是遵照一个什么国际c标准[/quote] vc呢，是一个集成开发环境，准确来讲，不是一个编译器，是包含编译器而已。 vc6有些实现不符合c标准。 gcc有很多版本，是否每个实现都符合c标准，我没有每个都去测试过，所以也无法下结论。 不过以我个人的经验来讲，gcc编译器是最贴近标准的。 据我所知，目前存在的才语言标准有：c89(被规范为iso90)，c99，c0x，c1x。[/quote] 谢谢啦，是不是我有条件的话用gcc是最好的吧。

引用 2 楼 caiwei_cs 的回复:[quote=引用 1 楼 user-2 的回复:] gcc -v 那我经常用的古老的vc6呢？ 这个gcc版本和vc的版本是不是都是遵照一个什么国际c标准[/quote] vc呢，是一个集成开发环境，准确来讲，不是一个编译器，是包含编译器而已。 vc6有些实现不符合c标准。 gcc有很多版本，是否每个实现都符合c标准，我没有每个都去测试过，所以也无法下结论。 不过以我个人的经验来讲，gcc编译器是最贴近标准的。 据我所知，目前存在的才语言标准有：c89(被规范为iso90)，c99，c0x，c1x。

引用 1 楼 user-2 的回复:gcc -v 那我经常用的古老的vc6呢？ 这个gcc版本和vc的版本是不是都是遵照一个什么国际c标准

gcc -v


Question: 【蓝桥杯】排他平方数 ssprintf()的疑问

目测是乘法溢出

问题见红色部分 int cmp(char *c,int n) {     int i,j;     for(j=0;j<n;j++)     for(i = 0;i < n;i++)     {         if(c[j] == c[i] && i!=j)         return 0;     } return 1; }  int main(void) {     long long s;     long long i;     int j;     int t;     int nc=0;     int ns = 0;     char cc[20];     char cs[20];     for(i = 123456;i <= 987654;i++)     {         sprintf(cc,"%lld",i);         nc = strlen(cc);         if(cmp(cc,nc))         {             s = i * i;             //printf("%d",i);             sprintf(cs,"%lld",s);             ns = strlen(cs);             for(j = 0;j < ns;j++) {                 for(t = 0;t<nc;t++)                      if(cs[j]== cc[t] )                          break;             if(t!=nc) break; }    if(j==ns) printf("%lld====%lld\n",i,s);         }      }      return 0; }


Question: 可变参数宏，做assert 断言编译过不了。

对不起啊，楼上，你们都说对了，编译器问题。我不小心结贴了。不能给你们分了。

很明显,你的编译器不支持

我在VS2005的环境能编译通过、并且正常运行


Question: 菜鸟在线跪等,低级错误!!!

我分不多,没必要分了吧,都给最快帮我解决的朋友了!谢谢大家的帮助,上帝会保佑大家的!!!

嗯，scanf中不要轻易加上非输入控制符（这里指的是逗号），关于scanf，lz可以看看这个——http://blog.csdn.net/u012421456/article/details/18501309

这样就好了，或者用我注释的那些。  #include<stdio.h> void main() { int a,b,c; scanf ("%d %d",&a, &b); //scanf ("%d",&a); //scanf ("%d",&b); printf ("a=%d,b=%d\n",a,b); }

非常感谢,几年没用了,都忘了,居然用的space分割!别急,我找找从哪里给你分!

scanf ("%d,%d",&a,&b);   这里的格式某种程序上决定了你的输入格式.  你这里定义的是输入数据以逗号隔开, 但是你却又没有这样做. 应该输入数据为: 1,2

scanf ("%d,%d",&a,&b); 输入时要用，分割


Question: 求教一个C的double类型高精度运算的问题。有代码

机器内不能很好的表示浮点数啊，这是计算机组成原理上写着的啊！除了那么偶然的数之外，其他的误差永远存在。

也遇到过浮点数表示偏差的情况，大概和内部存储计算方式有关。误差这么小就不用纠结了


Question: 关于C语言文件操作的问题

费那事儿！ system("copy D:\\C语言开发手册\\class15P411\\test1.txt+D:\\C语言开发手册\\class15P411\\test2.txt D:\\C语言开发手册\\class15P411\\test.txt");

可能： 1 写入文件最后没有写结束标志 2 读合并后文件时没有先把文件指针指到起始位置

文件内容是不是有中文？


Question: linux下的c程序，链接库在什么地方

linux fork系统调用，被libc封装了 为什么linux不需要lib只是和所使用的库文件格式相关的，linux使用的是elf格式，和windows下的不同

引用 16 楼 u013666035 的回复:[quote=引用 13 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 zmlovelx 的回复:] echo $LD_LIBRARY_PATH 其实这位仁兄的回复才是正解。[/quote]  明显不对，显示是空的[/quote]  前提是楼主定义过这个环境变量....没有当然是空的.

引用 21 楼 u013666035 的回复:[quote=引用 20 楼 u014162349 的回复:] 引用GLIBC_2.0是什么意思啊，对应哪个文件 glibc是C语言的实现库名称，貌似这个名称解决不了你的问题哦。  引用还有你是怎么链接到/lib/libc.so.6啊，这里用的是/lib/tls/libc.so.6 libc是C语言库文件名以及路径 为什么你的路径和我的不一样呢，这要看下你编译的文件makefile是怎么写的？ 比如你用一个库，并且指定查询路径 -L /lib/tls/ ，那边就会出现上面的路径 makefile中会有上面一些人说的 -L 后面带库路径  -l后面带库名称   其他都清楚了，现在就一个问题，为什么linux的动态链接不需要对应的lib[/quote] fork，系统调用之一。“系统调用”这个词暗示着它是和操作的实现紧密相关的，不具备移值性，不同于用户级层面的pthread 库。“系统调用”也意味着它是关联到操作系统的一部分。使用动态链接库，仅仅提供入口，用代码共享的方式，不仅节省程 序代码空间，而且在操作系统升级了.so的时候（通常伴随着内核的升级），只要保持接口不变，程序在新的环境下仍然能正 常运行。对比静态库，一旦代码绑定，在新的环境下不重新编译，未必还能正常运行。  个人见解，仅供参考。

引用 20 楼 u014162349 的回复:引用GLIBC_2.0是什么意思啊，对应哪个文件 glibc是C语言的实现库名称，貌似这个名称解决不了你的问题哦。  引用还有你是怎么链接到/lib/libc.so.6啊，这里用的是/lib/tls/libc.so.6 libc是C语言库文件名以及路径 为什么你的路径和我的不一样呢，这要看下你编译的文件makefile是怎么写的？ 比如你用一个库，并且指定查询路径 -L /lib/tls/ ，那边就会出现上面的路径 makefile中会有上面一些人说的 -L 后面带库路径  -l后面带库名称  其他都清楚了，现在就一个问题，为什么linux的动态链接不需要对应的lib

引用 16 楼 u013666035 的回复:[quote=引用 13 楼 zhao4zhong1 的回复:] [quote=引用 8 楼 zmlovelx 的回复:] echo $LD_LIBRARY_PATH 其实这位仁兄的回复才是正解。[/quote]  明显不对，显示是空的[/quote] 命令行参数 -L（.a库文件所在目录）

引用 楼主 u013666035 的回复:就是kernel32.lib这种，linux下应该是一样的  gcc默认是到什么地方去找，还有就是怎么知道fork对应的lib和dll是什么  ldd 还有种笨方法 就是 直接vim打开可执行程序，看看里面有哪些lib的符号

使用ldd命令查看可执行程序依赖的.so

引用 4 楼 u013666035 的回复:[quote=引用 2 楼 buyong 的回复:] glibc  linux下，lib和dll对应的是什么文件[/quote] .lib 对应.a 文件。 .dll对应.so文件。

引用 14 楼 u014162349 的回复:第一个问题：可以用ldd命令来观察进程  [root@TM4 fork_test]# ldd test  	linux-gate.so.1 =>  (0xb7746000) 	libc.so.6 => /lib/libc.so.6 (0x4d1db000) 	/lib/ld-linux.so.2 (0x4d1b4000)   还有你是怎么链接到/lib/libc.so.6啊，这里用的是/lib/tls/libc.so.6

引用 13 楼 zhao4zhong1 的回复:[quote=引用 8 楼 zmlovelx 的回复:] echo $LD_LIBRARY_PATH 其实这位仁兄的回复才是正解。[/quote]  明显不对，显示是空的

引用 14 楼 u014162349 的回复:第一个问题：可以用ldd命令来观察进程  [root@TM4 fork_test]# ldd test  	linux-gate.so.1 =>  (0xb7746000) 	libc.so.6 => /lib/libc.so.6 (0x4d1db000) 	/lib/ld-linux.so.2 (0x4d1b4000)   第二个问题：可以用nm查询进程中的函数属于哪个库  [root@TM4 fork_test]# nm test |grep fork          U fork@@GLIBC_2.0 [root@TM4 fork_test]#   GLIBC_2.0是什么意思啊，对应哪个文件

引用 8 楼 zmlovelx 的回复:echo $LD_LIBRARY_PATH 其实这位仁兄的回复才是正解。

使用objdump可以查看.so中都导出了哪些函数。

引用 7 楼 zhao4zhong1 的回复:使用ldd命令查看可执行程序依赖的.so  是不是linux下的系统调用函数全在libc.so.6啊

引用 6 楼 max_min_ 的回复:动态库 Linux .so   Windows .dll 静态库 Linux .a      Windows .lib  注意引导路径，  不是静态库，是动态库的隐式链接lib，好像linux不需要这个，不知道为什么

引用 5 楼 luotuo44 的回复:[quote=引用 4 楼 u013666035 的回复:] [quote=引用 2 楼 buyong 的回复:] glibc  linux下，lib和dll对应的是什么文件[/quote] .lib 对应.a 文件。 .dll对应.so文件。[/quote]  不是静态库，是动态库的隐式链接lib，好像linux不需要这个，不知道为什么

echo $LD_LIBRARY_PATH


Question: 关于lcd屏幕显示的问题

C源代码:12x12汉字点阵库(支持GBK)及其处理  http://download.csdn.net/detail/zhao4zhong1/2180241

嗯啊，用的是点阵字库，正常的话每行高度12，高度48，刚好四行，并且规定第四行高度必须是12（作为菜单用，特殊处理），并且和第三行间距为1，这样前三行的总高度就为35。但是个别人在开发过程中只考虑了当前的情况，人为的改变行的属性，等项目合在一起编译时出现了上述问题，因为显示的字体有大写、小写、中写、英文字母也有大写和小写，特别是一些特殊的字符，如String，里面有‘S’和‘g’，‘S’能显示，‘g’的下半部分就显示不全了，被覆盖了。还有，汉字显示的话，其高度必须是12才能显示完整。

一般高度为12的字库，其真实字体高度是11，留下最后一行来分隔行，要不然两行之间的字符会连在一起，但有些英文字符占用了最后一行，像“g”这个字符就是，这样如果只显示11行，这个字符就会显示不全，不过据我观察，所有英文字符上方均有空间，所以可以把所有英文字符和数字全部上移一行，这个操作可以在绘制字符时进行，也可以通过更改字库实现。

引用 楼主 mingxingming 的回复:最近在做一个项目，效果是在lcd屏幕上显示四行汉字或者英文字母，可是问题是，显示的这些字母或汉字上下行会有重叠，显示不全，屏幕大小是128*48，要求是字体大小不能再修改了，行数（四行）不能改变了，每行的行距必须是等宽的（保持美观），有没有有效的解决办法呢？？？？？谢谢您们了！！！！ 不够就自己处理,128*48的矩阵很大么?

是用的点阵字库吗，字体大小是多大的，按这个屏幕分辨率，要显示四行字体高度不能超过12。


Question: linux下的c程序，比如fork函数，为什么不需要头文件

有些C编译对没有提供原型的函数调用假设返回int, 但是对于类型，没有这种功能。   安全的做法： 不要让编译做任何假设


Question: linux下的c程序，变量怎么可以随便定义

为什么在vc6.0中写如下代码时，调用函数bioskey()无法获取键盘键码，头文件bios.h已经包含进来了。求大神指点

引用 3 楼 u013666035 的回复:[quote=引用 2 楼 akirya 的回复:] C89下是 GCC扩展 C99 直接规定可以随意定义了。  那vs2010为什么还是不可以[/quote] VS全系列不支持C99

引用 3 楼 u013666035 的回复:[quote=引用 2 楼 akirya 的回复:] C89下是 GCC扩展 C99 直接规定可以随意定义了。  那vs2010为什么还是不可以[/quote] 说明VS2010支持c89

引用 3 楼 u013666035 的回复:[quote=引用 2 楼 akirya 的回复:] C89下是 GCC扩展 C99 直接规定可以随意定义了。  那vs2010为什么还是不可以[/quote] VC++6.0也不可以 编译器不同，对标准的支持程度也不同

引用 2 楼 akirya 的回复:C89下是 GCC扩展 C99 直接规定可以随意定义了。  那vs2010为什么还是不可以

C89下是 GCC扩展 C99 直接规定可以随意定义了。

C语言中的变量就是可以随时定义的啊，不只是在Linux中


Question: linux网络编程unp.h配置问题

引用 1 楼 user-1 的回复:编译的时候加上-lunp 果然可以了，非常感谢。

编译的时候加上-lunp


Question: C语言字符数组输出问题

引用 6 楼 xdayong 的回复:有几个错误 第一,这里有优先级的问题，需要加小括号 while((ch=getchar())!='\n') 第二，在while循环里，在wile循环开始，需要判断i是否大于20，否则的话，会造成对内存的非法访问 { if( i>20) break; str[i]=ch; i++; } 第三，如果需要已字符串形式输出，则最好在开始初始化数组 str[i]={0},这时在while循环里，需要判断是否大于19，否则的话，字符串输出的话，多输出一些字符。  回复的很细致，受教了。没注意那么多。

改为 while((ch=getchar())!='\n')  引用 楼主 u011656266 的回复:int j,i=0,n=0; 	char ch,str[20]; 	while(ch=getchar()!='\n') 	{ 		str[i]=ch; 		i++; 	} 	for(j=0;j<5;j++) 		printf("%c",str[j]); 这是源代码，想输出str，可是一直没法输出。感觉对着，不明白怎么回事？求解答一下。还有那个字符流读取时怎么回事？

引用 1 楼 user-4 的回复:字符输出用:  int j,i=0,n=0; 	char ch,str[20] = {0}; 	while((ch=getchar())!='\n')//注意这里的括号，优先级顺序会错!=优先级比=高，ch变成条件判断的结果0或1 	{ 		str[i]=ch; 		i++; 	} 	str[i] = '\0'; 	printf("%s\n",str);//输入字符串  另外这里的str[20]要注意下，别输入长度超过上限。  明白了，谢谢

while(ch=getchar()!='\n') 应改为 while((ch=getchar())!='\n')

printf("%s\n",str);//输出字符串 上面的笔误：）


Question: 这个问题把我搞疯了!求指教

是不是lz不小心误删了什么文件啊？前两天我就是不小心删了一个文件结果重新装了好几次VS2012和VS2013，都不行，唉，只好用VC6.0现在

总是发现Path环境变量被某些软件安装时错误修改。比如带空格的目录名未加引号、带汉字的目录引起目录查找混乱等问题，严重影响系统查找可执行文件和dll。 编译此源代码，生成PathShortener.exe，然后在cmd窗口里面运行PathShortener.exe>path.txt，打开path.txt，手动将其内容拷贝粘贴覆盖修改‘我的电脑、属性、高级、环境变量、系统变量、Path、编辑、变量值’即可纠正设置错误的Path http://download.csdn.net/detail/zhao4zhong1/2652343

引用 楼主 u011665073 的回复:我用的是visual 2010,一直出现不是内部或外部命令，也不是可运行的程序 或批处理文件。 请按任意键继续. . .这样的问题，该怎么办呢 环境变量里路径没配置，添加进去就行了

引用 3 楼 u011665073 的回复:我是建立的32位控制台应用程序！应该没有问题！我想问一下自己亲自编程序有时候不出现问题，但是自己打开别人的或者有时候自己写的程序经常出现....exe不是内部或外部命令,也不是可运行程序或批处理文件?有时候不出现问题 我猜应该是设置问题。 楼主可以试着自己创建一个项目，再把别人写的代码导入进来。

简单，卸掉不用2010不就好了，或者装VS2008， 2005一样好用，再不行VC6.0，再没有直接text编辑就好了啊。

引用 楼主 u011665073 的回复:我用的是visual 2010,一直出现不是内部或外部命令，也不是可运行的程序 或批处理文件。 请按任意键继续. . .这样的问题，该怎么办呢你设置的启动项，或者你创建的工程是应用程序？确认可别是dll或者其它哦。


Question: c语言 关于do while 问题

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

引用 6 楼 lin5161678 的回复:[quote=引用 5 楼 ansonzxy 的回复:] [quote=引用 4 楼 lin5161678 的回复:] [quote=引用 3 楼 ansonzxy 的回复:] 这个是 空格符 的问题，具体参照 《C PREMIER》这本书。 只要这样 scanf (" %c", &char);  //要在 %c前面加一个空格就可以了。。。。nice 就是这样 [/quote]  其实我只是知道，不知道为什么，不知道大神可否稍微解释一下？[/quote]scanf 的格式控制字符串中  空格比较特殊 它匹配0个或多个连续空白字符 [\t \r \n 空格等等] [/quote]  好！谢谢老师！！！

引用 5 楼 ansonzxy 的回复:[quote=引用 4 楼 lin5161678 的回复:] [quote=引用 3 楼 ansonzxy 的回复:] 这个是 空格符 的问题，具体参照 《C PREMIER》这本书。 只要这样 scanf (" %c", &char);  //要在 %c前面加一个空格就可以了。。。。nice 就是这样 [/quote]  其实我只是知道，不知道为什么，不知道大神可否稍微解释一下？[/quote]scanf 的格式控制字符串中  空格比较特殊 它匹配0个或多个连续空白字符 [\t \r \n 空格等等]

引用 4 楼 lin5161678 的回复:[quote=引用 3 楼 ansonzxy 的回复:] 这个是 空格符 的问题，具体参照 《C PREMIER》这本书。 只要这样 scanf (" %c", &char);  //要在 %c前面加一个空格就可以了。。。。nice 就是这样 [/quote]  其实我只是知道，不知道为什么，不知道大神可否稍微解释一下？

引用 3 楼 ansonzxy 的回复:这个是 空格符 的问题，具体参照 《C PREMIER》这本书。 只要这样 scanf (" %c", &char);  //要在 %c前面加一个空格就可以了。。。。nice 就是这样

又或者   char ch; while ( (ch = getchar() ) !=  '\n') continue;  也可以

谭浩强书上写的清楚，看下吧。

你的回车还在缓冲区呢，加个getchar()把回车读了，不然下一次循环给你读到回车！ #include <stdio.h> int main(void) {     char ch;     do {         scanf("%c",&ch);         getchar();         puts("sss");     } while(ch != 'a'); }

在printf后面，调用下fflush(stdin);清下键盘缓冲区。清除那个回车。

引用 楼主 u013808483 的回复:do{  }while（）；  不是说 先执行循环体一次，然后在判断while中的条件语句，若为真，在继续执行循环体吗 可是 看看这个程序，得到的结果 不是我想要的啊 求解 哪里错了    这里我输入a这个字符，while条件判断是真啊 然后应该继续循环 要求我再输入一次才对啊 怎么会这样呢？好吧 我C语言基础差 求高人们指点 弄不明白 挺纠结的。。。 这个问题吧，是因为你敲了回车，回车会存在输入缓冲区，待你下次scanf的时候获取。 这就是第二次不等你按键，就自己退出的原因。 解决办法很简单，加一个getchar();在scanf后面。 具体详细的介绍网上查下吧。


Question: 64位机器编译的SO,怎么能在32位机器上运行啊。

无法运行。  引用 楼主 lgmsyy 的回复:64位机器编译的SO,怎么能在32位机器上运行啊。

32位机上能不能安装个64位虚拟机？如果能，将64位SO放在此虚拟机中运行。


Question: 菜鸟刚学位操作请教一个互换问题

引用 9 楼 leisuregame 的回复:[quote=引用 楼主 orangerx 的回复:] 各位大大好,今天刚学到位操作，互换两个数(把a,b互换)有一代码为： a=a^b; b=a^b; a=a^b; 以上的代码是正确的，然后我把它写成 a^=b^=a^=b; 这也正确，但： a=a^b=b^a=a^b;这就报错了，之前学习到'=赋值符好像是右结合性的，即从右到左计算。  另外还有一个问题：请问这个位操作还可以互换整个数组或字符串吗？  a^=b^=a^=b  实际上是a^=(b^=(a^=b)),执行的是下面的步骤： a^=b; b^=a; a^=b; 这样是没问题的。  a=a^b=b^a=a^b相当于a=(a^b=(b^a=a^b)) 但是b^a返回的是一个右值，无法对它进行赋值，所以是无法通过编译的。 [/quote] 原来是这样子的

引用 8 楼 nadleeh123 的回复:[quote=引用 楼主 orangerx 的回复:] 各位大大好,今天刚学到位操作，互换两个数(把a,b互换)有一代码为： a=a^b; b=a^b; a=a^b; 以上的代码是正确的，然后我把它写成 a^=b^=a^=b; 这也正确，但： a=a^b=b^a=a^b;这就报错了，之前学习到'=赋值符好像是右结合性的，即从右到左计算。  另外还有一个问题：请问这个位操作还可以互换整个数组或字符串吗？  为什么你们都喜欢把简单的东西复杂化？[/quote]  因为初学阶段对这些东西比较好奇

引用 楼主 orangerx 的回复:各位大大好,今天刚学到位操作，互换两个数(把a,b互换)有一代码为： a=a^b; b=a^b; a=a^b; 以上的代码是正确的，然后我把它写成 a^=b^=a^=b; 这也正确，但： a=a^b=b^a=a^b;这就报错了，之前学习到'=赋值符好像是右结合性的，即从右到左计算。  另外还有一个问题：请问这个位操作还可以互换整个数组或字符串吗？  a^=b^=a^=b  实际上是a^=(b^=(a^=b)),执行的是下面的步骤： a^=b; b^=a; a^=b; 这样是没问题的。  a=a^b=b^a=a^b相当于a=(a^b=(b^a=a^b)) 但是b^a返回的是一个右值，无法对它进行赋值，所以是无法通过编译的。

引用 楼主 orangerx 的回复:各位大大好,今天刚学到位操作，互换两个数(把a,b互换)有一代码为： a=a^b; b=a^b; a=a^b; 以上的代码是正确的，然后我把它写成 a^=b^=a^=b; 这也正确，但： a=a^b=b^a=a^b;这就报错了，之前学习到'=赋值符好像是右结合性的，即从右到左计算。  另外还有一个问题：请问这个位操作还可以互换整个数组或字符串吗？  为什么你们都喜欢把简单的东西复杂化？

引用 6 楼 zhao4zhong1 的回复:[quote=引用 3 楼 orangerx 的回复:] 二楼大大的代码好复杂，简化一些我是初学者来的。。 怕复杂当不了好程序员。[/quote]  是的。。。

引用 3 楼 orangerx 的回复:二楼大大的代码好复杂，简化一些我是初学者来的。。 怕复杂当不了好程序员。

引用 4 楼 orangerx 的回复:[quote=引用 2 楼 u013061236 的回复:] [quote=引用 楼主 orangerx 的回复:] 各位大大好,今天刚学到位操作，互换两个数(把a,b互换)有一代码为： a=a^b; b=a^b; a=a^b; 以上的代码是正确的，然后我把它写成 a^=b^=a^=b; 这也正确，但： a=a^b=b^a=a^b;这就报错了，之前学习到'=赋值符好像是右结合性的，即从右到左计算。   另外还有一个问题：请问这个位操作还可以互换整个数组或字符串吗？  先不说别的，代码要简洁明了，所以用最上面的即可。 另外：位操作应该是针对数字操作的，一般为整型 关于字符的操作，你可以试下，这个我没试过，不清楚[/quote]  字附串我不知道怎么操作，字符的话也属于整型的一种，测试过是没问题的[/quote]  那应该就没问题，字符串可以自己写个函数，一个个交换

引用 2 楼 u013061236 的回复:[quote=引用 楼主 orangerx 的回复:] 各位大大好,今天刚学到位操作，互换两个数(把a,b互换)有一代码为： a=a^b; b=a^b; a=a^b; 以上的代码是正确的，然后我把它写成 a^=b^=a^=b; 这也正确，但： a=a^b=b^a=a^b;这就报错了，之前学习到'=赋值符好像是右结合性的，即从右到左计算。  另外还有一个问题：请问这个位操作还可以互换整个数组或字符串吗？  先不说别的，代码要简洁明了，所以用最上面的即可。 另外：位操作应该是针对数字操作的，一般为整型 关于字符的操作，你可以试下，这个我没试过，不清楚[/quote]  字附串我不知道怎么操作，字符的话也属于整型的一种，测试过是没问题的

二楼大大的代码好复杂，简化一些我是初学者来的。。

引用 楼主 orangerx 的回复:各位大大好,今天刚学到位操作，互换两个数(把a,b互换)有一代码为： a=a^b; b=a^b; a=a^b; 以上的代码是正确的，然后我把它写成 a^=b^=a^=b; 这也正确，但： a=a^b=b^a=a^b;这就报错了，之前学习到'=赋值符好像是右结合性的，即从右到左计算。  另外还有一个问题：请问这个位操作还可以互换整个数组或字符串吗？  先不说别的，代码要简洁明了，所以用最上面的即可。 另外：位操作应该是针对数字操作的，一般为整型 关于字符的操作，你可以试下，这个我没试过，不清楚

计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）  #include <stdio.h> #define SWAP(a,b) do ((&(a))!=(&(b)))?((a)^=(b)^=(a)^=(b)):((a)=(a)); while (0) char   *p1="1" ,*p2="2" ; char    c1=1   , c2=2   ; short   s1=1   , s2=2   ; int     i1=1   , i2=2   ; __int64 I1=1i64, I2=2i64; float   f1=1.0f, f2=2.0f; double  d1=1.0 , d2=2.0 ; void main() {     SWAP((int)p1,(int)p2);                printf("char *     %5s,   %5s\n",p1,p2);     SWAP(c1,c2);                          printf("char       %5d,   %5d\n",c1,c2);     SWAP(s1,s2);                          printf("short      %5d,   %5d\n",s1,s2);     SWAP(i1,i2);                          printf("int        %5d,   %5d\n",i1,i2);     SWAP(I1,I2);                          printf("__int64 %5I64d,%5I64d\n",I1,I2);     SWAP(*(int     *)&f1,*(int     *)&f2);printf("float      %5g,   %5g\n",f1,f2);     SWAP(*(__int64 *)&d1,*(__int64 *)&d2);printf("double    %5lg,  %5lg\n",d1,d2);      SWAP(c1,c1);     printf("%d\n",c1); } //char *         2,       1 //char           2,       1 //short          2,       1 //int            2,       1 //__int64     2,    1 //float          2,       1 //double        2,      1 //2


Question: printf函数为什么耗时？

另外： printf 跟puts 比较起来也是很慢的，不过printf 比puts灵活多了

重定向到文件，就快多了 写文件，比打印屏幕，快了好多倍； 话说，写文件跟，直接内存读写比起来要慢很多的倍的，但是比写屏幕要快很多。。 DOS，Windows 控制台程序 xxx.exe >xx.txt 比 xxx.exe 要快很多

瓶颈一般都在设备IO那里。

那是网络延迟问题吧，在服务器本地登录打印试试

引用 4 楼 nj_wy 的回复:引用 1 楼 akirya 的回复:显示到屏幕上我要是把打印内容重定向到 /dev/null去，不知道能不能从质上改变这个状况？ 反正重定向到文件的话，会快很多很多

感觉快没啥意思到底是给人看的，有影响的话考虑分派一个线程阻塞消磨去...

我也没想过这事儿，学习一下

你是telnet到设备上的吧，那个输出文字确实很慢的

printf涉及I/O

楼主这么仔细，我从来没考虑这类问题。

好像原来做项目的时候，printf也是非常耗性能。printf 在linux下需要系统调用write,向标准设备打印输出，这个就要从用户态向内核态切换 ，然后再从内核态切换回来，这个非常影响性能。  对于实际项目，一般不会用printf，这个影响性能，一般都用自己的一套输出函数。正式产品中不允许使用printf。 重定向可能无法改善，

涉及到I/O就是一个耗时的动作了！

引用 4 楼 nj_wy 的回复:引用 1 楼 akirya 的回复:显示到屏幕上我要是把打印内容重定向到 /dev/null去，不知道能不能从质上改变这个状况？ 不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？

引用 4 楼 nj_wy 的回复:引用 1 楼 akirya 的回复:显示到屏幕上我要是把打印内容重定向到 /dev/null去，不知道能不能从质上改变这个状况？  应该没多大改观吧，想要了解具体细节的话，看汇编

引用 1 楼 akirya 的回复:显示到屏幕上 尤其是在显示到屏幕上时需要将整个屏幕中以前显示的行上卷一行的时候！ 试对比命令行最后加“>NUL”或“>文件名”让printf的输出重定向到空设备或文件中后速度快了多少倍。

显示到屏幕上


Question: 将一个数字转换为相应的字符？有不明白处，需解惑。

果真是这样，谢谢大家了~

就是一个函数声明吧，只不过他写在了itoa的函数内部。莫非是在这个文件中，reverse函数只想给itoa用，而对其它函数“隐藏”。所以选择在itoa的函数内部来声明？

这种写法头一次见

引用 楼主 u014082409 的回复:void itoa(int n, char s[]) { 	int i, sign; 	void reverse(char s[]);  	sign = n; 	i = 0; 	do{ 		s[i++] = abs(n % 10) + '0'; 	}while((n /= 10) != 0); 	if(sign < 0) 		s[i++] = '-'; 	s[i] = '\0'; 	reverse(s); }  其中，这步— void reverse(char s[ ]);貌似没有什么用。即使，把这一步直接跳过，程序一样正确。那这一步仅仅是做一个申明语句使用的？ 程序每次都是取的最右边一位数字,所以要反字符串。 如123，在上面程序中依次存入：s[0] = '3', s[1] = 2, s[2] = 3。 所以必须反转才能得出“正确”输出顺序。

将函数原型写在另一个函数内部的人依我看都是生手。


Question: 关于通用c语言随机数函数的问题

总不至于用 CoCreateGuid Creates a GUID, a unique 128-bit integer used for CLSIDs and interface identifiers.  HRESULT CoCreateGuid(   GUID  *pguid  //Pointer to the GUID on return );   Parameter pguid  [out] Pointer to the requested GUID on return.  Return Value S_OK  The GUID was successfully created.  Win32 errors are returned byUuidCreate but wrapped as an HRESULT.  Remarks The CoCreateGuid function calls the RPC function UuidCreate, which creates a GUID, a globally unique 128-bit integer. Use the CoCreateGuid function when you need an absolutely unique number that you will use as a persistent identifier in a distributed environment.To a very high degree of certainty, this function returns a unique value – no other invocation, on the same or any other system (networked or not), should return the same value.  QuickInfo   Windows NT: Use version 3.1 or later.   Windows: Use Windows 95 or later.   Windows CE: Unsupported.   Header: Declared in objbase.h.   Import Library: Included as a resource in ole32.dll.  See Also UuidCreate        吧

延时的思路不可取。  参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\rand.c /*** *rand.c - random number generator * *       Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: *       defines rand(), srand() - random number generator * *******************************************************************************/  #include <cruntime.h> #include <mtdll.h> #include <stddef.h> #include <stdlib.h>  /*** *void srand(seed) - seed the random number generator * *Purpose: *       Seeds the random number generator with the int given.  Adapted from the *       BASIC random number generator. * *Entry: *       unsigned seed - seed to seed rand # generator with * *Exit: *       None. * *Exceptions: * *******************************************************************************/  void __cdecl srand (         unsigned int seed         ) {         _getptd()->_holdrand = (unsigned long)seed; }   /*** *int rand() - returns a random number * *Purpose: *       returns a pseudo-random number 0 through 32767. * *Entry: *       None. * *Exit: *       Returns a pseudo-random number 0 through 32767. * *Exceptions: * *******************************************************************************/  int __cdecl rand (         void         ) {         _ptiddata ptd = _getptd();          return( ((ptd->_holdrand = ptd->_holdrand * 214013L             + 2531011L) >> 16) & 0x7fff ); }

引用 1 楼 zhao4zhong1 的回复:srand(time(NULL));//需且仅需在main()函数开头调用一次！  哦,我又运行了下,原来time(NULL)的返回值是相同的...  引用 6 楼 u011374013 的回复:[quote=引用 5 楼 lovenanforever 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] srand(time(NULL));//需且仅需在main()函数开头调用一次！  对srand()不熟,想问下...楼主每次在make_map(void) 不是都生成不同的种子了吗？难道每次生成的随机数种子开头都相同...?  [/quote]是这样的，我这个小程序有三个需要初始化的地方，全部都是用的make_map函数，并且是连续初始化的，所以每次调用time(NULL)获得的数都一模一样，导致三个地方初始化的结果都一样 搞个延时1秒应该也能解决问题。。[/quote]  ....嗯 确实 我在我这试时,延时下生成的就不同了,本身种子也不同了.  放到main()处,每次取得随机数,这三个make_map()就应该不同了.

引用 1 楼 zhao4zhong1 的回复:srand(time(NULL));//需且仅需在main()函数开头调用一次！  我自己试了下,确实是每次都生成的一样的序列,但这又是出于怎么样的原因呢？求解.

引用 5 楼 lovenanforever 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] srand(time(NULL));//需且仅需在main()函数开头调用一次！  对srand()不熟,想问下...楼主每次在make_map(void) 不是都生成不同的种子了吗？难道每次生成的随机数种子开头都相同...?  [/quote]是这样的，我这个小程序有三个需要初始化的地方，全部都是用的make_map函数，并且是连续初始化的，所以每次调用time(NULL)获得的数都一模一样，导致三个地方初始化的结果都一样 搞个延时1秒应该也能解决问题。。

引用 1 楼 zhao4zhong1 的回复:srand(time(NULL));//需且仅需在main()函数开头调用一次！  对srand()不熟,想问下...楼主每次在make_map(void) 不是都生成不同的种子了吗？难道每次生成的随机数种子开头都相同...?

来晚了，只需要调用一次就好！

来晚了，srand在程序开始调用一次就行了


Question: C指针传递问题

引用 楼主 pwy1198156945 的回复:为什么c语言中传一个指针必须要初始化，请求下边代码哪里出错了 #include<iostream> using namespace std; #include<stdlib.h> typedef char ElemType; typedef struct Node { 	ElemType data; 	struct Node *next; }Node,*LinkNode;  void IniLink(LinkNode L) { 	L=(LinkNode)malloc(sizeof(Node)); 	L->data = 'a'; 	L->next = NULL; } int main() { 	LinkNode L; 	IniLink(L); 	cout<<L->data; 	return 0; }  如果要在程序内部修改外部指针指向的值，必须使用二级指针才能做到

引用 11 楼 pwy1198156945 的回复:所以以后传指针时，一定要注意，不能传空指针，必须先让指针指向某一块内存，然后在调用函数中，把带有指向内存的指针，拷贝一个副本，这样就可以操作内存了。因为我们的目的是操作指针指向的内存，而不是指针。  你还是没理解问题出在哪儿。指针、非指针 在这儿没什么区别。 在 C中，函数参数都是通过值传递的。在C++中，又多了一种引用传递。  指针也是一个值，你想通过另一个函数修改它的值，你需要通过引用传递，或者通过值传递该指针的地址

计算机组成原理→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

感谢前面大牛，我懂了。原来指针也是变量，传到函数后那个指针也会在内存开辟空间，（我一直以为，变量会开辟空间副本，指针不会，原来这里错了）如果不初始化指针，传过去副本指针无论怎么弄也和main里边的原指针没关系。

iniLink的形参改为 LinkNode *L,同时函数内部的L前都加上*.然后main中调用时传入L的地址，也就是 iniLink(&L); 试试

引用 6 楼 pwy1198156945 的回复:[quote=引用 3 楼 user-4 的回复:] main中那个L是实参，传进函数后的形参是做了一个L的副本，对此副本做的改变没有影响main中的实参L  现在这个程序编译没问题，但是一运行，会出现一句提示“内存不能被读”[/quote]因为你的  引用 5 楼 pwy1198156945 的回复:[quote=引用 2 楼 dbzhang800 的回复:] 相信你清楚下面的问题出在哪儿  void func(int a) {      a = 2; }  int main() {     int a;     func(a);    //value of a??    return 0; }、  这个和上边的情况不同啊，你的这个是变量传递，内存中相当于有两个变量。而我的这个是指针，传到函数后依然是一个指针变量。[/quote]实参L并没有被函数改变，所以是个野指针，所以访问里边的东西(L->data等等)当然非法了。指针参数调用也是“值传递”，和非指针没有区别

引用 3 楼 user-4 的回复:main中那个L是实参，传进函数后的形参是做了一个L的副本，对此副本做的改变没有影响main中的实参L  现在这个程序编译没问题，但是一运行，会出现一句提示“内存不能被读”

引用 2 楼 dbzhang800 的回复:相信你清楚下面的问题出在哪儿  void func(int a) {      a = 2; }  int main() {     int a;     func(a);    //value of a??    return 0; }、  这个和上边的情况不同啊，你的这个是变量传递，内存中相当于有两个变量。而我的这个是指针，传到函数后依然是一个指针变量。

向函数传指针之前，问什么要初始化。可不可以在函数里初始化。


Question: 约瑟夫问题

http://www.cnblogs.com/EricYang/archive/2009/09/04/1560478.html 搜到这个文章，写得不错

也许，可以用数学公式，不过自己推导，估计没几个能轻易推导出来

引用 4 楼 u010165006 的回复:约瑟夫问题好像是无法用数学公式来推理的，只能用计算机来模拟。 非也。 维基百科上搜搜看。

约瑟夫问题好像是无法用数学公式来推理的，只能用计算机来模拟。

规律维基百科上搜搜看。

仅供参考：//假设有n个人团团围做，从第1个人开始数数，数到第m个人时候，第m个人出列， //然后继续从1开始数数，数到第m个人退出 #include <stdio.h> #include <conio.h> int i,k,t; int n,m; static char f[1001];//0该座位未出圈,1该座位已出圈 void main() {     while (1) {         printf("Input n m(1000>=n>=m>=1):");         fflush(stdout);         rewind(stdin);         if (2==scanf("%d%d",&n,&m)) {             if (1000>=n && n>=m && m>=1) break;         }     }     t=0;//已出圈总人数     i=1;//座位编号     k=1;//当前要数的数     while (1) {         if (0==f[i]) {             if (m==k) {                 t++;                 f[i]=1;                 printf("%3d ",i);                 if (0==t%10) printf("\n");                 if (t>=n) break;             }             k++;if (k>m) k=1;         }         i++;if (i>n) i=1;     }     cprintf("Press any key ...");     getch(); }

这有啥原理，没意思


Question: [SWU]第四周课后的学生来信以及我的回复

楼上说得很有道理。调试才是真正掌握的关键。 不过，很多程序员太依赖单步调试。作为程序的设计者，应该对程序流程和任何时刻的状态了如指掌。设计断点才是关键。在Linux终端下编程，使用printf比GDB更好用。

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

引用 2 楼 arthuryangsh 的回复:版主所讲甚是精要啊。我们还要继续努力。 厉害 牛牛的老师

偶    fantanstic   baby

版主所讲甚是精要啊。我们还要继续努力。

老师的能力体现在讲课的时候如何忘却知识


Question: 求详细解释代码

引用 1 楼 user-2 的回复:建议： 1. 单步调试。 2. 在代码中间插入打印语句。恩恩好

double mypower(double base, int exp) {     double power = 1;     if (exp < 0)         power = 1/mypower(base, -exp);//递归调用函数      else if (exp > 0)         while(exp-- > 0)//循环次数为exp              power *= base;//循环阶乘      else if(base != 0)          power = 1;     else             power = 1/base;//0的0次幂应是一个无意义数     return power; }  递归而已。。

建议： 1. 单步调试。 2. 在代码中间插入打印语句。


Question: 一个关于C语言宏的问题

dll 导出函数名的那些事 关键字：　VC++ 　DLL  导出函数　 经常使用VC6的Dependency查看DLL导出函数的名字，会发现有DLL导出函数的名字有时大不相同，导致不同的原因大多是和编译DLL时候指定DLL导出函数的界定符有关系。 VC++支持两种语言：即C/C++，这也是造成DLL导出函数差异的根源 我们用VS2008新建个DLL工程，工程名为"TestDLL" 把默认的源文件后缀 .CPP改为.C（C文件） 输入测试代码如下： 01 int _stdcall MyFunction(int iVariant) 02 { 03 return 0; 04 } 为了导出上面这个函数，我们有以下几个方法： 1. 使用传统的模块定义文件 (.def) 新建一个 后缀为.def的文本文件(这里建一个TestDll.Def)，文件内容为： LIBRARY TestDll EXPORTS MyFunction 在 Link 时指定输入依赖文件：/DEF:"TestDll.Def" 2. Visual C++ 提供的方便方法 在01行的int 前加入 __declspec(dllexport) 关键字 通过以上两种方法，我们就可以导出MyFunction函数。 我们用Dependency查看导出的函数： 第一种方法导出的函数为： MyFunction 第二种方法导出的函数为： _MyFunction@4 __stdcall会使导出函数名字前面加一个下划线，后面加一个@再加上参数的字节数，比如_MyFunction@4的参数（int iVariant）就是4个字节 __fastcall与 __stdcall类似，不过前面没有下划线，而是一个@，比如@MyFunction@4 __cdecl则是始函数名。 小结：如果要导出C文件中的函数，并且不让编译器改动函数名，用def文件导出函数。 下面我们来看一下C++文件 我们用VS2008新建个DLL工程，工程名为"TestDLL" 默认的源文件后缀为 .CPP （即C++文件）。 输入测试代码如下： 01 int _stdcall MyFunction(int iVariant) 02 { 03 return 0; 04 } 为了导出上面这个函数，我们有以下几个方法： 3. 使用传统的模块定义文件 (.def) 新建一个 后缀为.def的文本文件(这里建一个TestDll.Def)，文件内容为： LIBRARY TestDll EXPORTS MyFunction 在 Link 时指定输入依赖文件：/DEF:"TestDll.Def" 4. Visual C++ 提供的方便方法 在01行的int 前加入 __declspec(dllexport) 关键字 通过以上两种方法，我们就可以导出MyFunction函数。 我们用Dependency查看导出的函数： 第一种方法导出的函数为： MyFunction 第二种方法导出的函数为： ?MyFunction@@YGHH@Z 可以看到 第二种方法得到的 导出函数名 并不是我们想要的，如果在exe中用显示方法（LoadLibrary、GetProcAddress）调用 MyFunction 肯定会失败。 但是用引入库(*.LIB)的方式调用，则编译器自动处理转换函数名，所以总是没有问题。 解决这个问题的方法是： 用VC 提供的预处理指示符 "#pragma" 来指定链接选项。 如下： #pragma comment(linker, "/EXPORT:MyFunction=?MyFunction@@YGHH@Z") 这时，就会发现导出的函数名字表中已经有了我们想要的MyFunction。但我们发现原来的那个 ?MyFunction@@YGHH@Z 函数还在，这时就可以把 __declspec() 修饰去掉，只需要 pragma 指令即可。 而且还可以使如下形式： #pragma comment(linker, "/EXPORT:MyFunction=_MyFunction@4,PRIVATE") PRIVATE 的作用与其在 def 文件中的作用一样。更多的#pragram请查看MSDN。 小结：如果要导出C++文件中的函数，并且不让编译器改动函数名，用def文件导出函数。 同时可以用#pragma指令（C 中也可以用）。 总结： C++编译器在生成DLL时，会对导出的函数进行名字改编，并且不同的编译器使用的改编规则不一样，因此改编后的名字也是不同的（一般涉及到C++ 中的重载等）。 如果利用不同编译器分别生成DLL和访问DLL的exe程序，后者在访问该DLL的导出函数时就会出现问题。如上例中函数MyFunction在C++编译器改编后的名字是?MyFunction@@YGHH@Z。我们希望编译后的名字不发生改变，这里有几种方法。 第一种方法是通过一个称为模块定义文件DEF来解决。 LIBRARY TestDll EXPORTS MyFunction LIBRARY 用来指定动态链接库内部名称。该名称与生成的动态链接库名一定要匹配，这句代码不是必须的。 EXPORTS说明了DLL将要导出的函数，以及为这些导出函数指定的符号名。 第二种是定义导出函数时加上限定符：extern "C" 如：#define DLLEXPORT_API extern "C" _declspec(dllexport) 但extern "C"只解决了C和C++语方之间调用的问题(extern "C" 是告诉编译器，让它按C的方式编译)，它只能用于导出全局函数这种情况 而不能导出一个类的成员函数。 同时如果导出函数的调用约定发生改变，即使使用extern "C"，编译后的函数名还是会发生改变。例如上面我们加入_stdcall关键字说明调用约定（标准调用约定，也就是WINAPI调用约定）。 #define DLLEXPORT_API extern "C" _declspec(dllexport) 01 DLLEXPORT_API int _stdcall MyFunction(int iVariant) 02 { 03 return 0; 04 } 编译后函数名MyFunction改编成了_MyFunction@4 通过第一种方法模块定义文件的方式DLL编译后导出函数名不会发生改变。 DLL(动态库)导出函数名乱码含义 C++编译时函数名修饰约定规则：   __stdcall调用约定：   1、以"?"标识函数名的开始，后跟函数名；    2、函数名后面以"@@YG"标识参数表的开始，后跟参数表；    3、参数表以代号表示：   X--void   D--char   E--unsigned char   F--short   H--int   I--unsigned int   J--long   K--unsigned long   M--float   N--double   _N--bool   ....   PA--表示指针，后面的代号表明指针类型，如果相同类型的指针连续出现，以"0"代替，一个"0"代表一次重复；   4、参数表的第一项为该函数的返回值类型，其后依次为参数的数据类型,指针标识在其所指数据类型前；    5、参数表后以"@Z"标识整个名字的结束，如果该函数无参数，则以"Z"标识结束。   其格式为"?functionname@@YG*****@Z"或"?functionname@@YG*XZ"，例如                       int Test1(char *var1, unsigned long)-----"?Test1@@YGHPADK@Z"                      void Test2()-----"?Test2@@YGXXZ"    __cdecl调用约定：   规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YA"。   __fastcall调用约定：   规则同上面的_stdcall调用约定，只是参数表的开始标识由上面的"@@YG"变为"@@YI"。   如果要用DEF文件输出一个"C++"类，则把要输出的数据和成员的修饰名都写入.def模块定义文件   所以...   通过def文件来导出C++类是很麻烦的,并且这个修饰名是不可避免的

链接函数规则 如果是c++就按照c++方式链接， c就按照c的方式。  因为函数在编译后，函数名称会由于语言的差异，而产生的链接名称不同。

1. extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后，会指示编译器这部分代码按C语言的进行编译，而不是C++的。由于C++支持函数重载，因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中，而不仅仅是函数名；而C语言并不支持函数重载，因此编译C语言代码的函数时不会带上函数的参数类型，一般之包括函数名。 2. 表示在定义了宏__cplusplus的情况下使用extern “C”。

链接指示extern"C"  说明这是一个C函数,如果用C++调用该函数(即定义了__cplusplus)就用链接指示extern"C"指明要用C++的方式生成代码, 如果不是用C++(即没有定义__cplusplus)就不要   extern"C"{}   (即从#if直接跳到#endif).


Question: 为什么两个搜索LocItem1， LocItem2的返回地址p都是相同的啊？

#include <stdio.h> #include<malloc.h> typedef int elemtype; typedef struct node {   elemtype data;   struct node *next;//为什么是指针域？ }linklist;   linklist *Creatlist(void){ linklist*L; //改  linklist *Creatlist(linklist*L){   L=(linklist*)malloc(sizeof(linklist));   L->next=NULL;   return L; }   int Judge(linklist *L){   if(L->next==NULL)   {     printf("Creatlist is success.\n");   }   else     printf("Creatlist is fail.\n");   return 0; }  int Input(linklist *L,int n){   int i=1,x;   linklist *p,*r;   r=L;   if(L->next==NULL)   {     for(i=1;i<=n;i++)     {       printf("Input data %d:",i);       scanf("%d",&x);       p=(linklist*)malloc(sizeof(linklist));       p->data=x;       p->next=NULL;       r->next=p;       r=r->next;     }    }   else     printf("Input is fail.\n");   return 0; }  linklist *LocItem1(linklist *L,int n,int i){ //改  int LocItem1(linklist *L,int n,int i){   linklist *q,*p;   int j=0;   if(L->next==NULL)   {     printf("The linklist is empty\n");     return NULL;   }   else if(i>n)   {     printf("i>n is beyound\n");     return NULL;   }   else   {     q=L;     p=L->next;     while(p!=NULL&&j<i)     {       q=p;       p=p->next;       j++;     }   }   if(p==NULL)   {     printf("The node %d is not exist\n",i);     return NULL;   }   else     return p; }  linklist *LocItem2(linklist *L,int n,int item){//改  int LocItem2(linklist *L,int n,int item){   linklist *p,*q;   if(L->next==NULL)   {     printf("The linklist is empty\n");     return NULL;   }   else   {     q=L;     p=L->next;     while(p!=NULL)     {       if(p->data!=item)       {         q=p;         p=p->next;       }       else         break;     }   }   if(p==NULL)   {     printf("The node %d is not exist\n",item);     return NULL;   }   else     return p; } int main() {   int n,i,item;   long int k;   linklist *L;   L=Creatlist();//改  L=Creatlist(L);   Judge(L);   printf("Input nodes :");   scanf("%d",&n);   Input(L,n);   printf("Input i:");   scanf("%d",&i);   k=(long int)LocItem1(L,n,i); //改  k=LocItem1(L,n,i);   printf("The i %d address is %ld\n",i,k);   printf("Input item:");   scanf("%d",&item);   k=(long int)LocItem2(L,n,item);//改  k=LocItem2(L,n,item);   printf("The item %d address is %ld\n",item,k);   return 0; }

1.为什么是指针，建议看看链表的定义 2.两个函数返回相同的地址，是不是你输入的比较巧合。上运行的结果看下


Question: 函数中形参的引用和不引用的区别？

引用和不引用？？ 啥意思，引用参数，非引用参数之间的区别？？  还是，只有声明，函数实现的时候，没有使用；和声明的参数都用到了之间的区别？？  1） 前者，引用参数，非引用参数？？ 是地址传递（引用传递），和值传递的区别。  2）后者，只有声明，函数实现的时候，没有使用 不需要使用的数据，可以不写形式参数的名字。  有了名字，没有使用，会有警告产生。  多余的警告或者错误信息，会干扰调试的思路。。有时候要求必须去掉多余的警告。

不用引用将是按值传递，按值传递会（在函数调用堆栈上）产生一份实参值的副本，因此在被调函数中不会对原始数据造成任何影响，因为修改的是副本，而不是原始数据。  用引用将是按引用传递，按引用传递使得被调函数可以直接访问原始数据，在被调函数中修改的数据是原始数据。

一般形参使用const引用，防止参数拷贝带来的性能损耗。

拷贝和不拷贝  不引用会产生不必要的拷贝，而且在函数内的修改不会影响外部的实参，比如一个swap 引用会避免拷贝，但内部的修改，会直接影响外部的实参。如果你的确不想修改外部的值，请用const引用，避免不小心修改了。  一般来说函数的参数只要非内部类型：int char等等，都应该用引用，避免不必要的拷贝。

引用传指针；非引用传值，如果形成的size足够大，栈会爆掉。

引用效率高。

形参引不引用就是有没有副本的问题。如果是引用，那么实际上函数里边的参数就是调用函数时传的那个实参，如果不是引用，一般都是复制一个实参的内容给函数内的那个形参（两者值相同，但不是同一个对象）


Question: 【ＳＷＵ】　　求助

引用 1 楼 user-1 的回复:h=s/m;   s=1;m=1;   printf("%d ",h); 这样增加两个语句应该行了     我已经明白了，不过还是谢谢。


Question: 输入输出的一个函数运行出问题

要确保目录下有你输入的那个文件

引用 6 楼 devilplus 的回复:if(fp = NULL) 改为 if(fp == NULL)  这个正解,我调试了一下，也发现不能进入到 printf("Failed to open file. Bye\n"); 		exit(1); 里面去。

if(fp = NULL) 改为 if(fp == NULL)

引用 1 楼 richyhuang 的回复:怎么个报错法，报什么错误，有图么   我就在这个执行文件的目录下，我建立一个TXT格式的，但是还是报错！

[quote=引用 楼主 ly114kuang 的回复:] # include <stdio.h> # include <stdlib.h>  int main() { 	int ch; 	FILE * fp; 	char fname[50];  	printf("Enter the name of the file: "); 	scanf("%s", fname);//执行到这句时，当我输入一个文件名的时候，文件名我是随便打，直接报错！ 	fp = fopen(fname, "r"); 	if(fp = NULL) 	{ 		printf("Failed to open file. Bye\n"); 		exit(1); 	}

文件不存在的时候，fopen失败，自然会报错

怎么个报错法，报什么错误，有图么


Question: 编写了.h和.c文件，准备生成SO文件报错如下：

是没有引入#include <stdbool.h>  引用 4 楼 tuzhutuzhu 的回复:[quote=引用 3 楼 lgmsyy 的回复:] [quote=引用 1 楼 tuzhutuzhu 的回复:] DETECTION_STRUCT *candi-->struct DETECTION_STRUCT *candi  int testFromBuffer(int imgSize, struct DETECTION_STRUCT *candi);这个更改没问题了，但是我又加入一个布尔类型，怎么还报之前的错误呢  int testFromBuffer(int imgSize, struct DETECTION_STRUCT *candi,bool flag);[/quote] 代码跟编译报的错贴上来看看[/quote]

引用 3 楼 lgmsyy 的回复:[quote=引用 1 楼 tuzhutuzhu 的回复:] DETECTION_STRUCT *candi-->struct DETECTION_STRUCT *candi  int testFromBuffer(int imgSize, struct DETECTION_STRUCT *candi);这个更改没问题了，但是我又加入一个布尔类型，怎么还报之前的错误呢  int testFromBuffer(int imgSize, struct DETECTION_STRUCT *candi,bool flag);[/quote] 代码跟编译报的错贴上来看看

引用 1 楼 tuzhutuzhu 的回复:DETECTION_STRUCT *candi-->struct DETECTION_STRUCT *candi  int testFromBuffer(int imgSize, struct DETECTION_STRUCT *candi);这个更改没问题了，但是我又加入一个布尔类型，怎么还报之前的错误呢  int testFromBuffer(int imgSize, struct DETECTION_STRUCT *candi,bool flag);

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


Question: atoi函数，将字符串转换为相应的整型数，看不懂啊~

把数值带进代码公式 里, 你就看懂了

请点击上方结贴，谢谢

感谢，醍醐灌顶~最近在学ios，但想先打打c语言的基础~

引用 2 楼 u014082409 的回复:为什么说只有(s[i]-'0')才能将将ascil码，直接的s[i]也表示字符常量，不能转换为ascil码吗？还有，那个高位转换该如何理解？ 比如你想将“123”转换成123，for循环中第一个转换的是‘1’，这就是所谓的从高位开始 ‘1’是一个char的字符，它的值是‘1’的ascii码。想转换成1，需要s[i]-'0'。这个你看下ascii码表就知道了

for(i = 0; s[ i ] >= '0' && s[i] <= ' 9 ';  ++i)               n = 10  * n + (s[i] - '0'); 这个是从高位开始转换，s[ i ] >= '0' && s[i] <= ' 9 '表示字符的ascii值在‘0’-‘9’之间，也就是说是数字。否则不转换。 n = 10  * n + (s[i] - '0');中： s[i] - '0'，才能将ascii码转换成数字。10*n是将前一次的计算结果进位。


Question: 貌似数组越界问题，求大神们帮忙指明一下应该怎么改

复制有意思吗？只为了排名？

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

hash[101]   输入一个x = 101或者更大 不久越界了？  这段程序不知道楼主想干嘛

判断是否越界访问，可以在数组的最后一个元素之后对应的地址处设置数据读写断点。如果该地址对应其它变量干扰判断，可将数组多声明一个元素，并设置数据读写断点在该多出元素对应的地址上。 #include <time.h> #include <stdlib.h> #include <windows.h> int main() {     int a,b[11];//本来是b[10]，为判断哪句越界，故意声明为b[11]      srand((unsigned int)time(NULL));//按两次F11，等黄色右箭头指向本行时，调试、新建断点、新建数据断点，地址：&b[10]，字节计数：4，确定。     while (1) {//按F5，会停在下面某句，此时a的值为10，b[10]已经被修改为对应0..4之一。         b[(a=rand()%11)]=0;         Sleep(100);         b[(a=rand()%11)]=1;         Sleep(100);         b[(a=rand()%11)]=2;         Sleep(100);         b[(a=rand()%11)]=3;         Sleep(100);         b[(a=rand()%11)]=4;         Sleep(100);     }     return 0; }

引用 楼主 u013169758 的回复:#include <stdio.h> #include <stdlib.h>  int main(){ 	int i; 	int count; 	  	while (scanf("%d", &count) != EOF&&count!=0){ 		int hash[101] = { 0 }; 		 		for (i = 0; i < count; i++){ 			 int x; 			scanf("&d", &x); 			hash[x] ++; 		} 		 int x; 		scanf("%d", &x); 		printf("%d\n", hash[x]);  	} 	return 0; }  int x; scanf("&d", &x); hash[x] ++; 有两个问题，第一个scanf("%d",&x); 第二个问题,hash大小是101，所以输入x如果超过100，那就越界了。 修改为如下： int x; scanf("%d",&x); hash[x%101]++;

L14: scanf("&d", &x) --> scanf("%d", &x)

貌似是hash[x]++那里冲突，应该怎么改啊，求指导

count should not exceed 100

引用 3 楼 neustar1 的回复:[quote=引用 楼主 u013169758 的回复:] #include <stdio.h> #include <stdlib.h>  int main(){ 	int i; 	int count; 	  	while (scanf("%d", &count) != EOF&&count!=0){ 		int hash[101] = { 0 }; 		 		for (i = 0; i < count; i++){ 			 int x; 			scanf("&d", &x); 			hash[x] ++; 		} 		 int x; 		scanf("%d", &x); 		printf("%d\n", hash[x]);  	} 	return 0; }  int x; scanf("&d", &x); hash[x] ++; 有两个问题，第一个scanf("%d",&x); 第二个问题,hash大小是101，所以输入x如果超过100，那就越界了。 修改为如下： int x; scanf("%d",&x); hash[x%101]++; [/quote] 非常谢谢你，真的很感谢！


Question: C fnmatch函数的问题?

sprintf(dirname,"%s",lookup(filedir,filename)); printf("%s",dirname);  sprintf那个是干嘛的？直接lookup就好了啊。 lookup没有返回文件名字，但它已经完成了输出功能了

把33行去掉就行了，再说楼主在root帐号下编程可不是个好习惯啊

直接函数 lookup(filedir,filename)); 就不会打印出返回0

sprintf(dirname,"%s",lookup(filedir,filename)); printf("%s",dirname);  lookup返回的是0，相当于null，所以你最后打印的dirname是(null)


Question: 编程实现10进制转27进制

引用 1 楼 user-7 的回复:没明白你所谓的27进制到底是什么意思，27位分别是什么？ 引用 3 楼 xiaohuh421 的回复:这都是因为你没有表示0的数 引用 4 楼 majia2011 的回复:没有0？怎么表示27？  这设计本身就错了 引用 6 楼 PDD123 的回复:没有表示0的数的话，你不可能算对的。  。可能是我表达不清楚吧。看8楼：    引用 8 楼 dbzhang800 的回复:比如Excel的列，就是用 A~Z 这样的26进制表示的（只要不和其他进制不转换，就和其他其他进制的符号没任何关系，和0也没有任何关系，它本身最小的数就是 A）。  A B C D ....  你可以想象，如何把它转成10进制数呢？这就需要有个对应关系了：  0 1 2 3 ... 1000 ...  还是  1 2 3 4 ...  1001 ...  两种方式都有人在用。  就是表格里的列~

_ltoa, _ltow Convert a long integer to a string.  char *_ltoa( long value, char *string, int radix );  wchar_t *_ltow( long value, wchar_t *string, int radix );  Routine Required Header Compatibility  _ltoa <stdlib.h> Win 95, Win NT  _ltow <stdlib.h> Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns a pointer to string. There is no error return.  Parameters  value  Number to be converted  string  String result  radix  Base of value  Remarks  The _ltoa function converts the digits of value to a null-terminated character string and stores the result (up to 33 bytes) in string. The radix argument specifies the base of value, which must be in the range 2 – 36. If radix equals 10 and value is negative, the first character of the stored string is the minus sign (–). _ltow is a wide-character version of _ltoa; the second argument and return value of _ltow are wide-character strings. Each of these functions is Microsoft-specific.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _ltot _ltoa _ltoa _ltow    Example  /* ITOA.C: This program converts integers of various  * sizes to strings in various radixes.  */  #include <stdlib.h> #include <stdio.h>  void main( void ) {    char buffer[20];    int  i = 3445;    long l = -344115L;    unsigned long ul = 1234567890UL;     _itoa( i, buffer, 10 );    printf( "String of integer %d (radix 10): %s\n", i, buffer );    _itoa( i, buffer, 16 );    printf( "String of integer %d (radix 16): 0x%s\n", i, buffer );    _itoa( i, buffer, 2  );    printf( "String of integer %d (radix 2): %s\n", i, buffer );     _ltoa( l, buffer, 16 );    printf( "String of long int %ld (radix 16): 0x%s\n", l,                                                      buffer );     _ultoa( ul, buffer, 16 );    printf( "String of unsigned long %lu (radix 16): 0x%s\n", ul,                                                     buffer ); }   Output  String of integer 3445 (radix 10): 3445 String of integer 3445 (radix 16): 0xd75 String of integer 3445 (radix 2): 110101110101 String of long int -344115 (radix 16): 0xfffabfcd String of unsigned long 1234567890 (radix 16): 0x499602d2   Data Conversion Routines  See Also   _itoa, _ultoa

”常规整数“ ==> "楼主26进制" ： 先减 1， 而后常规变换。   ”楼主26进制“ ==> "常规整数"： 先常规变换，而后加 1

没有表示0的数的话，你不可能算对的。

楼主自己想复杂了，这就是一个"标准的" 26 进制数： A~Z  无非是，”和其他数制转换时“，习惯上我们以0开始，他这儿以 1开始罢了。

没有0？怎么表示27？  这设计本身就错了

这都是因为你没有表示0的数

因为你后面还加了一个'A'，‘A'代表1，后面加1了，前面当然要减1，换种思路，把10进制转换成10进制（A表示1，B表示2...I表示9），就比较好理解了 num[k++] = (sum - 1) % 10 + 'A'; sum = (sum - 1) / 10;

没明白你所谓的27进制到底是什么意思，27位分别是什么？

(sum - 1) % 26 + 'A' 如果不减1 公式就是这样的  sum%26 + 'A'  这时你想表达'Z' 即26.  这时你输入 26  那么就有  26%26 +'A'  = 'A'  这就不符合你的要求了.  减1就变成:   (26-1)%26+'A' = 25%26+'A' = 'Z' 刚好是你所想要的结果.  其它数据也是一样, 你自己算一下就知道了.     归根结底都是因为你的进制中没有表示0的数. A-Z  26个字母表示26进制, 取值范围也应该是 0-25, 而不应该是 1-26, 所以8楼说的是错的,  楼主你的进制也是错误的.  就像10进制也样, 你看到10进制中有10表示一位吗?  没有吧.  只能是0-9.  0是一个伟大的发明, 不能舍弃它.

所以你问的(sum - 1)为什么减1, 答案就已经有了撒,  本来正常的26进制应该是0对应A的.  因为你"26"进制中没有可以表示0的字符, 从1开始的, 所以只好减1, 让其能从0开始. 即 让1对应A.


Question: 大家以后写完程序之后一定要记得换行啊！

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

赞一个

你还是写作业阶段，输出随便写写就行了。  等你水平够了，写得的代码经常要拿给别人用的时候，输出，注释，接口文档，就会越来越标准了，呵呵呵

顶一个！  这个其实可以通过单步调试，很容易发现的。

越是简单的错误越是容易犯，找错误的时候还总是想复杂了

我记得了

我知道你是来送分的 ！

有道理，顶下周楼，

那lz以后不要再犯这样的错误了啊

用调试不就行了，打个断点

顶！！！！！！！！！！！！！！！

这是非常常见的错误，因此，我们在输出时，要记得写那个该死的\n，免得和后面的提示符混在一起了，那会看起来非常不爽的。


Question: 原来编译器也会说谎的啊

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

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

赵老板不是说要迷信编译器么？

计算机组成原理→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<<-1编译器在编译的时候做了常量折叠，直接替换成了0，而两个变量是在运行是计算的，结果就是-2147483648

楼上好犀利，学习了。

说明编译器里constant folding的结果和x86 cpu的shl指令结果对于负数行为不一样。 因为标准规定是undefined behavior所以他们都没错。你要这么用那是你的问题。


Question: 思考了好久，希望哪位大神可以指点指点，感激不尽！

引用 1 楼 user-10 的回复:还思考很久，丢人  谁都曾经是菜鸟，没有什么丢人的。

不要使用 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;  //... } 类似的例子还可以举很多。

LZ主要是没有搞明白while循环需要判定条件的

#include <stdio.h> int main(void) { 	int sno		= 0; 	int i = 5;  	while(i --) 	{ 		int score; 	                     scanf("%d",&score); 		if(score >= 60 && score <= 85) 			sno++; 	} 	printf("%d",sno); 	return 0; }

不用这么麻烦吧  #include <stdio.h> int main(void) { 	int sno		= 0; 	int i = 0; 	while(i < 5) 	{ 		int score; 		scanf("%d",&score); 		if(score >= 60 && score <= 85) 			sno += 1; 		i += 1; 	} 	printf("%d",sno); 	return 0; }

scanf中最好不要加非输入控制符（这里指逗号），关于scanf，lz可以看看这个——http://blog.csdn.net/u012421456/article/details/18501309 关于scanf的事已经在这里见过不少次了

#include <stdio.h> void main () { 	int score[5], sum = 0, i = 0; 	 	scanf("%d %d %d %d %d", &score[0], &score[1], &score[2], &score[3], &score[4]); 	while (i < 5) 	{ 		if(score[i]>=60 && score[i]<=85) 		{ 			sum += 1; 		} 		i++; 	} 	printf("sum = %d\n", sum); 	 }  这样才行

int i = 5; while( i-- ){  }

lz啊，你。。。唉 循环里根本没有改变条件的变量，怎么能结束循环啊 一楼代码稍有点儿问题，待会儿我改改啊

你输入的内容又没赋值给score这个变量，拿score来判断肯定是错的。再说你的循环条件也不对

还思考很久，丢人  #include <stdio.h> void main () { int score[5], sum=0,i=0;  scanf("%d,%d,%d,%d,%d",&score[0],&score[1],&score[2],&score[3],&score[4]); while (i<5) {     if(score[i]>=60&&score[i]<=85)             sum+=1;}     i++; } printf("sum=%d",sum);  }


Question: 大神们求教，用C中的数组怎么实现两个二进制数相乘，提前谢过。，。。

这个程序是c还是c++？

仅供参考#include <iostream> #include <string> using namespace std; inline int compare(string str1,string str2) {//相等返回0，大于返回1，小于返回-1          if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数     else if (str1.size()<str2.size()) return -1;     else                              return str1.compare(str2); //若长度相等，则头到尾按位比较 } string SUB_INT(string str1,string str2); string ADD_INT(string str1,string str2) {//高精度加法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         if (str2[0]=='-') {             sign=-1;             str=ADD_INT(str1.erase(0,1),str2.erase(0,1));         } else {             str=SUB_INT(str2,str1.erase(0,1));         }     } else {         if (str2[0]=='-') {             str=SUB_INT(str1,str2.erase(0,1));         } else { //把两个整数对齐，短整数前面加0补齐             string::size_type L1,L2;             int i;             L1=str1.size();             L2=str2.size();             if (L1<L2) {                 for (i=1;i<=L2-L1;i++) str1="0"+str1;             } else {                 for (i=1;i<=L1-L2;i++) str2="0"+str2;             }             int int1=0,int2=0; //int2 记录进位             for (i=str1.size()-1;i>=0;i--) {                 int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;                 int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;                 str=char(int1+'0')+str;             }             if (int2!=0) str=char(int2+'0')+str;         }     }     //运算后处理符号位     if ((sign==-1)&&(str[0]!='0')) str="-"+str;     return str; } string SUB_INT(string str1,string str2) {//高精度减法     int sign=1; //sign 为符号位     string str;     int i,j;     if (str2[0]=='-') {         str=ADD_INT(str1,str2.erase(0,1));     } else {         int res=compare(str1,str2);         if (res==0) return "0";         if (res<0) {             sign=-1;             string temp =str1;             str1=str2;             str2=temp;         }         string::size_type tempint;         tempint=str1.size()-str2.size();         for (i=str2.size()-1;i>=0;i--) {             if (str1[i+tempint]<str2[i]) {                 j=1;                 while (1) {//zhao4zhong1添加                     if (str1[i+tempint-j]=='0') {                         str1[i+tempint-j]='9';                         j++;                     } else {                         str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);                         break;                     }                 }                 str=char(str1[i+tempint]-str2[i]+':')+str;             } else {                 str=char(str1[i+tempint]-str2[i]+'0')+str;             }         }         for (i=tempint-1;i>=0;i--) str=str1[i]+str;     }     //去除结果中多余的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str ="-"+str;     return str; } string MUL_INT(string str1,string str2) {//高精度乘法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         sign*=-1;         str1 =str1.erase(0,1);     }     if (str2[0]=='-') {         sign*=-1;         str2 =str2.erase(0,1);     }     int i,j;     string::size_type L1,L2;     L1=str1.size();     L2=str2.size();     for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式         string tempstr;         int int1=0,int2=0,int3=int(str2[i])-'0';         if (int3!=0) {             for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;             for (j=L1-1;j>=0;j--) {                 int1=(int3*(int(str1[j])-'0')+int2)%10;                 int2=(int3*(int(str1[j])-'0')+int2)/10;                 tempstr=char(int1+'0')+tempstr;             }             if (int2!=0) tempstr=char(int2+'0')+tempstr;         }         str=ADD_INT(str,tempstr);     }     //去除结果中的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str="-"+str;     return str; } string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数     string quotient,residue; //定义商和余数     int sign1=1,sign2=1;     if (str2 == "0") {  //判断除数是否为0         quotient= "ERROR!";         residue = "ERROR!";         if (flag==1) return quotient;         else         return residue ;     }     if (str1=="0") { //判断被除数是否为0         quotient="0";         residue ="0";     }     if (str1[0]=='-') {         str1   = str1.erase(0,1);         sign1 *= -1;         sign2  = -1;     }     if (str2[0]=='-') {         str2   = str2.erase(0,1);         sign1 *= -1;     }     int res=compare(str1,str2);     if (res<0) {         quotient="0";         residue =str1;     } else if (res == 0) {         quotient="1";         residue ="0";     } else {         string::size_type L1,L2;         L1=str1.size();         L2=str2.size();         string tempstr;         tempstr.append(str1,0,L2-1);         for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式             tempstr=tempstr+str1[i];             tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加             if (tempstr.empty()) tempstr="0";//zhao4zhong1添加             for (char ch='9';ch>='0';ch--) { //试商                 string str;                 str=str+ch;                 if (compare(MUL_INT(str2,str),tempstr)<=0) {                     quotient=quotient+ch;                     tempstr =SUB_INT(tempstr,MUL_INT(str2,str));                     break;                 }             }         }         residue=tempstr;     }     //去除结果中的前导0     quotient.erase(0,quotient.find_first_not_of('0'));     if (quotient.empty()) quotient="0";     if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;     if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;     if (flag==1) return quotient;     else         return residue ; } string DIV_INT(string str1,string str2) {//高精度除法,返回商     return DIVIDE_INT(str1,str2,1); } string MOD_INT(string str1,string str2) {//高精度除法,返回余数     return DIVIDE_INT(str1,str2,0); } int main() {     char ch;     string s1,s2,res;      while (cin>>s1>>ch>>s2) {         switch (ch) {             case '+':res=ADD_INT(s1,s2);break;             case '-':res=SUB_INT(s1,s2);break;             case '*':res=MUL_INT(s1,s2);break;             case '/':res=DIV_INT(s1,s2);break;             case '%':res=MOD_INT(s1,s2);break;             default :                   break;         }         cout<<res<<endl;     }     return(0); }

搜一下大数乘法


Question: 图像处理(matlab)

小波变换算法。

你发错板块了


Question: 高分相赠 正确答案50

引用 3 楼 JiMoKuangXiangQu 的回复:引用 2 楼 molebin 的回复:[quote=引用 1 楼 vipda 的回复:] 看着太费眼。 我也不想条件有限啊 建议LZ还是用手敲上去，一方面熟悉代码，另一方面方便大家看。[/quote]  #include "stdafx.h" #include <stdio.h> #include <string.h>  int add(int x,int y) {return x+y;} int sub(int x,int y) {return x-y;} int mul(int x,int y) {return x*y;} int div(int x,int y) {return x/y;}  int (*func[]) (int x,int y)={add,sub,mul,div}; int num,curch;  char chtbl[]="+-*/()"; char corch[]="+-*/()=0123456789";  int getach() { 	unsigned int i; 	while(true) 	{ 		curch=getchar(); 		if(curch==00f)return -1; 		for(i=0;corch[i]&&curch!=corch[i];i++); 		if(i<strlen(corch))break; 		} 	return curch; } int getid(){ 	int i; 	if(curch>='0'&&curch<='9') 	{ 		for(num=0;curch>='0'&&curch<='9';getach()) 			num= ? 		return -1;  	} 	else 	{http://bbs.csdn.net/topics/390734919?page=1 		for(i=0;chtbl[i];i++) 			if(chtbl[i]==curch)break; 		if(i<=5) getach(); 		return 1; 	} 	}

引用 2 楼 molebin 的回复:引用 1 楼 vipda 的回复:看着太费眼。 我也不想条件有限啊 建议LZ还是用手敲上去，一方面熟悉代码，另一方面方便大家看。

引用 1 楼 vipda 的回复:看着太费眼。 我也不想条件有限啊

看着太费眼。


Question: 老师布置的作业，有没有哪位会啊，要求代码，可以编写出来

提问的艺术——http://bbs.csdn.net/topics/390623576

遇到这种问题，几乎没人会直接回答你的，建议lz自己做，遇到问题了好好想想，想不明白了看书，还不行就谷歌百度，再不行了来论坛，不然，大家怕是不会帮忙的。 不要像这样，直接就把作业往这儿一放，会有几个人有这心思回答啊？

去兼职网站花钱去吧，骚年


Question: 关于指针运用问题，求解惑

引用 4 楼 chybeyond123456789 的回复:数组名是常量，不能对其++ 正解 使用指针时，要注意指针指向的地址是否合法，理解指针的含义。

计算机组成原理→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

数组名是常量，不能对其++

数组名是不能够用于++ 的

修改了 指针的地址呗！

简单的讲，就是语法规定，不能这样干，不能对数组名++。 复杂的讲，去啃一下c标准文档吧。


Question: 神奇的for,他干了什么

程序结束所有io操作都要刷新输出。。恩 谢谢哥哥们的支持 结贴

引用 13 楼 u012564309 的回复:[quote=引用 7 楼 Adol1111 的回复:] [quote=引用 6 楼 u012564309 的回复:]  [quote=引用 1 楼 Automation_dmu 的回复:] printf默认是行缓冲的， 跟for没关系， 你改成printf("pppp\n") 再试试。 引用 4 楼 truelance 的回复:c中打印输出到内存中的缓冲区, 直到碰到回车或者eof才会真正输出到IO接口. 你的打印没加回车就会有这个现象.  话说当年我学编程第一次碰到这个问题时,也折腾了半个小时. 这是再说 如果没有 printf("pppp \n");没有 \n 就不会打印吗  引用 2 楼 vipda 的回复:我运行了一下，是先打印的pppp啊 先打印的是 pppp但是在 for之后 for带来的延迟之后  引用 3 楼 starytx 的回复:你的for里什么也没有，你怎么说pppp打印在了for之后？ for作为延迟使用 延迟 1s pppp的打印应该在1s之前 但实际不是 for要表达的意思类似挂起线程1s 只是从控制台的表面层次  \n 应该是表示换行吧 如果不换行 应该也可以打印  只是for就像是 \r 之后覆盖当前行 循环完毕之后 在从新打印 环境是 gcc -std=c99   我这里实际运行 期望的是 先打印 pppp 过 1s（for带来的延迟） 在打印 no 但实际是 过了1s后 pppp no一起打印 \n可以解决这个情况 但实际pppp一定会打印吧只是 太快了 即便没有\n应该也可以打印吧  那么都可以打印 为什么多了一个 延迟大概 4 5秒的for结果 结果就会不同 printf("pppp \n"); printf("pppp"); 结果是不同的 但 如果去掉for什么也不会看起出来 没有\n 表示 pppp在 for带来的延迟之后 打印  有\n 在for之前 （因为解析为 for会 使用\r 覆盖打印而后从新打印被覆盖的那一行 如果不是举一个反例子）  [/quote] 先理解下C/C++里流和缓冲的概念 printf默认是行缓冲，没有遇到换行符所以内容没有被冲出来。 http://www.cnblogs.com/wonderKK/archive/2012/06/13/2547740.html[/quote]  引用 9 楼 ypzhong 的回复:  摘自UNIX环境高级编程，看第一张图最后一句话。  那么当 printf("pppp");在for延迟之后 才打印是因为 第一次\n在for之后的printf(" \nno"); 因为打印是行缓冲的 直到遇到一个\n才实际打印 那么\n 后的no 为什么会打印 是填满了行缓冲吗 还是编译期会试图在最终的打印后添加一个\n？  [/quote] 那是因为程序结束，所有I/O操作都要刷新，输出。

引用 7 楼 Adol1111 的回复:[quote=引用 6 楼 u012564309 的回复:]  [quote=引用 1 楼 Automation_dmu 的回复:] printf默认是行缓冲的， 跟for没关系， 你改成printf("pppp\n") 再试试。 引用 4 楼 truelance 的回复:c中打印输出到内存中的缓冲区, 直到碰到回车或者eof才会真正输出到IO接口. 你的打印没加回车就会有这个现象.  话说当年我学编程第一次碰到这个问题时,也折腾了半个小时. 这是再说 如果没有 printf("pppp \n");没有 \n 就不会打印吗  引用 2 楼 vipda 的回复:我运行了一下，是先打印的pppp啊 先打印的是 pppp但是在 for之后 for带来的延迟之后  引用 3 楼 starytx 的回复:你的for里什么也没有，你怎么说pppp打印在了for之后？ for作为延迟使用 延迟 1s pppp的打印应该在1s之前 但实际不是 for要表达的意思类似挂起线程1s 只是从控制台的表面层次  \n 应该是表示换行吧 如果不换行 应该也可以打印  只是for就像是 \r 之后覆盖当前行 循环完毕之后 在从新打印 环境是 gcc -std=c99   我这里实际运行 期望的是 先打印 pppp 过 1s（for带来的延迟） 在打印 no 但实际是 过了1s后 pppp no一起打印 \n可以解决这个情况 但实际pppp一定会打印吧只是 太快了 即便没有\n应该也可以打印吧  那么都可以打印 为什么多了一个 延迟大概 4 5秒的for结果 结果就会不同 printf("pppp \n"); printf("pppp"); 结果是不同的 但 如果去掉for什么也不会看起出来 没有\n 表示 pppp在 for带来的延迟之后 打印  有\n 在for之前 （因为解析为 for会 使用\r 覆盖打印而后从新打印被覆盖的那一行 如果不是举一个反例子）  [/quote] 先理解下C/C++里流和缓冲的概念 printf默认是行缓冲，没有遇到换行符所以内容没有被冲出来。 http://www.cnblogs.com/wonderKK/archive/2012/06/13/2547740.html[/quote]  引用 9 楼 ypzhong 的回复:  摘自UNIX环境高级编程，看第一张图最后一句话。  那么当 printf("pppp");在for延迟之后 才打印是因为 第一次\n在for之后的printf(" \nno"); 因为打印是行缓冲的 直到遇到一个\n才实际打印 那么\n 后的no 为什么会打印 是填满了行缓冲吗 还是编译期会试图在最终的打印后添加一个\n？

引用 6 楼 u012564309 的回复:[quote=引用 1 楼 Automation_dmu 的回复:] printf默认是行缓冲的， 跟for没关系， 你改成printf("pppp\n") 再试试。 引用 4 楼 truelance 的回复:c中打印输出到内存中的缓冲区, 直到碰到回车或者eof才会真正输出到IO接口. 你的打印没加回车就会有这个现象.  话说当年我学编程第一次碰到这个问题时,也折腾了半个小时. 这是再说 如果没有 printf("pppp \n");没有 \n 就不会打印吗  引用 2 楼 vipda 的回复:我运行了一下，是先打印的pppp啊 先打印的是 pppp但是在 for之后 for带来的延迟之后  引用 3 楼 starytx 的回复:你的for里什么也没有，你怎么说pppp打印在了for之后？ for作为延迟使用 延迟 1s pppp的打印应该在1s之前 但实际不是 for要表达的意思类似挂起线程1s 只是从控制台的表面层次  \n 应该是表示换行吧 如果不换行 应该也可以打印  只是for就像是 \r 之后覆盖当前行 循环完毕之后 在从新打印 环境是 gcc -std=c99   我这里实际运行 期望的是 先打印 pppp 过 1s（for带来的延迟） 在打印 no 但实际是 过了1s后 pppp no一起打印 \n可以解决这个情况 但实际pppp一定会打印吧只是 太快了 即便没有\n应该也可以打印吧  那么都可以打印 为什么多了一个 延迟大概 4 5秒的for结果 结果就会不同 printf("pppp \n"); printf("pppp"); 结果是不同的 但 如果去掉for什么也不会看起出来 没有\n 表示 pppp在 for带来的延迟之后 打印  有\n 在for之前 （因为解析为 for会 使用\r 覆盖打印而后从新打印被覆盖的那一行 如果不是举一个反例子）  [/quote] 先理解下C/C++里流和缓冲的概念 printf默认是行缓冲，没有遇到换行符所以内容没有被冲出来。 http://www.cnblogs.com/wonderKK/archive/2012/06/13/2547740.html

引用 1 楼 Automation_dmu 的回复:printf默认是行缓冲的， 跟for没关系， 你改成printf("pppp\n") 再试试。 引用 4 楼 truelance 的回复:c中打印输出到内存中的缓冲区, 直到碰到回车或者eof才会真正输出到IO接口. 你的打印没加回车就会有这个现象.  话说当年我学编程第一次碰到这个问题时,也折腾了半个小时. 这是再说 如果没有 printf("pppp \n");没有 \n 就不会打印吗  引用 2 楼 vipda 的回复:我运行了一下，是先打印的pppp啊 先打印的是 pppp但是在 for之后 for带来的延迟之后  引用 3 楼 starytx 的回复:你的for里什么也没有，你怎么说pppp打印在了for之后？ for作为延迟使用 延迟 1s pppp的打印应该在1s之前 但实际不是 for要表达的意思类似挂起线程1s 只是从控制台的表面层次  \n 应该是表示换行吧 如果不换行 应该也可以打印  只是for就像是 \r 之后覆盖当前行 循环完毕之后 在从新打印 环境是 gcc -std=c99   我这里实际运行 期望的是 先打印 pppp 过 1s（for带来的延迟） 在打印 no 但实际是 过了1s后 pppp no一起打印 \n可以解决这个情况 但实际pppp一定会打印吧只是 太快了 即便没有\n应该也可以打印吧  那么都可以打印 为什么多了一个 延迟大概 4 5秒的for结果 结果就会不同 printf("pppp \n"); printf("pppp"); 结果是不同的 但 如果去掉for什么也不会看起出来 没有\n 表示 pppp在 for带来的延迟之后 打印  有\n 在for之前 （因为解析为 for会 使用\r 覆盖打印而后从新打印被覆盖的那一行 如果不是举一个反例子）

在每个最后不带\n的printf后面加fflush(stdout);

你的for里什么也没有，你怎么说pppp打印在了for之后？

我运行了一下，是先打印的pppp啊

引用 10 楼 mujiok2003 的回复:[quote=引用 1 楼 Automation_dmu 的回复:] printf默认是行缓冲的， 跟for没关系， 你改成printf("pppp\n") 再试试。  The default streams stdin and stdout are fully buffered by default if they are known to not refer to an interactive device.Otherwise, they may either be line buffered or unbuffered by default, depending on the system and library implementation.  The same is true for stderr, which is always either line buffered or unbuffered by default. [/quote]++

引用 楼主 u012564309 的回复:void test() { 		printf("pppp"); 		int soNow=clock(); 		//printf(" \n inset"); 		//for(;clock()-soNow<CLOCKS_PER_SEC;)  		//} 		for(int i=0;i<999999099;i++) { 			 		} 		printf("\nno"); 	} 在 java中  pppp一定会在 for之前  流的顺序就是如此 但是在c 中 for像是 对当前行 做了手脚 那么 printf("pppp \n")；可以在for之前输出打印  结果就是上面的程序 pppp打印在 for之后 请问 哥哥们 这是 怎么回事？  把你的int i换成 volatile int i 我估计那段循环变成 add reg，0x？

引用 1 楼 Automation_dmu 的回复:printf默认是行缓冲的， 跟for没关系， 你改成printf("pppp\n") 再试试。  The default streams stdin and stdout are fully buffered by default if they are known to not refer to an interactive device.Otherwise, they may either be line buffered or unbuffered by default, depending on the system and library implementation.  The same is true for stderr, which is always either line buffered or unbuffered by default.

摘自UNIX环境高级编程，看第一张图最后一句话。

引用 3 楼 starytx 的回复:你的for里什么也没有，你怎么说pppp打印在了for之后？ +1；  lz看看这样，是pppp先输出啊


Question: CreateProcess和子进程退出的相关疑问，求解答

引用 10 楼 u014123498 的回复:你好，我想再问下这方面的东西应该看什么书或者资料，谢谢 MSDN  ，《Windows  核心编程》，《Windows  图形编程》，《Windows  系统编程》  其中 MSDN  ，《Windows  核心编程》应该足够了， 《Windows  图形编程》，《Windows  系统编程》可以作为补充

引用 8 楼 lm_whales 的回复:子进程的主线程，是父进程CreateProcess建立的。 独立的进程的主线程，是Shell建立的。 线程内核数据结构和堆栈空间，是系统创建的，系统直接取回线程的返回值，再结束线程的运行即可。 堆栈不是父进程，而是操作系统创建的。 你好，我想再问下这方面的东西应该看什么书或者资料，谢谢

Windows 线程才是运行单位，进程只是线程的容器。

引用 6 楼 u014123498 的回复:[quote=引用 3 楼 neustar1 的回复:] [quote=引用 2 楼 u014123498 的回复:] [quote=引用 1 楼 neustar1 的回复:] LZ多想了，虽然不同进程的地址空间是不一样的，但是那仅限于用户态。 要知道所有的进程都有一个共享的地址区域，也就是内核所占用的那部分地址空间。 说到这，不知道楼主是否能明白一些呢？  内核态不是高2GB的地址吗？栈段里面出现的地址都是低2GB的啊[/quote] 不是return转到了Kernel中了吗？[/quote] 是不是父进程调用kernel32.dll里的CreateProcess以后会把kernel32.dll也映射到子进程啊[/quote] kernel32.dll就是内核相关的程序啊

引用 3 楼 neustar1 的回复:[quote=引用 2 楼 u014123498 的回复:] [quote=引用 1 楼 neustar1 的回复:] LZ多想了，虽然不同进程的地址空间是不一样的，但是那仅限于用户态。 要知道所有的进程都有一个共享的地址区域，也就是内核所占用的那部分地址空间。 说到这，不知道楼主是否能明白一些呢？  内核态不是高2GB的地址吗？栈段里面出现的地址都是低2GB的啊[/quote] 不是return转到了Kernel中了吗？[/quote] 是不是父进程调用kernel32.dll里的CreateProcess以后会把kernel32.dll也映射到子进程啊

引用 2 楼 u014123498 的回复:[quote=引用 1 楼 neustar1 的回复:] LZ多想了，虽然不同进程的地址空间是不一样的，但是那仅限于用户态。 要知道所有的进程都有一个共享的地址区域，也就是内核所占用的那部分地址空间。 说到这，不知道楼主是否能明白一些呢？  内核态不是高2GB的地址吗？栈段里面出现的地址都是低2GB的啊[/quote] 关键是那个kernel是哪来的，我导入表是空的啊

父进程用CreateProcess创建一个子进程，子进程ret退出的话是返回父进程吧  这好像不是真的。子进程退出就退出了。

引用 2 楼 u014123498 的回复:[quote=引用 1 楼 neustar1 的回复:] LZ多想了，虽然不同进程的地址空间是不一样的，但是那仅限于用户态。 要知道所有的进程都有一个共享的地址区域，也就是内核所占用的那部分地址空间。 说到这，不知道楼主是否能明白一些呢？  内核态不是高2GB的地址吗？栈段里面出现的地址都是低2GB的啊[/quote] 不是return转到了Kernel中了吗？

引用 1 楼 neustar1 的回复:LZ多想了，虽然不同进程的地址空间是不一样的，但是那仅限于用户态。 要知道所有的进程都有一个共享的地址区域，也就是内核所占用的那部分地址空间。 说到这，不知道楼主是否能明白一些呢？  内核态不是高2GB的地址吗？栈段里面出现的地址都是低2GB的啊


Question: 统计X中值为1的二进制位数。

引用 2 楼 u014082409 的回复:这么理解题目是对的，但是感觉这么说不严谨，因为为真为假是逻辑运算符的那个啥的，这个&是位运算符。  if 中为 0 则为假，非 0 都是真

按位右移，判断最后一位是否为1，直到没有1为止。 也可用std::bitset

(x & 1)  就是当x的最后一位是1的时候为真


Question: 关于指针和以为操作的问题（在线等）

已解决，其实是我定义的变量类型问题。

会不会是因为编译器？我用的vs2013写了一个测试：

lz你的第一个怎么还有个等号？ 会不会是因为优先级啊


Question: 我这个二进制转十进制程序怎么10个1可以，11个1就错呢？

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <locale.h> int main() {     int i,v;     char bs[33];     char b[33];     char hs[9];     char h[9];     char s[4];     char *e;  // 十进制整数转二进制串；     i=1024;     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("i=%d,bs=%s\n",i,bs); // 十进制整数转十六进制串；     i=1024;     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("i=%d,hs=%s\n",i,hs); // 十六进制字符串转成十进制数     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     printf("hs=%s,i=%d\n",hs,i); // 二进制字符串转化为十六进制字符串；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     ltoa(i,h,16);     sprintf(hs,"%08s",h);     printf("bs=%s,hs=%s\n",bs,hs); // 二进制字符串转化为十进制数；     strcpy(bs,"00000000000000000000010000000000");     i=strtol(bs,&e,2);     printf("bs=%s,i=%d\n",bs,i); // 十六进制字符串转成二进制串     strcpy(hs,"00000400");     sscanf(hs,"%x",&i);     ltoa(i,b,2);     sprintf(bs,"%032s",b);     printf("hs=%s,bs=%s\n",hs,bs); // ASC\GBK字符串转十六进制串     strcpy(s,"a汉");     i=0;     while (1) {         if (0==s[i]) break;         sprintf(hs+i*2,"%02X",(unsigned char)s[i]);         i++;     }     setlocale(LC_ALL,"chs");     printf("s=%s,hs=%s\n",s,hs); // 十六进制字符串转成汉字（GBK）及字符(ASC)     strcpy(hs,"61BABA");     i=0;     while (1) {         if (1!=sscanf(hs+i*2,"%2x",&v)) break;         s[i]=(char)v;         i++;     }     s[i]=0;     printf("hs=%s,s=%s\n",hs,s);      return 0;  } //i=1024,bs=00000000000000000000010000000000 //i=1024,hs=00000400 //hs=00000400,i=1024 //bs=00000000000000000000010000000000,hs=00000400 //bs=00000000000000000000010000000000,i=1024 //hs=00000400,bs=00000000000000000000010000000000 //s=a汉,hs=61BABA //hs=61BABA,s=a汉

可表示范围的问题

11位已经超出整形的表示范围了.  int 按32位算: 4294967295   已经不能表示11个1了.

参考一下

scanf("%d",&val);这个可以支持16进制，10进制和8进制，但是不支持2进数。

用字符串吧，用long能处理的有效位数只有10位

一楼正解，lz的情况是因为溢出，毕竟你输入的数太大，已经超出范围了。按二楼改了是不行的

可能跟你电脑的long有关，有些电脑的long只能表示十位二进制数，你试试将引用long val,sjz,sum=0;改成long long val,sjz,sum=0;

printf("请输入一个二进制数："); scanf("%d",&val); 你用整形11位肯定溢出了，觉得2进制用字串表示为妥...


Question: 100个16位无符号整形数组的增序函数

参考http://www.cnblogs.com/ForeverJoker/archive/2013/05/25/qsort-sort.html  引用 楼主 Chaos_upc 的回复:如题，求教大神写个函数，用C，JAVA都可以。 然后是对输出结果进行指定输入数值的相应位置查找函数(能再写出这个就更好了)

数组排序？直接用qsort就可以了


Question: C opendir 函数，下查找读取文件名？

fnmatch()的确更合适

多谢了，我用int main(int argc, char *argv[]) {         char *pattern;         DIR *dir;         struct dirent *entry;         int ret;          dir = opendir(argv[2]); //打开指定路径          pattern = argv[1];                        //路径存在         if(dir != NULL)         {                 //逐个获取文件夹中文件             while( (entry = readdir(dir)) != NULL)                 {               ret = fnmatch(pattern, entry->d_name, FNM_PATHNAME|FNM_PERIOD);               if(ret == 0)                      //符合pattern的结构                         {                 printf("%s\n", entry->d_name);               }else if(ret == FNM_NOMATCH){                 continue ;               }else                         {                 printf("error file=%s\n", entry->d_name);                         }                 }          closedir(dir);         } }  也可以使用了

#include <stdio.h> #include <string.h> #include <sys/types.h> #include <dirent.h> #include <sys/stat.h> char filename[256][256]; int len = 0; int trave_dir(char* path, int depth) {     DIR *d;//声明一个句柄     struct dirent *file;//readdir函数的返回值就存放在这个结构体中     struct stat sb;            if(!(d = opendir(path)))     {         printf("error opendir %s!!!\n",path);         return -1;     }     while((file = readdir(d)) != NULL)     {         if(strncmp(file->d_name, "aaaa_", 5) != 0)  // 你需要的前缀             continue;         strcpy(filename[len++], file->d_name);//保存遍历到的文件名     }     closedir(d);     return 0; } int main() {     int depth = 1;     int i;     trave_dir("/usr/keygoe/ini/", depth);     for(i = 0; i < len; i++)     {         printf("%s\t", filename[i]);     }     printf("\n");     return 0; }


Question: 关于C URL正则表达式报错

char url[] = "https?://[\d\-a-zA-Z]+(\.[\d\-a-zA-Z]+)*/?"; 改为 char url[] = "https?://[\da-zA-Z-]+(\.[\da-zA-Z-]+)*/?"; 试试看？

我自己，运行程序出现以下问题：Invalid range end: url :https?://[d-a-zA-Z]+(.[d-a-zA-Z]+)*/?  这个正则表达式在网上验证了可以通过的


Question: 学渣求助   求大神帮忙

引用 3 楼 u012421456 的回复:这是一个课程设计吧。建议lz还是自己做吧，不会了自己想，想不出来可以看书，还不行就谷歌百度，在不行了来论坛问吧，像这样，即使有人帮忙弄出来，也是很难有所收获的 如果lz不想自己做或难度实在太大，最起码也该把原文链接发出来啊我一点儿不会呀

引用 1 楼 u014199915 的回复:求助求助~~~~~~~~~~~~~~ 引用 2 楼 vipda 的回复:i是哪来的？你这代码不全啊，把原文链接发过来h t t p : // wenku.baidu.com/view/a0d6651555270722192ef7d3.html

i是哪来的？你这代码不全啊，把原文链接发过来

求助求助~~~~~~~~~~~~~~


Question: 一个简单c理解

函数指针应用举例： #include <stdio.h> double A[300][100]; double valuex[300]; double valuey[300]; int i; double fun00(double x,double y) {return x  +   y  ;}; double fun01(double x,double y) {return x*x+ 3*y  ;}; double fun02(double x,double y) {return x  + 2*y*x;}; //...  fun03(double x,double y) {return ...+...   ;}; //... //...  fun98(double x,double y) {return ...+...   ;}; double fun99(double x,double y) {return x/2+20*y  ;}; double (*funNN[100])(double,double)={     fun00,     fun01,     fun02, //  fun03, //  ... //  fun98,     fun99, }; int main() {     double x,y;     int f,FN;      for (i=0;i<300;i++) {         valuex[i]=(double)i;         valuey[i]=(double)i;     }     FN=3;     for (i=0;i<300;i++) {          x=valuex[i];          y=valuey[i];          for (f=0;f<FN;f++) A[i][f]=funNN[f](x,y);     }     for (i=0;i<3;i++) {         for (f=0;f<FN;f++) printf("%lg ",A[i][f]);         printf("\n");     }     return 0; } //0 0 0 //2 4 3 //4 10 10

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

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

引用 10 楼 zhao4zhong1 的回复:[quote=引用 9 楼 Bzy_NET 的回复:] [quote=引用 1 楼 zhao4zhong1 的回复:] 定义一个类型标识符mipi_eotp_t 表示类型： 指向一类函数的指针，这类函数的返回值类型为int32_t，这类函数带两个参数，类型分别为uint8_t，uint8_t  //char (*(*x[3])())[5];//x是什么类型的变量? // //分析C语言声明，关键是搞清楚这个变量是个什么东西（函数、指针、数组）， //是函数那么剩下的就是他的参数和返回值， //是指针那剩下部分是说明他指向什么， //是数组剩下的部分就是说明数组的成员是什么类型。 //解析C语言声明规则： //从左侧第一个标识符开始，按照优先级进行结合。*表示是..的指针，const表示只读的，volatile表示可变的，[]表示是数组，()表示是函数。 // //x和[3]结合说明是一个大小为3的数组，该数组指向了一个指针，该指针指向一个函数，该函数的无参数，返回一个指针，该指针指向一个大小为5的char型数组 #include <stdio.h> #include <typeinfo.h> char num[5]; char (*x00())[5] {     return # } int main() {     char (*x000)[5];//返回值     char (*(x00)())[5];//函数原型，参数为空，返回值为指针     char (*(*x0)())[5];//数组的元素，是个函数指针     char (*(*x[3])())[5];//是个数组，大小为3      x0 = x00;     x[0] = x0;     x[1] = x0;     x[2] = x0;     printf("typeid(x).name() is %s\n",typeid(x).name());     return 0; } //typeid(x).name() is char (* (__cdecl**)(void))[5]  这样定义是为了什么？干什么活需要这样弄？[/quote] 折腾大脑。[/quote] 干活只需要实现需求，比如： 定义一个大小为3的数组，该数组指向了一个指针，该指针指向一个函数，该函数的无参数，返回一个指针，该指针指向一个大小为5的char型数组。   typedef struct {     char i[5]; }RET;    // 定义函数返回的指针类型  typedef RET* (*FUNC)(void);    // 定义函数指针  FUNC x[3];    // 定义大小为3的数组

mipi_eotp_ t是函数指针类型 指向如下原型的函数： int32_t 为返回值 (uint8_t rx_en, uint8_t tx_en)为参数

声明函数指针mipi_eotp_t为一个类型,可用这个类型定义变量，变量就是函数指针。

typedef将标识符定义为它被声明的类型。 如果无视typedef，则： mipi_eotp_t是一个。。。 指针， 该指针指向。。。 函数。 该函数接受两个uint8_t类型的参数，返回类型为int32_t。 PS：参数列表中的名称是不必要的。

函数的参数是 uint8_t rx_en, uint8_t tx_en

typedef   int32_t (*mipi_eotp_t)(uint8_t rx_en, uint8_t tx_en); 就是定义一个函数指针类型 mipi_eotp_t 1.函数的返回类型是int32 2. 函数的参数是 *mipi_eotp_t)(uint8_t rx_en, uint8_t tx_en

右左法则 mipi_eotp_ t是一种类型，  函数指针类型 指向如下原型的函数： int32_t 为返回值 (uint8_t rx_en, uint8_t tx_en)为参数

typedef   int32_t (*mipi_eotp_t)(uint8_t rx_en, uint8_t tx_en);  这是一个函数类型的声明，函数类型名是mipi_eotp_t int32_t  函数返回值类型 uint8_t rx_en, uint8_t tx_en这两个是函数入参


Question: 有没有可以操作缓存的函数？

引用 6 楼 TheNewIpad 的回复:这种操作是CPU自动控制的吧。  记得深入探索里面说，当你访问 一个地址A的话， CPU会把A附近的数据也向上缓存（如果地址是在硬盘，存入内存， 如果在内存，存入高速缓存。 具体读取的数据大小， 由相关硬件决定。如硬盘4kb向内存缓存， 内存一次读取一行。大小由硬件决定）。 这就是地址访问的局部性。  二级缓存向一级缓存一次缓存64字节（我的机器）。

有吧？即使有也没有大面积传播，因为cache 主要是操作系统在操纵。

通常来讲，CPU的缓存对于编程人员是透明的，它压根没打算让你控制。

引用 楼主 cs_huster 的回复:比如把内存中4M的数据读入到处理器的LLC当中，也就是最后一级缓存 因芯片而异，具体看对应芯片的手册。

CPU的cache应该不能直接操作。即便可以，也不提倡。看看intel的编程手册。

没有


Question: union 的小问题（在线等，问题解决即结贴）

引用 2 楼 niceworkteam 的回复:[quote=引用 1 楼 zhao4zhong1 的回复:] 全部存为varchar类型。  使用sprintf函数将 double转为char long也转为char 可是我并不知道需不需要转，也不知道该怎么转，我只是直接使用联合体的字符串去存。  DevInfo di;   di.uVal.s ...// 我直接使用的是 s 字段，但是不知道啥时候该转，也不知道该怎么转。 [/quote]  保存&di.uVal地址，sizeof(DevInfo::UVAL)字节的数据就行了。

绝对没有  但是可以在一定程度上进行猜测,但并非准确

引用 5 楼 u013573183 的回复:给这个变量赋值的地方通知你,不过既然是黑暗的角落里,那通知也不会有  以上3种方法,没了  设计缺陷,无解  确定没有办法知道当前存储类型？

引用 3 楼 u013573183 的回复:typedef struct Dev {      int  ID;      int  Type;      union  UVAL      {             char s[128];             double d;             long   l;      }uVal; }DevInfo;  Type记录当前枚举的类型  或者 在你这个情况中,不需要使用枚举,都使用 char s[128]; 表示就够了  可是这个结构体的声明是我无权改变的，我只负责将里面的数据存入数据库……所以我说是在一个黑暗的角落……

引用 1 楼 zhao4zhong1 的回复:全部存为varchar类型。  使用sprintf函数将 double转为char long也转为char 可是我并不知道需不需要转，也不知道该怎么转，我只是直接使用联合体的字符串去存。  DevInfo di;   di.uVal.s ...// 我直接使用的是 s 字段，但是不知道啥时候该转，也不知道该怎么转。


Question: 编译错误

引用 11 楼 u012421456 的回复:其他的还真没怎么注意 有些东西不知道，自己可以在编译器下慢慢试试，稍微改动一下代码，看运行后出现什么结果  有时候，我不知怎么出现的错误，不知道错误的原理，就用这种方法，但有时也能改好（当然，这个一般仅限于相对简单的程序）恩恩，我也是用这种方法。不过还不够熟练，有时候不愿去尝试。

引用 8 楼 zhao4zhong1 的回复:C++浮点数常量的语法约定及其说明。好吧。。。

引用 7 楼 u012421456 的回复:[quote=引用 4 楼 u012523688 的回复:] [quote=引用 1 楼 u012421456 的回复:] 16行该 2*i 24行1e是什么啊真是，忘了放乘号了，亏我还看了半天呢，那个1e-3代表10的负三次方[/quote] 那减号两边不该有空格啊！ lz去掉空格试试代码能用不[/quote]太棒了，你，真的不应该有空格，我把那个当运算符了，好像这里不能把它当做运算符来看，所以就不能用空格，其实里面还有几处错误，x = 3.0/4;

C++浮点数常量的语法约定及其说明。

引用 4 楼 u012523688 的回复:[quote=引用 1 楼 u012421456 的回复:] 16行该 2*i 24行1e是什么啊真是，忘了放乘号了，亏我还看了半天呢，那个1e-3代表10的负三次方[/quote] 那减号两边不该有空格啊！ lz去掉空格试试代码能用不

引用 3 楼 zhao4zhong1 的回复:C++ Floating-Point Constants Floating-point constants specify values that must have a fractional part. These values contain decimal points (.) and can contain exponents.  Syntax  floating-constant :  fractional-constant exponent-partopt floating-suffixopt digit-sequence exponent-part floating-suffixopt  fractional-constant :  digit-sequenceopt . digit-sequence digit-sequence .  exponent-part :  e signopt digit-sequence E signopt digit-sequence  sign : one of  + –  digit-sequence :  digit digit-sequence digit  floating-suffix :one of  f l F L  Floating-point constants have a “mantissa,” which specifies the value of the number, an “exponent,” which specifies the magnitude of the number, and an optional suffix that specifies the constant’s type. The mantissa is specified as a sequence of digits followed by a period, followed by an optional sequence of digits representing the fractional part of the number. For example:  18.46 38.  The exponent, if present, specifies the magnitude of the number as a power of 10, as shown in the following example:  18.46e0      // 18.46 18.46e1      // 184.6  If an exponent is present, the trailing decimal point is unnecessary in whole numbers such as 18E0.  Floating-point constants default to type double. By using the suffixes f or l (or F or L — the suffix is not case sensitive), the constant can be specified as float or long double, respectively.  Although long double and double have the same representation, they are not the same type. For example, you can have overloaded functions like  void func( double );  and   void func( long double );这是什么啊，完全看不懂啊，

引用 2 楼 user-3 的回复:楼主粗心了，数字和变量的相乘中间要放乘号*恩恩，确实啊，惭愧。

引用 1 楼 u012421456 的回复:16行该 2*i 24行1e是什么啊真是，忘了放乘号了，亏我还看了半天呢，那个1e-3代表10的负三次方

楼主粗心了，数字和变量的相乘中间要放乘号*

16行该 2*i 24行1e是什么啊


Question: 通过JNI将JAVA对象映射为C语言的结构体，然后这个结构体作为参数传给下层C语言的问题，这个请大家帮忙看看我写的为什么不行啊。

请问楼主解决了吗？我最近也遇到了类似的问题，userInfo.name = temName;这么赋值不行，那么userInfo.nLeft=temLeft;那么整型赋值行不行啊？

不直接赋值的。使用 (env)->GetStringLength(jstr );，获取一下长度，或者知道长度直接定义一个char数组，然后使用(char*)env->GetStringUTFChars(jstr,0);  获取

不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。

哎。。。。。。

引用 3 楼 lgmsyy 的回复:[quote=引用 2 楼 user-4 的回复:] userInfo.name = temName;//但是这么赋值好像不行 java的String对象存储了字符对象"hello"，不想c语言的char*，只存储了一个指针，这样当然不行。 LZ要做的是提取String对象的内容，然后在JNI中分配一段同样大小的内存，然后存储该字符串。  有点糊涂，能具体说明下吗，现在我就是对细节不清楚。[/quote] Prompt.java: class Prompt { 	// native method that prints a prompt and reads a line 	private native String getLine(String prompt); 	public static void main(String args[]) { 		Prompt p = new Prompt(); 		String input = p.getLine("Type a line: "); 		System.out.println("User typed: " + input); 	} 	static { 		System.loadLibrary("Prompt"); 	} }  JNI文件代码示例： XXX.c JNIEXPORT jstring JNICALL Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt) { 	/* assume the prompt string and user input has less than 128 characters */ 	char outbuf[128], inbuf[128]; 	/* 下面的2句提取从Java那边传递过来的字符串到outbuf */ 	int len = (*env)->GetStringLength(env, prompt); 	(*env)->GetStringUTFRegion(env, prompt, 0, len, outbuf); 	printf("%s", outbuf); 	scanf("%s", inbuf); 	return (*env)->NewStringUTF(env, inbuf); }  到网上搜索 JNI Programmer’s Guide and Specification 文档，有详细的阐述。 以前做过几个java结合JNI的案子，这份资料帮助很大，呵呵。

引用 2 楼 user-4 的回复:userInfo.name = temName;//但是这么赋值好像不行 java的String对象存储了字符对象"hello"，不想c语言的char*，只存储了一个指针，这样当然不行。 LZ要做的是提取String对象的内容，然后在JNI中分配一段同样大小的内存，然后存储该字符串。  有点糊涂，能具体说明下吗，现在我就是对细节不清楚。

有人帮忙吗？？？


Question: 一个和宏#if相关的问题。

楼主你得理解运行时和编译的两个不同概念。。

引用 9 楼 dbzhang800 的回复:看来你不清楚　-o 是做什么用的。  gcc -E test.c 会默认生成一个 .i 的文件，即 test.i  但是你已经通过-o 告诉它，这个生成的文件叫 test,而不是默认名字 test.i 达人啊。

我是想用gcc -o test test.c 这个命令行来生成一个test程序， 但是现在的编译错误是： gg.c:18:32: error: token "{" is not valid in preprocessor expressions  然后刚才zhao4zhong1 说，可以加一个 -E的选项，然后看一下 .i 的内部的错误 但是我想用这个命令行来编译时： gcc -o test test.c -ep -p -E 还是提示有错误，也没有  .i 文件生成。

引用 5 楼 jelllove 的回复:我用这个命令编译了一下 [code=c]gcc -o test test.c -ep -p -E/code]  但是没有看到有一个 .i 的文件生成，是我的命令行有问题？ 你不是用 -o 指定生成的文件叫 test 了么？

引用 3 楼 jelllove 的回复:那就是说，我编译时的判断条件中，不能出现strstr这样的函数？ 不止是strstr这样的函数，而是你里面的所有的哪些以分号结束的运行时的语句都不能出现。

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

那就是说，我编译时的判断条件中，不能出现strstr这样的函数？

宏在编译前执行，源代码编译为程序，程序运行时执行strstr函数 所谓宏函数只是便于初学者理解的说法，宏和函数是完全不同的两个概念


Question: 一个题目的bug找不到

你输入的是 18,11？？

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

输入完成后，把ab的值都打印出来看看！是否正确！

不是楼主的输入问题，就是编译器的问题，我这里正常运行，结果正确


Question: 语句这样，我把语句改成那样可以吗？

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

引用 1 楼 u012586257 的回复:不是不行，是和原语句不等价 原程序中c=='\n' c==EOF 都会退出循环的，你修改后就不会退出了  同意，修改前后代码所表达的意思是不一样的；修改后，循环要执行 lim -1次，而修改前，循环不一定能到lim -1次，你按下回车键后，循环就结束了！

感谢~顿时有种柳暗花明的感觉~

for(i = 0; i < lim -1 ; ++i) {   c=getchar();   if ((c == '\n' || c == EOF)   {      break;   }   s[i] = c; }


Question: union联合体数组指针，怎么和数组一样用？

#include <stdio.h> union U {     unsigned _int64 uni;     unsigned char   pos[8]; } gene[3]; void function(U *pp) {     pp[1].uni = 0x0706050403020100ui64; } void main() {     function(gene);     printf("0x%I64xui64\n",gene[1].uni);     printf("%02x %02x %02x %02x %02x %02x %02x %02x\n",         gene[1].pos[0],         gene[1].pos[1],         gene[1].pos[2],         gene[1].pos[3],         gene[1].pos[4],         gene[1].pos[5],         gene[1].pos[6],         gene[1].pos[7]); } //0x706050403020100ui64 //00 01 02 03 04 05 06 07 //

0x0706050403020100 和 0x0706050403020100i64 和 0x0706050403020100ui64 不是一回事！

union 根struct  enum等关键字是一样的,   你能使用struct *p   这样定义一个变量吗, 显然是不正确的.  typedef union {  unsigned _int64 uni;  unsigned char pos[8]; } MyInt64;  MyInt64 gene[3];  void function(MyInt64*pp) {*(pp+1) = 0x0706050403020100;}     void main() {function(gene);}

觉得你应该先声明一个union比如tGene，然后声明数组 tGene gene[3], 函数说明用 function(tGene *p), 赋值用  p[1].uni=0x0706050403020100;

建议直接用int array[8];这样就简化了分段。 把超过32位的数值用两个或多个数组中的int来表示；


Question: 文件打开的问题

引用 3 楼 ly114kuang 的回复:if(argc != 2)//我问的不是很清楚，我还是不理解的，他这里不等于2的目的，是要到大什么？ putc(ch, stdout);//这里的stdout没有声明怎么可以用了？ 这个程序正确用法是 app my.txt 也就是有两个输入项，所以要求 argc == 2，否则就退出程序 stdout 在头文件 stdio.h 定义 楼主要先看书，进步才快

ch用字符型请问你怎么区别输入的是来自文件的ASCII码为255的字符呢还是到文件末尾了返回EOF即-1呢？

引用 1 楼 u012586257 的回复:解释下argc 和 argv 的含义 argc： 命令行输入的参数个数 argv： 命令行输入的参数指针  比如你的程序名字是 app, 运行时你从命令行输入 app my.txt 那么你的程序得到的argc 就是2，argv[0] 是“app”，argv[1]是“my.txt"  [quote=引用 楼主 ly114kuang 的回复:] # include <stdio.h> # include <stdlib.h>  int main(int argc, char *argv[])//定义argc 是什么意思，//我想问一下我argv[]数组是文件路径吗？ { 	int ch;//这里为什么用整形，用字符型不行吗？应该也行 	FILE * fp; 	long count = 0;  	if(argc != 2)//这个逻辑看不懂，为什么要！= 2 要求带一个参数，所以必须是2，否则报错退出 	{ 		printf("Usage: %s filename\n", argv[0]);//打印字符串的数量 		exit(1); 	}  	if((fp = fopen(argv[1], "r")) == NULL)//里面的逻辑我没有看懂，argv【1】为什么是1的下标，是0的下标不行吗？0下标指的是程序自身文件名，不是要处理的文件 	{ 		printf("Can't open %s\n", argv[1]); 		exit(1); 	}  	while((ch = getc(fp)) != EOF)//在文件输入单词 	{ 		putc(ch, stdout);//stdout是什么意思标准输出设备，通常是屏幕 		count++;//这个是什么意思计数 	} 	fclose(fp);//关闭文件的这个函数，一定要么？要和不要有什么区别？要，否则占资源且不安全 	printf("File %s has %ld characters\n", argv[1], count++); 	return 0; }[/quote]  if(argc != 2)//我问的不是很清楚，我还是不理解的，他这里不等于2的目的，是要到大什么？ putc(ch, stdout);//这里的stdout没有声明怎么可以用了？

ch = getc(fp) getc不仅仅返回读到的字符，当读到文件结尾时，还回返回EOF

解释下argc 和 argv 的含义 argc： 命令行输入的参数个数 argv： 命令行输入的参数指针  比如你的程序名字是 app, 运行时你从命令行输入 app my.txt 那么你的程序得到的argc 就是2，argv[0] 是“app”，argv[1]是“my.txt"  引用 楼主 ly114kuang 的回复:# include <stdio.h> # include <stdlib.h>  int main(int argc, char *argv[])//定义argc 是什么意思，//我想问一下我argv[]数组是文件路径吗？ { 	int ch;//这里为什么用整形，用字符型不行吗？应该也行 	FILE * fp; 	long count = 0;  	if(argc != 2)//这个逻辑看不懂，为什么要！= 2 要求带一个参数，所以必须是2，否则报错退出 	{ 		printf("Usage: %s filename\n", argv[0]);//打印字符串的数量 		exit(1); 	}  	if((fp = fopen(argv[1], "r")) == NULL)//里面的逻辑我没有看懂，argv【1】为什么是1的下标，是0的下标不行吗？0下标指的是程序自身文件名，不是要处理的文件 	{ 		printf("Can't open %s\n", argv[1]); 		exit(1); 	}  	while((ch = getc(fp)) != EOF)//在文件输入单词 	{ 		putc(ch, stdout);//stdout是什么意思标准输出设备，通常是屏幕 		count++;//这个是什么意思计数 	} 	fclose(fp);//关闭文件的这个函数，一定要么？要和不要有什么区别？要，否则占资源且不安全 	printf("File %s has %ld characters\n", argv[1], count++); 	return 0; }

引用 10 楼 user-4 的回复:[quote=引用 8 楼 ly114kuang 的回复:] [quote=引用 7 楼 u012586257 的回复:] [quote=引用 3 楼 ly114kuang 的回复:] if(argc != 2)//我问的不是很清楚，我还是不理解的，他这里不等于2的目的，是要到大什么？ putc(ch, stdout);//这里的stdout没有声明怎么可以用了？ 这个程序正确用法是 app my.txt 也就是有两个输入项，所以要求 argc == 2，否则就退出程序 stdout 在头文件 stdio.h 定义 楼主要先看书，进步才快[/quote]   是这样的，我看了，但是讲这个程序不是很清楚，就这里卡住了！  那么我想问下，这个打开文件的，为什么要两个输入项！就是没搞懂，还有如果我不要这个if可以吗？[/quote] 执行的时候用可执行文件+参数，是外部的输入。你想啊，外部输入的选择性比代码中写死的大多了吧 至于if判断，是保证你的输入正确。如果参数穿的不对，后面的程序也没法正常执行。这样可以尽早的发现错误[/quote]  谢谢  明白了！

引用 9 楼 zhao4zhong1 的回复:命令行解释器概述 命令行解释器是一个单独的软件程序，它可以在用户和操作系统之间提供直接的通讯。非图形命令行解释器用户界面提供运行基于字符的应用程序和实用程序的环境。通过使用类似于 MS-DOS 命令解释程序 Command.com 的单独字符，命令行解释器执行程序并在屏幕上显示其输出。Windows 服务器操作系统命令行解释器使用命令解释程序 Cmd.exe（该程序加载应用程序并指导应用程序之间的信息流动）将用户输入转换为操作系统可理解的形式。 可以使用命令行解释器创建和编辑可自动执行常规任务的批处理文件（也称作脚本）。例如，可以使用脚本自动管理用户帐户或夜间备份。还可以使用 Windows 脚本宿主 CScript 的命令行版本在命令行解释器中运行更高级的脚本。详细信息，请参阅运行 Windows 脚本宿主。通过使用批处理文件来执行操作，可比使用用户界面更有效率。批处理文件接受命令行上可用的所有命令。有关批处理文件和脚本的详细信息，请参阅使用批处理文件。 您可以自定义命令提示符窗口以易于查看并增强对程序运行方式的控制。有关自定义命令提示符窗口的详细信息，请参阅配置命令提示符。  使用命令语法 语法按命令及所带参数必须遵循的键入顺序出现。下面的 xcopy 命令示例显示了各种语法文本格式：  xcopy Source [Destination] [/w] [/p] [/c] [/v] [/q] [/f] [/l] [/g] [/d[:MM-DD-YYYY]] [/u] [/i] [/s [/e]] [/t] [/k] [/r] [/h] [{/a | /m}] [/n] [/o] [/x] [/exclude:File1[+[File2]][+[File3]] [{/y | /-y}] [/z]  下表说明如何解释不同的文本格式。  格式化图例 格式                                             含义 斜体                                             用户必须提供的信息 粗体                                             用户必须准确键入的要显示的元素 省略号(...)                                      在命令行中可多次重复的参数 中括号([])                                       可选项 大括号({})；选项用竖线(|)分隔。例如：{even|odd}  用户必须从选项集合中选择一个 Courier字体                                      代码或程序输出  使用多个命令和条件处理符号 使用条件处理符号可以在单个命令行或脚本中运行多个命令。通过条件处理符号运行多个命令时，条件处理符号右边的命令根据条件处理符号左边命令的执行结果来发挥作用。例如，只有在前一个命令失败的情况下才可能需要运行一个新命令。或者，只有在前一个命令成功时才可能需要运行一个新命令。 可以使用下表列出的特殊字符来传递多个命令。  字符       语法                            定义 & [...]    Command1 & Command2             用来分隔一个命令行中的多个命令。Cmd.exe 运行第一个命令，然后运行第二个命令。 && [...]   Command1 && Command2            只有在符号 && 前面的命令成功时，才运行该符号后面的命令。Cmd.exe 运行第一个命令，然后只有在第一个命令运行成功时才运行第二个命令。 || [...]   Command1 || Command2            只有在符号 || 前面的命令失败时，才运行符号 || 后面的命令。Cmd.exe 运行第一个命令，然后只有在第一个命令未能运行成功（接收到大于零的错误代码）时才运行第二个命令。 ( ) [...]  (Command1 & Command2)           用来分组或嵌套多个命令。 ;或者,     Command1 Parameter1;Parameter2  用来分隔命令参数。  注意 “与”符号 (&)、管道符号 (|) 以及括号 () 是特殊字符，将它们作为参数传递时，必须在其前面加上转义字符 (^) 或引号。 如果某个命令成功完成操作，该命令就返回零 (0) 退出代码或不返回任何退出代码。有关退出代码的详细信息，请参阅 Microsoft Windows 部署和资源工具包。  嵌套命令行解释器 通过在命令提示符下打开新的 Cmd.exe 实例，可以在 Cmd.exe 内嵌套命令行解释器。默认情况下，Cmd.exe 的每个实例继承其父 Cmd.exe 应用程序的环境。通过嵌套 Cmd.exe 的实例，可以更改局部环境，而不会影响 Cmd.exe 的父应用程序。这使您能够保留 Cmd.exe 的原始环境，并在终止嵌套的命令行解释器之后返回到原始环境。但是在嵌套的命令行解释器中所做的更改将不会被保存。 要嵌套命令行解释器，请在命令提示符下键入：  cmd  出现类似于下面内容的消息：  Microsoft (R) Windows Server 2003 Standard Edition (TM) (C) 版权所有 1985-2002 Microsoft Corp. 要关闭嵌套的命令行解释器，请键入 exit。  使用 setlocal 和 endlocal 命令，可以在 Cmd.exe 的实例中（或在脚本中）进一步将更改局部化。Setlocal 创建局部作用范围，而 endlocal 终止局部作用范围。在 setlocal 和 endlocal 作用范围内所做的更改将会被放弃，从而保持原始环境不变。这两个命令的嵌套最高可达到 32 级。有关 setlocal 和 endlocal 命令的详细信息，请参阅 Setlocal 和 Endlocal。  将环境变量与 Cmd.exe 一起使用 Cmd.exe 命令行解释器环境由确定命令行解释器和操作系统行为的变量进行定义。可以使用两种类型的环境变量（系统和局部）来定义命令行解释器环境或整个操作系统环境的行为。系统环境变量定义全局操作系统环境的行为。局部环境变量定义 Cmd.exe 当前实例环境的行为。 系统环境变量预置于操作系统之中，并可用于所有 Windows 服务器操作系统进程。只有具有管理凭据的用户才可以更改系统变量。这些变量最常用于登录脚本。 局部环境变量只有在创建变量时针对的目标用户登录到计算机时才有效。HKEY_CURRENT_USER 配置单元中设置的局部变量只对当前用户有效，但它们可定义全局操作系统环境的行为。  下表按优先顺序的降序描述变量的各种类型： 1.内置系统变量 2.在 HKEY_LOCAL_MACHINE 配置单元中找到的系统变量 3.在 HKEY_CURRENT_USER 配置单元中找到的局部变量 4.在 Autoexec.bat 文件中设置的所有环境变量和路径 5.在登录脚本（如果有的话）中设置的所有环境变量 6.在脚本或批处理文件中交互使用的变量  在命令行解释器中，Cmd.exe 的每个实例都继承其父应用程序的环境。因此，可以在不影响父应用程序环境的情况下更改新的 Cmd.exe 环境中的变量。 下表列出 Windows server operating system 的系统和本地环境变量。  变量                     类型       描述 %ALLUSERSPROFILE%        本地       返回“所有用户”配置文件的位置。 %APPDATA%                本地       返回默认情况下应用程序存储数据的位置。 %CD%                     本地       返回当前目录字符串。 %CMDCMDLINE%             本地       返回用来启动当前的Cmd.exe的准确命令行。 %CMDEXTVERSION%          系统       返回当前的“命令处理程序扩展”的版本号。 %COMPUTERNAME%           系统       返回计算机的名称。 %COMSPEC%                系统       返回命令行解释器可执行程序的准确路径。 %DATE%                   系统       返回当前日期。使用与date/t命令相同的格式。由Cmd.exe生成。有关date命令的详细信息，请参阅Date。 %ERRORLEVEL%             系统       返回上一条命令的错误代码。通常用非零值表示错误。 %HOMEDRIVE%              系统       返回连接到用户主目录的本地工作站驱动器号。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。 %HOMEPATH%               系统       返回用户主目录的完整路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。 %HOMESHARE%              系统       返回用户的共享主目录的网络路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。 %LOGONSERVER%            本地       返回验证当前登录会话的域控制器的名称。 %NUMBER_OF_PROCESSORS%   系统       指定安装在计算机上的处理器的数目。 %OS%                     系统       返回操作系统名称。Windows2000显示其操作系统为Windows_NT。 %PATH%                   系统       指定可执行文件的搜索路径。 %PATHEXT%                系统       返回操作系统认为可执行的文件扩展名的列表。 %PROCESSOR_ARCHITECTURE% 系统       返回处理器的芯片体系结构。值：x86或IA64（基于Itanium）。 %PROCESSOR_IDENTFIER%    系统       返回处理器说明。 %PROCESSOR_LEVEL%        系统       返回计算机上安装的处理器的型号。 %PROCESSOR_REVISION%     系统       返回处理器的版本号。 %PROMPT%                 本地       返回当前解释程序的命令提示符设置。由Cmd.exe生成。 %RANDOM%                 系统       返回0到32767之间的任意十进制数字。由Cmd.exe生成。 %SYSTEMDRIVE%            系统       返回包含Windowsserveroperatingsystem根目录（即系统根目录）的驱动器。 %SYSTEMROOT%             系统       返回Windowsserveroperatingsystem根目录的位置。 %TEMP%和%TMP%            系统和用户 返回对当前登录用户可用的应用程序所使用的默认临时目录。有些应用程序需要 TEMP，而其他应用程序则需要 TMP。 %TIME%                   系统       返回当前时间。使用与time/t命令相同的格式。由Cmd.exe生成。有关time命令的详细信息，请参阅Time。 %USERDOMAIN%             本地       返回包含用户帐户的域的名称。 %USERNAME%               本地       返回当前登录的用户的名称。 %USERPROFILE%            本地       返回当前用户的配置文件的位置。 %WINDIR%                 系统       返回操作系统目录的位置。  设置环境变量 使用 set 命令创建、更改、删除或显示环境变量。set 命令只更改当前解释器环境中的变量。  要查看变量，请在命令提示符下键入：  set VariableName  要添加变量，请在命令提示符下键入：  set variablename=Value  要删除变量，请在命令提示符下键入：  set VariableName=  可以将大多数字符用作变量值，其中包括空格。如果使用特殊字符 <、>、|、& 或 ^，则必须在它们前面加上转义字符 (^) 或引号。如果使用引号，则必须将引号作为值的组成部分，因为等号后面的任何内容都会被视为值。请考虑下列示例：  要创建变量值 new&name，请键入： set varname=new^&name  要创建变量值 "new&name"，请键入： set varname="new&name"  如果在命令提示符下键入 set varname=new&name，就会出现与下面内容类似的错误消息： “'name' 不是内部或外部文件，也不是可运行的程序或批处理文件。” 变量名不区分大小写。但是，set 显示的变量与您键入的完全相同。可以在变量名中结合使用大写字母和小写字母，这样可以使代码更具有可读性（例如，UserName）。  注意  单个环境变量的最大大小为 8192 字节。 所有环境变量的大小总和（包括变量名和等号）最大为 65,536 KB。 替换环境变量值 要在命令行或脚本中启用变量值替换，请将变量名包括在百分号之中（即，%VariableName%）。使用百分号可以确保 Cmd.exe 引用变量值，而不是进行文字比较。为变量名定义变量值之后，请将变量名包括在百分号之中。Cmd.exe 搜索该变量名的所有实例，并用定义的变量值进行替换。例如，如果创建包含不同值（例如，用户名）的脚本，并且想要用这些值为每个用户定义 USERNAME 环境变量，可以使用包括在百分号之中的 USERNAME 来编写代码。运行此脚本时，Cmd.exe 将用变量值替换 %USERNAME%，这样就消除了为每个用户手动执行此任务的必要。变量替换是不可递归的。Cmd.exe 检查变量一次。有关变量替换的详细信息，请参阅 For 和 Call。    哦。原来是这样啊！意思这个就是必须要的，你记住就行了！ 谢谢！

引用 8 楼 ly114kuang 的回复:[quote=引用 7 楼 u012586257 的回复:] [quote=引用 3 楼 ly114kuang 的回复:] if(argc != 2)//我问的不是很清楚，我还是不理解的，他这里不等于2的目的，是要到大什么？ putc(ch, stdout);//这里的stdout没有声明怎么可以用了？ 这个程序正确用法是 app my.txt 也就是有两个输入项，所以要求 argc == 2，否则就退出程序 stdout 在头文件 stdio.h 定义 楼主要先看书，进步才快[/quote]   是这样的，我看了，但是讲这个程序不是很清楚，就这里卡住了！  那么我想问下，这个打开文件的，为什么要两个输入项！就是没搞懂，还有如果我不要这个if可以吗？[/quote] 执行的时候用可执行文件+参数，是外部的输入。你想啊，外部输入的选择性比代码中写死的大多了吧 至于if判断，是保证你的输入正确。如果参数穿的不对，后面的程序也没法正常执行。这样可以尽早的发现错误

引用 7 楼 u012586257 的回复:[quote=引用 3 楼 ly114kuang 的回复:] if(argc != 2)//我问的不是很清楚，我还是不理解的，他这里不等于2的目的，是要到大什么？ putc(ch, stdout);//这里的stdout没有声明怎么可以用了？ 这个程序正确用法是 app my.txt 也就是有两个输入项，所以要求 argc == 2，否则就退出程序 stdout 在头文件 stdio.h 定义 楼主要先看书，进步才快[/quote]   是这样的，我看了，但是讲这个程序不是很清楚，就这里卡住了！  那么我想问下，这个打开文件的，为什么要两个输入项！就是没搞懂，还有如果我不要这个if可以吗？


Question: i++,i--,++i,--i 求解释

http://bbs.csdn.net/topics/370153775 建议看看这个帖子

引用 16 楼 u013320991 的回复:[quote=引用 12 楼 jiandingzhe 的回复:] [quote=引用 10 楼 u013320991 的回复:] int  a = 1; //  ++a  同等  a = a + 1,  a += 1 //  - -a  同等  a = a - 1,  a -= 1 //  a++  同等  a = a + 1,  a += 1 //  a- -  同等  a = a - 1,  a -= 1 a + a - - // 同等  a + a 之后  a=a- 1 a + --a   // 同等  a=a- 1之后  a + a 等同个毛啊啊啊啊啊。抓狂中。 看置顶贴……[/quote]   的确是同等, 只是在进行运算时,  符号在后面的是先使用前面的, 再做后面的符号运算 例如:  a = 1;  c = 2;   a = a + c++;  // 先执行这步 a = 1 + 2;   c = c + 1;] 而  a = a +  ++c; c = c+1; 先执行 a = 1 + 3[/quote] 你这个操作没有在一个表达式里多次读写同一个值，和楼主的情况是不一样的。

引用 16 楼 u013320991 的回复:的确是同等, 只是在进行运算时,  符号在后面的是先使用前面的, 再做后面的符号运算 例如:  a = 1;  c = 2;   a = a + c++;  // 先执行这步 a = 1 + 2;   c = c + 1;] 而  a = a +  ++c; c = c+1; 先执行 a = 1 + 3 未定义行为，你贴出一个编译器的结果不能说明任何问题。

引用 12 楼 jiandingzhe 的回复:[quote=引用 10 楼 u013320991 的回复:] int  a = 1; //  ++a  同等  a = a + 1,  a += 1 //  - -a  同等  a = a - 1,  a -= 1 //  a++  同等  a = a + 1,  a += 1 //  a- -  同等  a = a - 1,  a -= 1 a + a - - // 同等  a + a 之后  a=a- 1 a + --a   // 同等  a=a- 1之后  a + a 等同个毛啊啊啊啊啊。抓狂中。 看置顶贴……[/quote]   的确是同等, 只是在进行运算时,  符号在后面的是先使用前面的, 再做后面的符号运算 例如:  a = 1;  c = 2;   a = a + c++;  // 先执行这步 a = 1 + 2;   c = c + 1;] 而  a = a +  ++c; c = c+1; 先执行 a = 1 + 3

引用 10 楼 u013320991 的回复:int  a = 1; //  ++a  同等  a = a + 1,  a += 1 //  - -a  同等  a = a - 1,  a -= 1 //  a++  同等  a = a + 1,  a += 1 //  a- -  同等  a = a - 1,  a -= 1 a + a - - // 同等  a + a 之后  a=a- 1 a + --a   // 同等  a=a- 1之后  a + a  的确是同等, 只是在进行运算时,  符号在后面的是先使用前面的, 再做后面的符号运算 例如:  a = 1;  c = 2;   a = a + c++;  // 先执行这步 a = 1 + 2;   c = c + 1;] 而  a = a +  ++c; c = c+1; 先执行 a = 1 + 3

VC6.0是 8 7 8 8 不错，没必要纠结这样的问题，lz实在想知道就看看楼上的地址吧，那是很久以前的一个置顶帖

http://bbs.csdn.net/topics/370153775  学到东西了！

楼主搞这个有什么意思…………。

真是谢谢各位

引用 1 楼 user-15 的回复:我这边测试(vs2012)是 8 8 7 8 哦，看来跟编译器有关系，其实这个问题早就在论坛里讨论n次了，不需要去纠结  我测试vs2008是 8 8 8 8  看来确实不需要再纠结这个问题了。  以后编程时，尽量避免这样使用就行了。

引用 2 楼 starytx 的回复:看看这个置顶帖 http://bbs.csdn.net/topics/370153775  强烈建议版主把置顶帖的标题修改下, 加入 ++i, --i 这样的东西, 让其他人一看就知道是在说这个问题.  现在的标题难让新手知道是在讲 ++i这类的东西.

来这里发这样的贴 能看置顶贴？ 楼主真无聊

这 真的是个世界性难题！

printf("%d\n%d\n%d\n%d\n", ++i, --i, i++, i--); 标准没有规定这里面的++i、--i、i++、i--先计算哪一个，实际项目中避免写出这样的代码就可以了。

引用 10 楼 u013320991 的回复:int  a = 1; //  ++a  同等  a = a + 1,  a += 1 //  - -a  同等  a = a - 1,  a -= 1 //  a++  同等  a = a + 1,  a += 1 //  a- -  同等  a = a - 1,  a -= 1 a + a - - // 同等  a + a 之后  a=a- 1 a + --a   // 同等  a=a- 1之后  a + a 等同个毛啊啊啊啊啊。抓狂中。 看置顶贴……


Question: 数据结构设计

用map，Address当key，速度应该很快

通常≤10000不必考虑效率。

就是效率低着

遍历一下也没什么的。  引用 楼主 u014162415 的回复:一个用户ID下有15个地址Address，每个地址都是唯一的值，不重复。 有500个用户，也就有7500个地址Address,需求是：给个地址Address，能快速查找到用户ID。 也就是下面结构。 用户ID1：Address1 = 15             Address2 = 2000           Address3 = 200000050           .           . 	  Address15= 0xFFFFFFFE 用户ID2：Address16 = 99           Address17 =10000000           Address18 = 634345345           .           . 	  Address30 =324532453451 . . 用户ID500：Address7486 = 4654634           Address7487 =3664356346           Address7488=3425646326           .           . 	  Address7500=2 因为Address值的范围是0~0XFFFFFFFF,把Address作为数组下标，太耗内存。 把用户ID作为数组小标，Address[15]作为值可以，但是每次根据Address取用户ID，都要遍历数组。 大家有不用遍历，好的建议吗？


Question: 我想知道哪里出错了——关于以数组为参数的函数

引用 楼主 u014026652 的回复:#include<graphics.h> #include<stdio.h> #include<math.h> #include<stdlib.h> #include<string.h>   #include <conio.h>  int a[100],b[100],c[100]; void putstar() {   int i,dotx,doty,w,h,t;   w=getmaxx();   h=350;   for(i=0;i<100;i++)   {     dotx=rand()%(w-1);     a[i]=dotx;     doty=rand()%(h-1);     b[i]=doty;     t=rand()%(3);     c[i]=t;     setfillcolor(WHITE);     fillcircle(dotx,doty,t);   } } void revertstar(int a[],int b[],int c[]) {   int i;   for(i=0;i<100;i++)   {     setfillcolor(WHITE);     fillcircle(a[i],b[i],c[i]);   } }  void main() { 	initgraph(640, 480); 	 	int x = 320,y=240; setfillcolor(LIGHTBLUE); bar(0, 0,640,480); setfillcolor(GREEN); bar(0, 350,640,480);  putstar(); 	 	// 画初始图形 	setlinecolor(YELLOW); 	setfillcolor(YELLOW); 	fillcircle(x, y, 30);  	 	char c; 	while(c != 27) 	{ 		// 获取按键 		c = getch(); 		 		// 先擦掉上次显示的旧图形 		setlinecolor(BLACK); 		setfillcolor(BLACK); 		fillcircle(x, y, 50); 		 		// 根据输入，计算新的坐标 		switch(c) 		{ 			case 75: x-=2; break; 			case 77: x+=2; break;             case 72: y-=2; break;             case 80: y+=2; break; 			case 27: break; 		} 		 		// 绘制新的图形 		setlinecolor(YELLOW); 		setfillcolor(YELLOW); 		fillcircle(x, y, 50);         revertstar(a,b,c); 		 		// 延时 		Sleep(10); 	} 	 	closegraph(); }  参数传递入栈的时候，是需要cpu的寄存器来存储这些值的，你的cpu能给你当做数据存储的非特殊寄存器就算是CISC也就32个上下，通常比这个值少，难道你数组有1000个元素也挨个让传进去？怎么放的下！  这个问题之后你再想想，数组的特性，告诉数组里面某个元素的地址，再告诉你这个元素是第几个，再知道类型，让你输出数组所有元素，你会办不到么？

main中，char c;的定义c传给revertstar(a,b,c);的C了，能不错吗

为什么楼主不将整个互联网内容作为函数参数传递呢？！

#include<graphics.h> #include<stdio.h> #include<math.h> #include<stdlib.h> #include<string.h> #include<conio.h>  int a[100],b[100],c[100];  void fillcircle(int x, int y, int radius) {     /* add your code here... */ }  void setfillcolor(int color) {     /* add your code here... */ }  void setlinecolor(int color) {     /* add your code here... */ }  void putstar() {     int i,dotx,doty,w,h,t;     w=getmaxx();     h=350;     for(i=0;i<100;i++)     {         dotx=rand()%(w-1);         a[i]=dotx;         doty=rand()%(h-1);         b[i]=doty;         t=rand()%(3);         c[i]=t;         setfillcolor(WHITE);         fillcircle(dotx,doty,t);     } }  void revertstar(int a[],int b[],int c[]) {     int i;     for(i=0;i<100;i++)     {         setfillcolor(WHITE);         fillcircle(a[i],b[i],c[i]);     } }  void main() {     int gdriver = DETECT, gmode;     int x = 320,y=240;     char c;      initgraph(&gdriver, &gmode, "");     /*initgraph(640, 480);*/       setfillcolor(LIGHTBLUE);     bar(0, 0,640,480);     setfillcolor(GREEN);     bar(0, 350,640,480);      putstar();      /* 画初始图形 */     setlinecolor(YELLOW);     setfillcolor(YELLOW);     fillcircle(x, y, 30);      while(c != 27)     {         /* 获取按键 */         c = getch();          /* 先擦掉上次显示的旧图形 */         setlinecolor(BLACK);         setfillcolor(BLACK);         fillcircle(x, y, 50);          /* 根据输入，计算新的坐标 */         switch(c)         {         case 75: x-=2; break;         case 77: x+=2; break;         case 72: y-=2; break;         case 80: y+=2; break;         case 27: break;         }          /* 绘制新的图形 */         setlinecolor(YELLOW);         setfillcolor(YELLOW);         fillcircle(x, y, 50);         revertstar(a,b,c);          /* 延时 */         sleep(10);         /*Sleep(10);*/     }      closegraph(); }   已经在Win-TC下通过编译。有3个函数有待LZ实现：fillcircle,setfillcolor,setlinecolor，逻辑错误有待LZ自己查找。

不要把什么都定义成a,b,c, 到时候你自己的区分不了.  比如全局数组的a,b,c. 你可以加一个g_ 作为前缀.  如: g_a[100]. 函数参数的名字也要改变下.


Question: 顺序栈和链栈

是我们自己OJ上的题错了。我自己的代码没问题，谢谢大家。

我觉得就这个题而言，顺序栈要好些吧，起码是一次性malloc，而链栈却要malloc MaxElements多次

while条件有问题吧，getchar会吃掉第一个字符，然后回车前有多余空格的话，会继续读下行，那么不是死循环就是最后n值没读到还是原来未初始的垃圾值，貌似改成简单全部scanf读入即可...  while(scanf("%d",&x))!=EOF)     Push(x,S);  int n = TopandPop(S); ...

目前现在这样超时 怎么改？


Question: 关于用C语言进行的开发

引用 11 楼 RJGCSS 的回复:[quote=引用 7 楼 DUAN521414 的回复:] 做电信方面后台开发，一般都是前台JAVA后台C，LINUX还是更亲向于C的，C工作要求较其他高点，但是也没事，努力就好，搞C在语言里还是很赚钱的   做C开发薪资待遇方面怎么样 [/quote]  引用 11 楼 RJGCSS 的回复:[quote=引用 7 楼 DUAN521414 的回复:] 做电信方面后台开发，一般都是前台JAVA后台C，LINUX还是更亲向于C的，C工作要求较其他高点，但是也没事，努力就好，搞C在语言里还是很赚钱的   做C开发薪资待遇方面怎么样 [/quote]待遇在语言里还算是高的吧，如果你用C做的是技术不是皮毛，在沈阳这种城市四年以上经验6K基本随便跳，可以要到8K，平均的，当然也有个别过万的，如果去北京这种城市从6K到6W不等吧，看个人能力。

《Unix环境高级编程》《Unix网络编程》这就是了，界面GNOME下GTK，KDE下Qt 如果往OS走，解析内核，搞搞嵌入式

引用 楼主 RJGCSS 的回复:请问用C在Linux环境下进行应用层的开发多吗？ 现在Linux环境下的C程序员大都做什么？？ 应届生找C程序员的工作好找吗？？  我即将毕业找工作，希望各位点建议。  想真正的搞计算机就搞C底层，想当名攻城师就去搞上层，不过在我看来是缘木求鱼。

我学了两三年的纯C。如今开始全面转面向对象。倒不是觉得C不够好，技多不压身。而且学会C语言再转其他语言，真的很容易。 C这种面向过程的语言，他只是在程序中有结构和体系，但是他的代码是没有结构的，所有函数都是平等的。面向对象就不一样了，他连代码都有结构，我想这也是面向对象现在更火的原因吧。

混饭吃而已，学什么已经不重要了。

上面有人提到金融、电信行业用C来开发后台程序，以前是这样，但随着互联网金融、现代通信业务的兴起，业务模式的升级，而且硬件性能的提高，用C写的程序很难升级，早晚会被面向对象编程模式替代，就是说C这方面已经没有优势了。

引用 楼主 RJGCSS 的回复:请问用C在Linux环境下进行应用层的开发多吗？ 现在Linux环境下的C程序员大都做什么？？ 应届生找C程序员的工作好找吗？？  我即将毕业找工作，希望各位点建议。工作的话，要看你的基础与兴趣，而不只是纯粹看钱，做哪方面都有钱多钱少的，看你的水平。如果你的数据结构，操作系统基础不错，喜欢中下层的开发，C是不错的选择。C是面向过程的开发，运行效率高，不适合用来开发大的系统（操作系统除外）。用C来写软件还是很有技术含量的。

《Linux C编程一站式学习》

引用 7 楼 DUAN521414 的回复:做电信方面后台开发，一般都是前台JAVA后台C，LINUX还是更亲向于C的，C工作要求较其他高点，但是也没事，努力就好，搞C在语言里还是很赚钱的   做C开发薪资待遇方面怎么样

发现已经很长时间没用Ｃ了。

我在国企用Linux开发，基本上就是写一些后台程序

新手学习学习

学习下，占楼。

大型程序用C的不多。Linux下只有GNU-Gnome-Gtk一系抱着C不放。即便如此，它们也出了C++的binding库，以及自己的高级语言。

现在基于linux/unix下的c语言开发，国内的主要领域大部分是金融和电信行业的开发。

引用 1 楼 user-14 的回复:c主要用在嵌入式开发上了，效率高，linux下c++开发比较多，主要在服务端。   我是学软件工程的，请问您一下， 就您看来应届生找这两个方向的哪一个薪资会高一些。 虽然这个话题有点俗， 但是对于现在的社会， 这也是很现实的问题。 谢谢

c主要用在嵌入式开发上了，效率高，linux下c++开发比较多，主要在服务端。


Question: 内联汇编的一道简单的问题

受教了~~  thank you!

查了下，是IBM Enterprise Systems Architecture/390芯片的指令。 可参考链接： http://www-947.ibm.com/support/entry/portal/search_results?sn=spe&q=ESA/390%20Principles%20of%20Operation&filter=language:en 下载手册：ESA/390 Principles of Operation (SA22-7201-08)   STORE CPU ADDRESS STAP D(B) [S] ┌────────────────┬────┬────────────┐ │ 'B212' │ B │ D │ └────────────────┴────┴────────────┘  16 2 31 The 16-bit unsigned binary integer by which this CPU is identified in a multiprocessing configuration is stored at the halfword location designated by the second-operand address. Special Conditions The operand must be designated on a halfword boundary; otherwise, a specification exception is recognized. Condition Code: The code remains unchanged. Program Exceptions:  Access (store, operand 2)  Privileged operation  Specification


Question: 网络设置，收发包

现有一个DHCP服务器程序    eth1(lan)                           eth2(wan)<----------------xp(将eth2与xp配置在同一个vm net。 例如vm net2)       |                                          | ----------------------------------------------------- 在xp里启动自动获取ip地址。查看，正常分配到DHCP地址池里的一个有效地址。   现有一个加、去VLAN程序，在eth3收到的数据包加上一层vlan 在eth4收到的数据包加去掉一层vlan      eth3(lan)                 eth4(wan)        |                                 | ---------------------------------------------   现在想dhcp服务器发offer包的时候给它加上一层vlan，然后用一台xp的wireshark去抓取这个数据包。验证是否加上了一层vlan。 现在这个网络拓扑图要怎么画，在虚拟机里应该怎么连接。 请大家帮忙解决！！！！！！！！

引用 8 楼 xihu1364 的回复:用NAT  3个系统 xp1 xp2 linux 你到底想怎么连？  xp1连接linux  网卡1 xp2连接linux  网卡2  然后让xp1 ->linux 网卡1 ->linux 网卡2->xp2   是这样子么？  这样xp1怎么能跟xp2通信呢？因为不在一个网段  除非在linux弄个中转...   在linux上将网卡1和网卡2桥接不知道是否可以...  你没有看我的配置吗，XP1  XP2  同一个网段，同一个VM NET。这时就是通的，用NAT肯定是不通的。  我是要xp  与 linux的dma网卡连通。

都是虚拟机的话 不知道数据包是不是走的网卡 也不知道你用的什么软件抓包 ping通是最基本的吧 个人意见

引用 3 楼 zhao4zhong1 的回复:VM配置不熟. 我的意思是说我VM配置不熟，爱莫能助； 不是说你VM配置不熟，需要进一步熟悉。

现做了这样的实验 第一台XP  配置 ip:192.168.30.120 第二台XP  配置 ip:192.168.30.130 linux的eth3(DMA口)      配置 ip:192.168.30.140 以上全在vm net2下 结果 两台xp与eth3都ping不通。   现增加一个eth6(非DMA口)  配置 ip:192.168.30.110 也在vm net2下 此时两台xp与eth3、eth6都是互通的。这是为什么？

引用 3 楼 zhao4zhong1 的回复:VM配置不熟.先行谢过。。回帖了！！

在虚拟网络编辑器里添加vm net2 这里只能设置为模式的host模式吗？ 默认vm net1是桥接  vm net1 是host  vm net8是NAT。

VM配置不熟.

没人回！！！！！