Question: 数组与指针sizeof

引用 13 楼 fdsafwagdagadg6576 的回复:int a[5]={1,2,3,4,5}; printf("%x, %x,%x,%x\n", a, &a,a+1,&a+1); ffbee248, ffbee248,ffbee24c,ffbee25c a和&a 地址相同。 根据12楼的解释 &a + 1 在数值上等于 ((char *)&a) + sizeof(a); 为什么a+1不能这样算呢。 这是编译器的设计吗 原理上指针加1，就是指向下一个object a + 1: 这里的数组a退化成一个指针 pointer to ingeter, 所以 a + 1 在数值上等于 ((char *)a) + sizeof(a[0]);

sizeof(数组名) -> 数组的大小 sizeof(指针) -> 指针的大小，在32位系统下是4个字节

sizeof(数组名) 求的是 数组的大小 数组名 不是指针 但神似指针 所以sizeof（数组名） =  sizeof(sizeof(数组类型)) * 数组大小

&a 数据类型是 int(*)[5] a 数据类型是 int[5] //ps是数组类型 pps 数组是一种数据类型 &a+1 数据类型是 int(*)[5] a+1 数据类型是 int*  你可以直接  sizeof(int[5]) sizeof(int*) 看到这些数据类型的大小

sizeof(a) = 4 * 5 = 20 其他的都是指针, 长度 4

刚才的格式有问题  int a[5]; &a 的类型是 pointer to an array of five integers &a + 1 是指向下一个 five integers, 在数值上要加上 sizeof(a) = 4 * 5 = 20; 也就是说 &a + 1 在数值上等于 ((char *)&a) + sizeof(a); a--------------------&a+1--------------- ----------------------------------------- || 1 | 2 | 3 |4 | 5 || 1 | 2 | 3 |4 |5 || -----------------------------------------

引用 5 楼 fdsafwagdagadg6576 的回复:int a[5]={1,2,3,4,5}; adl1=sizeof(&a+1); 结果是4  int *ptr11=(int*)(&a+1); printf ("%x",ptr11[-1]) 结果是5  为什么呢 int a[5]={1,2,3,4,5}; adl1=sizeof(&a+1); 结果是4 &a是个指针，指针 + 1还是指针 sizeof(指针) = sizeof( void *);   int *ptr11=(int*)(&a+1); printf ("%x",ptr11[-1])  int a[5]; &a 的类型是 pointer to an array of five integers &a + 1 是指向下一个 five integers, 在数值上要加上 sizeof(a) = 4 * 5 = 20; 也就是说 &a + 1 在数值上等于 ((char *)&a) + sizeof(a); a____________________&a+1________________ ----------------------------------------- || 1 | 2 | 3 |4 | 5 || 1 | 2 | 3 |4 |5 || -----------------------------------------                          这个在C89标准里有明确的说明  3.3.6 Additive operators  Syntax            additive-expression:                   multiplicative-expression                   additive-expression +  multiplicative-expression                   additive-expression -  multiplicative-expression  Constraints     For addition, either both operands shall have arithmetic type, or one operand shall be a pointer to an object type and the other shall have integral type.  (Incrementing is equivalent to adding 1.)     For subtraction, one of the following shall hold:    * both operands have arithmetic type;    * both operands are pointers to qualified or unqualified versions of    compatible object types; or   * the left operand is a pointer to an object type and the right    operand has integral type.  (Decrementing is equivalent to subtracting 1.)  Semantics     If both operands have arithmetic type, the usual arithmetic conversions are performed on them.     The result of the binary + operator is the sum of the operands.     The result of the binary - operator is the difference resulting from the subtraction of the second operand from the first.     When an expression that has integral type is added to or subtracted from a pointer, the integral value is first multiplied by the size of the object pointed to.  The result has the type of the pointer operand.  If the pointer operand points to a member of an array object, and the array object is large enough, the result points to a member of the same array object, appropriately offset from the original member.  Thus if P points to a member of an array object, the expression P+1 points to the next member of the array object.  Unless both the pointer operand and the result point to a member of the same array object, or one past the last member of the array object, the behavior is undefined.  Unless both the pointer operand and the result point to a member of the same array object, or the pointer operand points one past the last member of an array object and the result points to a member of the same array object, the behavior is undefined if the result is used as the operand of a unary * operator.     When two pointers to members of the same array object are subtracted, the difference is divided by the size of a member.  The result represents the difference of the subscripts of the two array members.  The size of the result is implementation-defined, and its type (a signed integral type) is ptrdiff_t defined in the <stddef.h> header.  As with any other arithmetic overflow, if the result does not fit in the space provided, the behavior is undefined.  If two pointers that do not point to members of the same array object are subtracted, the behavior is undefined.  However, if P points either to a member of an array object or one past the last member of an array object, and Q points to the last member of the same array object, the expression (Q+1) - P has the same value as (Q-P) + 1 , even though Q+1 does not point to a member of the array object.

嗯，指针一般都占四个字节，一楼回答一针见血 另外，提醒一下楼主，代码中的标识符最好不要用L（大小写都不要用），容易让人误会

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

printf ("%x",ptr11[-1]) 结果是5  为什么呢   自己顶

&a是求存储数组a[5]的首地址的地址，而地址是long型的，是4个字节，所以adl为4； sizeof（数组首地址）相当于求整个数组所占的字节数，所以al=5*sizeof（a[0]）=5*4=20,其中5为数组个数； adl1其实相当于求一个long型数据的字节数，即为4，千万不要被a所迷惑了，只要一对a取地址，所得即为指向数组首地址的地址； al1相当于sizeof(a[1]),所以即为4.


Question: 今天的华为上级题第一道，求解

还可以使用两个线程，一个将产生的结果存入文件中，另一个sleep（）10秒，然后输出文件内存

引用 3 楼 chybeyond123456789 的回复:引用 1 楼 lovesmiles 的回复:计算出起始字节，按位与或并算就行了。多行输入怎么实现，什么时候结束？定时，现将输出存放在文件中，每执行一次写一次换行。十秒产生一个信号后打印文件中所有的数据，（我感觉这样可以）

引用 1 楼 lovesmiles 的回复:计算出起始字节，按位与或并算就行了。+1

计算出起始字节，按位与或并算就行了。


Question: fork ,vfork

回复4楼： (1)pid_t可以当做windows下的进程句柄看，但是句柄是一个广义的概念，在Windows中，任何通过操作系统API创建的东西都返回一个句柄，句柄就是一个指针（在我的vs中）；pid_t只有当创建一个进程时才能得到，在UNIX系统中，描述符使用的比较广泛，比如打开一个文件（open），会得到一个文件描述符，描述符通常是一个int类型的变量。  (2)我提供的命令没问题，是你用错了，命令ps的参数我可没有加横线哦 ps aux | grep ‘Test'  (3)system('pause')，pause是Windows下的命令，Linux是没有这个命令的，但是有一个函数，pause()，在头文件unistd.h中  稍稍修改后，代码如下：   #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h>  int gval = 0;  int main () {   int nval = 7;    pid_t pid = fork();    if (pid < 0)     return -1;    if (0 == pid) { // child     gval++;     nval++;      printf("In child process %u\n", (unsigned int)getpid());     printf("[c] %d %d\n", gval, nval);     pause();     exit(0);   } else {     printf("In parent process %u\n", (unsigned int)getpid());     printf("[p] %d %d\n", gval, nval);     wait(NULL);   }    return 0; }   输出： [root@localhost src]# ./Test In child process 5015 [c] 1 8 In parent process 5014 [p] 0 7  命令输出： [root@localhost test_env]# ps aux | grep 'Test' root      5014  0.0  0.0   1608   344 pts/2    S+   10:13   0:00 ./Test root      5015  0.0  0.0   1608   220 pts/2    S+   10:13   0:00 ./Test root      5025  0.0  0.0   4016   672 pts/3    R+   10:14   0:00 grep Test

引用 3 楼 user-2 的回复:先入为主而已。楼主先接触Windows的进程，所以总会想在POSIX标准的OS中找到Windows已有的功能。找不了就难免有些失望  帮忙看4楼

引用 2 楼 jwj070524 的回复:（1）你创建的进程当然有名字了，如果父进程名字叫A，fork之后，若没有使用exec系列的函数执行其他程序的话，子进程的名字跟父进程一样，LInux命令"ps aux | grep 'A'"就可以看到了 （2）一个进程fork时，操作系统会新建一个进程，复制父进程的所有代码与数据，成为自身进程的执行环境，此次此刻，父子进程的状态一模一样（所有数据，包括各种描述符等，堆栈以及保存的cpu寄存器值），唯一的不同是：父子进程从系统调用fork中得到的返回值，父进程得到子进程的pid，子进程得到0，这个是操作系统实现的，应用程序据此判断自己是父还是子。   1. pid_t 是不是类似widnows 下的句柄？  2. 你提供的命令有问题。  我发我的命令给你看：   ps -aux | grep -i "Test"  可执行文件名字叫Test ，所以 我这样匹配，应该对啊。  结果为（你看图）   http://i2.tietuku.com/4d48b0c0578c0985.jpg  复制链接，就可以看到图了。 图中，没有看到2个进程，怎么回事？    另外付程序代码： #include <iostream> #include<unistd.h> #include<stdio.h> #include<dirent.h> #include<string.h> #include<sys/stat.h> #include<stdlib.h>  using namespace std;  //extern char* const* environ; int gval = 0; int main() { 	int nval = 7; 	pid_t pid; 	pid = fork(); 	if(pid < 0 ) 		return -1; 	if( pid ==0 ) 	{ 		gval++; 		nval++; 		printf("in child process\n"); 		printf("%d %d\n",gval, nval); 		system("pause"); 		_exit(0); 	} 	else 	{ 		printf("in parent process\n"); 		printf("%d %d\n",gval, nval); 	} 	system("pause"); 	return 0; 	//execve("new", "", environ); }    注意代码中有 system("pause");  说明 程序不会关闭，除非强制关闭。  我在shell中 ./Test运行程序的。  然后terminal没有关闭。


Question: 还是sizeof与strlen的问题

你记住一点.   strlen    是计算字符串长度的.  只有要计算字符串的长度, 才能使用这个函数.   就不会乱了.  strlen   ==   string lenght  sizeof是编译的时候就执行的,   也就是"类似"一个宏. 而strlen是程序执行过各中调用, 它是一个函数.

sizeof 是操作符（关键字）所求的是类型的大小，编译时就有结果；strlen是函数，计算的是字符串的长度，要在程序中运行时才会出现；

strlen是个函数， 在运行时计算， sizeof是个运算符， 在编译时就出结果了。

说的有道理   学习了

比如有一个300ml的瓶子，装了150ml的水，sizeof会得到300，strlen得到150 sizeof里边如果是一个指针，那么就是计算指针所占的空间，32位系统一般就是4. “hello”这个常量字符串共有5个字符和一个隐含的结束符'\0'，所以char str[] 的总空间就是5+1=6.（定义数组如果不标明元素个数，在初始化时系统会根据后边的常量值自动计算）

sizeof的源代码在编译器中 strlen的源代码在库函数中

sizeof求的是编译系统跟变量分配的空间数。不同的编译系统分配的空间也不同。turbo-c给指针分配的是2个字节。

sizeof()是求数组或变量所占的字节数；在第一个sizeof (str)中，它是包括'\0'的。而第二个sizeof表示的是字符串指针变量所占的字节，即4。 strlen()是字符串的长度，不包含‘\0’；

这种问题还要问？百度一下不就知道了吗

第一：字符串在使用sizeof计算时是要计算字符串结束符的，但是strlen是不计算字符串结束符的，所以会相差1； 第二：一个是字符数组，一个字符指针；对于指针变量都是4个字节（在32系统）；

其实char str[] = {'h', 'e', 'l', 'l', 'o', '\0'}

sizeof得到的是所占的字节，strlen得到的是字符串长度 第二个是个字符指针，一般是4个字节


Question: 关于数据类型转换之间的错误！求指教！！附程序 运行结果

引用 4 楼 u012861727 的回复:[quote=引用 3 楼 zxh707wk 的回复:] 自己写个输入浮点数的函数 能说的具体点吗[/quote]好吧，具体点：自己本人用c语言写个实现能输入浮点数的函数

引用 3 楼 zxh707wk 的回复:自己写个输入浮点数的函数 能说的具体点吗

自己写个输入浮点数的函数

非常好的帖子 但是估计我为了解决这个问题而要看懂这个帖子要花太多时间了 水平还不够 跪求更直接或者水平低一点的解决方法


Question: 帮忙推荐一本C语言经典书籍

C程序设计语言。

msdn98下载地址我也没现成的。 自己搜搜看。

引用 3 楼 zhao4zhong1 的回复:查MSDN是Windows程序员必须掌握的技能之一。 搜索下载安装MSDN98： mk:@MSITStore:C:\MSDN98\98VS\2052\vccore.chm::/html/_crt_run.2d.time_routines_by_category.htm Run-Time Routines by Category This chapter lists and describes Microsoft run-time library routines by category. For reference convenience, some routines are listed in more than one category. Multibyte-character routines and wide-character routines are grouped with single-byte – character counterparts, where they exist. msdn98下载地址找不到，能不能给个啊？

觉得楼主表达的就有问题 “C语言的api函数”？  介绍windows程序设计的基础书籍：《windows程序设计》 这本书当然是用C。。。

引用 6 楼 gojoy_x13 的回复:谭浩强的 c程序设计 薛非的 品悟c

引用 7 楼 u012184298 的回复:[quote=引用 6 楼 gojoy_x13 的回复:] 谭浩强的 c程序设计 薛非的 品悟c[/quote] 同意这两本书很经典的，完全超过 C专家编程 和 C和指针

领教领教来来来~

《编译原理及实践》 && 《深入理解计算机系统》

《C primer plus》感觉很很基础，也很经典

《Windows 程序设计》+《Windows核心编程》

引用 6 楼 gojoy_x13 的回复:谭浩强的 c程序设计 薛非的 品悟c

谭浩强的 c程序设计 薛非的 品悟c

引用 4 楼 max_min_ 的回复:c和指针吧！比较基础浅显！ ps：c语言和windows有什么关系？为毛推荐windowswindows桌面用户多。。。

查MSDN是Windows程序员必须掌握的技能之一。 搜索下载安装MSDN98： mk:@MSITStore:C:\MSDN98\98VS\2052\vccore.chm::/html/_crt_run.2d.time_routines_by_category.htm Run-Time Routines by Category This chapter lists and describes Microsoft run-time library routines by category. For reference convenience, some routines are listed in more than one category. Multibyte-character routines and wide-character routines are grouped with single-byte – character counterparts, where they exist.  The main categories of Microsoft run-time library routines are:  Argument access Floating-point support  Buffer manipulation Input and output  Byte classification Internationalization  Character classification Memory allocation  Data conversion Process and environment control  Debug Searching and sorting  Directory control String manipulation  Error handling System calls  Exception handling Time management  File handling

想学习 windows sdk/c 编程，1楼那本就可以。 如果是想学习c语言本身的话，推荐：C语言程序设计 现代方法

windows程序设计


Question: 关于命令行参数的问题

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括C++）、架构……  命令行解释器概述 命令行解释器是一个单独的软件程序，它可以在用户和操作系统之间提供直接的通讯。非图形命令行解释器用户界面提供运行基于字符的应用程序和实用程序的环境。通过使用类似于 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。

引用 7 楼 mymtom 的回复:命令的相关资料？嗯。这个初学者需要了解吗？

命令的相关资料？

引用 1 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/390469280  待我复制到Word里再看……这里看着太麻烦了

引用 3 楼 mymtom 的回复:修改该过的程序如下  #include<stdio.h> #include<string.h> #define MAXLINE 1000   int my_getline(char *line,int size);   int main(int argc,char *argv[]) {     char line[MAXLINE];     long lineno = 0;     long c, except = 0, number = 0,found = 0;       while(--argc > 0 && (*++argv)[0] == '-')         while(c = *++argv[0])             switch(c){             case 'x':                 except = 1;                 break;             case 'n':                 number = 1;                 break;             default :                 printf("find: illeagal option %c\n",c);                 argc = 0;                 found = -1;                 break;         }     if(argc != 1)         printf("Usage: find -x -n pattern\n");     else         while(my_getline(line,MAXLINE) > 0){             lineno++;             if((strstr(line,*argv)!= NULL) != except){                 if(number)                     printf("%5ld:  ",lineno);                 printf("%s",line);                 found++;             }         }          return found; }   int my_getline(char *s,int size) {     int c,i;      for(i = 0;i < size - 1 && (c=getchar())!=EOF && c!='\n'; ++i)         *s++ = c;     if(c=='\n'){         ++i;         *s++ = c;     }     *s = '\0';     return i; }   找出含有main的行 ./find -n main < find.c     7:  int main(int argc,char *argv[])  找出不含等号"="的行  ./find -x -n "=" < find.c     1:  #include<stdio.h>     2:  #include<string.h>     3:  #define MAXLINE 1000     4:        5:  int my_getline(char *line,int size);     6:        7:  int main(int argc,char *argv[])     8:  {     9:      char line[MAXLINE];    12:       15:              switch(c){    16:              case 'x':    18:                  break;    19:              case 'n':    21:                  break;    22:              default :    23:                  printf("find: illeagal option %c\n",c);    26:                  break;    27:          }    29:          printf("Usage: find -x -n pattern\n");    30:      else    31:          while(my_getline(line,MAXLINE) > 0){    32:              lineno++;    34:                  if(number)    35:                      printf("%5ld:  ",lineno);    36:                  printf("%s",line);    37:                  found++;    38:              }    39:          }    40:      41:          return found;    42:  }    43:       44:  int my_getline(char *s,int size)    45:  {    46:      int c,i;    47:      51:          ++i;    53:      }    55:      return i;    56:  }  按着您的，我这样可以调用了，能不能给点儿相关资料？就是这些命令方面的

引用 1 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/390469280+1

楼主的程序有问题啊 48行 *s = c; 应该是 *s++ = c; 49-51行，要加个++i;     if(c=='\n'){         *s++ = c;     } ===>     if(c=='\n'){         ++i;         *s++ = c;     }  find -x -n pattern 程序的用途就是匹配pattern的行啊，比如 find main 就是找出含有main的行， find -x main 就是找出不含main的行， -n 参数表示要输出行号


Question: 关于斐波那契查找

楼主是否仔细思考过这个问题？ 可以看看这个——http://v.163.com/movie/2011/12/H/S/M7KV3072J_M89ASJKHS.html

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


Question: 新手提问！关于stdbool.h的问题

谢谢大家！我选择了dev-c++

引用 6 楼 conanky 的回复:请问你们都用什么编译器，我也觉得vc6不好  vc6是轻便，但是你用c++，总得对c++标准支持的好点吧。vc6都是什么年代的老古董了，可以用vc2012。

引用 8 楼 conanky 的回复:谢谢，还有其他推荐吗？  大型的IDE必须是 vs2010 vs2012 vs2013 较小型的推荐 code::blocks

dev c++ c-free

dev-c++ code::blocks 这两款都是不错的免费IDE，前者自带中文，对新手友好，后者我很喜欢它的工作空间可以多开

谢谢，还有其他推荐吗？

请问你们都用什么编译器，我也觉得vc6不好

自己定TRUE FALSE吧。

建议换个编译器，对C99支持较好的

不要用vc6.0了，太老了，都不符合最新标准了。。。

stdbool.h/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.  This file is part of GCC.  GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version.  GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.  You should have received a copy of the GNU General Public License along with GCC; see the file COPYING.  If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */  /* As a special exception, if you include this header file into source    files compiled by GCC, this header file does not by itself cause    the resulting executable to be covered by the GNU General Public    License.  This exception does not however invalidate any other    reasons why the executable file might be covered by the GNU General    Public License.  */  /*  * ISO C Standard:  7.16  Boolean type and values  <stdbool.h>  */  #ifndef _STDBOOL_H #define _STDBOOL_H  #ifndef __cplusplus  #define bool    _Bool #define true    1 #define false   0  #else /* __cplusplus */  /* Supporting <stdbool.h> in C++ is a GCC extension.  */ #define _Bool   bool #define bool    bool #define false   false #define true    true  #endif /* __cplusplus */  /* Signal that all the definitions are present.  */ #define __bool_true_false_are_defined   1  #endif  /* stdbool.h */


Question: 请看看程序中的数组有无初始化，哪些需要注意的

#include <iostream> #include <string>       // string #include <map>          // multimap #include <functional>   // greater #include <sstream>      // istringstream #include <cstdlib>      // system("pause") using namespace std;  typedef multimap<int, string, greater<int>>::iterator Iterator;  int main() { 	string s, buf; 	multimap<int, string, greater<int>> str;    // greater<int>指定按key降序排列  	getline(cin, s);                            // 读取一行 	istringstream ss(s);                        // 用字符流读取每个单词 	while (ss >> buf)                           // 循环将每个单词加入multimap 	{ 		str.insert(make_pair(buf.size(), buf)); 	}  	Iterator beg = str.begin(); 	int i = beg->first;                         // i就是最长的单词长度 	while (beg != str.end()) 	{ 		if (beg->first == i) 		{ 			cout << beg->second << endl; 			++beg; 		} 		else 		{ 			break; 		} 	} 	system("pause"); 	return 0; }   输入：  it string abc buffer iter is stream  输出：  string buffer stream 请按任意键继续. . .


Question: 使用fseek后，fscanf无法读取文件中数据

用记事本打开文件看看就知道了

引用 1 楼 brookmill 的回复:文件是用文本方式打开的，最后一个double不一定是在离文件尾部8个字节处+1

你确定是离尾部八字节处吗？

fp_account = fopen(“A.txt”,"rb");

文件是用文本方式打开的，最后一个double不一定是在离文件尾部8个字节处


Question: C语言位操作结果取决于硬件，关于位字段和位的对应关系的问题

掩码是应用于从右向左装入的前八位的，例如0121


Question: 有关于TCP数据包包头包尾的处理

谢邀，我个人网络方面的还在学习中，这个问题暂时不知道怎么回答。

问题是啥？ 还有  包头+数据，包头包含数据长度，还有加包尾处理干啥？

What are u talking about?

引用 3 楼 cheng7068 的回复:给了一段函数，请问你的问题是什么呢这个是公司规定的数据包协议，咱们不用管。关键是包头+长度+数据+包尾，我怎么来解析出包头包尾看是否是合法的数据包。是的话，num+1，否则继续寻找。然后，我编写的代码不能实现这个功能，所以过来求助。

引用 2 楼 max_min_ 的回复:问题是啥？ 还有  包头+数据，包头包含数据长度，还有加包尾处理干啥？这个是公司规定的数据包协议，咱们不用管。关键是包头+长度+数据+包尾，我怎么来解析出包头包尾看是否是合法的数据包。是的话，num+1，否则继续寻找。然后，我编写的代码不能实现这个功能，所以过来求助。

引用 1 楼 lineage191 的回复:What are u talking about?我需要接受一个数据包，然后解析该数据包的包头包尾，看是否为我们所需要的数据包，是的话，num+1，否则继续寻找。然后，我编写的代码不能实现这个功能，所以过来求助。

不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545

给了一段函数，请问你的问题是什么呢


Question: 优先级逆转

引用 12 楼 DelphiGuy 的回复:在循环中调用SwitchToThread()释放时间片的代价有点大，这意味着当前线程在当前处理器上的线程队列中要重新排队，（正常情况下）要执行一圈之后才能再次得到执行，如果活跃线程比较多、当前线程的优先级比较低，那可能要挂起比较长的时间，比如一两秒甚至更长。还是用Sleep/SleepEx释放一点时间片好一些，这只是暂时挂起当前线程一段时间，之后该线程会得到优先执行。  低优先级的饥饿线程， 达到3-4秒钟时候，系统会强制将其优先级提到15. 给2个cpu时间片。  最后回到该线程的基本优先级的。  也就所， 根本不存在 作者的说法，“This can happen if the primary thread has a higher priority than the thread executing the RecalcFunc function. In this case, the system never assigns any time slices to the RecalcFunc thread, which never executes the statement that sets g_fFinishedCalculation to TRUE.”  这段文字是有问题的。   当然，只是以下的做法，效率低一些而已。  volatile BOOL g_fFinishedCalculation = FALSE 主线程 { 创建子线程 while(!g_fFinishedCalculation);  }  子线程代码：  { g_fFinishedCalculation = TRUE; }  效率低， 不代表子线程没有机会执行。 在单核cpu上也是有执行机会的。  无论多核，单核。都有机会。  作者的说法不对

引用 10 楼 DelphiGuy 的回复:我觉得作者说的有问题，高优先级线程占用CPU时间多（比如一直轮询某个状态）并不代表低优先级线程得不到执行，抢先式多任务调度的处理方式是根据优先级和建立顺序进行排队，高优先级线程执行过一遍之后才轮到优先级低一档的线程执行。 当然作者说你不要一直轮询、要在循环中经常释放一点时间片，这肯定是好的编程习惯，可以降低CPU占用率、加快任务流转的速度、提高GUI的响应速度等等。 另外，7楼的代码是不会造成死循环的，只是因为他的代码子线程优先级低、循环时间长而已，把WORK_LOOP减小一下就可以看出来。比如这样（注意略加修改是为了便于使用非ms编译器通过，不影响代码执行效果）：  #include <stdio.h> #include <windows.h>   #pragma optimize("", off) #define WORK_LOOP 5000000   volatile BOOL g_fFinishedCalculation = FALSE;   DWORD WINAPI RecalcFunc(PVOID pvParam)  {     SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);     for (int i = 0; i < WORK_LOOP; i++);     printf("secondary thread done.\n");     g_fFinishedCalculation = TRUE;     return 0; }   DWORD WINAPI SomeOtherFunc(PVOID pvParam)  {     while (!g_fFinishedCalculation)         //Sleep(100);         ;     return 0; }   int main(int argc, char* argv[]) {       HANDLE hThread1 = (HANDLE)CreateThread(NULL, 0 , SomeOtherFunc, NULL, 0, NULL);     HANDLE hThread2 = (HANDLE)CreateThread(NULL, 0 , RecalcFunc, NULL, 0, NULL);           while (!g_fFinishedCalculation)         //Sleep(100);         ;     printf("primary thread done.\n");      CloseHandle(hThread1);     CloseHandle(hThread2);     return 0; }  你说对了，  作者的说法是扯淡，错误的。  我在你的代码基础修改一下；   #define WORK_LOOP 5000000  volatile BOOL g_fFinishedCalculation = FALSE;  DWORD WINAPI RecalcFunc(PVOID pvParam)  { 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); 	for (int i = 0; i < WORK_LOOP; i++); 	printf("secondary thread done.\n"); 	g_fFinishedCalculation = TRUE; 	return 0; }  DWORD WINAPI SomeOtherFunc(PVOID pvParam)  { 	while (!g_fFinishedCalculation) 		SwitchToThread(); 	return 0; }  int main(int argc, char* argv[]) {  	HANDLE hThread1 = (HANDLE)CreateThread(NULL, 0 , SomeOtherFunc, NULL, 0, NULL); 	HANDLE hThread2 = (HANDLE)CreateThread(NULL, 0 , RecalcFunc, NULL, 0, NULL);  	while (!g_fFinishedCalculation) 		SwitchToThread(); 	printf("primary thread done.\n");  	CloseHandle(hThread1); 	CloseHandle(hThread2); 	return 0; }   这才是更好的做法

引用 3 楼 angel_su 的回复:貌似只有你的测试的进程在跑，其他进程都处于等待，所以没有卡死。试试另外跑个while(1);进程，你的测试进程就会卡死，但是不要一直轮询sleep一下，优先继较低的子线程又会执行了...  现在才看到3楼有回复：  “貌似只有你的测试的进程在跑，其他进程都处于等待，所以没有卡死。试试另外跑个while(1);进程，你的测试进程就会卡死，但是不要一直轮询sleep一下，优先继较低的子线程又会执行了... ”  貌似只有你的测试的进程在跑，其他进程都处于等待，所以没有卡死  这是不可能的，你的依据是什么？    但是不要一直轮询sleep一下，优先继较低的子线程又会执行了  但是不要，  这是汉语的病句吗， 没有看懂，能不能说详细一点。

引用 7 楼 angel_su 的回复:我在3楼说会卡死的类似下面代码，取消注释开启某一个sleep就能正常，感觉作者本意应改是在说用polling方法不妥，即便不卡死也浪费大量cpu时间...#include "stdafx.h" #include <Windows.h>  #pragma optimize("", off) #define WORK_LOOP 500000000  BOOL g_fFinishedCalculation = FALSE;  DWORD WINAPI RecalcFunc(PVOID pvParam)  { 	SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); 	for (int i = 0; i < WORK_LOOP; i++) 			;     g_fFinishedCalculation = TRUE;     return 0; }  DWORD WINAPI SomeOtherFunc(PVOID pvParam)  { 	while (!g_fFinishedCalculation) 		//Sleep(100); 		;     return 0; }  int _tmain(int argc, _TCHAR* argv[]) {  	HANDLE hThread1 = (HANDLE)CreateThread(NULL, 0 , SomeOtherFunc, NULL, 0, NULL);     HANDLE hThread2 = (HANDLE)CreateThread(NULL, 0 , RecalcFunc, NULL, 0, NULL); 	 	while (!g_fFinishedCalculation) 		//Sleep(100); 		;     CloseHandle(hThread1); 	CloseHandle(hThread2); 	return 0; }   1. 你的代码测试实验环境是什么？    2.  你认为 作者的那段英文有问题吗？   用单核测试  ，如果你注释掉sleep后， 程序的唯一缺点：消耗cpu，但绝对不会导致子线程永远没有机会执行。 你不信的话，可以在 线程里加上 printf语句进行验证。

引用 3 楼 angel_su 的回复:貌似只有你的测试的进程在跑，其他进程都处于等待，所以没有卡死。试试另外跑个while(1);进程，你的测试进程就会卡死，但是不要一直轮询sleep一下，优先继较低的子线程又会执行了...  我发作者源代码： int WINAPI _tWinMain(...) {    CreateThread(..., RecalcFunc, ...);    ...    // Wait for the recalculation to complete.    while (!g_fFinishedCalculation)         ;    ... }  DWORD WINAPI RecalcFunc(PVOID pvParam) {    // Perform the recalculation.    ...    g_fFinishedCalculation = TRUE;    return(0); }

高手帮忙顶一下

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

引用 1 楼 user-5 的回复:我觉得这个和操作系统的调度算法有关系。 如果调度是严格按照优先级的，只要有高优先级线程在运行，低优先级线程就没有机会，就会出现书上提到的情况。 而如果有基于时间片的调度算法，也就是说不管优先级高低都有机会运行(虽然可能机会有多有少)，那就不会出现这个状况了。  谢谢你的参与


Question: 一个函数，返回数组中最大和最小值的差值，但是我编写的程序中最大值和最小值始终是一样的。

初学c,感谢大家的帮助，这个程序是习题，一定要指针。3楼的解释启发了我，指针指向的是一个地址，*运算符是取指针指向地址的值。我对程序做了修改，成功运行了。#include<stdio.h> double sub(double ar[],int i);//找出最大最小值并返回他们的差值 void main() { 	double res; 	double ar[]={1.1,2.2,3.3,4.4,5.5,6.6}; 	res=sub(ar,6); 	printf("数组中最大数和最小数之差是%Lf\n",res); 	system("pause"); }  double sub(double ar[],int i) { 	double sub; 	int n; 	double * min; 	double * max;  	min=ar; 	max=ar; //	*min=ar[0]; //	*max=ar[0]; 	for(n=0;n<i;n++) 	{ 		if(*min>ar[n])//如果当前的min比要比较的数大，那么则更新为比较小的数 			//*min=ar[n];这句是指针的地址不变，给指针指向的地址重新赋值。 			min=&ar[n];//这句是直接让指针指向一个新的地址，就不会和max指针发生冲突了。 		if(*max<ar[n])//如果当前的max比要比较的数小，那么则更新为比较大的数 			//*min=ar[n]; 			max=&ar[n]; 	} 	printf("max is %Lf,min is %Lf",*max,*min); 	sub=*max-*min; 	return sub; }

#include<stdio.h> #include<malloc.h> double sub(double ar[],int i);//找出最大最小值并返回他们的差值  int main() {     double res;     double ar[]={1.1,2.2,3.3,4.4,5.5,6.6};     res=sub(ar,6);     printf("数组中最大数和最小数之差是%Lf\n",res); 	 	return 0; }   double sub(double ar[],int i) {     double sub;     int n;     double * min;     double * max;       min = malloc(sizeof(double));     max = malloc(sizeof(double));     *min=ar[0];     *max=ar[0];     for(n=0;n<i;n++)     {         if(*min>ar[n])//如果当前的min比要比较的数大，那么则更新为比较小的数             *min=ar[n];         if(*max<ar[n])//如果当前的max比要比较的数小，那么则更新为比较大的数             *max=ar[n];     }     printf("max is %Lf,min is %Lf",*max,*min);     sub=*max-*min;      return sub; } vs2010编译通过，结果也没错。楼主思路是没什么错，完全按照逻辑来，于是用malloc，可能有点杀鸡用牛刀了。可能有其它更好的方法，但是我懒得想了。一楼的话可能有些伤人了，但是要敢问问题，不要怕丢脸，害羞什么的。当然，问的问题，应该是仔细思考后，实在无法独立解决的。

楼主不清楚指针就不要乱用啊！两个指向了同一个地址， 好好看看指针吧 #include<stdio.h> double sub(double ar[],int i);//找出最大最小值并返回他们的差值 int main() { 	double res; 	double ar[]={1.1,2.2,3.3,4.4,5.5,6.6}; 	res=sub(ar,6); 	printf("数组中最大数和最小数之差是%Lf\n",res); //	system("pause"); 	 	return 0; }  double sub(double ar[],int i) { 	double sub; 	int n; 	double min; 	double max;  //	min=ar; //	max=ar; 	min=ar[0]; 	max=ar[0]; 	for(n=0;n<i;n++) 	{ 		if(min>ar[n])//如果当前的min比要比较的数大，那么则更新为比较小的数 			min=ar[n]; 		if(max<ar[n])//如果当前的max比要比较的数小，那么则更新为比较大的数 			max=ar[n]; 	} 	printf("max is %Lf,min is %Lf",max,min); 	sub=max-min; 	return sub; }

当时十二点了，脑子不太好使，今天再看看，楼上说的没错，好像不用malloc

实际开发中这个用指针可能确实有点儿复杂，不过研究一下指针的用法我觉得思路 不错呢。 呵呵，弱弱的说，我虽然大概知道问题在哪儿，但也不是完全想明白了，6楼的解答很有用，但是我理解声明min和max这两个指针变量的时候，不就已经为这两变量分配了存储地址了么？按照楼主的思路和我所理解的指针，不断改变指针指向内容，for循环执行结束后，这两个地址里面存储的内容，应该就是最大值、最小值的地址了呗，为啥还要malloc一下呢？

double sub(double ar[],int i) {     double sub;     int n;     double * min;     double * max;       min=ar; // 这里，你的min，max本身没有申请内存，而是同时指向了ar数组的第0个元素                     //*min,*max 实际上都是a[0]     max=ar;     *min=ar[0]; // 此时的*min实际上就是ar[0]，你这一行的代码相当于ar[0] = ar[0]     *max=ar[0];//*max实际上也是ar[0]，你这一行的代码依然还是相当于ar[0] = ar[0]     for(n=0;n<i;n++)     {         if(*min>ar[n])             *min=ar[n]; // *min实际上就是ar[0]，你这一行的代码相当于ar[0] = ar[n]         if(*max<ar[n])             *max=ar[n]; // *max实际上就是ar[0]，你这一行的代码相当于ar[0] = ar[n]     }          //以上找出来的最大值，最小值，统统都是存在ar[0]中的，所以你下面*max-*min     //相当于ar[0] - ar[0]           printf("max is %Lf,min is %Lf",*max,*min);     sub=*max-*min;     return sub; }

怎么说呢，被你的指针绕晕了。 其实把指针全部去掉这个程序就差不多没什么问题了。

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

#include<stdio.h> double sub(double ar[],int i);//找出最大最小值并返回他们的差值 int main(void) { 	double res; 	double ar[]={1.1,2.2,3.3,4.4,5.5,6.6}; 	res=sub(ar,6); 	printf("数组中最大数和最小数之差是%Lf\n",res); 	//system("pause"); 	getchar(); 	return 0; }  double sub(double ar[],int i) { 	double sub; 	int n; 	double  min; 	double  max;  	//min=ar; 	//max=ar; 	min=ar[0]; 	max=ar[0]; 	for(n=0;n<i;n++) 	{ 		if(min>ar[n])//如果当前的min比要比较的数大，那么则更新为比较小的数 			min=ar[n]; 		if(max<ar[n])//如果当前的max比要比较的数小，那么则更新为比较大的数 			max=ar[n]; 	} 	printf("max is %Lf,min is %Lf",max,min); 	sub=max-min; 	return sub; } 不要乱用指针，你用两个指针指到同一个地址，那么从这个地址取出的值肯定是相同的.

看到这个，我笑了。。。 #include<stdio.h> double sub(double ar[],int i);//找出最大最小值并返回他们的差值 void main() {     double res;     double ar[]={1.1,2.2,3.3,4.4,5.5,6.6};     res=sub(ar,6);     printf("数组中最大数和最小数之差是%Lf\n",res);     system("pause"); }   double sub(double ar[],int i) {     double sub;     int n;     double * min;     double * max;       min=ar;     max=ar;     for(n=0;n<i;n++)     {         if(*min>ar[n])//如果当前的min比要比较的数大，那么则更新为比较小的数             min=&ar[n];         if(*max<ar[n])//如果当前的max比要比较的数小，那么则更新为比较大的数             max=&ar[n];     }     printf("max is %Lf,min is %Lf",*max,*min);     sub=*max-*min;     return sub; }


Question: 上海贝尔笔试题   为什么程序这样执行？

int minus(int a, int b) {    cout<<a<<" "<<b<<endl;    return a-b; } int main() { 	int c=4; 	int d=3; 	printf("%d", minus(++c, ++c));         printf("%d", minus(d++, d++)); 	system("pause"); } 在win7 vs2010中，输出结果为6 6 0,4 3 1

printf后面从右往左进行计算！

win7 64位  vs2010 表示运行之后的结果是0

这种题，没啥意思

我就是面试过这样的问题，当时没找到地方，耽误了半小时，然后是各种刁难，

难怪上海贝尔活不下去，要和人家合并。

不同的编译器有不同的实现

引用 4 楼 FightForProgrammer 的回复:win7  vs2012 表示运行之后的结果是0 和我结果一样，这种东西和编译器有关的，再说，实际应用中写这样代码的自己都要疯掉

引用贴里关于这个问题讲得好明确！

结果未定义。这种公司不用去了。

好蛋疼的笔试题

引用 34 楼 FrankHB1989 的回复:[quote=引用 16 楼 my3439955 的回复:] 这个题不是普通的考察++的顺序或结合性，他考察的关键点是函数调用的入栈顺序。就是问你觉得执行的流程是怎样的？  一般的，在vc环境中，cdecl是默认的调用约定，参数的入栈顺序是由右至左，参数的求值顺序也是由右至左，所以是后一个参数先++，前边的参数后++，前边的参数比后边的参数大  具体实现和编译器相关，只要答出入栈顺序就好了 这是连求值都没概念的典型瞎扯蛋。 C都没给你保证这里就应该有个栈，关入栈几毛钱关系？  [/quote]  好臭的嘴

引用 16 楼 my3439955 的回复:这个题不是普通的考察++的顺序或结合性，他考察的关键点是函数调用的入栈顺序。就是问你觉得执行的流程是怎样的？  一般的，在vc环境中，cdecl是默认的调用约定，参数的入栈顺序是由右至左，参数的求值顺序也是由右至左，所以是后一个参数先++，前边的参数后++，前边的参数比后边的参数大  具体实现和编译器相关，只要答出入栈顺序就好了 这是连求值都没概念的典型瞎扯蛋。 C都没给你保证这里就应该有个栈，关入栈几毛钱关系？

上海贝尔原来有这么SB么。

引用 19 楼 zhao4zhong1 的回复:http://bbs.csdn.net/topics/370153775 谢谢赵老师！学习了

应该就是考察入栈顺序的问题，不过出的太不严谨了！

gcc编译后执行值是0

引用 26 楼 u012421456 的回复:[quote=引用 7 楼 lovesmiles 的回复:] 呵呵，又是i++，楼主看下置顶贴吧，这出题的人估计会被喷  这种问题，不想多说，置顶帖——http://bbs.csdn.net/topics/370153775[/quote]++

引用 1 楼 zxh707wk 的回复:这样可以看懂了吧 int minus(int a, int b) {    return a-b; } int c=4; int a=++c; int b=++c; printf("%d", minus(a, b)) ； 误人子弟啊

调用方式，开始以为是0


Question: ACM 1002 究竟错在哪里了？ 求指点

还是发现了很多小Bug  终于AC过了，谢谢提醒 #include    "stdio.h" #include <string.h>  char* super_sum(const char* pS1, const char *pS2, char *pSum) { 	const char *pBigger = pS1, *pSmaller = pS2; 	int len1, len2, small = 0, big = 0, sum =0, added =0; 	if((!*pS1) || (!*pS2)) 	{ 		return 0; 	}  	len1 = strlen(pS1); 	len2 = strlen(pS2);  	if(len1 <= len2) 	{ 		small = len1; 		big = len2; 	} 	else 	{ 		big = len1; 		small = len2; 	}  	if(small != big) 	{ 		pBigger = (len1<len2)? pS2 : pS1; 		pSmaller= (len1<len2)? pS1 : pS2; 	}  	while(small) 	{ 		sum = pSmaller[small-1] - '0' + pBigger[big-1] - '0' + added; 		if(sum > 9) 		{ 			pSum[big] = sum - 10 + '0'; 			added =1; 		} 		else 		{ 			pSum[big] = sum + '0'; 			added =0; 		} 		small--; 		big--; 	}  	while(big) 	{ 		sum = pBigger[big-1] - '0' + added; 		if(sum > 9) 		{ 			pSum[big] = sum - 10 + '0'; 			added =1; 		} 		else 		{ 			pSum[big] = sum + '0'; 			added =0; 		} 		big--; 	} 		 	/* Processing the first bit */ 	pSum[0] = added ? '1' : 0; 	return pSum; }  int main(void) { 	int count; 	int i; 	char input1[20][1001]={0}, input2[20][1001]={0}, output[20][1001]={0}; 	 	scanf("%d", &count); 	if(count == 0) 	{ 		return 0; 	}  	i =count; 	while(i--) 	{ 		scanf("%s %s", input1[count -i -1], input2[count -i -1]); 	}  	i = 0; 	while(i < count) 	{ 		printf("Case %d:\n", i+1); 		super_sum(input1[i], input2[i], output[i]); 		printf("%s + %s = %s", input1[i], input2[i], output[i][0] ? output[i] : &output[i][1]); 		++i; 		if(i < count) 		{ 			printf("\n\n"); 		} 		else 		{ 			printf("\n"); 		} 	} }

LZ程序不能正确处理有前导0的输入，例如： 001 1

ACM的输出规则是每完成一个测试用例就输出结果，不是把结果放到数组中最后统一输出。

http://acm.hdu.edu.cn/showproblem.php?pid=1002 Problem Description I have a very simple problem for you. Given two integers A and B, your job is to calculate the Sum of A + B.    Input The first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line consists of two positive integers, A and B. Notice that the integers are very large, that means you should not process them by using 32-bit integer. You may assume the length of each integer will not exceed 1000.    Output For each test case, you should output two lines. The first line is "Case #:", # means the number of the test case. The second line is the an equation "A + B = Sum", Sum means the result of A + B. Note there are some spaces int the equation. Output a blank line between two test cases.    Sample Input 2 1 2 112233445566778899 998877665544332211    Sample Output Case 1: 1 + 2 = 3  Case 2: 112233445566778899 + 998877665544332211 = 1111111111111111110  引用 1 楼 zxhuser-3 的回复:这个代码是做啥的？

这个代码是做啥的？


Question: 这函数里的memcpy是不是多此一举?

引用 3 楼 lisong694767315 的回复:不是，bit_set(bits, i, bit_get(bits, mapping[i] - 1));一边修改bits，一边使用bits，会出错的。  再说你可以自己测试一下啊 压根没想到这点

引用 1 楼 jerry_dqh 的回复:不行，bit_get(bits, mapping[i] - 1));这里面一在使用bits，然后又赋值给bits，这样应该不行 你太强了


Question: 关于踩内存，有没有比较好的定位问题的方法，最近工作中遇到了两个，还没有解决

一群措，gdb，打个断点 然后watch下你的全局变量，当你的全局变量被改时就能抓到凶手了

引用 11 楼 a826632030 的回复:[quote=引用 5 楼 nadleeh123 的回复:] [quote=引用 楼主 a826632030 的回复:] 关于踩内存，有没有比较好的定位问题的方法，最近工作中遇到了两个，还没有解决。 苦于没有比较好的解决思路和办法  这种越界一般就是写代码的时候没做好错误处理，慢慢找吧少年，注释符能帮点忙，设断点神马的不靠谱，除非每次必现[/quote]  =========================================================== 昨天老大让通宵加班搞这个问题，纠结死了[/quote]  这种错误一般是指针没判断返回值，数组没判断下标，还有异常的同步数据IO，努力吧少年，过渡依赖工具是不行的，还得靠自己。以前调过最难的bug是写测试程序胀满cpu，能跑上1天只死个1-2次，还附带轻微的内存泄露，调了我半个多月

引用 6 楼 zhao4zhong1 的回复:[quote=引用 5 楼 nadleeh123 的回复:] [quote=引用 楼主 a826632030 的回复:] 关于踩内存，有没有比较好的定位问题的方法，最近工作中遇到了两个，还没有解决。 苦于没有比较好的解决思路和办法  这种越界一般就是写代码的时候没做好错误处理，慢慢找吧少年，注释符能帮点忙，设断点神马的不靠谱，除非每次必现[/quote] 那是因为你不会用数据断点。[/quote]  赵老师 linux 1台机器怎么设置内核debug断点啊 还有内核被飞踩了 如何确定是谁干的坏事啊  如果跟踪到了汇编部分的代码怎么玩啊

不会下数据断点，参考下面：  有时不将“调用函数名字＋各参数值，进入函数后各参数值，中间变量值，退出函数前准备返回的值，返回函数到调用处后函数名字＋各参数值＋返回值”这些信息写日志到文件中是无论如何也发现不了问题在哪里的，包括捕获各种异常、写日志到屏幕、单步或设断点或生成core文件、……这些方法都不行！ 写日志到文件参考下面： #include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef WIN32     #include <windows.h>     #include <io.h> #else     #include <unistd.h>     #include <sys/time.h>     #include <pthread.h>     #define  CRITICAL_SECTION   pthread_mutex_t     #define  _vsnprintf         vsnprintf #endif //Log{ #define MAXLOGSIZE 20000000 #define MAXLINSIZE 16000 #include <time.h> #include <sys/timeb.h> #include <stdarg.h> char logfilename1[]="MyLog1.log"; char logfilename2[]="MyLog2.log"; static char logstr[MAXLINSIZE+1]; char datestr[16]; char timestr[16]; char mss[4]; CRITICAL_SECTION cs_log; FILE *flog; #ifdef WIN32 void Lock(CRITICAL_SECTION *l) {     EnterCriticalSection(l); } void Unlock(CRITICAL_SECTION *l) {     LeaveCriticalSection(l); } #else void Lock(CRITICAL_SECTION *l) {     pthread_mutex_lock(l); } void Unlock(CRITICAL_SECTION *l) {     pthread_mutex_unlock(l); } #endif void LogV(const char *pszFmt,va_list argp) {     struct tm *now;     struct timeb tb;      if (NULL==pszFmt||0==pszFmt[0]) return;     _vsnprintf(logstr,MAXLINSIZE,pszFmt,argp);     ftime(&tb);     now=localtime(&tb.time);     sprintf(datestr,"%04d-%02d-%02d",now->tm_year+1900,now->tm_mon+1,now->tm_mday);     sprintf(timestr,"%02d:%02d:%02d",now->tm_hour     ,now->tm_min  ,now->tm_sec );     sprintf(mss,"%03d",tb.millitm);     printf("%s %s.%s %s",datestr,timestr,mss,logstr);     flog=fopen(logfilename1,"a");     if (NULL!=flog) {         fprintf(flog,"%s %s.%s %s",datestr,timestr,mss,logstr);         if (ftell(flog)>MAXLOGSIZE) {             fclose(flog);             if (rename(logfilename1,logfilename2)) {                 remove(logfilename2);                 rename(logfilename1,logfilename2);             }         } else {             fclose(flog);         }     } } void Log(const char *pszFmt,...) {     va_list argp;      Lock(&cs_log);     va_start(argp,pszFmt);     LogV(pszFmt,argp);     va_end(argp);     Unlock(&cs_log); } //Log} int main(int argc,char * argv[]) {     int i; #ifdef WIN32     InitializeCriticalSection(&cs_log); #else     pthread_mutex_init(&cs_log,NULL); #endif     for (i=0;i<10000;i++) {         Log("This is a Log %04d from FILE:%s LINE:%d\n",i, __FILE__, __LINE__);     } #ifdef WIN32     DeleteCriticalSection(&cs_log); #else     pthread_mutex_destroy(&cs_log); #endif     return 0; } //1-78行添加到你带main的.c或.cpp的那个文件的最前面 //81-85行添加到你的main函数开头 //89-93行添加到你的main函数结束前 //在要写LOG的地方仿照第87行的写法写LOG到文件MyLog1.log中

如果可以打数据断点，当然最好。如果没有办法，以下思路供借鉴。 查堆栈，看被覆盖内存的地址，以及内容有没有什么规律。 1. 可以看出是全局变量的值被篡改，但是能否确定被篡改的内存的开始地址就是这个全局变量？ 2. 全局变量位于程序的数据区，可以找一找。看一下这个变量周围有没有什么数组之类的。 3. 看堆栈中，每次被篡改的值是否都一致。有没有可能是某种数据结构。

引用 11 楼 a826632030 的回复:[quote=引用 5 楼 nadleeh123 的回复:] [quote=引用 楼主 a826632030 的回复:] 关于踩内存，有没有比较好的定位问题的方法，最近工作中遇到了两个，还没有解决。 苦于没有比较好的解决思路和办法  这种越界一般就是写代码的时候没做好错误处理，慢慢找吧少年，注释符能帮点忙，设断点神马的不靠谱，除非每次必现[/quote]  =========================================================== 昨天老大让通宵加班搞这个问题，纠结死了[/quote] 通宵加班，身心疲惫，效率更低

引用 6 楼 zhao4zhong1 的回复:[quote=引用 5 楼 nadleeh123 的回复:] [quote=引用 楼主 a826632030 的回复:] 关于踩内存，有没有比较好的定位问题的方法，最近工作中遇到了两个，还没有解决。 苦于没有比较好的解决思路和办法  这种越界一般就是写代码的时候没做好错误处理，慢慢找吧少年，注释符能帮点忙，设断点神马的不靠谱，除非每次必现[/quote] 那是因为你不会用数据断点。[/quote]  老师威武，就是数据断点。

引用 5 楼 nadleeh123 的回复:[quote=引用 楼主 a826632030 的回复:] 关于踩内存，有没有比较好的定位问题的方法，最近工作中遇到了两个，还没有解决。 苦于没有比较好的解决思路和办法  这种越界一般就是写代码的时候没做好错误处理，慢慢找吧少年，注释符能帮点忙，设断点神马的不靠谱，除非每次必现[/quote]  =========================================================== 昨天老大让通宵加班搞这个问题，纠结死了

引用 4 楼 zhao4zhong1 的回复:正解在此！ #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; }  =================================================== 的确不是必先的问题，数据断点貌似只可以在调试的时候执行吧？我还是第一次听说数据断点，涨知识了，对我很有帮助以后可能会用到

引用 2 楼 xiaohuh421 的回复:是全局变量的访问越界, 还是其它程序越界访问 , 导致全局变量被修改了? 如果全局变量自己访问越界, 则下每个用到的地方下断排查. 否则就只有下 内存断点.  可知道是哪里改变了这个内存. ================================================= 这个不是很清楚，全局变量是一个数据结构

引用 2 楼 xiaohuh421 的回复:是全局变量的访问越界, 还是其它程序越界访问 , 导致全局变量被修改了? 如果全局变量自己访问越界, 则下每个用到的地方下断排查. 否则就只有下 内存断点.  可知道是哪里改变了这个内存.+1

是全局变量被踩了，导致进程退出

core dump

引用 5 楼 nadleeh123 的回复:[quote=引用 楼主 a826632030 的回复:] 关于踩内存，有没有比较好的定位问题的方法，最近工作中遇到了两个，还没有解决。 苦于没有比较好的解决思路和办法  这种越界一般就是写代码的时候没做好错误处理，慢慢找吧少年，注释符能帮点忙，设断点神马的不靠谱，除非每次必现[/quote] 那是因为你不会用数据断点。

引用 楼主 a826632030 的回复:关于踩内存，有没有比较好的定位问题的方法，最近工作中遇到了两个，还没有解决。 苦于没有比较好的解决思路和办法  这种越界一般就是写代码的时候没做好错误处理，慢慢找吧少年，注释符能帮点忙，设断点神马的不靠谱，除非每次必现


Question: Thu, 21 Aug 2014 19:15:12 +0800 (CST) 时间格式化

引用 5 楼 zhao4zhong1 的回复:仅供参考： #include <stdio.h> #include <string.h> #include <time.h> #include <time.h> #include <sys/timeb.h>  struct tm st; time_t tt; char mon[4]; char mn[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; int i; char timstr[27]; char tmpbuf[128]; struct _timeb tb; int tz; char c;  void main() {     strcpy(timstr,"08/Dec/2011:15:25:03 +0800");     sscanf(timstr,"%2d/%3s/%4d:%2d:%2d:%2d",&st.tm_mday,mon,&st.tm_year,&st.tm_hour,&st.tm_min,&st.tm_sec);     for (i=0;i<12;i++) if (0==stricmp(mn[i],mon)) {st.tm_mon=i; break;}     st.tm_year-=1900;     tt=mktime(&st);     if (-1!=tt) {         strftime(tmpbuf,128,"%Y-%m-%d %H:%M:%S\n",localtime(&tt));         printf(tmpbuf);//2011-12-08 15:25:03     } else {         printf("[%s] is Invalid time string!\n",timstr);     }      _ftime(&tb);     strftime(tmpbuf,128,"%m/%b/%Y:%H:%M:%S",localtime(&tb.time));     tz=-tb.timezone;     c=(tz>0)?'+':'-';     tz=(tz>0)?tz:-tz;     sprintf(tmpbuf,"%s %c%02d%02d\n",tmpbuf,c,tz/60,tz%60);     printf(tmpbuf);//12/Dec/2011:17:36:41 +0800 }   忘记结贴了，非常感谢你！！

多谢，总监的对C不了解，一定要我掉函数，我欲哭无泪，自己已写好了

引用 5 楼 zhao4zhong1 的回复:仅供参考： #include <stdio.h> #include <string.h> #include <time.h> #include <time.h> #include <sys/timeb.h>  struct tm st; time_t tt; char mon[4]; char mn[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; int i; char timstr[27]; char tmpbuf[128]; struct _timeb tb; int tz; char c;  void main() {     strcpy(timstr,"08/Dec/2011:15:25:03 +0800");     sscanf(timstr,"%2d/%3s/%4d:%2d:%2d:%2d",&st.tm_mday,mon,&st.tm_year,&st.tm_hour,&st.tm_min,&st.tm_sec);     for (i=0;i<12;i++) if (0==stricmp(mn[i],mon)) {st.tm_mon=i; break;}     st.tm_year-=1900;     tt=mktime(&st);     if (-1!=tt) {         strftime(tmpbuf,128,"%Y-%m-%d %H:%M:%S\n",localtime(&tt));         printf(tmpbuf);//2011-12-08 15:25:03     } else {         printf("[%s] is Invalid time string!\n",timstr);     }      _ftime(&tb);     strftime(tmpbuf,128,"%m/%b/%Y:%H:%M:%S",localtime(&tb.time));     tz=-tb.timezone;     c=(tz>0)?'+':'-';     tz=(tz>0)?tz:-tz;     sprintf(tmpbuf,"%s %c%02d%02d\n",tmpbuf,c,tz/60,tz%60);     printf(tmpbuf);//12/Dec/2011:17:36:41 +0800 } +1

”Thu, 21 Aug 2014 19:15:12 +0800 (CST)“，如果格式固定的话，自己转很简单，最基本的c语言编程。 总监还管你调用哪个函数？

引用 4 楼 chenxiong815 的回复:多谢，总监的对C不了解，一定要我掉函数，我欲哭无泪，自己已写好了  你们总监很有才啊，这么个细节也要关注一下。

linux里面可以用strptime和strftime，windows里面好像没有。 自己写很简单，就用sscanf和sprintf，转换一下月份就行了

已写，老大一直认为是有对应的库函数的，我一直觉得是没有的，还是自己写一写吧

Jan Feb Mar Apr May June July Aug Sept Oct Nov Dec 自己写个函数转换吧，不是很困难


Question: 获取开发板IP？

不是Linux，在Linux里面编译的，但是移到板子上了，前端通信

引用 2 楼 user-2 的回复:如果没有记错的话，有通信的，告诉ip端口用户名这些  cgi有个环境变量，REMOTE_ADDR，但是接出来是主机的IP，想要开发板的啊

有操作系统吗，不能调用系统接口？ 获取本机IP地址

如果没有记错的话，有通信的，告诉ip端口用户名这些


Question: 新手请教 C 语言 从文件中 读取指定内容

参考《编译原理》中的词法分析和有限状态自动机。

这个难度有点大 如果code中包括不匹配的{}，几乎没有办法实现 如果没有不匹配的{}，则可以通过计算大括号的层数来实现

嘛意思？

code中包含{}么


Question: 拷贝数组内容，我的方法是直接复制内容，可以修改成将源数组内容的地址赋给目标指针吗？

引用 2 楼 amoyman 的回复:感觉楼主的后一个问题不涉及复制。 double s[5] = {1.1,2.2,3.3,4.4,5.5}; double *p = s; 这样 就可以调用 p[0],p[1]....了，它们的值和s是一样的。  另外，copy的时候，目标写在前，源写在后 这虽然是一个不成文的约定，但很多人也是这么做的，至少，vc 是这么做的 如： memcpy(void *dst, void *src, size_z count); 这样其他人（或自己在别的地方）调用的时候，不会把目标和源弄错了。 受用了，谢谢

取决于你想怎么用

（接2楼）为了传递，建议把返回类型改为 double * 如： double copy_double_arr(double *dst, double *src, int count) {     memcpy(dst, src, sizeof(double) * count);     return dst; }

参数改成 double **ar1, double **ar2. 然后 double * tmp = *ar1;           *ar1 = *ar2;           *ar2 = tmp;


Question: 学C后想学做网站页面

C语言也能干大事？

学了汉语再学英语不代表就不会汉语了。

学php、python 或 ruby

学php


Question: 外网做socket通信--问题

谢谢各位解答。 问题已经解决。 程序本身没有什么太大问题。 是公司路由这边设置有问题，导致数据包只能收到几个。

引用 5 楼 cheng7068 的回复:看了一下你的代码，不知道你的锁用在这里的作用是什么；另外在线程传递参数的时候最好用结构体指针传递参数，你直接用SOCKET类型的引用，这个很容易早晨问题的，不明白你的调试环境，就这么多了 谢谢。  锁和线程的话，我都去掉了。测试起来，还是一样有问题。 环境的话我说的详细点吧,不好意思。 客户端和服务器端，处于2个不同的网络中。 比如客户端是你家里的网络，服务器是你公司的网络。 从客户端发起请求连接到服务器，建立连接之后，2者进行数据传递。 这就是我说的外网。 我说的局域网测试通过，就是 客户端和服务器都在你公司的网络里，直接用192.168.2.xxx的网络就可以传递了，这样测试是没问题的。

引用 3 楼 user-2 的回复:貌似lock/unlock的点不对，譬如外网可能有来源不明的连接，对应线程拿到锁后recv不到阻塞了，其他正常连接的线程拿不到锁也不跑了...  我试过把lock去掉，还是同样的会出现问题。 谢谢你呀，都没人鸟我。。 tcp协议应该就可以直接传送了吧？不需要再外加别的头了吧(比如HTTP)？

更新一下问题，经过测试，我把client端发送速度调慢，1s发送一个字符串到server， server这边第一次会及时接收到，但是server端第2次接收时候就处于阻塞态了。这时让程序继续进行那么1分来钟，再直接把client端断开,ctrl+c。发现server端一次性把前面的数据都收到了。但是如果时间久了就不行，时间久了，我想应该是server端认为这个socket已经是断开的，所以不去收数据了。现在这样，我该怎么去处理，让server立即接收数据，不处于等待状态呢？

高手快点出现啊。急急急！


Question: #ifdef #undef 的应用

百度。。。。

就是条件编译  #ifdef interface读作如果interface被定义了 #undef interface读作解除interface的定义 #endif读作条件编译完了  为什么要这么做，得看完整的代码才能理解

#ifdef interface  #undef interface // 一般会在这里重新定义 // 比如 #define interface IMyNewInterface  // 你可以看看 C 语言如何定义接口，就知道了。   #endif

这个真不好回答啊！

#include <stdio.h>   int main() { #define interface 1 #ifdef interface 	printf("%d\n", interface); #undef interface 	//printf("%d\n", interface);		// 这句话加上会报错 因为interface的定义被取消了 #endif 	getchar(); 	return 0; }  #undef  的作用就是取消先前的定义

这是条件编译语句，告诉编译器你的编译规则而已，熟悉一下这几个语句的语法就好了

#ifdef The #ifdef directive controls conditional compilation of the resource file by checking the specified name. If the name has been defined by using a #define directive or by using the /d command-line option with the resource compiler, #ifdef directs the compiler to continue with the statement immediately after the #ifdef directive. If the name has not been defined, #ifdef directs the compiler to skip all statements up to the next #endif directive.  Syntax #ifdef name   Parameters name  Specifies the name to be checked by the directive.  Example This example compiles the BITMAP statement only if the name Debug is defined:  #ifdef Debug BITMAP 1 errbox.bmp #endif    See Also #define, #endif, #if, #ifndef, #undef     #undef The #undef directive removes the current definition of the specified name. All subsequent occurrences of the name are processed without replacement.  Syntax #undef name   Parameters name  Specifies the name to be removed. This value is any combination of letters, digits, and punctuation.  Example This example removes the definitions for the names nonzero and USERCLASS:  #undef     nonzero #undef     USERCLASS    See Also #define


有没有谁有办法解决

引用 1 楼 user-1 的回复:客户端与服务器端设置一个心跳机制啊，可以手动实现，也可以用系统的KEEP_ALIVE功能，上网查下。  心跳这个没有用，这个原因的产生是因为客户端没有做close动作，同时客户端没有退出，导致系统也没有办法帮他完成FIN和ACK包发送。


Question: C文件操作中，fprintf无法连续向文本文件中写入数据。请教这是什么情况

引用 2 楼 u010030181 的回复:close后，肯定不能写啊！还有你那个free也有问题，你那个出错了就return?就不free？内存不照样泄露了，最好free之后赋值成NULL,防止出现野指针……+1

引用 3 楼 angel_su 的回复:读写切换之间重新定位一下吧，不然是会有些奇怪的问题... fseek(fp, 0, SEEK_END); fprintf(fp_account,"%s %ld %s %lf\n",... ++  C89  4.9.5.3 The fopen function ......    When a file is opened with update mode ('+' as the second or third character in the mode argument), both input and output may be performed on the associated stream.  However, output may not be directly followed by input without an intervening call to the fflush function or to a file positioning function ( fseek , fsetpos , or rewind ), and input may not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.  Opening a file with update mode may open or create a binary stream in some implementations.


Question: HBase REST接口使用

楼主 你hbase rest研究好了吗 求共享啊

资料上的插头表  sishen@sishen-mac:~/Work/Personal/java/apache/hbase-trunk$curl -v -X POST -T - http://localhost:60050/api/ * About to connect() to localhost port 60050 (#0) *   Trying ::1... connected * Connected to localhost (::1) port 60050 (#0) > POST /api/ HTTP/1.1 > User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3 > Host: localhost:60050 > Accept: */* > Transfer-Encoding: chunked > Expect: 100-continue >  < HTTP/1.1 100 Continue <?xml version="1.0" encoding="UTF-8"?> <table>   <name>tables</name>   <columnfamilies>     <columnfamily>       <name>subscription</name>       <max-versions>2</max-versions>       <compression>NONE</compression>       <in-memory>false</in-memory>       <block-cache>true</block-cache>     </columnfamily>   </columnfamilies> </table> ^D < HTTP/1.1 200 OK < Date: Wed, 13 Aug 2008 18:59:38 GMT < Server: Jetty/5.1.4 (Mac OS X/10.5.4 i386 java/1.5.0_13 < Content-Length: 0 <  * Connection #0 to host localhost left intact * Closing connection #0    本地上  root@wangxin hbase]# curl -v -X POST -T - http://localhost:8000/api/ * About to connect() to localhost port 8000 (#0) *   Trying ::1... connected * Connected to localhost (::1) port 8000 (#0) > POST /api/ HTTP/1.1 > User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2 > Host: localhost:8000 > Accept: */* > Transfer-Encoding: chunked > Expect: 100-continue >  < HTTP/1.1 100 Continue /////////他这里的xml格式的文件时怎么加进去的？


Question: curl如何发送和接收多线程

做互斥不就可以了？Linux还是windows？


Question: 问一个关于指定文件的问题

引用 1 楼 user-2 的回复:C:\Users\Administrator>explorer /select, C:\Windows\notepad.exe  参考http://www.360doc.com/content/12/0831/08/7123232_233319841.shtml 谢谢

谢谢 不过我要的不是打开文件，也不是打开文件夹 而是打开文件夹后，选定文件就可以了


Question: 求帮忙，c 语言

感谢zxh707wk 朋友的帮忙。现在问题已经解决了！

暂时的思路就是fgets()函数按行读取文件，将读入的字符串存储在一个字符数组中，然后用ctype.h头文件的isdigit()函数判断每个字符是否为数字,同时设定一个计数器，记录遍历字符数组时找到的数字的个数，每找到三个进行一次求平方和计算，再用math.h头文件中的函数sqrt()求平方根,然后将这个结果存储再记录单个文件综合的变量中，继续重复前面步骤(这个思路对于细节的地方是有BUG的，需要自己处理，看你的文件存储数据的格式是否规范)

由于是64位系统，所以只能用vs来测试代码，没测试过，希望各位能把问题指出来，谢谢了 下载地址： http://pan.baidu.com/s/1hqGHhSK

引用 5 楼 u010030181 的回复:这个不难啊！有函数可以读一个文件夹下的所有文件的，不管是20个还是200个文件都可以读出来的…如果格式都一样，那么可以对每个文件进行行读，对读出的行进行解析，然后就可以进行运算了……（由于你的文件格式给出的只是一部分，不知道你所谓的格式怎么样，是每一行都一样？还是每三个数字之后就一个“|”，这个不确定，所以也不好编码）   格式都一样。就是每3个数之后就一个“|”  列数是固定的。以3个数为最小单位， 共四列。

引用 4 楼 zxh707wk 的回复:每个文本文件里的数据数都是确定的吗 每个文件里的数据数不一样。。有多有少的。没有规律。。

读入，平方，求和，搞定

引用 8 楼 zxh707wk 的回复:各位，这贴的代码让我练练手 那提前感谢高人！

各位，这贴的代码让我练练手

每个文本文件里的数据数都是确定的吗

引用 2 楼 zxh707wk 的回复:读取数据-》计算-》输出 不谢 谢谢你的回复， 可以帮忙写代码实现吗？

读取数据-》计算-》输出 不谢

我也很想帮你 但是我不会啊


Question: for循环中定义变量 的问题

c语言函数内的变量, 不管你在哪个位置定义的, 编译器自动会帮你, 把变量提到最新面,

引用 9 楼 zhao4zhong1 的回复:栈中的基本变量退出其作用域时，没有谁执行一段代码去释放/销毁/析构它所占用的内存，仅仅是没人再去理会的留在当前栈顶上方的若干遗留下来可被后续压栈操作覆盖的无用数据而已。 而栈中的类变量退出其作用域时，会自动执行其析构函数，…… 赵老师的解答还是不错

cout << "Now test array...\n\n"; 	char test[30] = "test Is a address ?"; 	cout << "test1 = " << test << endl; 	printf("test2 = %0X\n", test); 	printf("test3 = %0X\n", &test); 	printf("test4 = %s\n", test); 	printf("test5 = %s\n", &test); 	printf("test6 = %0X\n", &test[0]); 	printf("test7 = %s\n", &test[0]);  	cout << "\n\nNow test point...\n\n";  	char *ptest = test; //"ptest Is a address ?"; 	cout << "ptest1 = " << ptest << endl; 	printf("ptest2 = %0X\n", ptest); 	printf("ptest3 = %0X\n", &ptest); 	printf("ptest4 = %s\n", ptest); 	printf("ptest5 = %s\n", &ptest); 	printf("ptest6 = %0X\n", &ptest[0]); 	printf("ptest7 = %s\n", &ptest[0]); 	getchar(); 你那个Vector存的是地址，那么打印的时候肯定是找到这个地址再打印出其内容，在你进入{ }进行插入的时候，插入的是str地址，在整个{}的进行中，str这个地址并没有改变，改变的只是这个str里面的也即地址存的内容，当你退出循环时，插入的是三个一样的地址，打印的时候是打印这个地址的内容，可以说是垃圾值（因为退出这个循环后，栈就回收了，由于并没有其他操作这个地址的内容，故还是保留了最后循环中最后进行赋的值），故……

这是一个局部变量和堆栈的问题，栈没用一次销毁一次，用malloc 或者new 就可以，

栈你学过的吧， 新来个就堆在现有的这一堆上面，  自动变量也是这样的，  新来一个就在最上面， 走了再来还在同一个位置， 一个函数里自动变量的位置， 以这函数被调用时刻栈的位置为基准， 是可预测的

这个问题我前两天也刚遇到，就是每次赋值都把前边的值修改了。把char*改成string就可以了，vector<string>  vecTest;赋值过程不用改，输出时按%s输出的话，要改为vecTest[i].c_str();

自古二楼出真相。。。

换用new去分配空间就行了。。。  #include<iostream> #include<vector> #include<cstdio> #include<cstring> using namespace std;  int main() { 	vector<char*> vecTest; 	for (int i=0; i<3; i++) 	{ 	    char *str = new char[10]; 	    memset(str,0,10);         // 置0 	    sprintf(str,"%d",i); 	    vecTest.push_back(str); 	}  	// 输出 	for(int i=0; i<vecTest.size(); ++i) 	{ 		printf("%s ", vecTest[i]); 	} 	return 0; }

why not? 局部变量作用域到}为止，之后它占用的空间可以被编译器随便使用于其它需求；对第二次循环来说这个局部变量是全新的，至于具体在哪是编译器决定的，既然可以重用上一次循环体中的无用空间为什么不用？


Question: 旋转锁spinlock 为什么会和优先级有关系

好帖子啊，mark

引用 5 楼 u012879806 的回复:[quote=引用 4 楼 Idle_ 的回复:] 针对单cpu来说，spinlock当然可以锁死整个机器，只要禁止硬件中断，保证当前线程处于运行中（不管优先级如何）就可以了。调度程序其实可以看成是一个函数，它必须有调用者调用才能进行线程切换，这个调用者可以是硬件中断处理程序，可以是用户代码中调用系统函数的一部分。 那么针对单cpu来说，在执行spinlock等待时它其实是占满cpu在运行变量判断的，没人去调用系统函数，禁止硬件中断后也没有中断处理程序去调度，结果就是系统死锁。  你好 3个问题，再次感谢你的参与回复。  1. 禁止硬件中断,   何止是spinlock会导致死锁，其他用户同步对象或者内核同步对象，都会死锁吧。  2.   用户代码调用系统函数的一部分，  请问： 可以举例吗，比如什么函数？    3. 你这些回复， 方便透露一下，是出自哪本书吗？   我想深入学习一下。   [/quote]  1、是的 2、调用系统函数进内核的部分完成功能后很多会调用调度函数，比如所以的IO处理函数，比如创建/销毁线程/进程函数等等。 再加上硬件中断函数中也会调用调度函数 3、没看过书，绝大部分知识来自网络和实践，比如当初尝试ring0 hook时需要独占某个资源时就使用了禁止中断然后用自己写的spinlock创建内核线程锁住了所有非当前cpu，我记得网上查资料就用了至少一周，然后对系统了解加深了很多；少部分来自于面对面交流。

《The Intel 64 and IA-32 Architectures Software Developer's Manual》

引用 楼主 u012879806 的回复:核心编程 8.1里有个例子：  BOOL g_fResourceInUse  = FALSE; void fun1() { while(interlockedexchange(&g_fResourceInUse, true) == true) sleep(0); //access  ...  //no longer need to access interlockedexchange(&g_fResourceInUse,false); }   作者在这个例子后面，加了2段话；  You must take extreme care when using this technique because a spinlock wastes CPU time. The CPU must constantly compare two values until one "magically" changes because of another thread. Also, this code assumes that all threads using the spinlock run at the same priority level. You might also want to disable thread priority boosting (by calling SetProcessPriorityBoost or SetThreadPriorityBoost) for threads that execute spinlocks  问题1： 旋转锁和优先级有什么关系？  作者在这里提是什么用意？     You should avoid using spinlocks on single-CPU machines. If a thread is spinning, it's wasting precious CPU time, which prevents the other thread from changing the value. My use of Sleep in the while loop shown earlier improves this situation somewhat. If you use Sleep, you might want to sleep a random amount of time, and each time the request to access the resource is denied, you might want to increase the sleep time even more. This prevents threads from simply wasting CPU time. Depending on your situation, it might be better to remove the call to Sleep altogether. Or you might want to replace it with a call to SwitchToThread. I hate to say it, but trial and error might be your best approach.  问题2： 在单核上，为什么会阻扰另一个线程去修改锁的值。 先回答你第2个问题,单核,更确切说是单线程cpu,自旋锁的意义就是为了禁止抢占,典型的场景就是,一段数据结构描绘了vip和非vip用户,想象一下查询线程如果准备要查询指定的id是否为vip,这时候管理线程删掉了该id的vip权限,free了该id的vip数据,会有什么样的后果?  多线程并发而造成数据IO冲突在多核cpu的时代,这个问题不像以前禁用抢占那么简单就能完成了.所以才会出现spinlock系列函数.  spinlock 不能锁住软中断,硬中断,也就是说,处于spinlock状态的cpu核心可以被irq,sirq打断,从而使锁失效,假如你的数据正好被中断使用,这时候对数据的IO你并不能保证唯一性. 所以就有spin_lock_bh和spin_lock_irq.以及他们的延生,这2个可以锁软中断,后者是最严格的锁,硬中断一起锁上.

些微膜拜一下Idle_

引用 4 楼 Idle_ 的回复:针对单cpu来说，spinlock当然可以锁死整个机器，只要禁止硬件中断，保证当前线程处于运行中（不管优先级如何）就可以了。调度程序其实可以看成是一个函数，它必须有调用者调用才能进行线程切换，这个调用者可以是硬件中断处理程序，可以是用户代码中调用系统函数的一部分。 那么针对单cpu来说，在执行spinlock等待时它其实是占满cpu在运行变量判断的，没人去调用系统函数，禁止硬件中断后也没有中断处理程序去调度，结果就是系统死锁。  你好 3个问题，再次感谢你的参与回复。  1. 禁止硬件中断,   何止是spinlock会导致死锁，其他用户同步对象或者内核同步对象，都会死锁吧。  2.   用户代码调用系统函数的一部分，  请问： 可以举例吗，比如什么函数？    3. 你这些回复， 方便透露一下，是出自哪本书吗？   我想深入学习一下。

引用 2 楼 Idle_ 的回复:spinlock说白了就是一个死循环判断某值是否改变直到其它线程改变这个变量的值才能退出循环。那么对等待的这个线程来说它就是在反复判断某个值，所以分配给它的cpu时间等于是浪费了。如果这个线程是最高优先级的话那么就意味着没有线程可以抢占它的cpu时间，因此也没有线程可以执行代码修改这个lock，最后结果就是所有cpu指令都是判断lock值，整个系统死锁。 如果有比它更高优先级的线程的话，在硬件中断的处理中（比如系统时钟中断）调度程序会暂停现有线程然后切换到那个更高优先级的线程去执行。因此spinlock和线程优先级有极大的关系，即使没有更高优先级的线程，调度程序也会轮流切换到相同优先级的线程中，这个切换的判断条件就是分配给当前线程的cpu时间片，由此可见对单核cpu来说，如果当前线程正在执行spinlock的等待，那么在它时间片用完前，调度程序不会主动切换到其它线程（除非有更高优先级的线程或某个等待线程中有更高优先级的任务在等待cpu），而这个时间片的cpu时间则是完全浪费的（因为它只是在判断某个变量的值）。  大神，看的出来你很有研究。   1. 操作系统会打破优先级逆转的现象，  不知道你对这个了解不，不了解的话，我贴段英文给你： Another situation causes the system to dynamically boost a thread's priority level. Imagine a priority 4 thread that is ready to run but cannot because a priority 8 thread is constantly schedulable. In this scenario, the priority 4 thread is being starved of CPU time. When the system detects that a thread has been starved of CPU time for about three to four seconds, it dynamically boosts the starving thread's priority to 15 and allows that thread to run for twice its time quantum. When the double time quantum expires, the thread's priority immediately returns to its base priority.   操作系统会动态提升优先级，请参考7.10.1  如果你赞同我的说法，那么就会质疑 spinlock是不会死锁。  2.单核cpu的问题，  只能说 在等待线程的某个时间片是浪费的， 但不能说，其他线程（同级或者低优先级线程）没有机会去  修改 某个值。  是有机会的。 作者在书本里的表述有些含糊，让人误解为，单核cpu会导致其他线程（同级或者低优先级的线程）永远没有机会去修改。    我有些疑问：

这个问题涉及操作系统内部实现。 可参考Linux源代码中相关内容。


Question: 不同优先级的线程，是否会存在优先级逆转现象

按我的了解windows的调度机制是比较复杂的，不是说高级永远挡死低级的，除非高到最高级    另外现在都是用多核CPU， 一个高级线程是不可能挡死所有其它线程的， 你可以试试多个高级线程是不是能挡死低级线程

会。 参考《深入解析Windows操作系统-Windows Internals》


Question: 请教一个读取csv文件的问题

引用 9 楼 CarsonChen 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] 仅供参考#include <stdio.h> #include <string.h> char string[80]; char seps1[3]; char seps2[3]; char *token; char *zzstrtok (     char *string,     const char *control1,//连续出现时视为中间夹空token     const char *control2 //连续出现时视为中间无空token     ) {     unsigned char *str;     const unsigned char *ctrl1 = control1;     const unsigned char *ctrl2 = control2;     unsigned char map1[32],map2[32];     static char *nextoken;     static char flag=0;     unsigned char c;     int L;      memset(map1,0,32);     memset(map2,0,32);     do {         map1[*ctrl1 >> 3] |= (1 << (*ctrl1 & 7));     } while (*ctrl1++);     do {         map2[*ctrl2 >> 3] |= (1 << (*ctrl2 & 7));     } while (*ctrl2++);      if (string) {         if (control2[0]) {             L=strlen(string);             while (1) {                 c=string[L-1];                 if (map2[c >> 3] & (1 << (c & 7))) {                     L--;                     string[L]=0;                 } else break;             }         }         if (control1[0]) {             L=strlen(string);             c=string[L-1];             if (map1[c >> 3] & (1 << (c & 7))) {                 string[L]=control1[0];                 string[L+1]=0;             }         }         str=string;     }     else        str=nextoken;      string=str;     while (1) {         if (0==flag) {             if (!*str) break;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 break;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 string++;                 str++;             } else {                 flag=1;                 str++;             }         } else if (1==flag) {             if (!*str) break;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 flag=0;                 break;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 flag=2;                 break;             } else str++;         } else {//2==flag             if (!*str) return NULL;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 str++;                 string=str;                 flag=0;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 str++;                 string=str;             } else {                 string=str;                 str++;                 flag=1;             }         }     }     nextoken=str;      if (string==str) return NULL;     else             return string; } void main() {    strcpy(string,"A \tstring\t\tof ,,tokens\n\nand some  more tokens, ");    strcpy(seps1,",\n");strcpy(seps2," \t");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234| LIYI|China | 010 |201110260000|OK");    strcpy(seps1,"|");strcpy(seps2," ");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234|LIYI||010|201110260000|OK");    strcpy(seps1,"");strcpy(seps2,"|");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234|LIYI||010|201110260000|OK");    strcpy(seps1,"|");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",a");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",a,,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,a,,b,,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,,");    strcpy(seps1,",");strcpy(seps2," ");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    } } // //[A      string          of ,,tokens // //and some  more tokens, ] //Tokens: // <A> <string> <of> <> <tokens> <> <and> <some> <more> <tokens> <> //[1234| LIYI|China | 010 |201110260000|OK] //Tokens: // <1234> <LIYI> <China> <010> <201110260000> <OK> //[1234|LIYI||010|201110260000|OK] //Tokens: // <1234> <LIYI> <010> <201110260000> <OK> //[1234|LIYI||010|201110260000|OK] //Tokens: // <1234> <LIYI> <> <010> <201110260000> <OK> //[a] //Tokens: // <a> //[a,b] //Tokens: // <a> <b> //[a,,b] //Tokens: // <a> <> <b> //[,a] //Tokens: // <> <a> //[a,] //Tokens: // <a> <> //[,a,,b] //Tokens: // <> <a> <> <b> //[,,a,,b,,] //Tokens: // <> <> <a> <> <b> <> <> //[,] //Tokens: // <> <> //[,,] //Tokens: // <> <> <> //[,,,] //Tokens: // <> <> <> <>   十分感谢赵4老师！久仰大名！一开始看你那么长的代码我还吓了一跳，然后仔细读了一下发现你给我提供了很多例子，十分感谢！！[/quote] 此乃“测试驱动编程TDD”是也！

引用 8 楼 CarsonChen 的回复:[quote=引用 3 楼 zyc_0204 的回复:] 闲来无事，自己写个，只支持单个字符分隔，不支持字符串分隔。   #include "stdio.h" #include "string.h"  char*  m_strtok(char* src, char demial) { 	static char *p; 	char *tmp; 	if(src){ p = src;} 	tmp = p; 	if(*tmp == 0) return 0; 	while(*p != demial && *p != 0) ++p; 	if(*p != 0) 	 *p++ = 0; 	return tmp; }  int main() { 	char test[] = "1,2,,3,,4"; 	char test1[] = "1,2,,3,,4"; 	char *p = m_strtok(test , ','); 	while(p != 0) 	{ 		printf("[%s] ",p); 		p = m_strtok(0 , ',');	 	} 	 	p = strtok(test1 , ","); 	while(p!=0) 	{ 		printf("[%s] " , p); 		p = strtok(0 , ","); 	} }  谢谢！ 哥们你的代码写的好好啊！ 请问为什么是0呢？如果我是空白值，是不是应该用NULL和\0呢？[/quote] 0,NULL,'\0'都是一个值0.

引用 4 楼 zhao4zhong1 的回复:仅供参考#include <stdio.h> #include <string.h> char string[80]; char seps1[3]; char seps2[3]; char *token; char *zzstrtok (     char *string,     const char *control1,//连续出现时视为中间夹空token     const char *control2 //连续出现时视为中间无空token     ) {     unsigned char *str;     const unsigned char *ctrl1 = control1;     const unsigned char *ctrl2 = control2;     unsigned char map1[32],map2[32];     static char *nextoken;     static char flag=0;     unsigned char c;     int L;      memset(map1,0,32);     memset(map2,0,32);     do {         map1[*ctrl1 >> 3] |= (1 << (*ctrl1 & 7));     } while (*ctrl1++);     do {         map2[*ctrl2 >> 3] |= (1 << (*ctrl2 & 7));     } while (*ctrl2++);      if (string) {         if (control2[0]) {             L=strlen(string);             while (1) {                 c=string[L-1];                 if (map2[c >> 3] & (1 << (c & 7))) {                     L--;                     string[L]=0;                 } else break;             }         }         if (control1[0]) {             L=strlen(string);             c=string[L-1];             if (map1[c >> 3] & (1 << (c & 7))) {                 string[L]=control1[0];                 string[L+1]=0;             }         }         str=string;     }     else        str=nextoken;      string=str;     while (1) {         if (0==flag) {             if (!*str) break;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 break;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 string++;                 str++;             } else {                 flag=1;                 str++;             }         } else if (1==flag) {             if (!*str) break;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 flag=0;                 break;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 *str=0;                 str++;                 flag=2;                 break;             } else str++;         } else {//2==flag             if (!*str) return NULL;             if (map1[*str >> 3] & (1 << (*str & 7))) {                 str++;                 string=str;                 flag=0;             } else if (map2[*str >> 3] & (1 << (*str & 7))) {                 str++;                 string=str;             } else {                 string=str;                 str++;                 flag=1;             }         }     }     nextoken=str;      if (string==str) return NULL;     else             return string; } void main() {    strcpy(string,"A \tstring\t\tof ,,tokens\n\nand some  more tokens, ");    strcpy(seps1,",\n");strcpy(seps2," \t");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234| LIYI|China | 010 |201110260000|OK");    strcpy(seps1,"|");strcpy(seps2," ");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234|LIYI||010|201110260000|OK");    strcpy(seps1,"");strcpy(seps2,"|");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"1234|LIYI||010|201110260000|OK");    strcpy(seps1,"|");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",a");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,"a,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",a,,b");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,a,,b,,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,");    strcpy(seps1,",");strcpy(seps2,"");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    }     strcpy(string,",,,");    strcpy(seps1,",");strcpy(seps2," ");    printf("\n[%s]\nTokens:\n",string);    token=zzstrtok(string,seps1,seps2);    while (token!=NULL) {       printf(" <%s>",token);       token=zzstrtok(NULL,seps1,seps2);    } } // //[A      string          of ,,tokens // //and some  more tokens, ] //Tokens: // <A> <string> <of> <> <tokens> <> <and> <some> <more> <tokens> <> //[1234| LIYI|China | 010 |201110260000|OK] //Tokens: // <1234> <LIYI> <China> <010> <201110260000> <OK> //[1234|LIYI||010|201110260000|OK] //Tokens: // <1234> <LIYI> <010> <201110260000> <OK> //[1234|LIYI||010|201110260000|OK] //Tokens: // <1234> <LIYI> <> <010> <201110260000> <OK> //[a] //Tokens: // <a> //[a,b] //Tokens: // <a> <b> //[a,,b] //Tokens: // <a> <> <b> //[,a] //Tokens: // <> <a> //[a,] //Tokens: // <a> <> //[,a,,b] //Tokens: // <> <a> <> <b> //[,,a,,b,,] //Tokens: // <> <> <a> <> <b> <> <> //[,] //Tokens: // <> <> //[,,] //Tokens: // <> <> <> //[,,,] //Tokens: // <> <> <> <>   十分感谢赵4老师！久仰大名！一开始看你那么长的代码我还吓了一跳，然后仔细读了一下发现你给我提供了很多例子，十分感谢！！

引用 3 楼 zyc_0204 的回复:闲来无事，自己写个，只支持单个字符分隔，不支持字符串分隔。   #include "stdio.h" #include "string.h"  char*  m_strtok(char* src, char demial) { 	static char *p; 	char *tmp; 	if(src){ p = src;} 	tmp = p; 	if(*tmp == 0) return 0; 	while(*p != demial && *p != 0) ++p; 	if(*p != 0) 	 *p++ = 0; 	return tmp; }  int main() { 	char test[] = "1,2,,3,,4"; 	char test1[] = "1,2,,3,,4"; 	char *p = m_strtok(test , ','); 	while(p != 0) 	{ 		printf("[%s] ",p); 		p = m_strtok(0 , ',');	 	} 	 	p = strtok(test1 , ","); 	while(p!=0) 	{ 		printf("[%s] " , p); 		p = strtok(0 , ","); 	} }  谢谢！ 哥们你的代码写的好好啊！ 请问为什么是0呢？如果我是空白值，是不是应该用NULL和\0呢？

引用 1 楼 xydp1987108 的回复:需要自己处理下，遍历一遍字串，当前元素的值为','时判断下个元素是否依然为','，如果是将此元素值设置为' '，再遍历一次字串取出字符不为','的元素就是你需要的+1

引用 2 楼 fengqinqdca 的回复:这个问题我也遇到过。如果在windows平台 使用AfxExtractSubString拆分字符串 谢谢你的回复，查了一下，AfxExtractSubString只有VC有呢，我用的是mac，服务器是Linux，所以貌似用不了这个函数。请问你当时遇到这个问题的时候，有没有找到别的无平台差别的解决办法呢？

引用 1 楼 xydp1987108 的回复:需要自己处理下，遍历一遍字串，当前元素的值为','时判断下个元素是否依然为','，如果是将此元素值设置为' '，再遍历一次字串取出字符不为','的元素就是你需要的  谢谢回复，所以是要遍历两次吗？请问有没有更廉价的处理办法呢，因为我本质上要处理的数据是上百万的，如果要遍历两次，时间消耗貌似比较大


Question: 回传值,程式一执行就当机?

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

谢谢您><问题已解决了

没学过C，但我想，应该是scanf那句，x该传地址，  scanf(“%d",&x);


Question: C语言处理缓存数据

大赞4楼 哈哈

确实，归根到底还是遍历，只是效率不同而已

遍历整个报文，设置一个标志变量，依次检测0x0d和0x0a，连续检测到这两个字符时设置标志，表示新的缓冲区，参考如下示意代码  int state = 0; for(;;) { if( pstPluginState->pcUartRxBuffer==0x0d) {   state=1;/*有可能是新的缓冲区开始，先做个标记*/ } else if( pstPluginState->pcUartRxBuffer==0x0a && state==1) {  state=2;  //确实是一个新的缓冲区起始，做下标记 } else {  if(state==2) {  state=0;  ............../* 开始处理新缓冲区 */ } else if(state==1) /*老缓冲区，并且之前标记了0x0d，因此漏掉一个字符*/ { 之前有一个0x0d作为了缓冲区起始标识，但现在并不是真的缓冲区起始，因此要先处理先前漏掉的0x0d，然后继续处理当前字符 } else/* if(state==0) 老缓冲区*/ { ..../*缓冲区中，处理当前字符*/ } } }

pstPluginState->pcUartRxBuffer是一个指针，用 *（pstPluginState->pcUartRxBuffer）==0D  和 *（pstPluginState->pcUartRxBuffer）+1==0A  就能判断pcUartRxBuffer所指向内容中是0D0A的数据了  但是给出一个数据包 一共78个数  0D 0A D7 A2 3A 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 0D 0A B9 CA D5 CF 3A 30 31 2D 31 2D 31 38 20 20 55 53 43 39 35 30 31 20 0D 0A CA B1 BC E4 3A 30 31 2F 30 31 20 20 30 32 3A 31 39 0D 0A   nHead=0x 0D 要从nHead 开始查找到末尾 ，怎么用pstPluginState->pcUartRxBuffer指正来控制啊 我想用for循环 求大家指点

引用 楼主 SUXIN091237 的回复:pstPluginState->pcUartRxBuffer  是缓存 怎么用C语句查找数据缓存区的数据是0D 0A   谢谢大家 \r\n啊? 在抓HTTP流的数据

楼主 大爱  这个积分我要拿走啊啊啊啊 啊哈哈哈

引用 1 楼 liu111qiang88 的回复:不论你用什么办法 ，最后都是遍历+1

不论你用什么办法 ，最后都是遍历


Question: 问一个关于数据结构的问题

引用 1 楼 user-7 的回复:想要 链表 跟 数据 解耦  ，  又不想用模板 ，  那么这是一个 插入式的双链表  感谢思路 找到能用的了 以后在研究

引用 6 楼 u013592079 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 照Linux内核的list抄一遍也不让？！  包含了其他的头文件啊 [/quote] 只要把内核源码里的list.h文件拷贝到你的代码目录下，注释掉里面所有的include行，然后把 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #define container_of(ptr, type, member) ({      \   const typeof( ((type *)0)->member ) *__mptr = (ptr);  \   (type *)( (char *)__mptr - offsetof(type,member) );})  # define POISON_POINTER_DELTA 0 #define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA) #define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)  这几个宏放在list.h文件前面就能用了。  另外还可以用零长度数组，在分配节点内存时把数据结构的长度放在结尾。 struct head {     struct head * next;     char data[0]; }; struct mydata {     int x;     unsigned long long y;     double z; }; ... struct head * node = (struct head *)malloc(sizeof(struct head)+sizeof(struct mydata)); ... struct mydata * data = (struct mydata *)node->data; printf("x = %d, y=%llu, z=%f\n", data->x, data->y, data->z); 当然也可以象8楼所说的用void * data指向分配数据的内存。 另外我还试过： struct node {     struct head * next; }; struct list {     struct node * head;     struct node * tail;     int size; } struct mydata {     struct node link; //只要保证链表节点是数据结构的第一个项，那么节点的地址就是就是数据结构的地址。     int x;     unsigned long long y;     double z; };  ... struct node * node = list->head->next; struct mydata * data = (struct mydata *)node; //取数据的时候只要转换一下就可以了 printf("x = %d, y=%llu, z=%f\n", data->x, data->y, data->z); 方法非常多。

你是说数据存储在一个数组里然后另外弄个链表管理它们吗？  　链表里放指针就好了啊，　或者如果性能很重要的话就用另外一个同样大小的数组，对应位置记录链表的ｎｅｘｔ序号，　类似这样的简化吧

引用 5 楼 zhao4zhong1 的回复:照Linux内核的list抄一遍也不让？！  包含了其他的头文件啊

照Linux内核的list抄一遍也不让？！

Linux源代码中有实现。

给你一个我用的。 我也是从其他代码修改过来的。  			typedef struct List 			{ 				struct List *_Next; 				struct List *_Prev; 			} List;  			/* Define a list like so: 			* 			*   struct gadget 			*   { 			*       List  entry;   <-- doesn't have to be the first item in the struct 			*       int          a, b; 			*   }; 			* 			*   static List global_gadgets = LIST_INIT( global_gadgets ); 			* 			* or 			* 			*   struct some_global_thing 			*   { 			*       List gadgets; 			*   }; 			* 			*   Init( &some_global_thing->gadgets ); 			* 			* Manipulate it like this: 			* 			*   AddHead( &global_gadgets, &new_gadget->entry ); 			*   Remove( &new_gadget->entry ); 			*   AddAfter( &some_random_gadget->entry, &new_gadget->entry ); 			* 			* And to iterate over it: 			* 			*   struct gadget *gadget; 			*   LIST_FOR_EACH_ENTRY( gadget, &global_gadgets, struct gadget, entry ) 			*   { 			*       ... 			*   } 			* 			*/  			/* add an element after the specified one */ 			__inline static void AddAfter(List *elem, List *to_add) 			{ 				to_add->_Next = elem->_Next; 				to_add->_Prev = elem; 				elem->_Next->_Prev = to_add; 				elem->_Next = to_add; 			}  			/* add an element before the specified one */ 			__inline static void AddBefore(List *elem, List *to_add) 			{ 				to_add->_Next = elem; 				to_add->_Prev = elem->_Prev; 				elem->_Prev->_Next = to_add; 				elem->_Prev = to_add; 			}  			/* add element at the head of the list */ 			__inline static void AddHead(List *list, List *elem) 			{ 				AddAfter(list, elem); 			}  			/* add element at the tail of the list */ 			__inline static void AddTail(List *list, List *elem) 			{ 				AddBefore(list, elem); 			}  			/* remove an element from its list */ 			__inline static void Remove(List *elem) 			{ 				elem->_Next->_Prev = elem->_Prev; 				elem->_Prev->_Next = elem->_Next; 			}  			/* get the _Next element */ 			__inline static List *Next(List const *list, List const *elem) 			{ 				List *ret = elem->_Next; 				if (elem->_Next == list) ret = NULL; 				return ret; 			}  			/* get the previous element */ 			__inline static List *Prev(List const *list, List const *elem) 			{ 				List *ret = elem->_Prev; 				if (elem->_Prev == list) ret = NULL; 				return ret; 			}  			/* get the first element */ 			__inline static List *Head(List const *list) 			{ 				return Next(list, list); 			}  			/* get the last element */ 			__inline static List *Tail(List const *list) 			{ 				return Prev(list, list); 			}  			/* check if a list is empty */ 			__inline static int Empty(List const *list) 			{ 				return list->_Next == list; 			}  			/* initialize a list */ 			__inline static void Init(List *list) 			{ 				list->_Next = list->_Prev = list; 			}  			/* count the elements of a list */ 			__inline static unsigned int Count(List const *list) 			{ 				unsigned count = 0; 				List const *ptr; 				for (ptr = list->_Next; ptr != list; ptr = ptr->_Next) 				{ 					count++; 				} 				return count; 			}  			/* move all elements from src to the tail of dst */ 			__inline static void MoveToTail(List *dst, List *src) 			{ 				if (Empty(src)) return;  				dst->_Prev->_Next = src->_Next; 				src->_Next->_Prev = dst->_Prev; 				dst->_Prev = src->_Prev; 				src->_Prev->_Next = dst; 				Init(src); 			}  			/* move all elements from src to the head of dst */ 			__inline static void MoveToHead(List *dst, List *src) 			{ 				if (Empty(src)) return;  				dst->_Next->_Prev = src->_Prev; 				src->_Prev->_Next = dst->_Next; 				dst->_Next = src->_Next; 				src->_Next->_Prev = dst; 				Init(src); 			}  			/* iterate through the list */ #define LIST_FOR_EACH(elem, list) for ((elem) = (list)->_Next; (elem) != (list); (elem) = (elem)->_Next)  			/* iterate through the list, with safety against removal */ #define LIST_FOR_EACH_SAFE(elem, safetynext, list) for ((elem) = (list)->_Next, (safetynext) = (elem)->_Next; (elem) != (list); (elem) = (safetynext), (safetynext) = (elem)->_Next)  			/* iterate through the list using a list entry */ #define LIST_FOR_EACH_ENTRY(elem, list, type, field) for ((elem) = LIST_ENTRY((list)->_Next, type, field); &(elem)->field != (list); (elem) = LIST_ENTRY((elem)->field._Next, type, field))  			/* iterate through the list using a list entry, with safety against removal */ #define LIST_FOR_EACH_ENTRY_SAFE(elem, safetynext, list, type, field) for ((elem) = LIST_ENTRY((list)->_Next, type, field), (safetynext) = LIST_ENTRY((elem)->field._Next, type, field); &(elem)->field != (list); (elem) = (safetynext), (safetynext) = LIST_ENTRY((elem)->field._Next, type, field))  			/* iterate through the list in reverse order */ #define LIST_FOR_EACH_REV(cursor,list) for ((cursor) = (list)->_Prev; (cursor) != (list); (cursor) = (cursor)->_Prev)  			/* iterate through the list in reverse order, with safety against removal */ #define LIST_FOR_EACH_SAFE_REV(elem, safetynext, list) for ((elem) = (list)->_Prev, (safetynext) = (elem)->_Prev; (elem) != (list); (elem) = (safetynext), (safetynext) = (elem)->_Prev)  			/* iterate through the list in reverse order using a list entry */ #define LIST_FOR_EACH_ENTRY_REV(elem, list, type, field) for ((elem) = LIST_ENTRY((list)->_Prev, type, field); &(elem)->field != (list); (elem) = LIST_ENTRY((elem)->field._Prev, type, field))  			/* iterate through the list in reverse order using a list entry, with safety against removal */ #define LIST_FOR_EACH_ENTRY_SAFE_REV(elem, safetynext, list, type, field) for ((elem) = LIST_ENTRY((list)->_Prev, type, field), (safetynext) = LIST_ENTRY((elem)->field._Prev, type, field); &(elem)->field != (list); (elem) = (safetynext), (safetynext) = LIST_ENTRY((elem)->field._Prev, type, field))  			/* macros for statically initialized lists */ #define LIST_INIT(list) { &(list), &(list) }  			/* get pointer to object containing list element */ #define LIST_ENTRY(elem, type, field) ((type *)((char *)(elem) - offsetof(type, field)))

（1）存指针，void* （2）使用宏，我曾经看到过一个文件khash.h，用C宏实现了一个模板哈希表，但是代码的可读性完全没有，而且难用

想要 链表 跟 数据 解耦  ，  又不想用模板 ，  那么这是一个 插入式的双链表


Question: 宏定义该如何解析

宏展开只是一方面，  另一方面是一个老掉牙的问题， ++的副作用的问题      按照规范被++的变量是不能在表达式里再次使用的， 否则编译器理解成什么样就是个没标准的事了， 可是总有些人每天热衷于讨论这个不合规范的做法的结果，给出种种解释， 有什么意义呢

引用 10 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！+1

理解和讨论之前请先学会如何观察！

引用 8 楼 liu111qiang88 的回复:宏  就是替换展开，像数学函数一样 你把宏带进去展开就行啦

宏  就是替换展开，像数学函数一样 你把宏带进去展开就行啦

定义宏的时候 加上括号就好了

宏定义在编译过程中直接替换。

宏用到程序中是不带括号的 建议一般最好不要用宏

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

这有什么可以纠结的呢，宏定义引用的时候没有加括号导致的结果么

++a%4+3*a%4/2  a=10时 结果为3 没错的。楼主以为是多少呢？

printf("%d\n", ++ Z);  相当于  printf("%d\n", ++Y*X/2)相当于 printf("%d\n", ++X+3*X/2)相当于 printf("%d\n", ++a%4+3*a%4/2)  这种表达式 完全没有括号的 lz就别纠结了


Question: C语言中宏定义的使用：最后输出为什么i变成3，输出D

引用 2 楼 mujiok2003 的回复:何苦跟自己过不去？ 代码写简单点不好吗？  把它简化吧，让楼主瞧瞧！！！

代码写这么复杂，为难自己呢么

你可以把'a'<=(c)&&(c)<='z'这两个条件去掉一个，会发现结果变成了 C   建议不要这么用宏

因为在你的程序中，c 就等于s[++i], i的初值是0，s[i]为a，而进行TOUPPER(s[++i])时，'a'<=(c)&&(c)<='z'将i的值加了两次，再进行(c)-'a'+'A'操作时又加了一次，所以是d-‘a’+'A'，最终为D

i的变化和宏也没有关系吧？

何苦跟自己过不去？ 代码写简单点不好吗？

把 TOUPPER 展开就明白了


Question: dos下外部RAM的访问

您好： 我用char far *pRAm=(char far*)0xe0000000L和char far *pRAm=(char far*)MK_FP(0xe0000,0) 都测试过了，pc104的IOR也没有反应，另外640K高端内存使用可行吗

在纯DOS下，内存地址请用seg:offset的格式，永远不要用offset的格式。  第一个问题：外设地址定0xe000:0x0000，char far *pRAm=(char far*)(char far*)MK_FP(0xe000,0);操作，pc104 isa总线的 IOR读信号一直是高电平，请另找原因。 第二个问题：dos 内存640k以上是给视频显示(A000:0000～D000:0000)和bios中断(F000:0000)的，内存映射地址为E000:0000,正好是dos 内存640k以上的，所以不会有冲突 第三个问题：外设地址我定的0xe000:0x0000等价于(char far*)0xe0000000L;

赵老师您好： 第一个问题：我的外设地址我定的0xe0000，我用您说的方法char far *pRAm=(char far*)0xe0000000L;操作但是pc104 isa总线的 IOR读信号一直是高电平，没有反应 第二个问题：dos 内存640k以上是给视频显示和bios中断的，如内存映射地址为0xe0000,正好是dos 内存640k以上的，所以我说会不会有冲突 第三个问题：外设地址我定的0xe0000能等价于0xe0000000L;吗

在纯DOS下，内存地址请用seg:offset的格式，永远不要用offset的格式。  0～640KB对应 0000:0000～A000:0000 当然不会和 E000:0000 冲突了。

您好，赵老师我加你qq好吗

char far *pRAm=(char far*)0xe0000000L; 等价于 char far *pRAm=(char far*)MK_FP(0xe000,0) 而不等价于 char far *pRAm=(char far*)MK_FP(0xe0000,0)

0xe0000000对应e000:0000 0xe0000对应000e:0000

为什么用这种char far *pRAm=(char far*)0xe0000读法，pc的IOR没有反应呢

char far *pRAm=(char far*)0xe0000000L;


Question: 新手求助啊！！！！我也不知道是啥子问题了。。反正就是出错了。

指针越界了哦

引用 7 楼 zxh707wk 的回复:突然发现自己已经3个月没写代码了。。。 失去之后才会觉得珍贵。

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

引用 8 楼 u013344915 的回复:自己写了一份 http://blog.csdn.net/a_flying_bird/article/details/38690025该页面8.20有更新

突然发现自己已经3个月没写代码了。。。

一些教科书可能会喜欢拿scanf之类的来教学，其实真正做项目之后，会发现几乎好几年都不会用scanf。也正因为学校教科书中的scanf方式，往往无法理解模块化的思想。

# include <stdio.h> # include <stdlib.h> int n;  struct Student { 	int age; 	char sex; 	int score; 	char name[20]; };  void Inputstudent(struct Student * p) { 	int i; 	for (i = 0; i < n; i++) 	{ 		printf("\nPlease enter the name\nThe name is "); 		scanf("%s", p[i].name); //not need '&'  		printf("\nAnd then tell me that %s is a boy or a girl\n", p[i].name); 		printf("Enter B if a boy,and G if a girl\n"); 		char * q = (char*)malloc(sizeof(char));          	if(p == NULL) 		          exit(1);    		*q = '0'; 		scanf(" %c", q);  //add a space before %c , 						//make sure to skip something like '\n' '\t'			 		printf("So how old is ");	 		if (*q == 'b' ||*q == 'B')//here 		{ 			p[i].sex = 'B'; 			printf("he?\nHe is "); 		} 		else if (*q == 'g' || *q == 'G')//here 		{ 			p[i].sex = 'G'; 			printf("she?\nShe is "); 		} 		else 			printf("Can you iust do what I told you?!\nThis student is neither a boy nor a girl.\n");	  		scanf("%d", &p[i].age);  		printf("\nAt last,what is the socre?\nThe score is "); 		scanf("%d", &p[i].score);//here need '&'  	}  }  void Outputstudent(struct Student * p) { 	printf("Name     Sex     Age     score    \n"); 	for (int i = 0; i < n; i++) 		printf("%s\t%c\t%d\t%d\t\n", p[i].name, p[i].sex, p[i].age, p[i].score);	 }  int main(void) { 	printf("How many students are there totally?\nThe namber is "); 	scanf("%d", &n); 	struct Student * p = (struct Student *)malloc(n * sizeof(struct Student));//need to check  whether p == NULL or not; 	if(p == NULL) 		exit(1); 	Inputstudent(p); 	Outputstudent(p);  	return 0; }

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

scanf("%s", &p[i].name); 这里多了一个&符号。  malloc后都判断一下其返回值是否为NULL的说。

谢谢！我在去查查看。

这是非法访问，你出错的地方是在： Inputstudent函数的最后一句： scanf("%d", p[i].score); 此处丢了一个&符号。 你程序里还有其他的问题，自己再检查下。


Question: cout／printrf的内容是放在 文字常量区吗

嵌入系统很有可能没有所谓的文字常量区。 所以，楼主，你还是说说你的原始问题吧。

回复7楼 54454 编译器是gcc 他们的有区别。我用vs模拟了一下汇编，  char mm[10] ={'h', 'e', 'l', 'l', 'o', 0}， 直接赋值给mm char mm[10] = "hello".                      先存”hello“， 然后从”hello“的地址取出来再赋值给mm  回复6楼 ParsifalC 是嵌入式系统  问题基本解决了。 没有单独的文字常量区，不能直接访问地址。   但是系统提供某些间接访问的方法，可以读取到常量的地址。  谢谢大家。

看了一下原帖，照理来说应该是没分别的。字符串“abcd”，最后编译器会帮你加上一个'\0'。至于这些内容放在哪，那块内存的属性是只读或者别的，你没指定的话就都是由编译器默认决定的。问一下用的什么编译器？

char mm[10] = "hello"; "hello"是常量区的，赋值时编译器的操作是将常量区的6个字符拷贝到栈区。 你这样的报错，可能是跟环境有关。 貌似嵌入式系统的有可能不存在常量区，不是很确定。 你这个是什么环境下做的？

引用 8 楼 registercsdn 的回复:需要纠正一下，四楼说的不对。 printf("%s", "hello")   这个不能打印出来 #include <stdio.h> #include <windows.h> int main() {     int i;      for (i=0;i<5;i++) {         printf("%s","hello");         fflush(stdout);         Sleep(500);     }      return 0; }

这样就会报错 char mm[10] = "hello".    找不到地址  这样就是对的 char mm[10] ={'h', 'e', 'l', 'l', 'o', 0}

回复二楼taodm  使用 printf("%s", "hello")   这个没有问题，可以打印出来。

这是原始问题。 http://bbs.csdn.net/topics/390864598?page=1#post-398011460

是，包括"%s"也是，都在文字常量区 这和cout/printf没关系。代码里面任何地方的"fdsarewfdsa"，都是在文字常量区


Question: linux scanf问题

引用 12 楼 sinat_19761531 的回复:在每一行的scanf下面再加上一个scanf("%*c")意思是晴空输入流缓冲区里面的一个字符，这里清空的是‘\n’不然即使你的scanf里面变量都加了&，结果你第二个显示永远是个换行符

scanf函数用错了！再看看

引用 4 楼 lin5161678 的回复:[quote=引用 1 楼 xinsuixiaofeiyu 的回复:] fflush可移植性不好！在VC下都能成功但在gcc下不一定成功，标准不一样，有兴趣可以看看这篇文章 不是标准不一样 标准是一样  标准保证 fflush(stdin)这样的情况结果不做任何保证  所以可以是 清空 可以没清空 [/quote]貌似是的，对这种情况是未定义的。还有个疑问，为什么在VC下一般都能成功呢？

man  scanf

scanf("%c",ch);---->scanf("%c",&ch); scanf("%c",nch);---->scanf("%c",&nch);

引用 1 楼 xinsuixiaofeiyu 的回复:fflush可移植性不好！在VC下都能成功但在gcc下不一定成功，标准不一样，有兴趣可以看看这篇文章 不是标准不一样 标准是一样  标准保证 fflush(stdin)这样的情况结果不做任何保证  所以可以是 清空 可以没清空

fflush(stdin);用法错了

引用 楼主 u012422205 的回复:#include <stdio.h> int main() {  	char ch,nch;  	fflush(stdin); 	scanf("%c",ch); 	printf("ch = %c\n",ch);  	fflush(stdin); 	scanf("%c",nch); 	printf("nch = %c\n",nch);  	return 0; } 运行结果是 ch = nch = 为什么??????? 检查一下输出本地环境的设置，如果是unicode环境变成ANSI环境的，应当就好了。

fflush可移植性不好！在VC下都能成功但在gcc下不一定成功，标准不一样，有兴趣可以看看这篇文章http://ydiandiandian.diandian.com/post/2012-05-17/40028316972 linux下可以直接用getchar()消耗就行了  另外你的程序中scanf("ch=%c",&ch)，需要用取地址符&

printf里面的%和变量的一一对应关系 scanf里面的%和变量以及变量前加不加&的一一对应关系 是C代码中非常容易出错的地方，而且通常编译还不出错。 所以在编译源代码之前值得专门仔细检查一遍甚至多遍。  在每个最后不带\n的printf后面加fflush(stdout); 在每个不想受接收缓冲区旧内容影响的scanf前面加rewind(stdin); 另外请检查scanf的返回值。  作为一个C程序员，对  scanf,sscanf,fscanf  printf,sprintf,fprintf 这类函数的用法，还是要做到“拳不离手，曲不离口”的。

编译器用错了，Linux有两个编译器啊，你用g++还是gcc

scanf后面参数加&


Question: 数组不同赋值方法导致不同结果 [重新发帖，纠正刚才的问题】

引用 5 楼 registercsdn 的回复:回复二楼 max 如果是这种方式赋值的话，“abcd”它会自动加上结束符号。 我非常同意这个观点

第一种方法没错，第二种方法，{"abcd"}是对char[][]的初始化写法。 如果只是对char[]初始化应该用 char m2[10] = "abcd"

m2后面是如何使用的？是不是要通过'\0'来判断

回复四楼zhi_ai_yaya 芯片没有开辟文字常量区，有可能“abcd”，没有地方放，导致赋值的时候数组找不到“abcd”。  这种情况下，可以把“abcd”先放到堆， 栈，或者全局区吗

回复二楼 max 如果是这种方式赋值的话，“abcd”它会自动加上结束符号。

芯片没有问题

可能是芯片的问题吧

验证证明ASCII值为0的是一个null字符。初始化时，没有指定值的，都默认为该值。 事实上m1和m2的值是一样的，但是在芯片上运行出现差别，是因为后面一段没有初始化。没有初始化就使用变量，这不是一个好习惯。


Question: 函数里的取模有点问题

我没看清，原来用的就是fmod，抱歉。不过，判断浮点数是否为0，不能用 f != 0.0这样判断.不知道是不是这个原因 你要确定一个精度，比如0.00001 if( f  >= -0.00001 && f <=0.00001)来判断f是否为0

好吧，%这个取模运算只针对整数，浮点数请用fmod函数


Question: char[100]类型 但是加0就变成char *型了

地址+ xxx实际上是改变这个地址指向的内存。。 说的不太准确，大致就是这个意思了

数组的名直接拿来用相当于一个内存地址，用地址加xxx不就是地址吗？  地址是指针你懂的 函数名啊 数组名啊什么的都是一个地址

正常的 楼主  这是隐式类型转换  1 //int  1+0.0// double   类似

引用 3 楼 zxh707wk 的回复:ss本来就是char*型的呀 ss本来的数据类型是 char[100]

ss[100] 有中括号和数值100，他就是个数组，而且是个字符串数组，因为内容是双引号围住的；  ss就是这个数组的首地址，自然可以用指针表示，就如同用ss[i] 下标表示一样！

ss是你明确定义的数组，所以编译器说ss是一个100的char数组，这里的编译器的解释翻译有点点问题，其实没这个类型，不过可以忽略； ss＋0已经把ss从一个数组名隐式转为数组首地址（只有值才支持运算符），变成地址之后肯定就是char *了

建议重新看看数组这一章节。 多留意数组名的含义。或者直接百度。。数组名 这一两句话说不清楚。

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

引用 8 楼 lin5161678 的回复:[quote=引用 3 楼 zxh707wk 的回复:] ss本来就是char*型的呀 ss本来的数据类型是 char[100]  [/quote]忘了。。。

这里char *和字符数组都表示字符串，可以理解为等价 关于字符串，可以看看这里——http://blog.csdn.net/u012421456/article/details/38645335

ss本来就是char*型的呀

这就是传说中的隐式转换。

如果不是char*，你觉得应该是啥类型呢？


Question: #########数字魔术游戏#########

重要的是数组的元素啊

楼主我转帖了哈

仔细看 肯定懂得！

现在的数组规模稍微扩充一点点就可以算出1-63了，还是看得有点晕，我再琢磨下

没啥功能，就是一个数字魔术的小游戏。  游戏的玩法如下，  可以把六组数字想象成6张卡片。 游戏开始时，先让对方在心里面想一个数（1到60之间）， 然后问对方想的数字在不在第一张卡片里，以此类推， 直到第6张卡片让对方看完后，就可以推断出对方心里想到的数字了， 至于原理嘛，程序里写的很清楚，哈哈。

说说原理，我们也好改进

终于能看懂程序了

功能，效果，原理啥都基本的介绍下撒

game..........

做啥的？

ding!!!!!!!!!!!!!

没整明白是什么意思。。。。


Question: 求教emIDE安装后的JLink菜单问题

老的版本，比如V2.08是有jlink菜单的，新版本V2.20是没有的，相关功能分散到其他菜单下边了。好了，楼主可以结贴了。

遇到和楼主一样的疑惑。。。


Question: 数组不同赋值方法导致不同结果

无法重新编辑帖子，修正请看四楼

不好意思，题目说错了。并非c不过关。 全都定义都是char，不小心写成int， 方法1中，用0来标记结束是自己规定的，没有说清楚。

第一个，'a' 是ANSIC字符，当然是正确的． 第二个数组，"abcd"是常量字符串，当然不能用int数组来初始化！ 楼主，该去学习Ｃ＋＋／Ｃ基础知识，明显基础不过关呀！

引用 1 楼 zhi_ai_yaya 的回复:m1[0]=97,m1[1]=98,m1[2]=99,m1[3]=100,m1[4]=0。而m1[5]-m1[9]因为没有指定值，所以可能是默认为0，也可能是一个随机值。别胡说 有初始化 没指定的值的元素 默认初始化为 0  不会有其他的情况

引用 楼主 mfcappwizard 的回复:方法1 int m1[10] = {'a', 'b', 'c', 'd', 0} 写0， 是为了标记最后一个，表明结束，运行成功  方法2 int m2[1] = {"abcd"} 运行失败，提示不能找到相应地址块     我认为上面个两种方法是对等的，为什么会一个成功，一个不同通过？ 我是在芯片上做的模拟运行，难道是因为芯片缺少某个分区导致的失败？  谢谢。 方法1 int m1[10] = {'a', 'b', 'c', 'd', 0} 写0， 是为了标记最后一个，表明结束，运行成功 红色标记的那句话是错误的。 那句代码的本质是： 申请一个10个元素的int型数组，并使用{'a', 'b', 'c', 'd', 0}这5个元素初始化，字符a对应的ASCII值是97，所以m1[0]=97,m1[1]=98,m1[2]=99,m1[3]=100,m1[4]=0。而m1[5]-m1[9]因为没有指定值，所以可能是默认为0，也可能是一个随机值。  方法2 int m2[1] = {"abcd"} 这尝试使用一个字符串常量去初始化一个int型变量，肯定报错。  int和char可以根据ASCII值隐式转换，但是字符串不提供，只能进行显示转换。  lz的基础知识还不过，要回去恶补下噢。不断学习才能不断进步。


Question: 如何将一个二进制文件进行倒序输出，要求速度？

小文件用 map 大文件分块map 可能是最快的吧

我想问下8楼，程序的32行那个地方为什么是-2呢？我试着把它改成-1结果好像死循环了……新手表示有点不太理解，有没有大神能帮忙解答一下？谢谢！

无profiler不要谈效率！！尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代！

仅供参考#include <stdio.h> #include <string.h> #include <conio.h> FILE *fi,*fo; int i; int main(int argc,char **argv) {     if (argc<3) {         printf("Usage:%s src des\n",argv[0]);         return 1;     }     if (0==stricmp(argv[1],argv[2])) {         printf("Src and des is same!\n");         return 2;     }     fo=fopen(argv[2],"wb");     if (NULL==fo) {         printf("Can not create file %s\n",argv[2]);         return 3;     }     fi=fopen(argv[1],"rb");     if (NULL==fi) {         fclose(fo);         printf("Can not find file %s\n",argv[1]);         return 4;     }     i=0;     fseek(fi,-1L,SEEK_END);     while (1) {         fputc(fgetc(fi),fo);         i++;         if (i%1000000==0) cprintf("\r%dKB",i/1000);         if (fseek(fi,-2,SEEK_CUR)) break;     }     fclose(fi);     fclose(fo);     cprintf("\r%dKB OK.\r\n",i/1000);     return 0; }

引用 6 楼 xhw88398569 的回复:打开文件之后让文件指针指向文件最后？读取然后再对每个字节的每一位进行操作，这样感觉太慢了。。。[/quote]可以一次读取一块数据

引用 1 楼 zxh707wk 的回复:打开文件之后让文件指针指向文件最后？读取然后再对每个字节的每一位进行操作，这样感觉太慢了。。。

用文件偏移量反着定位读

从文件尾开始读啊，读一块出来，倒序输出，文件指针往前移，再读一块出来，倒序输出。

mmap最快吧

要速度就上scsi磁盘阵列。 这个场景基本上和你的代码写啥样没太大关系。

打开文件之后让文件指针指向文件最后？


Question: 纯C语言实现二叉树，不知道这样写有什么问题没，大神们给点意思，数据结构菜鸟求指点。

引用 1 楼 lisong694767315 的回复:在main函数里多进行几次测试，测试正确就没有问题咯....... 嗯嗯，可以试一下的，因为找到的资料要么用java写的，要么用c++写的，这个是从那些里面转化过来的，不知道大方向有没有问题

在main函数里多进行几次测试，测试正确就没有问题咯.......