Question: 一个奇怪问题

远离啊远离 LZ保重

考试这个就是孔乙己回字有第四种写法罢了。

可能其他人已经有正确答案了，我简单说一下：首先优先级++ > ==,所以 两个判断条件里最终进行==判断的时候，左右两边都是 i的值（是同一块内存的值）,所以不管前缀还是后缀，==的运算结果都为真

这。。。。看到这种感觉真的是晕啊。

LZ的问题是“副作用”范畴的－－－－任何层次的程序员都不要纠结这种东西－－－－楼上有人建议过了。 这种东西从哪里来的，是书就换一本，是老师就拒绝回答－－－－关爱生命、珍惜青春

#include <stdio.h> void main() { 	int i = 1; 	int j = 1;              //需要定義兩個變數 	if(i++ == ++j) 	{ 		printf("ok1\r\n"); 	} 	if(++i == j++) 	{ 		printf("ok2\r\n"); 	}  	if(i++ == ++j) 	{ 		printf("ok1\r\n"); 	} 	if(++i == ++j) 	{ 		printf("ok3\r\n"); 	} }   因該要定義兩個變數  打印出結果為   ok3 應該就是你想要的吧

前置++和后置++的运算优先级比==要高

每行i的值都是i的值

刚接触的c的时候总觉得搞懂这些东西很有必要。现在看到这样的问题直接忽视，谁写这样的代码，直接毙掉

x86/debian gnu linux/gcc 0804840c <main>: #include <stdio.h>  int main(void) {  804840c:       55                      push   %ebp  804840d:       89 e5                   mov    %esp,%ebp  804840f:       83 e4 f0                and    $0xfffffff0,%esp  8048412:       83 ec 20                sub    $0x20,%esp         int i=1;  8048415:       c7 44 24 1c 01 00 00    movl   $0x1,0x1c(%esp)  804841c:       00          if(i++==++i)  804841d:       83 44 24 1c 01          addl   $0x1,0x1c(%esp)  8048422:       8b 44 24 1c             mov    0x1c(%esp),%eax  8048426:       3b 44 24 1c             cmp    0x1c(%esp),%eax  804842a:       0f 94 c0                sete   %al  804842d:       83 44 24 1c 01          addl   $0x1,0x1c(%esp)  8048432:       84 c0                   test   %al,%al  8048434:       74 0c                   je     8048442 <main+0x36>         {                 printf("ok1\r\n");  8048436:       c7 04 24 00 85 04 08    movl   $0x8048500,(%esp)  804843d:       e8 ae fe ff ff          call   80482f0 <puts@plt>         }         if(++i==i++)  8048442:       83 44 24 1c 01          addl   $0x1,0x1c(%esp)  8048447:       8b 44 24 1c             mov    0x1c(%esp),%eax  804844b:       3b 44 24 1c             cmp    0x1c(%esp),%eax  804844f:       0f 94 c0                sete   %al  8048452:       83 44 24 1c 01          addl   $0x1,0x1c(%esp)  8048457:       84 c0                   test   %al,%al                                                                                178,23-29     65% 8048459:       74 0c                   je     8048467 <main+0x5b>         {                 printf("pk2\r\n");  804845b:       c7 04 24 05 85 04 08    movl   $0x8048505,(%esp)  8048462:       e8 89 fe ff ff          call   80482f0 <puts@plt>         }         return 0;  8048467:       b8 00 00 00 00          mov    $0x0,%eax }  804846c:       c9                      leave  804846d:       c3                      ret  LC编程一站式学习 --宋劲杉 P.253  P.236

引用 3 楼 cyd54454 的回复:不要用这样的表达式，这结果是未定义的，也就是依赖编译器的具体实现。编程本就该避免这些未定义的行为+1，但为什么考试总喜欢靠这些

建议不用过多纠结这种东西，看看置顶那个帖子

楼上几位都说了，实现取决于编译器 VS反汇编： 	int i=1; 00E413BE  mov         dword ptr [i],1   	if(i++==++i) 00E413C5  mov         eax,dword ptr [i]  00E413C8  add         eax,1  00E413CB  mov         dword ptr [i],eax  00E413CE  mov         ecx,dword ptr [i]  00E413D1  mov         edx,dword ptr [i]  00E413D4  mov         eax,dword ptr [i]  00E413D7  add         eax,1  00E413DA  mov         dword ptr [i],eax  00E413DD  cmp         ecx,edx               // 这两 比较的是eac = edx = 2               00E413DF  jne         wmain+4Dh (0E413EDh)  00E413E1  mov         dword ptr [ebp-0D0h],1  00E413EB  jmp         wmain+57h (0E413F7h)  00E413ED  mov         dword ptr [ebp-0D0h],0  00E413F7  cmp         dword ptr [ebp-0D0h],0  00E413FE  je          wmain+77h (0E41417h)

引用 楼主 anlun 的回复:int i=1; if(i++==++i) { printf("ok1\r\n"); } if(++i==i++) { printf("pk2\r\n"); } 为何两个ok都打印出来了意思及  i++==++i   ++i==i++ 这就是 编译器计算顺序的问题 第一个 i++ 的值是2 而i = 1；后面 ++i = 2 ，i的值也是2 所以相等的。 第二个++i 的是2 而i = 2；后面先取i的值是2 ，再进行++运算。所以也想等！

这很正常 1) 这个表达式可能有这样几种处理方式 if(i++ == ++i) s;=======>             // if(i==i){ s; i ++ ,++i;}   //OK                          或者   =======>// if(i==i){ s; i ++ ,++i;}      //OK                           或者   =======> if(i++,i==++i)s;                 //                         if(i++,i==++i)s;   可以理解为                              ====>  if(i++ ,i==i){++i;s;}                      //OK                         或者  if(i++ ,i==i){s;++i;}                              //OK                                                 或者    if(i++,++i ,i==i){s;}                          //OK                                                                        或者 if(t=i++,t1=++i,t==t1)s; // 这个不OK  if(++i == i++ )s;=======>             // if(++i,i==i++) s;  //OK                        或者 if(t=++i,t1=i++,t==t1)s; // 这个不OK  这里对i有两次副作用，C，C++没有规定副作用的实现时机                 PS: 其实讨论这个没有意义。


Question: 用C console程序翻译大师用汇编写的WINDOWS 窗口程序

_procwinmain 最后不能返回 0，必须返回 return DefWindowProc(hwnd, uMsg, wParam, lParam);

p2 和 p1 写反了，其中 RegisterClass 中 CreateWindow 中 ClassName 必须一直才可以。

console程序是字符界面，没有窗口、消息循环的概念。

调试出来了，多谢大家的关注及adlay指导，定义WNDCLASSEX时少写了一个数据项，导致错误，另外windows 的窗口过程处理的消息返回值不都是0。  #include <windows.h> #pragma warning (disable:4047 4027 4133 4024 ) #include <stdio.h>  int _procwinmain(int,int,int,int); void mini(); //未初始化数据 int hinstance; int hWinMain; int *p1; int *p2; char *p; int m; int(*pro)()=_procwinmain; //字符串 char classname[] ="my class"; char captionmain[] ="window powered by console program"; char text[]="standard window of windows powered by console"; char* sz=classname; //定义结构 struct WNDCLASSEX{      int cbsize;      int style;      int lpfnwndproc;      int cbclsextra;      int cbwndextra;      int hinstance;      int hicon;      int hcursor;      int hbrbackground;      int lpszmenuname;      int lpszclassname;      int hiconsm;         };  struct POINT {      double x;      double y;         };  struct MSG{      int hwnd;      int message;      int wparam;      int lparam;      int time;      POINT pt;             };  struct RECT{     LONG left;     LONG top;     LONG right;     LONG bottom;     };  struct PAINTSTRUCT{   int hdc ;             int fErase;           RECT  rcPaint;          int fRestore  ;       int fIncUpdate ;   double RGB1;   double RGB2;         };  int main( ) {mini(); ExitProcess(NULL); }    void mini() { //在栈中定义局部变量，获取模块句柄，初始化局部变量 struct WNDCLASSEX stwindclass; struct MSG stmsg; p=classname; p1=(int*)p; p=captionmain; p2=(int*)p; hinstance= GetModuleHandle(NULL); RtlZeroMemory(&stwindclass,sizeof(WNDCLASSEX));  //注册窗口类 stwindclass.hcursor= LoadCursor(0,IDC_ARROW); stwindclass.hinstance=hinstance; stwindclass.cbsize=sizeof(WNDCLASSEX); stwindclass.style=(CS_HREDRAW|CS_VREDRAW); stwindclass.lpfnwndproc= pro; stwindclass.hbrbackground= COLOR_WINDOW+1; stwindclass.lpszclassname= sz;   RegisterClassEx(&stwindclass);   m=GetLastError();     //建立并显示窗口 m=hWinMain= CreateWindowEx(WS_EX_CLIENTEDGE,p1,p2,WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hinstance,NULL);   ShowWindow(hWinMain,SW_SHOWNORMAL);   UpdateWindow(hWinMain);  //消息循环 while(TRUE) {if (GetMessage(&stmsg,NULL,0,0)==0)    break;   else   { TranslateMessage(&stmsg);        DispatchMessage(&stmsg);   } }  }    int  _procwinmain(int hwnd ,int umsg,int wparam, int lparam) {      struct PAINTSTRUCT stps;    struct RECT strect;    int hDC;    if (umsg== WM_PAINT)         {hDC= BeginPaint(&stps,hwnd);         GetClientRect(hwnd,&strect);           DrawText(hDC,&text,-1,&strect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);          EndPaint(hwnd,&stps);         }     else         if(umsg== WM_CLOSE)         { DestroyWindow(hWinMain);           PostQuitMessage(NULL);         }         else         {     DefWindowProc(hwnd,umsg,wparam,lparam);             _asm mov m,eax                 printf("%d\n",m);//测试消息的数量，及返回值时多少             return;         }         return 0; }

不知道，在没有定义这些结构的情况下，编译器老是报错，说有未定义标识符，本人比较菜，学化工出身的，编程都是自学的，求讲解的清楚些，在这里多谢了

重定义了那么多 windows.h 中已经定义过了的结果，你怎么编译过的。。。。 返回 NULL 后用 GetLastError 看错误代码撒


Question: 关于scanf()函数的理解（原创）

引用 11 楼 laishangxiao 的回复:[quote=引用 1 楼 user-6 的回复:] (scanf("%s",e))&&(strlen(e)>10)，请问这句话什么意思？ 实际e的值为 "hello\000\200\322\376\267"  因为e是一个数组。 怕输入的太多   导致数组溢出吧   [/quote] 怕溢出可以用%9s

引用 11 楼 laishangxiao 的回复:[quote=引用 1 楼 user-6 的回复:] (scanf("%s",e))&&(strlen(e)>10)，请问这句话什么意思？ 实际e的值为 "hello\000\200\322\376\267"  因为e是一个数组。 怕输入的太多   导致数组溢出吧   [/quote]  没有用的， &&前面如果已经溢出， 行为已经未定义。

引用 1 楼 user-6 的回复:(scanf("%s",e))&&(strlen(e)>10)，请问这句话什么意思？ 实际e的值为 "hello\000\200\322\376\267"  因为e是一个数组。 怕输入的太多   导致数组溢出吧

引用 8 楼 mujiok2003 的回复:另外getchar()返回int, 不要用char去接。 恩  试了下代码   getchar()会读入字符 然后转成ACSII码为int型 作为返回值

引用 3 楼 truelance 的回复:[quote=引用 楼主 laishangxiao 的回复:] 首先我们知道scanf是一直读到空白符为止：包括 制表符，换行符，回车符，空格；读取成功后会自动将后面的这些字符清理。  这句话的理解是错误的。 C标准中的定义(7.19.6.2.9)是: The first character, if any, after the input item remains unread. 后面的字符不会自动清理，而是等读下一个%时才自动跳过不需要的空白。 而getchar()是不会跳过空白的，所以就把回车读出来了[/quote]  引用 3 楼 truelance 的回复:[quote=引用 楼主 laishangxiao 的回复:] 首先我们知道scanf是一直读到空白符为止：包括 制表符，换行符，回车符，空格；读取成功后会自动将后面的这些字符清理。  这句话的理解是错误的。 C标准中的定义(7.19.6.2.9)是: The first character, if any, after the input item remains unread. 后面的字符不会自动清理，而是等读下一个%时才自动跳过不需要的空白。 而getchar()是不会跳过空白的，所以就把回车读出来了[/quote] 恩   这样就好理解了

另外getchar()返回int, 不要用char去接。

linux g++，输入hello回车后，其实是输入hello\n, 没有\r

fflush会清空输出流的缓冲， 会不会清空输入流的缓冲区则由实现决定。

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

引用 楼主 laishangxiao 的回复:首先我们知道scanf是一直读到空白符为止：包括 制表符，换行符，回车符，空格；读取成功后会自动将后面的这些字符清理。  这句话的理解是错误的。 C标准中的定义(7.19.6.2.9)是: The first character, if any, after the input item remains unread. 后面的字符不会自动清理，而是等读下一个%时才自动跳过不需要的空白。 而getchar()是不会跳过空白的，所以就把回车读出来了

事实上，scanf只要格式转换符不是%c，那么它是是直接跳过最前面的空白符的。然后根据格式串去匹配，而当读到不匹配的输入时，它把不匹配的输入，返回给输入流，并结束匹配，返回


Question: 求问：关于linux下so文件和-l选项

结贴了，根据回帖的正确性给分。

arm-linux gcc 如无-static先so后.a  同1楼。

具体看看gcc manual

-static On systems that support dynamic linking, this prevents linking with the shared libraries. On other systems, this option has no effect.

引用 12 楼 mujiok2003 的回复:[quote=引用 11 楼 u011761982 的回复:] 红色那段只是表示会去link liblibrary.so或者liblibrary.a。并没有说版本号！ 那就是不管版本号， 你可以把把版本后放于文件后前，比如library1.1.0.so，然后在link时指定具体版本 -l library1.1.0[/quote] 在centos下验证了，不行。 我有两个文件，文件1是库，文件2是调用库的。 文件1: #include<stdio.h>  void printMyLib1() { 	printf("In printMyLib1()\n"); }  文件2： #include<stdio.h>  void printMyLib1();  int main(int argc, char*argv[]) { 	printMyLib1(); } 文件1(mylib1.cpp)编译为.o文件，然后生成so文件并加上版本号： gcc -shared -fPIC -c mylib1.cpp -o mylib1.o ld -shared mylib1.o -o libmylib.so.1.1 -soname=libmylib.so.1 该文件放置于/home/dodomouse/workspace/Test  文件2(test.cpp)编译的时候link文件1生成的so文件，发现出错: gcc test.cpp -o test -L/home/dodomouse/workspace/Test/ -lmylib /usr/bin/ld: cannot find -lmylib collect2: error: ld returned 1 exit status  如果生成的时候不加版本号，则是ok的： ld -shared mylib1.o -o libmylib.so gcc test.cpp -o test -L/home/dodomouse/workspace/Test/ -lmylib  这是为什么？

如果-l的名称带版本号，就直接找对应的版本号；如果不带版本号，则在搜索路径下找最新的版本号。

引用 3 楼 u011761982 的回复:[quote=引用 1 楼 truelance 的回复:] 1. 不指定-static时，优先用.so 这个在man手册里面有吗？[/quote] 这个在man里面是有的，在ld下面 现在就是想要确定第3点了，link的时候会把版本号去掉然后查找吗？

引用 1 楼 truelance 的回复:1. 不指定-static时，优先用.so 这个在man手册里面有吗？

引用 11 楼 u011761982 的回复:[quote=引用 7 楼 mujiok2003 的回复:] -llibrary -l library  Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)  It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.   The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.   The directories searched include several standard system directories plus any that you specify with -L.   Normally the files found this way are library files—archive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with ‘lib’ and ‘.a’ and searches several directories. 红色那段只是表示会去link liblibrary.so或者liblibrary.a。并没有说版本号！[/quote] 那就是不管版本号， 你可以把把版本后放于文件后前，比如library1.1.0.so，然后在link时指定具体版本 -l library1.1.0

引用 7 楼 mujiok2003 的回复:-llibrary -l library  Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)  It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, ‘foo.o -lz bar.o’ searches library ‘z’ after file foo.o but before bar.o. If bar.o refers to functions in ‘z’, those functions may not be loaded.   The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.   The directories searched include several standard system directories plus any that you specify with -L.   Normally the files found this way are library files—archive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an -l option and specifying a file name is that -l surrounds library with ‘lib’ and ‘.a’ and searches several directories. 红色那段只是表示会去link liblibrary.so或者liblibrary.a。并没有说版本号！

2. 如果.so文件里没有这个信息，那么软连接就都需要手工生成。现在.so文件里有这个信息，执行ldconfig, 就会自动搜索系统目录下的所有.so文件，自动提取这个信息生成软连接。

1. 不指定-static时，优先用.so


Question: 用c编写一个控制USB口的小程序要求如下，请各位大神指教；

最好改usb的驱动，在usb probe的时候做事件通知用户层程序，如果不这样做的话，禁止usb没意义，其它程序照样可以重新激活usb

楼上这像是灌水类似的东东

赶脚这像是银行U盾类似的东东


Question: C语言指针问题

你交换的是值，不是地址

输出就是先输出大的，再输出小的，因为你有判断处理，如果a小那么和b交换，所以到最后a肯定是大数。sort(实际上应该是swap，sort是排序不是交换)函数就是利用指针来修改（交换）实参的值的。p1,p2的指向（也就是指针值）没有变，而是改变了指向的对象的值。

1）了解下传值和传应用的区别（void sort(int *p1,int *p2);）。 2）了解下C++别名的知识（p1 = &a;）。

代码里明明交换的是*p1和*p2么，也就是a和b，不是p1和p2.  btw: 谭浩强自己都没写过实用的代码，实在是误人子弟。

sort这里应该是swap吧，你的sort函数交换的是p1和p2所指对象的值，而 p1 = &a; // p1指向的是a p2 = &b; // p2指向的是b 所以sort交换的是a和b的值

sort中将p1, p2指向的内容进行了交换而不是交换了p1, p2本身，所以输出a, b是正确的

这是传址调用，是会改变原来变量的值的。简单来说，p1是a的地址，p2是b的地址，在sort里，你取出了相应地址的值，进行了交换，结果就是现在a的值是原来b的值，现在b的值是原来a的值。传值调用才不会改变原变量的值。特意下了一本看了一下，人家明明交换的是p1，p2的值啊.....现在p1指向了b，p2指向的a而已。  贴个源码：  if(a < b) {p = p1;p1 = p2;p2 = p;}


Question: C语言编写一个程序能够铺货本机上午记录；

读取浏览器历史记录？

对获取浏览器上网地址


Question: c语言一道题 怎么做

参考一下这个： #include <stdio.h>  int main( ) { 	int first_num, last_num; 	int odd_sum = 0, even_sum = 0; 	scanf( "%d %d", &first_num, &last_num ); 	for( int i = first_num; i <= last_num; i++ ) 	{ 		if( i % 2 == 0) 		{ 			even_sum += i * i; 		} 		else 		{ 			odd_sum += i * i * i; 		} 	} 	printf( "The sum of even number is : %d\n", even_sum ); 	printf( "The sum of odd number is : %d\n", odd_sum );  	return 0; }

#include <stdio.h> int main() { int b,c; scanf("%d %d",&b,&c); int a[c],i,s=0,d=0;            //没错  for(i=b;i<=c;i++)             //这段有些问题你只能用输入的数来确定数组的大小，而不能用来确定他们在数组中的位置                          a[i]=i;                             for(i=b;i<=c;i++)           {if[i]%2==0) s=s+a[i]*a[i]; else d=d+a[i]*a[i]*a[i];} printf("%d %d",s,d)      return 0; }

路过，10分到手

引用 5 楼 truelance 的回复:我这段代码有好几个错误你没看出来么?  本来是想改正LZ的一处错误，结果发现这个代码问题很多。1楼已经贴了代码，我就懒得写了。

引用 4 楼 zxh707wk 的回复:[quote=引用 2 楼 truelance 的回复:] 编程语言分为编译型和解释型(脚本语言)，像c这样的编译型语言基本都不支持int a[c];这样定义的动态太小的数组。 这个题目完全没必要用数组 另外c中，变量必须在函数开头定义。只有到了c++，才允许在函数中间定义变量。  #include <stdio.h> int main(void) {     int b,c;     int s=0, d=0;     int i;     scanf("%d %d",&b,&c);     for(i=b;i<=c;i++)     {         if[i]%2==0)             s=s+i*i;         else             d=d+i*i*i;     }     printf("%d %d",s,d)     return 0; } +1,这下不用写代码了[/quote] 我这段代码有好几个错误你没看出来么?  本来是想改正LZ的一处错误，结果发现这个代码问题很多。1楼已经贴了代码，我就懒得写了。

引用 2 楼 truelance 的回复:编程语言分为编译型和解释型(脚本语言)，像c这样的编译型语言基本都不支持int a[c];这样定义的动态太小的数组。 这个题目完全没必要用数组 另外c中，变量必须在函数开头定义。只有到了c++，才允许在函数中间定义变量。  #include <stdio.h> int main(void) {     int b,c;     int s=0, d=0;     int i;     scanf("%d %d",&b,&c);     for(i=b;i<=c;i++)     {         if[i]%2==0)             s=s+i*i;         else             d=d+i*i*i;     }     printf("%d %d",s,d)     return 0; } +1,这下不用写代码了

#include <stdio.h> int main() { int b,c; scanf("%d %d",&b,&c); int a[c],i,s=0,d=0;     //这里定义a[c]，表示这个数组有c个元素。这里没错。  for(i=b;i<=c;i++)       //你这段就有问题，如果我输入2,4.那么你只能从a[2]也就是                         //数组的第三个值赋值，前面就是空的，后面又溢出了。  a[i]=i;                 //你只能用输入的数来确定数组的大小，而不能用来确定他们在数组中的位置  for(i=b;i<=c;i++) {if[i]%2==0) s=s+a[i]*a[i]; else d=d+a[i]*a[i]*a[i];} printf("%d %d",s,d)      return 0; }  具体怎么做你自己想想看，不难的

#include <stdio.h> int main(void) {      int b,c;      int s=0, d=0;      int i;      scanf("%d %d",&b,&c);      for(i=b;i<=c;i++)      {          if[i]%2==0)              s=s+i*i;          else             d=d+i*i*i;      }      printf("%d %d\n",s,d);      return 0;  }

#include <stdio.h> int main() {   int i, j;   unsigned int sum_even, sum_odd;    while (1)   {     sum_even = sum_odd = 0;     scanf("%d %d", &i, &j);      for (; i <= j; ++i) {       if (0 == i % 2) // even         sum_even += i * i;       else         sum_odd += i * i * i;     }     printf("%u %u\n", sum_even, sum_odd);   }      return 0; }


Question: EOF ^Z 的问题

這個程式在Windows(命令提示字元)下使用Crtl+Z，如果再UNIX等環境下執行，就使用Crtl+D 來傳回EOF。 另外通常EOF多半代表-1這個整數值。

Windows：Enter、Ctlr+Z、Enter

看有帮助没——http://www.ruanyifeng.com/blog/2011/11/eof.html

如何在stdin（键盘）中输入EOF呢？在不同的系统中的输入方法不同  ctrl-d -- Unix terminal "End of File" (same as "exit" on many shells)   ctrl-z -- DOS "End of File"


Question: win7服务程序中如何弹出对话框

引用 4 楼 xiaoruiaichi 的回复:问题已解决。 是通过createprocessuser的么

问题已解决。

win7下这种方法我试过，但是不懂它具体操作流程，所以没有成功，有什么现成的例子可以参考吗

引用 1 楼 user-3 的回复:服务程序一般在后头运行，不与用户交互， 一般写日志就新了。  被session0 隔离了，  win7下可以用createprocessuser来模拟  具体网上搜索。

服务程序一般在后头运行，不与用户交互， 一般写日志就新了。


Question: 求思路： 从服务器下载视频，视频比较大，很占空间，上百个客户端

引用 11 楼 mujiok2003 的回复:把视频分散在磁盘阵列中， 换固态硬盘， 加大内存。 这是硬伤

把视频分散在磁盘阵列中， 换固态硬盘， 加大内存。

为什么我连楼主的问题都没看明白

如果你要下载视频网站上面的视频，可以直接分析flvcd的方式，基本就差不多了

你在iqiyi随便找个视频，然后到flvcd下载一下就明白了，视频全是分小段存的。不然一个文件就太大了

用p2p技术

引用 4 楼 super_admi 的回复:楼主到底是想使用文件下载服务器，还是媒体播放服务器？  下载视频啊？  多个客户端 从服务器下载 各种文件，到本地。  其中有一种文件：视频， 视频比较大，  光一个客户端下载多个视频就够强了。  何况多个客户端同时发出请求，下载视频。

引用 3 楼 u012879787 的回复:[quote=引用 2 楼 zilaishuichina 的回复:] 压缩、分段。  能具体一些吗？  [/quote]  比如  有很多视频  一个视频1G， 这些视频存在电脑上的时候，一个视频文件分割成很多个小文件，比如存成1M一个的小文件，内存里面维护一个视频文件名称 和 硬盘上的小文件的对应关系表（也可以用数据库来维护这张表），客户端请求视频数据的时候，请求这个视频的第几部分，然后服务器将这一小部分发过去

楼主到底是想使用文件下载服务器，还是媒体播放服务器？

引用 2 楼 zilaishuichina 的回复:压缩、分段。  能具体一些吗？

压缩、分段。

参考eMule或BitTorrent源代码。


Question: 一个c语言的小问题，请教高手。。。

引用 16 楼 pz239 的回复:赵老师的方法已经超出了我的理解能力了，有没有简单点的方法。。，我自己想了个笨办法，如下。，不知是否正确。。  在B不大的情况下： unsigned long value = 0; p = p + B; for (i = 0; i < B; i++)     value =  *(unsigned char *)p-- * (256的i次方）  可以的。  unsigned char* p = ...; unsigned long long v = 0; for(size_t i = 0; i < B;  ++i){    v <<= 8;    v += *p; }  或者  unsigned char* p = ...; unsigned long long v = 0;  for(int  i = B-1; i >=  0;  --i){    v <<= 8;    v += p[i]; }

我想这样应该可以，在x86上不考虑bus error。  unsigned int *q = p;   //(p为char *) cnt = B / sizeof(unsigned int); int i;  for(i = 0;i < cnt;i++) {         printf("%u\n",*q);         q++; }  p = q; int rest = B - cnt*szieof(unsigned int); switch(rest) {       case 1:               printf("%u\n",(unsigned int)*p);break;        case 2:              printf("%u\n",(unsigned int)(*p | (*(p+1) << 8));break;//小端模式下       case 3:               printf("%u\n",(unsigned int)(*p | (*(p+1) << 8) | (*(p+2) << 16));break;       default:             break; }

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

B的长度有个范围吧，大于8就不能用long或者long long表示啦

B不是个确定值，所以B个字节的内存空间不一定对应有特定的类型的长度（比如int要求B是4），所以不能用将这块内存空间看做是某种特定类型来提取其值。。  说白了就是给定了一片内存空间，起始位置是p，长度是B（B不是很大），想把这块内存空间中的二进制位转换成一个大整数。。

引用 11 楼 mymtom 的回复:[quote=引用 6 楼 cyd54454 的回复:] 这个B是多少啊？你把p强制转换成(unsigned int *)，然后取值，就是这样。因为对于二进制来说哪有什么无符号有符号啊，看你想怎么去解释这些二进制而已。你用int *指针去取，它把最高位解释成符号位以此确定正负；你用unsigned int *指针去取，它就不会把最高位解释成符号位而是当做数据位。 最好不要真么做，char *p强制转换成(unsgined int *)再取值 u = *((unsgined int *)p);  在某些系统上会出现BUS ERROR的。[/quote] 好吧，的确有疏忽，没去考虑地址未对齐的读写。因为从来没遇到过....

引用 6 楼 cyd54454 的回复:这个B是多少啊？你把p强制转换成(unsigned int *)，然后取值，就是这样。因为对于二进制来说哪有什么无符号有符号啊，看你想怎么去解释这些二进制而已。你用int *指针去取，它把最高位解释成符号位以此确定正负；你用unsigned int *指针去取，它就不会把最高位解释成符号位而是当做数据位。 最好不要真么做，char *p强制转换成(unsgined int *)再取值 u = *((unsgined int *)p);  在某些系统上会出现BUS ERROR的。

引用 8 楼 pz239 的回复:B是个变量。。，我想把这些二进制换算成一个无符号整数，这个无符号整数要能用p和B表示出来。。 什么类型的变量？能说下基于什么情况要把B转换成一个无符号数么？在什么都不知道的时候，我只能说强制转换呗。

再次重申一次，01不是字符，而是内存本身的二进制位。。

是字符串吗， 用strtoul啊  #include <stddef.h> #include <stdio.h> #include <stdlib.h>  int main(int argc, char *argv[]) {     unsigned int u;     char s1[] =         "0000" "0001" "0010" "0011"         "0100" "0101" "0110" "0111";      char s2[] =         "1000" "1001" "1010" "1011"         "1100" "1101" "1110" "1111";      u = strtoul(s1, NULL, 2);     printf("%08x\n", u);      u = strtoul(s2, NULL, 2);     printf("%08x\n", u);      return 0; }

[quote=引用 2 楼 starytx 的回复:] 你说的这个01串是字符串形式吗？是的话需要一个字符一个字符的进行计算[/quote 01串指的是这B个字节本身所包含的二进制位，要求计算速度越快越好，就是用c本身实现，不涉及它语言。。

01串指的是这B个字节本身所包含的二进制位。。

引用 2 楼 starytx 的回复:你说的这个01串是字符串形式吗？是的话需要一个字符一个字符的进行计算 要用ASCII来判断吗？ c#直接int.Parse(string)就好了。。。

你说的这个01串是字符串形式吗？是的话需要一个字符一个字符的进行计算

二进制与十进制之间的转化


Question: C99怎么初始化结构体中的int数组的全部变量 ?

如果有这样的需要，我使用 REPEAT 宏处理。 比如说想生成静态的表之类的。

用memset 吧。

引用 6 楼 mymtom 的回复:gcc的扩展初始化时允许指定数组下标范围，但是这不是C99标准 https://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/Designated-Inits.html#Designated-Inits  #include <inttypes.h>  #include <stdio.h>   #define N   10 struct A { int32_t array[N]; };  struct A a = {    .array = {[0 ... N - 1] = 0x80}, };  int main(int argc, char *argv[]) {      int i, n;      n = N;     for (i = 0; i < n; ++i) {         printf("%d\n", a.array[i]);     }      return 0; }  谢谢,我代码跑在android的kernel,这样下标的[1...9]不行..

仅供参考#include <stdio.h> float data[500]; int i; void main() {     for (i=0;i<500;i++) {data[i]=1.0f;printf("%g\n",data[i]);}     __asm {         push ecx         push edi         mov ecx,500         mov eax,0xBF800000 //-1.0f         lea edi,data         rep stosd         pop edi         pop ecx     }     for (i=0;i<500;i++) printf("%g\n",data[i]); }

struct A { int32_t array[10]; A() {     for(int i = 0; i != 10; i++)         array[i] = 0x80; } };  仅供参考

引用 1 楼 mymtom 的回复:没有办法的，只有写够10个0x80吧 struct A { int32_t array[MAX]; };  struct A a = {    .array = {[0...MAX-1]:0x80}, }; 我试着这么写,但是不允许里面有marco减1...

只知道在构造中循环初始化

C99: If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.  If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then: — if it has pointer type, it is initialized to a null pointer; — if it has arithmetic type, it is initialized to (positive or unsigned) zero; — if it is an aggregate, every member is initialized (recursively) according to these rules; — if it is a union, the first named member is initialized (recursively) according to these rules.  所以不希望初始化成0的都必须明确写出来

没有办法的，只有写够10个0x80吧


Question: 单链表删除元素的参数有疑问求助

引用 5 楼 dasdase 的回复:[quote=引用 1 楼 relaxisland 的回复:] 因为你要的是返回  已删除数据的指针 要传递指针，必须用指针的指针 你可以先从 要传出一个数需要指针 开始理解 传出一个数需要指针，传出一个数的指针就需要指向这个数的指针的指针？是不是这个意思？[/quote] 是的

引用 1 楼 relaxisland 的回复:因为你要的是返回  已删除数据的指针 要传递指针，必须用指针的指针 你可以先从 要传出一个数需要指针 开始理解 传出一个数需要指针，传出一个数的指针就需要指向这个数的指针的指针？是不是这个意思？

应该是楼上所说，我理解错意思了

data参数返回的是指针型的数据吧。

发下你的链表结构体。我想应该是用void **data用来指向数据域的，它里面存的是指向数据节点的指针，只是个猜测


Question: 求牛人优化快排算法，先谢谢了

/*   *快排法；   *通过一次排序将数组分为独立的两部分，其中一部分的所用数据比另一部分都要小。   *然后再对两部分独立排序，递归进行。   */   void Quick(int str[],int i,int j)   {       int m,n,temp;       int k;       m=i;       n=j;       k=str[(m+n)/2];       do       {           while(str[m]<k&&m<j)               m++;           while(str[n]>k&&n>i)               n--;           if(m<=n)           {               temp=str[m];               str[m]=str[n];               str[n]=temp;               m++;               n--;           }       }while(m<=n);       if(m<j)           Quick(str,m,j);       if(n>i)           Quick(str,i,n);   }

引用 5 楼 misskissC 的回复:快速排序的层次改进 :http://blog.csdn.net/misskissc/article/details/19246569排相等元素 is the last result

glibc中的代码，供参考  /* Copyright (C) 1991,1992,1996,1997,1999,2004 Free Software Foundation, Inc.    This file is part of the GNU C Library.    Written by Douglas C. Schmidt (schmidt@ics.uci.edu).     The GNU C Library is free software; you can redistribute it and/or    modify it under the terms of the GNU Lesser General Public    License as published by the Free Software Foundation; either    version 2.1 of the License, or (at your option) any later version.     The GNU C Library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Lesser General Public License for more details.     You should have received a copy of the GNU Lesser General Public    License along with the GNU C Library; if not, write to the Free    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA    02111-1307 USA.  */  /* If you consider tuning this algorithm, you should consult first:    Engineering a sort function; Jon Bentley and M. Douglas McIlroy;    Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993.  */  #include <alloca.h> #include <limits.h> #include <stdlib.h> #include <string.h>  /* Byte-wise swap two items of size SIZE. */ #define SWAP(a, b, size)                            　　\ do                                                     \ {                                                      \     register size_t __size = (size);                　 \     register char *__a = (a), *__b = (b);            　\     do                                                 \     {                                                  \         char __tmp = *__a;                             \           *__a++ = *__b;                               \           *__b++ = __tmp;                              \     } while (--__size > 0);                            \ } while (0)  /* Discontinue quicksort algorithm when partition gets below this size.    This particular magic number was chosen to work best on a Sun 4/260. */ #define MAX_THRESH 4  /* Stack node declarations used to store unfulfilled partition obligations. */ typedef struct {     char *lo;     char *hi; } stack_node;  /* The next 4 #defines implement a very fast in-line stack abstraction. */ /* The stack needs log (total_elements) entries (we could even subtract log(MAX_THRESH)).    Since total_elements has type size_t, we get as upper bound for log (total_elements):    bits per byte (CHAR_BIT) * sizeof(size_t).  */ #define STACK_SIZE　　　　 (CHAR_BIT * sizeof(size_t)) #define PUSH(low, high)　 ((void) ((top->lo = (low)), (top->hi = (high)), ++top)) #define POP(low, high)　　((void) (--top, (low = top->lo), (high = top->hi))) #define STACK_NOT_EMPTY  (stack < top)   /* Order size using quicksort.  This implementation incorporates    four optimizations discussed in Sedgewick:     1. Non-recursive, using an explicit stack of pointer that store the       next array partition to sort.  To save time, this maximum amount       of space required to store an array of SIZE_MAX is allocated on the       stack.  Assuming a 32-bit (64 bit) integer for size_t, this needs       only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).       Pretty cheap, actually.     2. Chose the pivot element using a median-of-three decision tree.       This reduces the probability of selecting a bad pivot value and       eliminates certain extraneous comparisons.     3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving       insertion sort to order the MAX_THRESH items within each partition.       This is a big win, since insertion sort is faster for small, mostly       sorted array segments.     4. The larger of the two sub-partitions is always pushed onto the       stack first, with the algorithm then concentrating on the       smaller partition.  This *guarantees* no more than log (total_elems)       stack size is needed (actually O(1) in this case)! */  void _quicksort (void *const pbase, size_t total_elems, size_t size, __compar_d_fn_t cmp, void *arg) {     register char *base_ptr = (char *) pbase;      const size_t max_thresh = MAX_THRESH * size;      if (total_elems == 0)         /* Avoid lossage with unsigned arithmetic below.  */         return;      if (total_elems > MAX_THRESH)     {         char *lo = base_ptr;         char *hi = &lo[size * (total_elems - 1)];         stack_node stack[STACK_SIZE];         stack_node *top = stack;          PUSH (NULL, NULL);          while (STACK_NOT_EMPTY)         {             char *left_ptr;             char *right_ptr;              /* Select median value from among LO, MID, and HI. Rearrange                LO and HI so the three values are sorted. This lowers the                probability of picking a pathological pivot value and                skips a comparison for both the LEFT_PTR and RIGHT_PTR in                the while loops. */              char *mid = lo + size * ((hi - lo) / size >> 1);              if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)                 SWAP (mid, lo, size);             if ((*cmp) ((void *) hi, (void *) mid, arg) < 0)                 SWAP (mid, hi, size);             else                 goto jump_over;             if ((*cmp) ((void *) mid, (void *) lo, arg) < 0)                 SWAP (mid, lo, size); jump_over:             ;              left_ptr  = lo + size;             right_ptr = hi - size;              /* Here's the famous ``collapse the walls'' section of quicksort.                Gotta like those tight inner loops!  They are the main reason                that this algorithm runs much faster than others. */             do             {                 while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)                     left_ptr += size;                  while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)                     right_ptr -= size;                  if (left_ptr < right_ptr)                 {                     SWAP (left_ptr, right_ptr, size);                     if (mid == left_ptr)                         mid = right_ptr;                     else if (mid == right_ptr)                         mid = left_ptr;                     left_ptr += size;                     right_ptr -= size;                 }                 else if (left_ptr == right_ptr)                 {                     left_ptr += size;                     right_ptr -= size;                     break;                 }             }             while (left_ptr <= right_ptr);              /* Set up pointers for next iteration.  First determine whether                left and right partitions are below the threshold size.  If so,                ignore one or both.  Otherwise, push the larger partition's                bounds on the stack and continue sorting the smaller one. */              if ((size_t) (right_ptr - lo) <= max_thresh)             {                 if ((size_t) (hi - left_ptr) <= max_thresh)                     /* Ignore both small partitions. */                     POP (lo, hi);                 else                     /* Ignore small left partition.*/                     lo = left_ptr;             }             else if ((size_t) (hi - left_ptr) <= max_thresh)                 /* Ignore small right partition.*/                 hi = right_ptr;             else if ((right_ptr - lo) > (hi - left_ptr))             {                 /* Push larger left partition indices. */                 PUSH (lo, right_ptr);                 lo = left_ptr;             }             else             {                 /* Push larger right partition indices. */                 PUSH (left_ptr, hi);                 hi = right_ptr;             }         }     }      /* Once the BASE_PTR array is partially sorted by quicksort the rest        is completely sorted using insertion sort, since this is efficient        for partitions below MAX_THRESH size. BASE_PTR points to the beginning        of the array to sort, and END_PTR points at the very last element in        the array (*not* one beyond it!). */  #define min(x, y) ((x) < (y) ? (x) : (y))      {         char *const end_ptr = &base_ptr[size * (total_elems - 1)];         char *tmp_ptr = base_ptr;         char *thresh = min(end_ptr, base_ptr + max_thresh);         register char *run_ptr;          /* Find smallest element in first threshold and place it at the            array's beginning.  This is the smallest array element,            and the operation speeds up insertion sort's inner loop. */          for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size)             if ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)                 tmp_ptr = run_ptr;          if (tmp_ptr != base_ptr)             SWAP (tmp_ptr, base_ptr, size);          /* Insertion sort, running from left-hand-side up to right-hand-side.  */          run_ptr = base_ptr + size;         while ((run_ptr += size) <= end_ptr)         {             tmp_ptr = run_ptr - size;             while ((*cmp) ((void *) run_ptr, (void *) tmp_ptr, arg) < 0)                 tmp_ptr -= size;              tmp_ptr += size;             if (tmp_ptr != run_ptr)             {                 char *trav;                  trav = run_ptr + size;                 while (--trav >= run_ptr)                 {                     char c = *trav;                     char *hi, *lo; 　　　　　　　　　　　 for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo)                         * hi = *lo;                     *hi = c;                 }             }         }     } }

快速排序的分析与优化：http://blog.csdn.net/lisonglisonglisong/article/details/32982809

quickly sort喷了


Question: warning: excess elements in scalar initializer [enabled by default]   };

引用 5 楼 lisong694767315 的回复:[quote=引用 3 楼 doubleselect 的回复:] [quote=引用 2 楼 lisong694767315 的回复:] 把 static int *daytab 改成 static int daytab[]试试  按照你的做法，修改可以运行（先表示感谢），但我还有一个问题：我想定义的是一个指针数组，把static int *daytab 改为static int *daytab[] ={.....} 为什么还是报同样的错呢？我的思路有什么问题吗？为什么上面代码中的 //the function will return the pointer of the month of sting     char *month_name(int n) {         static char *name[]={"January","February","March",         "April","May","June","July","August","September","October","November",         "December"};         return name[n-1];     } static char *name[]却可以呢？（我之前测试过了）。 谢谢！[/quote]  你要搞清楚static int daytab[]中的 daytab 是一个一维数组，每个元素是一个整数。而  static char *name[] 你可以看作是一个二维的字符数组，其中每个元素是一个字符串（还是一个字符数组）。区分开一维和二维。  或者你可以这么看 static char *name[] 这个数组中的元素是 char*指针，每个指针指向一个字符串的首地址。。。 [/quote]   想明白了，谢谢！

引用 3 楼 doubleselect 的回复:[quote=引用 2 楼 lisong694767315 的回复:] 把 static int *daytab 改成 static int daytab[]试试  按照你的做法，修改可以运行（先表示感谢），但我还有一个问题：我想定义的是一个指针数组，把static int *daytab 改为static int *daytab[] ={.....} 为什么还是报同样的错呢？我的思路有什么问题吗？为什么上面代码中的 //the function will return the pointer of the month of sting     char *month_name(int n) {         static char *name[]={"January","February","March",         "April","May","June","July","August","September","October","November",         "December"};         return name[n-1];     } static char *name[]却可以呢？（我之前测试过了）。 谢谢！[/quote]  你要搞清楚static int daytab[]中的 daytab 是一个一维数组，每个元素是一个整数。而  static char *name[] 你可以看作是一个二维的字符数组，其中每个元素是一个字符串（还是一个字符数组）。区分开一维和二维。  或者你可以这么看 static char *name[] 这个数组中的元素是 char*指针，每个指针指向一个字符串的首地址。。。

引用 1 楼 truelance 的回复:应该是 static int *daytab = [ ... ] 而不是 static int *daytab = { ... }  声明是用 {}没错的吧。

引用 2 楼 lisong694767315 的回复:把 static int *daytab 改成 static int daytab[]试试  按照你的做法，修改可以运行（先表示感谢），但我还有一个问题：我想定义的是一个指针数组，把static int *daytab 改为static int *daytab[] ={.....} 为什么还是报同样的错呢？我的思路有什么问题吗？为什么上面代码中的 //the function will return the pointer of the month of sting     char *month_name(int n) {         static char *name[]={"January","February","March",         "April","May","June","July","August","September","October","November",         "December"};         return name[n-1];     } static char *name[]却可以呢？（我之前测试过了）。 谢谢！


Question: 关于C语言的问题。

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

The conversion specifiers and their meanings are:       diouxX  The int (or appropriate variant) argument is converted to signed              decimal (d and i), unsigned octal (o), unsigned decimal (u), or              unsigned hexadecimal (x and X) notation.  The letters ``abcdef''              are used for x conversions; the letters ``ABCDEF'' are used for X              conversions.  The precision, if any, gives the minimum number of              digits that must appear; if the converted value requires fewer              digits, it is padded on the left with zeros.

x86/debian linux/gcc vi print.c  #include<stdio.h> int main(){ int i=01234, j=8; long p=-1l; printf("%o %04o %4d",i,j,p); return 0;  }    gcc print.c  -1's in momory  is 0xffffffff on my computer. %o read this momory will explain 0xffffffff to be unsigned(and is 8 jinzhi).  my computer can't support chinese temporay.

引用 4 楼 lovesmiles 的回复:错误的代码导致的错误结果，没有分析的意义。 代码有错吗？结果有错嘛？

错误的代码导致的错误结果，没有分析的意义。

引用 2 楼 Kai_gai 的回复:楼主电脑上long是几个字节啊？如是4字节应该是37777777777，如是8字节则应是1777777777777777777777。建议单步调试一下。 不好意思，弄错了。字节应该是17777777777

引用 1 楼 ll2009301953 的回复:long型为8字节64位，-1的补码为64个1，你用8进制输出按内存取出来的就是全为1的值。+1


Question: 以下程序输出是什么？

引用 6 楼 pangbin106 的回复:我已经编译运行有结果，不明白compare函数起什么作用，因为它没有实参，请大侠们帮忙解释  先把main的原型改正确

引用 6 楼 pangbin106 的回复:我已经编译运行有结果，不明白compare函数起什么作用，因为它没有实参，请大侠们帮忙解释 void qsort (void* base, size_t num, size_t size,             int (*compar)(const void*,const void*));  转换为了函数指针。

引用 6 楼 pangbin106 的回复:我已经编译运行有结果，不明白compare函数起什么作用，因为它没有实参，请大侠们帮忙解释 compare是个函数啊，qsort函数里的每次比较都会调用compare函数啊

用 法： void qsort(void *base,int nelem,int width,int (*fcmp)(const void *,const void *)); 参数： 1 待排序数组首地址 2 数组中待排序元素数量 3 各元素的占用空间大小 4 指向函数的指针，用于确定排序的顺序

是骡子是马拉出来溜溜！

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

按F5编译运行

cab can cap car cat

按字典序排序的结果呀


Question: 请问一个buffer overflow detected的问题

sprintf()实际输出的内容长度超过了输出buffer的长度 你把用到sprintf及前面相关的代码贴出来吧

./rout[0x40a275]  将rout使用-g选项重新编译链接

大概是这段程序出问题了，大家帮我看看，谢谢  #include <stdlib.h> #include <string.h> #include <stdio.h> #include <rout.h>  void WriteData(double *FLOW, 	       float *R_FLOW, 	       float *STORAGE, 	       float *LEVEL, 	       float *PowerProd, 	       char *name, 	       char *outpath, 	       int ndays, 	       int nmonths, 	       TIME *DATE, 	       float factor_sum, 	       int first_year, 	       int first_month, 	       int last_year, 	       int last_month,                int start_year, 	       float lat, 	       float lon, 	       int type, 	       int decimal_places)  {   FILE *fp,*fp_routed,*fp_reservoir;   char *filename_fp,*filename_fp_routed,*filename_fp_reservoir;   char fmtstr[50];   char fmtstr_routed[50];   char LATLON[50];   float MONTHLY[MAXYEARS+1][13];  /*variables for monthly means*/   float YEARLY[13];   float R_MONTHLY[MAXYEARS+1][13];   float R_YEARLY[13];   float S_MONTHLY[MAXYEARS+1][13];   float S_YEARLY[13];   float L_MONTHLY[MAXYEARS+1][13];   float L_YEARLY[13];   float days;   int DaysInMonth[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };   int nyears[13];   int feb_days,feb_nrs;   int i,j,k;   int yy,mm;   int leap_year;   int count_years;    filename_fp = (char*)calloc(100,sizeof(char));   filename_fp_routed = (char*)calloc(100,sizeof(char));   filename_fp_reservoir = (char*)calloc(100,sizeof(char));      printf("Write data is opened!!!\n");    sprintf(filename_fp,"%s%s.day",outpath,name);   if((fp = fopen(filename_fp, "w")) == NULL) {     printf("Cannot open %s\n",filename_fp);     exit(1);   }//if  printf("WHY_0!!!\n");   if(type == 2 ) { //reservoir     strcpy(filename_fp_reservoir,outpath);     sprintf(fmtstr,"reservoir_%%.%if_%%.%if", 	    decimal_places,decimal_places);     sprintf(LATLON,fmtstr,lat,lon);     strcat(filename_fp_reservoir,LATLON);     if((fp_reservoir = fopen(filename_fp_reservoir, "w")) == NULL) {       printf("Cannot open %s\n",filename_fp_reservoir);       exit(1);     }//open   }//reservoir  printf("WHY_1!!!\n");   strcpy(filename_fp_routed,outpath);   sprintf(fmtstr_routed,"streamflow_%%.%if_%%.%if", 	  decimal_places,decimal_places);   sprintf(LATLON,fmtstr_routed,lat,lon);   strcat(filename_fp_routed,LATLON);   printf("filename_fp_routed=%s\n",filename_fp_routed);   if((fp_routed = fopen(filename_fp_routed, "w")) == NULL) {     printf("Cannot open %s\n",filename_fp_routed);     exit(1);   }   else { printf("Routed file opened: %s\n",filename_fp_routed);}      printf("WHY_3!!!\n");    /* Initialize */   for(i=0;i<=12;i++) {     YEARLY[i]=0.;     R_YEARLY[i]=0.;         S_YEARLY[i]=0.;     L_YEARLY[i]=0.;         nyears[i]=0;     for(j=0;j<=MAXYEARS;j++) {       MONTHLY[j][i]=0.;       R_MONTHLY[j][i]=0.;       S_MONTHLY[j][i]=0.;       L_MONTHLY[j][i]=0.;     }   }    count_years=0;   if(last_year==first_year) {     for(i=first_month;i<=last_month;i++)        nyears[i]+=1;   }   else {     for(i=first_month;i<=12;i++)        nyears[i]+=1;     count_years++;     for(i=1;i<=last_month;i++)        nyears[i]+=1;     count_years++;     for(k=0;k<count_years;k++) {       for(i=1;i<=12;i++)  	nyears[i]+=1;     }   }          /* Write daily data and store monthly values */   for(i=1;i<=ndays;i++) {     if((DATE[i].year>first_year && DATE[i].year<last_year)         || (DATE[i].year==first_year && DATE[i].month>=first_month)        || (DATE[i].year==last_year && DATE[i].month<=last_month)) {       yy=DATE[i].year-first_year;       mm=DATE[i].month;       MONTHLY[yy][mm]+=FLOW[i];       YEARLY[mm]+=FLOW[i];       R_MONTHLY[yy][mm]+=R_FLOW[i];       R_YEARLY[mm]+=R_FLOW[i];       S_MONTHLY[yy][mm]+=STORAGE[i];       S_YEARLY[mm]+=STORAGE[i];       L_MONTHLY[yy][mm]+=LEVEL[i];       L_YEARLY[mm]+=LEVEL[i];       if(type==2) { /* i.e. reservoir */ 	fprintf(fp,"%d %d %d %f %f %.2f %.2f\n", 		DATE[i].year,DATE[i].month,DATE[i].day,R_FLOW[i],FLOW[i],STORAGE[i],LEVEL[i]); 	fprintf(fp_reservoir,"%d %d %d %f %f %.2f %.2f %.2f\n", 		DATE[i].year,DATE[i].month,DATE[i].day,R_FLOW[i],FLOW[i],STORAGE[i],LEVEL[i],PowerProd[i]); 	fprintf(fp_routed,"%d %d %d %f\n", 		DATE[i].year,DATE[i].month,DATE[i].day,R_FLOW[i]);       }       else { 	fprintf(fp,"%d %d %d %f %f %.2f %.2f\n", 		DATE[i].year,DATE[i].month,DATE[i].day,FLOW[i],R_FLOW[i],0.,0.); 	fprintf(fp_routed,"%d %d %d %f\n", 		DATE[i].year,DATE[i].month,DATE[i].day,FLOW[i]);       }     }   }    fclose(fp);   fclose(fp_routed);   if(type==2) fclose(fp_reservoir);    /* Write monthly data */   sprintf(filename_fp,"%s%s.month",outpath,name);   if((fp = fopen(filename_fp, "w")) == NULL) {     printf("Cannot open %s\n",filename_fp);     exit(1);   }    feb_days=feb_nrs=0;   i=0;   leap_year=IsLeapYear(i+first_year);   if(first_year==last_year) {     for(j=first_month;j<=last_month;j++) {       days=DaysInMonth[j];       if(j==2) { 	days=DaysInMonth[j]+leap_year; 	feb_days+=days; 	feb_nrs+=1;       }       if(type==2) { 	fprintf(fp,"%d %d %f %f %f %f\n", 		i+first_year,j,R_MONTHLY[i][j]/days, 		MONTHLY[i][j]/days, 		S_MONTHLY[i][j]/days, 		L_MONTHLY[i][j]/days);       }       else { 	fprintf(fp,"%d %d %f %f %f %f\n", 		i+first_year,j,MONTHLY[i][j]/days, 		R_MONTHLY[i][j]/days, 		0.,0.);       }     }       }   else {     for(j=first_month;j<=12;j++) {       days=DaysInMonth[j];       if(j==2) {         days=DaysInMonth[j]+leap_year; 	feb_days+=days; 	feb_nrs+=1;       }       if(type==2) { 	fprintf(fp,"%d %d %f %f %f %f\n", 		i+first_year,j,R_MONTHLY[i][j]/days, 		MONTHLY[i][j]/days, 		S_MONTHLY[i][j]/days, 		L_MONTHLY[i][j]/days);       }       else { 	fprintf(fp,"%d %d %f %f %f %f\n", 		i+first_year,j,MONTHLY[i][j]/days, 		R_MONTHLY[i][j]/days, 		0.,0.);       }     }     for(i=1;i<last_year-first_year;i++) {       leap_year=IsLeapYear(i+first_year);       for(j=1;j<=12;j++) { 	days=DaysInMonth[j]; 	if(j==2) { 	  days=DaysInMonth[j]+leap_year; 	  feb_days+=days; 	  feb_nrs+=1; 	} 	if(type==2) { 	  fprintf(fp,"%d %d %f %f %f %f\n", 		  i+first_year,j,R_MONTHLY[i][j]/days, 		  MONTHLY[i][j]/days, 		  S_MONTHLY[i][j]/days, 		  L_MONTHLY[i][j]/days); 	} 	else  { 	  fprintf(fp,"%d %d %f %f %f %f\n", 		  i+first_year,j,MONTHLY[i][j]/days, 		  R_MONTHLY[i][j]/days, 		  0.,0.); 	}       }     }     i=last_year-first_year;     leap_year=IsLeapYear(i+first_year);     for(j=1;j<=last_month;j++) {       days=DaysInMonth[j];       if(j==2) {        days=DaysInMonth[j]+leap_year; 	feb_days+=days; 	feb_nrs+=1;       }       if(type==2) { 	fprintf(fp,"%d %d %f %f %f %f\n", 		i+first_year,j,R_MONTHLY[i][j]/days, 		MONTHLY[i][j]/days, 		S_MONTHLY[i][j]/days, 		L_MONTHLY[i][j]/days);       }       else {	 	fprintf(fp,"%d %d %f %f %f %f\n", 		i+first_year,j,MONTHLY[i][j]/days, 		R_MONTHLY[i][j]/days, 		0.,0.);       }     }      }   fclose(fp);    /* Write mean monthly data */   sprintf(filename_fp,"%s%s.year",outpath,name);   if((fp = fopen(filename_fp, "w")) == NULL) {     printf("Cannot open %s\n",filename_fp);     exit(1);   }    for(i=1;i<=12;i++) {     days=DaysInMonth[i];     if(i==2) days=(float)feb_days/(float)feb_nrs;     if(type==2) {       fprintf(fp,"%d %f %f %f %f\n", 	      i,R_YEARLY[i]/(nyears[i]*days), 	      YEARLY[i]/(nyears[i]*days), 	      S_YEARLY[i]/(nyears[i]*days), 	      L_YEARLY[i]/(nyears[i]*days));     }     else {       fprintf(fp,"%d %f %f %f %f\n", 	      i,YEARLY[i]/(nyears[i]*days), 	      R_YEARLY[i]/(nyears[i]*days), 	      S_YEARLY[i]/(nyears[i]*days), 	      L_YEARLY[i]/(nyears[i]*days));     }   }    fclose(fp); }

Makefile里面有-g啊  引用 4 楼 zhao4zhong1 的回复:./rout[0x40a275]  将rout使用-g选项重新编译链接

能具体一点么？谢谢  引用 1 楼 user-4 的回复:好像是sprintf出问题了

好像是sprintf出问题了


Question: 互斥锁总是被锁死出不来了

引用 13 楼 Cabbage_c 的回复:问题解决了，是因为中断里面调用了信号p操作，当信号被占用的时候，中断里面是p不到信号而阻塞，但是中断里面阻塞占用了cpu时间片，而外部程序不能执行所以没法v操作，所以一直死在了中断时间片里，这样就相当于死循环了。  尽然花了3个多月解决这个问题

引用 9 楼 Cabbage_c 的回复:[quote=引用 7 楼 mujiok2003 的回复:] [quote=引用 5 楼 Cabbage_c 的回复:] [quote=引用 4 楼 mujiok2003 的回复:] open error的时候没有解锁。 解锁了呀！！！[/quote] 都return -1;了， 哪里解锁。 [/quote]  不是先t_sem_V()，然后再return -1的么？ [/quote] OKay， 没有看清楚。

引用 7 楼 mujiok2003 的回复:[quote=引用 5 楼 Cabbage_c 的回复:] [quote=引用 4 楼 mujiok2003 的回复:] open error的时候没有解锁。 解锁了呀！！！[/quote] 都return -1;了， 哪里解锁。 [/quote]  不是先t_sem_V()，然后再return -1的么？

到P操作阻塞了就说明是上次没有V操作，可是为什么会出现没有V操作呢？  不可能的呀！！

引用 5 楼 Cabbage_c 的回复:[quote=引用 4 楼 mujiok2003 的回复:] open error的时候没有解锁。 解锁了呀！！！[/quote] 都return -1;了， 哪里解锁。

这个程序是修改过的 ，本来这个内存拷贝，ioctrl和open都是在锁中间的   原来的流程是： _sem_P(); open() ioctrl(); memcpy(); _sem_V();  我想先确定一下，在锁中间open，ioctrl，内存拷贝不会出现问题吗？ 我担心会不会是内存拷贝引起的错误。

引用 4 楼 mujiok2003 的回复:open error的时候没有解锁。 解锁了呀！！！

open error的时候没有解锁。

引用 2 楼 truelance 的回复:P失败了就不应该往下走 对，P失败就阻塞了，可是现在的情况是永远阻塞，出不来了。为什么会出现这种情况，这里的代码有问题吗？ 内存拷贝，打开文件，ioctrl都没有问题吗？

P失败了就不应该往下走

最后面的代码注释完了后会关闭文件流。  close(_dev_fd);

引用 11 楼 pengzhixi 的回复:你 p操作的ret为非0的时候 你还是进行了v操作 你只有p操作成功了后面才可以用v操作  P操作如果失败就阻塞了，应该不会继续走了吧。


Question: 来瞅瞅这个问题   说bool类型没有定义

在C89标准里，C语言是没有bool（布尔）类型的。  但在C99标准里面，又定义了bool类型变量。这时，只要引入头文件 <stdbool.h>，就能在C语言里面正常使用bool类型。  当然像楼上说的，你也可以自己#define

你是.c文件， bool是c++中的基本类型。 不是每个c编译器都支持bool的

bool是C++的关键字 C不支持 C99标准中有_BOOL  你可以 #define bool int #define true 1 #define false 0

奥， 了解了， 可能是我用的编译器版本比较早 网上说C89标准时没有定义布尔类型的

C语言标准里是没有 bool 这个东西的, 没有很正常.


Question: 这段代码啥意思啊？大神们救救俺吧！！！

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

你不知道这代码要干啥，那你复制这段代码干啥，或者。。。这是书上的题目？要求写出此代码的功能

同3L。。。

那你就先分段讲讲都是什么意思

把你main里面的代码都搬到不同的函数里面，每个函数什么功能，再看看主函数调用函数的逻辑，不就明白了。

引用这代码分段都能看懂，但是连起来看就啥也不知道意思了！！！该怎样克服这种困境??? 单步调试。


Question: GNU GetText切换显示界面语言的问题

自己顶一下。 难道都没有人遇到此问题吗？


Question: C语言读写文件的问题

引用 1 楼 truelance 的回复:if((out = fopen(name, "w")) == NULL);  这个条件后面多了一个分号嗯，刚刚发现了。 一个分号害人不浅啊，折腾了半天，以为哪里出问题了。


Question: 一个字符串逆转的程序，不知道错误出在哪里？？？

引用 2 楼 u011432602 的回复:Str指向常量……

引用 12 楼 FENGQIYUNRAN 的回复:下面是我的代码，请大神解释： #include "stdafx.h" #include <stdio.h> #include <string> #include <iostream> using namespace std;   char* ReverseString(char *str,char *str1,int n) { 	int j=0; 	for(int i=(n-1);i>=0;i--) 	{ 		str1[j]=str[i]; 		j++; 	} 	return str1; } int _tmain(int argc, _TCHAR* argv[]) { 	char* str="hello world!"; 	int n=strlen(str); 	char* str1=new char(n); 	ReverseString(str,str1,n); 	printf("%s\n",str1); 	return 0; }  输出： 这个是把常量内容复制到新开辟的堆区里

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

引用 2 楼 u011432602 的回复:Str指向常量……+1

的穷是常量

不要试图改变一个常量

Line 18: warning: deprecated conversion from string constant to 'char*''

*str2是常量，不能被修改的。

可以将字符串的头部和尾部都传递给函数，这样即直观又简洁 #include<stdio.h> #include<string.h> void ReverseOpr(char *str2, char *str3){     while(str2 <= str3)     {         putchar(*str3);         str3--;     } }  int main(){     char *str="nihao";     ReverseOpr(str, str+strlen(str)-1);     return 0; }

字符串字面值 存在 静态存储区(文字常量区) 中,不能被修改。。。

char *str="nihao";这是个字符串常量，是只读的

引用 2 楼 u011432602 的回复:Str指向常量……嗯 ，的确是这里的问题。

Str指向常量……

上二级指针或引用


Question: 定义一个二维数组a[][],关于a[0],a,*a与指针的问题

int *p; int a[3][4]; 这样一个二维数组定义后，相关于a的指针有三个： &a[0][0]-----这是int *类型的，即指向数组元素类型的（等效写法还有a[0]和*a） &a[0]----这是int(*)[4]类型的，即指向一维数组（4个int元素）类型的（等效写法还有a） &a----这是int(*)[3][4]类型的，即指向二维数组（三行四列个int元素）类型的 LZ遇到的问题是指针类型不一致： 指针变量是int *，所以它只能指向数组元素（int类型） p=&a[0][0]; p=a[0]; p=*a; 都是正确的。 教给LZ一个“指向数组、数组元素的指针”的推演方法： 1.数组名和&数组名[0]等效，如a, &a[0]等效；a[0].&a[0][0]等效－－－－－数组名前的&和最后的[0]可以同时消去 2.* 和&是互逆操作，可以同时加上或同时消去，如a[0],*&a[0]等——消去a前的&和a后的[0]得*a

p是指针，而a[][]是指针的指针，变量类型都不对。除非你定义int * p [4].

p 的類型是 int* ， a的類型是int** 所以不行

计算机组成原理→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",...);或者cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的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

两个变量的类型不同，C语言中对这个情况会报警，C++中会报错 如果确实需要，可以通过加强制类型转换来实现

引用 4 楼 sagittarius_520 的回复:因为p是一个一级指针，而你定义的是一个二维数组，所以想要用p指向二维数组a当然不可能。一维数组对应一级指针，二维数组对应二级指针，以此类推。 所以p = a 是不成立的。  p = *a中*a表示取a地址的内容，而a表示二维数组第一个元素，所以相当于p = a[0][0] p = a[0]中a[0]表示二维数组第一行的地址，所以这里是将p指向了二维数组的第一行  楼主这里可以打印一下这两个表达式p的值分别是什么，这样就能更直观一些。

引用 6 楼 lm_whales 的回复:int *p; int (*pa)[4] ; // 一维数组的指针和二维数组匹配，就是这样子 int a[3][4]; p = *a; p = a[0]; pa = a;         // 一维数组的指针和二维数组匹配，就是这样子  主要是数据类型无法匹配， 表达式中 ，a 可以看作&a[0] ,  &a[0] 和p这个一级指针类型无法匹配。 ++ 另外p只能表示二位数组的一行，所以，p = a[0]是可以的，如果要存储整个数组也是可以那就需要：p = &a[0][0];那么p要遍历整个数组需要偏移3*4个元素。 但是，pa是可以指向数组a的原因是pa是一个宽度为4个int类型的指针；所以，pa = a；

数组名作为左值时表示整个数组的存储空间，而作为右值时则转换成指向数组首元素的指针。  x86/debian gnu linux/gcc vi two_arrary.c  #include <stdio.h>  int main(void) {         int a[3][4] = {0};         int *p = NULL;          p       = *a;          p       = a[0];         p       = a; //      printf("%p\n", p);         return 0; }   1. gcc -g two_arrary.c two_array.c: In function 'main': two_array.c:10:4: warning: assignment from incompatible pointer type [enabled by default]  2. objdump -dS a.out > a_disasm.txt  in "*a" a as left value.

二维数组是“数组的数组”，你可以把 a 的类型看作 int** ，而 p的类型是 int* ，把a赋给p当然不行啦。


Question: K&R 的书中 通过编写 UNIX 程序 sort 的一个简化版本说明这一点。 该程序按字母顺序对由文本行组成的集合进行排 序。请问这个程序要如何结束输入？

引用 3 楼 zhao4zhong1 的回复:Linux：Ctrl+D Windows：Enter、Ctrl+Z、Enter  Ctrl+D 已经试过了。

Linux：Ctrl+D Windows：Enter、Ctrl+Z、Enter

引用 6 楼 zhao4zhong1 的回复:不要使用 while (条件) 更不要使用 while (组合条件) 要使用 while (1) {  if (条件1) break;  //...  if (条件2) continue;  //...  if (条件3) return;  //... } 因为前两种写法在语言表达意思的层面上有二义性，只有第三种才忠实反映了程序流的实际情况。 典型如： 下面两段的语义都是当文件未结束时读字符 while (!feof(f)) {  a=fgetc(f);  //...  b=fgetc(f);//可能此时已经feof了！  //... } 而这样写就没有问题： while (1) {  a=fgetc(f);  if (feof(f)) break;  //...  b=fgetc(f);  if (feof(f)) break;  //... } 类似的例子还可以举很多。  代码功能归根结底不是别人帮自己看或讲解或注释出来的；而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。 提醒：再牛×的老师也无法代替学生自己领悟和上厕所！ 单步调试和设断点调试（VS IDE中编译连接通过以后，按F10或F11键单步执行，按Shift+F11退出当前函数；在某行按F9设断点后按F5执行停在该断点处。）是程序员必须掌握的技能之一。   恩，感谢指点。

由于在调试的程序中又发现了一些问题，所以把最后的代码贴上来  /* 	date:9-2-2014 	author:doodlesomething 	version:1.0  	sort strings as linux tool  	how: 	1.read lines; 	2.sort lines; 	3.write lines; */  #include <stdio.h> #include <string.h>  #define MAXLINES 1000	//define the maxsize of input lines #define MAXBUFPSIZE 50000 //define the maxsize of bufp  #define MAXLEN 1000 //the maxsize of evey line  char *lineptr[MAXLINES];  //to store the pointers of lines  int readlines(char *lineptr[],int lim); void writelines(char *lineptr[],int nlines);  void qsort(char *lineptr[],int left,int right);   //main function  int main() { 	int nlines; 	//the number of all input lines 	//when the nlines bigger than 1 we sort the lines 	if( (nlines = readlines(lineptr,MAXLINES) ) >1) { 		qsort(lineptr,0,nlines-1); 		writelines(lineptr,nlines); 		return 0; 	} 	else { 		printf("the input line is too big!Sorry we can not handle it\n"); 		return 1; 	} 	return 0; }  	//read line string 	int readlines(char *lineptr[],int lim)	{ 		int len,inlines; 		char *p; 		char line[MAXLEN]; 		int getLine(char *line,int lim); 		char *alloc(int n); 	 		inlines = 0; 		 		while( (len = getLine(line,MAXLEN)) > 0 ) { 			if( inlines > lim ||  ( p = alloc(len) ) == NULL )  				return -1; 			else { 				/* 				the end of input line is '\n',and we should store it 				as a string so we can should add a flag '\0' end of a string array 				*/ 				line[len-1]='\0';   				strcpy(p,line); 				lineptr[inlines++]=p; 			} 		}  		return inlines; 	}   	//quick sort the lines -- key code 	void qsort(char *lineptr[],int left,int right) { 		int last,i; 		void swap(char *v[],int i,int j); 		//if the lines fewer than two 		if(left >= right) 			return; 		 		swap(lineptr,left,(left+right)/2);  		last = left;  		for(i=left+1;i <= right;i++) { 			if( strcmp(lineptr[i],lineptr[left]) <0 ) 				swap(lineptr,++last,i); 		} 		 		swap(lineptr,left,last); 		qsort(lineptr,left,last-1); 		qsort(lineptr,last+1,right); 	}  	//swap pointer 	void swap(char *v[],int i,int j) { 		char *tmp; 		tmp=v[i]; 		v[i]=v[j]; 		v[j]=tmp; 	}  	//write line string 	void writelines(char *lineptr[],int nlines) { 		printf("\nThe result is :\n\n"); 		while(--nlines>0) { 			printf("%s\n",*lineptr++); 		} 	}  	//get the single line 	int getLine(char *line,int lim) { 		int c; 		char *tmp;  		tmp = line; 		 		while(--lim > 0 && (c = getchar()) != EOF && c != '\n') 			*tmp++=c;  		if(c == '\n') 			*tmp++= c;  		*tmp= '\0';  		//return the length of line 		return (int) (tmp-line); 	} 	 	//buf 	static char buf[MAXBUFPSIZE]; 	static char *bufp = buf;  	//ask for buf 	char *alloc(int n) { 		if(n > 0 && (buf + MAXBUFPSIZE - bufp) >= n) { 			bufp = bufp + n; 			return (bufp - n); 		} 		else  			return 0; 	}  	//free buf 	void afree(char *p) { 		if( p >= buf && p < (buf + MAXBUFPSIZE) ) 			bufp = p; 	}

引用 5 楼 cyd54454 的回复:*++tmp= '\0';原因我想是在这，你就算按了ctrl+d，结果你还是把tmp++了，那么你返回的长度是tmp - line = 1，函数返回之后的while循环中len = 1 > 0.当然不会结束了  一语惊醒啊，程序应该改为：               if(c == '\n')                        *tmp++= c;                   *tmp= '\0';  这样当另起一行时马上输入Ctrl+D时，tmp并没有自加，返回值就为0了。 感谢！！！（自己没有认真想问题可能会出现在哪就伸手党了）

引用 1 楼 zmlovelx 的回复:可以试试回车之后加ctrl+D  我之前就测试过回车ctrl+d，不管用。

可以试试回车之后加ctrl+D


Question: 按键消息中a为何收不到SUM的值呢？

a 的值输出为0， 我是想在另一个自定义事件中计算所传数组的元素之和，然后再获得这个值，可是，居然是没有作用。

int buffer[]={100,200,300,400,500};  int a=SendMessage(hwndDlg,WM_SEND,0,(LONG)buffer);  char sz[10];  sprintf(sz,"所有数据之和为：%d",a);  MessageBox(NULL,sz,NULL,MB_OK);  第一不要强制转换， 第二，buffer WM_SEND得到处理前已经game over了

简单的方法就是下断点单步。

sprintf(sz,"数组：%d\n%d\n%d\n%d\n%d",a[0],a[1],a[2],a[3],a[4]); MessageBox(NULL,sz,"",MB_OK|MB_ICONEXCLAMATION); 能运行不？ 能的话在这里把sum的值也打印出来。

收不到sum的值 是什么意思？ 是说等于0啊  是不是因为 buffer  是局部变量啊， 除了花括号，就不存在了


Question: 带省略号的函数

va_arg, va_end, va_start Access variable-argument lists.  type va_arg( va_list arg_ptr, type );  void va_end( va_list arg_ptr );  void va_start( va_list arg_ptr );   (UNIX version)  void va_start( va_list arg_ptr, prev_param );   (ANSI version)  Routine Required Header Optional Headers Compatibility  va_arg <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT  va_end <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT  va_start <stdio.h> and <stdarg.h> <varargs.h>1 ANSI, Win 95, Win NT    1 Required for UNIX V compatibility.  For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  va_arg returns the current argument; va_start and va_end do not return values.  Parameters  type  Type of argument to be retrieved  arg_ptr  Pointer to list of arguments  prev_param  Parameter preceding first optional argument (ANSI only)  Remarks  The va_arg, va_end, and va_start macros provide a portable way to access the arguments to a function when the function takes a variable number of arguments. Two versions of the macros are available: The macros defined in STDARG.H conform to the ANSI C standard, and the macros defined in VARARGS.H are compatible with the UNIX System V definition. The macros are:  va_alist  Name of parameter to called function (UNIX version only)  va_arg  Macro to retrieve current argument  va_dcl  Declaration of va_alist (UNIX version only)  va_end  Macro to reset arg_ptr  va_list  typedef for pointer to list of arguments defined in STDIO.H  va_start  Macro to set arg_ptr to beginning of list of optional arguments (UNIX version only)  Both versions of the macros assume that the function takes a fixed number of required arguments, followed by a variable number of optional arguments. The required arguments are declared as ordinary parameters to the function and can be accessed through the parameter names. The optional arguments are accessed through the macros in STDARG.H or VARARGS.H, which set a pointer to the first optional argument in the argument list, retrieve arguments from the list, and reset the pointer when argument processing is completed.  The ANSI C standard macros, defined in STDARG.H, are used as follows:   All required arguments to the function are declared as parameters in the usual way. va_dcl is not used with the STDARG.H macros.   va_start sets arg_ptr to the first optional argument in the list of arguments passed to the function. The argument arg_ptr must have va_list type. The argument prev_param is the name of the required parameter immediately preceding the first optional argument in the argument list. If prev_param is declared with the register storage class, the macro’s behavior is undefined. va_start must be used before va_arg is used for the first time.   va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve arguments from the list.   After all arguments have been retrieved, va_end resets the pointer to NULL.  The UNIX System V macros, defined in VARARGS.H, operate somewhat differently:   Any required arguments to the function can be declared as parameters in the usual way.   The last (or only) parameter to the function represents the list of optional arguments. This parameter must be named va_alist (not to be confused with va_list, which is defined as the type of va_alist).   va_dcl appears after the function definition and before the opening left brace of the function. This macro is defined as a complete declaration of the va_alist parameter, including the terminating semicolon; therefore, no semicolon should follow va_dcl.   Within the function, va_start sets arg_ptr to the beginning of the list of optional arguments passed to the function. va_start must be used before va_arg is used for the first time. The argument arg_ptr must have va_list type.   va_arg retrieves a value of type from the location given by arg_ptr and increments arg_ptr to point to the next argument in the list, using the size of type to determine where the next argument starts. va_arg can be used any number of times within the function to retrieve the arguments from the list.   After all arguments have been retrieved, va_end resets the pointer to NULL.  Example  /* VA.C: The program below illustrates passing a variable  * number of arguments using the following macros:  *      va_start            va_arg              va_end  *      va_list             va_dcl (UNIX only)  */  #include <stdio.h> #define ANSI            /* Comment out for UNIX version     */ #ifdef ANSI             /* ANSI compatible version          */ #include <stdarg.h> int average( int first, ... ); #else                   /* UNIX compatible version          */ #include <varargs.h> int average( va_list ); #endif  void main( void ) {    /* Call with 3 integers (-1 is used as terminator). */    printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );     /* Call with 4 integers. */    printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );     /* Call with just -1 terminator. */    printf( "Average is: %d\n", average( -1 ) ); }  /* Returns the average of a variable list of integers. */ #ifdef ANSI             /* ANSI compatible version    */ int average( int first, ... ) {    int count = 0, sum = 0, i = first;    va_list marker;     va_start( marker, first );     /* Initialize variable arguments. */    while( i != -1 )    {       sum += i;       count++;       i = va_arg( marker, int);    }    va_end( marker );              /* Reset variable arguments.      */    return( sum ? (sum / count) : 0 ); } #else       /* UNIX compatible version must use old-style definition.  */ int average( va_alist ) va_dcl {    int i, count, sum;    va_list marker;     va_start( marker );            /* Initialize variable arguments. */    for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )       sum += i;    va_end( marker );              /* Reset variable arguments.      */    return( sum ? (sum / count) : 0 ); } #endif   Output  Average is: 3 Average is: 8 Average is: 0   Argument Access Routines  See Also   vfprintf

不定参数。就是参数个数和类型都是不确定的。

引用 6 楼 user-8 的回复:[quote=引用 3 楼 zxh707wk 的回复:] [quote=引用 1 楼 zilaishuichina 的回复:] 这叫不定参数  比如 printf("%d", a1); printf("%d,%d", a1, a2); printf("%d,%d,%d", a1, a2, a3);  像这种 函数的参数是不固定的， lz可以百度一下 "不定参数"+1,比如main函数[/quote]main是另一回事  [/quote]

引用 4 楼 qianqiubiluo 的回复:[quote=引用 1 楼 zilaishuichina 的回复:] 这叫不定参数  比如 printf("%d", a1); printf("%d,%d", a1, a2); printf("%d,%d,%d", a1, a2, a3);  像这种 函数的参数是不固定的， lz可以百度一下 "不定参数"[/ 那后面参数的类型就是不确定的？  类型就也是不确定的啊， 就像printf里面， 你传int， float，char，都是可以的啊

引用 5 楼 qianqiubiluo 的回复:[quote=引用 2 楼 truelance 的回复:] 省略号表示可变参数，比如printf(char *format, ...) 你可以搜索va_arg, va_list进行参考 省略号代表的参数的类型是什么样的[/quote]  不确定。例如printf(char *format, ...)就是根据format中的%确定后面参数的个数和类型。

可变参数函数

引用 3 楼 zxh707wk 的回复:[quote=引用 1 楼 zilaishuichina 的回复:] 这叫不定参数  比如 printf("%d", a1); printf("%d,%d", a1, a2); printf("%d,%d,%d", a1, a2, a3);  像这种 函数的参数是不固定的， lz可以百度一下 "不定参数"+1,比如main函数[/quote]main是另一回事

引用 2 楼 truelance 的回复:省略号表示可变参数，比如printf(char *format, ...) 你可以搜索va_arg, va_list进行参考 省略号代表的参数的类型是什么样的

引用 1 楼 zilaishuichina 的回复:这叫不定参数  比如 printf("%d", a1); printf("%d,%d", a1, a2); printf("%d,%d,%d", a1, a2, a3);  像这种 函数的参数是不固定的， lz可以百度一下 "不定参数"+1,比如main函数


Question: 双挂起进程状态模型就是七状态进程模型吗？

任务：指的可能是一个进程，也可能是一个线程 Linux 实现的是内核线程。

引用 4 楼 user-1 的回复:作业是一个或多个程序的运行 find /usr/src -type f -name "*.c" | xargs grep int16_t > $HOME/tmp/find.log  大牛，最后一个额问题：  任务是什么?  linux的线程实现方式是什么？  内核线程， 用户线程，混合方式。 linux是哪一种？

引用 2 楼 user-1 的回复:双挂起进程模型就是7状态进程模型吧。 这里讲的挺清楚的啊 http://www.docin.com/p-591480686.html 看第七页和第八页  操作系统中的“作业”到底是什么意思？   有时候，它是进程  有时候又不是进程，  理解起来很吃力。

引用 4 楼 user-1 的回复:作业是一个或多个程序的运行 find /usr/src -type f -name "*.c" | xargs grep int16_t > $HOME/tmp/find.log  作业就是一个多个程序啊？  好吧


Question: 关于ReadFile读数据读不完整的问题

推荐使用PortMon软件辅助调试串口通讯相关程序。

推荐使用FileMon软件辅助调试文件读写相关功能。

引用 9 楼 u010848119 的回复:引用 8 楼 zhao4zhong1 的回复:任何通讯机制，收方收得太慢都会导致发方发的速度受阻或发的数据丢失。我是循环接收的，有数据应该是立刻接收，希望赵老师能深入指点。  再怎么循环，Read之后的操作总是要花时间的，你不可能保证Write和Read一定能保持同样的速率，

引用 7 楼 zxh707wk 的回复:一次不能发多点吗20个字节是为了测试基本功能用，发的越多，数据收不全的问题出现几率越大。

如果你学习过通信中的OSI 7层协议模型，就很容易理解了。 底层的串口通信就相当于物理层，每帧20字节或者更多字节，是数据链路层的事，这是你的程序自己要处理的。你自己的程序要不断读，然后按照每20字节（或者其他定帧方法）进行重组，底层是不可能保证发送的20字节一定一次性收到的。

希望有人能够指点迷津

希望有人能够指点迷津

希望有人能够指点迷津

任何通讯机制，收方收得太慢都会导致发方发的速度受阻或发的数据丢失。

一次不能发多点吗

关注此问题！

关注此问题！

关注此问题！


Question: .exe停止工作

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

printf("%s+%s=%d\n",x+y); 对吗？

printf("%s+%s=%d\n",x+y);  少参数  改为 printf("%s+%s=%d\n",s1,s2,x+y);

debug


Question: 如何实现打开某个磁盘时运行指定的软件？

我想利用系统右键菜单，即当用户在磁盘的空地点击右键时执行我指定的软件，此时要用到shell扩展编程， 好像也不简单。

典型病毒性行为，如果使用autorun.inf会被杀软干掉的

挂上文件系统挂钩， 也可以开发文件系统驱动， 这是比较专业一点的，不过要费老鼻子劲，才能做好 否则 autorun.inf 之类的，比较简单

百度一下autorun.inf 双击磁盘就可以运行某个程序，这个文件是病毒专用的技巧。

要耍流氓吗？

这个 autorun.inf 好像不好用

我知道的就只有脚本


Question: c语言 字符串截取

引用 3 楼 qq_15796845 的回复:鄙人之见：  # include <stdio.h>  int main() { 	char p[256] = "GF9600||windows7||4G"; 	char a[10], b[10], c[10]; 	int i; 	for (i = 0; i < 6; i++) 	{ 		a[i] = p[i]; 		printf("%c", a[i]); 		 	} 	printf("\n"); 	for (i = 8; i < 16; i++) 	{ 		b[i] = p[i]; 		printf("%c", b[i]); 	} 	printf("\n"); 	for (i = 18; i < 20; i++) 	{ 		c[i] = p[i]; 	    printf("%c", c[i]);	 		 	} 	printf("\n"); 	getchar(); 	return 0; } 引用 3 楼 qq_15796845 的回复:鄙人之见：  # include <stdio.h>  int main() { 	char p[256] = "GF9600||windows7||4G"; 	char a[10], b[10], c[10]; 	int i; 	for (i = 0; i < 6; i++) 	{ 		a[i] = p[i]; 		printf("%c", a[i]); 		 	} 	printf("\n"); 	for (i = 8; i < 16; i++) 	{ 		b[i] = p[i]; 		printf("%c", b[i]); 	} 	printf("\n"); 	for (i = 18; i < 20; i++) 	{ 		c[i] = p[i]; 	    printf("%c", c[i]);	 		 	} 	printf("\n"); 	getchar(); 	return 0; }  这个还用你说   谁不会啊 ！！！！

strtok, wcstok, _mbstok Find the next token in a string.  char *strtok( char *strToken, const char *strDelimit );  wchar_t *wcstok( wchar_t *strToken, const wchar_t *strDelimit );  unsigned char *_mbstok( unsigned char*strToken, const unsigned char *strDelimit );  Routine Required Header Compatibility  strtok <string.h> ANSI, Win 95, Win NT  wcstok <string.h> or <wchar.h> ANSI, Win 95, Win NT  _mbstok <mbstring.h> Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  All of these functions return a pointer to the next token found in strToken. They return NULL when no more tokens are found. Each call modifies strToken by substituting a NULL character for each delimiter that is encountered.  Parameters  strToken  String containing token(s)  strDelimit  Set of delimiter characters  Remarks  The strtok function finds the next token in strToken. The set of characters in strDelimit specifies possible delimiters of the token to be found in strToken on the current call. wcstok and _mbstok are wide-character and multibyte-character versions of strtok. The arguments and return value of wcstok are wide-character strings; those of _mbstok are multibyte-character strings. These three functions behave identically otherwise.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tcstok strtok  _mbstok  wcstok     On the first call to strtok, the function skips leading delimiters and returns a pointer to the first token in strToken, terminating the token with a null character. More tokens can be broken out of the remainder of strToken by a series of calls to strtok. Each call to strtok modifies strToken by inserting a null character after the token returned by that call. To read the next token from strToken, call strtok with a NULL value for the strToken argument. The NULL strToken argument causes strtok to search for the next token in the modified strToken. The strDelimit argument can take any value from one call to the next so that the set of delimiters may vary.  Warning   Each of these functions uses a static variable for parsing the string into tokens. If multiple or simultaneous calls are made to the same function, a high potential for data corruption and inaccurate results exists. Therefore, do not attempt to call the same function simultaneously for different strings and be aware of calling one of these function from within a loop where another routine may be called that uses the same function.  However, calling this function simultaneously from multiple threads does not have undesirable effects.  Example  /* STRTOK.C: In this program, a loop uses strtok  * to print all the tokens (separated by commas  * or blanks) in the string named "string".  */  #include <string.h> #include <stdio.h>  char string[] = "A string\tof ,,tokens\nand some  more tokens"; char seps[]   = " ,\t\n"; char *token;  void main( void ) {    printf( "%s\n\nTokens:\n", string );    /* Establish string and get the first token: */    token = strtok( string, seps );    while( token != NULL )    {       /* While there are tokens in "string" */       printf( " %s\n", token );       /* Get next token: */       token = strtok( NULL, seps );    } }   Output  A string   of ,,tokens and some  more tokens  Tokens:  A  string  of  tokens  and  some  more  tokens   String Manipulation Routines  See Also   strcspn, strspn, setlocale

#include <stdio.h>  int main() { 	char p[256] = "GF9600||windows7||4G"; 	char str[3][100]; 	int i; 	int j=0; 	int k=0; 	for (i = 0; p[i]; i++) 	{ 		if (p[i] == '|'&&p[i + 1] == '|') 		{ 			str[j][k] = '\0'; 			j++; 			i++; 			k = 0; 		} 		else str[j][k++] = p[i]; 	} 	str[j][k] = '\0'; 	for (i = 0; i < 3; i++)puts(str[i]); 	getchar(); 	return 0; }


Question: 有关结构体大小的疑问

引用 3 楼 truelance 的回复:一种改法是你把unsigned short unused; 移到结构的最后，这样所有的字段都是对齐的，不用加padding 另一种就是在结构定义前后用 #pragma pack(1) ... #pragma pack() 强制用1字节对齐，不加padding  提出的方法很有用，谢谢！

引用 1 楼 truelance 的回复:struct mbr_partition 是4字节对齐的，所以在unused之后会有2个字节padding. 整个mbr 结构也是4字节对齐的，因此mbr_signature后面也会有2个字节padding.  所以总计有4个字节padding, 整个结构的sizeof会比每个字段之后多4.  谢谢回复！ 请问如何改写该结构体，使其大小为512？


Question: opencv两个不相连通的轮廓怎么让他们连通到一起呢?

要是轮廓离得不是很远的话，可以尝试形态学处理里面的腐蚀或者膨胀。

自己顶一下~


Question: 请教数据结构链表参数问题

链表的典型结构无非就是在某个元素结构中定义了一个（单链表，多个就可以是双向的或其他）该元素的指针而，然后通过一个接一个的建立起联系来，好像是一个链子一样，只需捏住链头就可以一个接一个的访问下去

可以是类，也可以是typedef出来的类型  btw: 求求你们别用vc6了，那是史前的不符合标准的编译器。如果哪本书上是用vc6的，就把那本书烧了；如果是哪个老师让你们用vc6的，就上去扇他两个耳光。


Question: 这题的结果是多少呢？

难道就没人发现楼主的代码已经是   2^0+2^1……+2^32  了么？

sum 定义成 unsigned  long 类型。

cout << "4294967295" << endl;

溢出了，用无符号数就行了。

对的，楼主正解,有很多方法可以解囧

sum初始化应给是0

2^0 = 1 2^1=10 2^2=100 ... 2^31=1000 0000 0000 0000 他们的和，就是1111 1111 1111 1111 = FFFF=-1 就是这个味

正好溢出

x86/debian gnu linux/gcc  # include <stdio.h>   int main(void) {     char i;     long int sum = 1;       for (i=0;i<32;++i)         sum += 2<<i;     printf("%ld",sum);       return 0; }   lly@debian:~/mydir/csdn/practice$ gcc shift.c  lly@debian:~/mydir/csdn/practice$ ./a.out  4294967295

用 __int64时，由于是64位，打印要指明64位 printf("%I64d\n", sum);

用 unsigned int 或者，__int64  __int64 v = 1; __int64 sum = 0; for (int i = 0; i < 32; i++) {     sum += v;     v <<= 1; }

引用 6 楼 lin5161678 的回复:2的32次方 -1+1,按照补码的规则，输出-1，建议用无符号数

2的32次方 -1

char i; 	long int sum = 1;  	for (i=0;i<32;++i) 		sum += 2<<i; 	printf("%lu\r\n",sum);//为%lu已验证 为4294967295

int main () {   unsigned int sum = 0, v = 1, i;    for (i = 0; i < 32; ++i) {     if (0 == i)       /*sum += 1;*/ sum |= 1;     else       /*sum += (v <<= 1);*/ sum |= (v <<= 1);   }    printf("%u == %u\n", sum, (unsigned int)(-1)); // 2^32-1 }

应该加上unsigned. 结果是2的32次方减1，必须要用unsighed

因为结果就是-1啊   你要用printf("%lu",sum);

建议你把 2定义为unsigned  long类型吧， 安全起见。右移的话，int 只有31位，32位为符号位。 另外sum初始化应给是0


Question: 如何创建一个链表并显示出来

“多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，搬手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

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

引用 6 楼 Adol1111 的回复:[quote=引用 5 楼 hujiyanchina 的回复:] [quote=引用 2 楼 u010030181 的回复:] 把creatlist函数中的for(i=0;i<=n;++i)改成 i < n;  好了，大神啊~~~可是为什么呢？[/quote] 因为当i=n时就超过你传入的数组范围了啊！[/quote] 所以对于这样的循环，一般都是用<号，很少用<=的……除非特别的需要！因为一不留神，你就认为第四个数是a[4]，其实是a[3]……

引用 5 楼 hujiyanchina 的回复:[quote=引用 2 楼 u010030181 的回复:] 把creatlist函数中的for(i=0;i<=n;++i)改成 i < n;  好了，大神啊~~~可是为什么呢？[/quote] 因为当i=n时就超过你传入的数组范围了啊！

引用 2 楼 u010030181 的回复:把creatlist函数中的for(i=0;i<=n;++i)改成 i < n;  好了，大神啊~~~可是为什么呢？

C++以前自学guo ,但是输出代码有乱码肯定是因为内存分配的问题，或者指针未初始化等，我记得c++没有指针的吧

仅供参考 http://pan.baidu.com/s/17yIcQ 突然发现我这代码好万能。。。

好久没用c语言了，


Question: 怎么实现向文件中指定位置添加字符串

所谓修改删除文件a某位置的内容，其实是读打开文件a，再将‘a中修改删除位置之前的内容＋修改删除的内容＋a中修改删除位置之后的内容’保存到文件b，关闭文件a，删除文件a，将文件b改名为与之前文件a相同的名字，仅此而已。

引用 1 楼 user-3 的回复:没办法，只能重建文件，然后删掉原来的，把新文件改名。+1

那像word等办公软件是怎么实现替换的呢，也是用这种方法？遇到很大的文件怎么办？比如说2G多的文件，是分段处理吗？那岂不是很慢？

没办法，只能重建文件，然后删掉原来的，把新文件改名。


Question: 求解，不太明白

换行是要以 \ 结尾吧。。。

啥叫“自由风格”？

引用 5 楼 Adol1111 的回复:听说这个和C语言的黑历史有关系，当年屏幕太小，一行的内容太长了会被截断，所以需要手动插入换行符 \，现在的技术应该无所谓了，不过可能是为了兼容吧，还是保留了这个特点。+1

可以看一下这里的介绍https://gcc.gnu.org/onlinedocs/gcc-3.2/cpp/Initial-processing.html

C语言中一行只可以输入80个字符，如果代码需要换行，则在每行后面加上行结束符“\”  char *p = "test\n\                    ----\n";     就可以。2楼链接给出答案  C语言中一行只可以输入80个字符，如果代码需要换行，则在每行后面加上行结束符“\”

我自己瞎猜的：引号内容里面的东西，编译器是要照原样保存到字符串的，包括空格、换行、TAB都要保持原样，所以必须明确。 其他的“自由风格”，空格什么的多了少了都无所谓，反正唯一的作用就是当作分隔符

引号还是要求在同一行吧 或者这样写也行   6         char *p = "test\n"   7                 "----\n";


Question: 关于Visual Studio 2013单步调试出错的问题！

算了，还没学汇编，已经找出问题，

点“查看反汇编”


Question: 为什么有这么多的编程风格，语言格式为什么不统一？

引用 12 楼 zhao4zhong1 的回复:比用什么风格更重要的是在任何地方，任何时候都坚持用一种风格。 比爱哪种美眉更重要的是在任何地方，任何时候都坚持爱一个美眉。好比喻！！

啥都一样了，这世界还有什么魅力可言吗

就像这个世界上有无数的方言一样，照理说有了汉语和英语就足够了。  引用 楼主 Esaak 的回复:有些疑惑，各个编程语言对语法块的区分方法、注释的表示、语句结尾的表示都不尽相同。有些语言本身就是用C实现的，比如Python等，但对格式要求迥异。想知道各语言为什么不把风格统一，是为了强调个性才高出这么多代码的格式要求吗？ 真心求教。

就像寫一道程式題目，結果都一樣，但是方法可能不完全相同而已

有了选择， 真好

世界上有这么多国家，为什么不统一？

因为它们不是从一个大师手中出来的。这样才丰富多彩啊

因为没有一个强制的标准组织去规定这些； 因为不同种类的语言在一开始出现时是基于创始人想用在某个特定领域或解决某些问题才发明的，所以必然就会出现不同； 最先出现的，最受用户的往往成为事实上但不是书面上的标准。

编程是种艺术，艺术的美在多样，而不在单一。

这就跟有人是长脸  有人是方脸   有人胖  有人瘦  大家都是细胞组成的， 难道所有人都得长成一个模子刻出来的么

每种语言都有它各自的特色  不一样就不一样咯

因为对美的认识和理解，各语言大师并不能统一。 代沟，你听说过么？你能和你父母在音乐、艺术等方面都达成共识么？

因为各种语言的语法不一样啊。。。比如C用大括号区分代码块，Python用缩进区分代码块。。。  难道你要各种语言的语法都一样吗。。。

代码怎么写并没有明确的规定，自己喜欢就行


Question: 求将BMP彩色图像转化为黑白图像的程序，或者显示4色BMP图像的程序，求大神帮忙，有的发我邮箱626022479@qq.com，谢谢！！

http://download.csdn.net/detail/ko1_1ok/4734848 参考

Image Magick

已发送。结贴给分吧


Question: C语言宏定义的问题

原来如此，谢谢各位了

lz的代码相当于   #include <stdio.h>   void bbb() {    printf("aaa()\n"); }   int main() {    bbb();  }

引用 2 楼 dbzhang800 的回复:因为代码没有问题，无论是用 aaa替换bbb，还是bbb替换aaa，都没有问题+1

x86/Debian GNU/Linux/gcc vi macro.c  lly@debian:~/mydir/csdn/marco$ gcc  -E  macro.c ........ void bbb() {       printf("aaa()\n"); }   int main() {  bbb(); } lly@debian:~/mydir/csdn/marco$

把aaa换成了bbb  #include <stdio.h>  void bbb() { 	printf("aaa()\n"); }  int main() { 	bbb(); }

因为代码没有问题，无论是用 aaa替换bbb，还是bbb替换aaa，都没有问题

楼主，看教材，别扯百度百科，浪费生命不是怎么浪费的。


Question: 结构体含有指针和指针指向的数据长度，怎么初始化

引用 2 楼 truelance 的回复:变长的字段只能有一个，而且必须放在最后 typedef struct HEAD { unsigned int regf; unsigned char head; unsigned int namelength; unsigned char name[1]; }HEAD,*PHEAD;我也一直这么觉得，只是不太相信自己，可以结贴了，谢谢

能不能得到namelength的数据。能得到的话用下面的结构体 typedef struct HEAD { unsigned int regf; unsigned int namelength; unsigned char name[0]; }HEAD,*PHEAD;  给这个结构体分配地址空间的时候， PHEAD *p = (PHEAD)calloc(sizeof(struct HEAD) + namelength, 1); 你就可以通过name这个指针去访问后面分配的数据，name将指向name后面数组的首地址。这样就实现了可变长的访问。

中间有变长数据的话，只有一个数据一个数据的解析了，不要期望用结构体直接映射。  引用 楼主 braveheart2010 的回复: 如图，这是一段内存的数据，现在我要用定义一个结构体来解析这段数据。但是问题是，里面有name长度是可变的，长度存储在namelength里面。我定义了下面的结构体，但是有问题，应该如何定义来解析这段数据呢？谢谢各位  typedef struct HEAD { 	unsigned int regf; 	unsigned int namelength; 	unsigned char* name; 	unsigned char head; }HEAD,*PHEAD;  [/size]

#include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h>  typedef struct HEAD { unsigned int regf; unsigned int namelength; unsigned char* name; unsigned char head; }HEAD,*PHEAD;  int main(int argc, _TCHAR* argv[]) { 	HEAD h; 	char tmp[1024] = {0}; 	const char* p = tmp; 	printf("input name:\n"); 	scanf("%s", tmp);  	h.namelength = strlen(p); 	h.name = (unsigned char*)p;   	printf("name is : %s , name lenth is : %d \n", h.name, h.namelength);  	system("pause"); 	return 0; }

结构体里不是存储额长度了吗，没听懂你意思


Question: 关于GCC编译过程中头文件问题

当然除了手写makefile，有时候还会用CMake等自动化工具来自动生成makefile，比你自己手写要容易多了

1、这根gcc的工作方式有关系，gcc是顺着指定目录去查找相应的头文件，而不是你指定头文件，我就引入该头文件，如果是这样的话，那么对于复杂的工程来说，这个工作量是非常大，而且容易出错。 2、这个还跟C的预编译指令，C在使用#include的时候已经指定了目录，比如<>是环境变量中的C头文件目录（如果查不到才是当前目录），而""只从当前目录查起。 有了这两点，编译时就不需要写头文件了。当然作为代替，有可能需要链接放置于其他位置的第三方库，所以就需要用-I参数指定相应的目录就可以了。当然你要指定.h头文件我也没意见，但项目大了，管理就很麻烦了。  不过真的到了大型项目，一般也不会直接在后面写-I啥的，而是专门定义变量CFLAGS之类的来代替吧。具体我就不说了，你可以看看这里：http://www.chinaunix.net/old_jh/23/408225.html

引用 3 楼 lkt2005 的回复:那我makefile该怎么写呢？   objs = main.o sum.o  main : $(objs)         gcc -o main $(objs)  main.o : main.c //此处是否需要添加sum.h？？？ sum.o : sum.c  .PHONY : clean clean:         -rm main $(objs)   gcc中头文件依赖关系什么时候用写，什么时候不用写？  1. 头文件名称不用写在makefile,  只需要把头文件所在的目录用-i加载编译选项里 2. 依赖关系都可以不写，带来的问题是如果你修改了.h，没有修改.c时，没法使用增量编译。依赖关系主要用于增量编译，检查哪些文件需要重新编译。

是这样的，你是把 gcc main.o sum.o -o main 一起编译的所以不会出问题，  因为在生成.o文件的时候，也就是编译过程中，只是对语法进行了检测，sum这个函数是没有地址的，你可以在编译好了main.o后，使用 nm main.o ，就会发现sum 那个符号的类型是U ，U就是表示没有地址，等连接的时候再去查看，不信的话，你可以直接gcc main.c -o main 就会出错，告诉你sum这个地址没找到（没有定义）。之所以gcc main.o sum.o -o main 会正确，是因为main函数能找到sum的地址。   好吧，回头来说头文件，头文件其实在编译的时候，会将头文件里面的内容给替换到.c文件#include 处 ，因此他也不神秘，在每个头文件开头都有一个   #ifndef _XX_H_ #define _XX_H_  /*内容 */  #endif  这就是为了防止重复包含头文件，对于头文件我没其他好说的了。

引用 2 楼 truelance 的回复:c里在函数没有声明的情况下调用，认为返回值是int类型，形参类型和实参类型相同。你的例子就满足这个假设，所以没有头文件也可以。 你换个例子，比如 double sum(double a, double b) {     return a + b; } 就不行了  确实是这样，不过main.c改为：  #include <stdio.h> #include <sum.h>   int main() {     int a = sum(3);     printf("%d\n", a);     return 0; }   那我makefile该怎么写呢？   objs = main.o sum.o  main : $(objs)         gcc -o main $(objs)  main.o : main.c //此处是否需要添加sum.h？？？ sum.o : sum.c  .PHONY : clean clean:         -rm main $(objs)   gcc中头文件依赖关系什么时候用写，什么时候不用写？

谢谢各位的回答，明白了很多。

x86/debian gnu/linux/gcc  main.c  #include <stdio.h>   int main() {     int a = sum(3);     printf("%d\n", a);     return 0; }  gcc -c main.c [compile c code to asm code to main.o] nm main.o       00000000 T main          U printf          U sum    [sum will be used, but not defined in this file]  sum.c  #include <stdio.h>   int sum(int a) {     if (a <= 1)         return a;     else         return a + sum(a-1); }  gcc  -c sum.c nm sum.o 00000000 T sum  ]in obj file(*.o), there is only smybol(sum) but not address.[/b   gcc sum.o main.o -o main nm main ...... 08048444 T main          U printf@@GLIBC_2.0 08048390 t register_tm_clones [b]0804841c T sum ...... linker modify sum's address to main  first define second use in c language, function will be as return integer type if not declare it. my computer can't support chinese now

问题就是，你用的是C，而且你的sum的返回值什么的都是整数，你应该弄个稍微复杂一个函数。


Question: c写屏问题

这也太古老了吧！现在编译器都是32位保护模式的啦，这个得用Turbo C编译运行

在纯DOS下或DosBox环境下运行。

也不一定，还有可能是通信协议错了，I/O口配置问题，还有你的地址都没有置0初始化等，都可能不能读写


Question: 这个printf的写法有点奇怪啊，看不懂啊。

再啰嗦两句，如果楼主知道那就当我没说 "abc" "def" "gh" 就等于 "abcdefgh" 比如 printf("abc" "def" "gh\n" ); 还有这个 printf("the source file is: " __FILE__ " abcd\n");

https://github.com/OculusVR/RakNet/blob/master/Source/RakNetTypes.h #if defined(_MSC_VER) && _MSC_VER > 0 #define PRINTF_64_BIT_MODIFIER "I64" #else #define PRINTF_64_BIT_MODIFIER "ll" #endif

这里的关键显然是PRINTF_64_BIT_MODIFIER，可能在不同的系统或编译器有不同的定义。 比如，如果 #define PRINTF_64_BIT_MODIFIER "ll" 那么这一行就变成了 printf("ID_ALREADY_CONNECTED with guid %llu\n", p->guid); p->guid应该是个64位整数，这个printf就是要把它按照64位的格式打出来


Question: 为什么我写出来的控制台程序不支持用鼠标滚轮来上下滑动翻页

好吧，我已经解决了，不是代码的问题。

试试这个代码#pragma comment(lib,"user32") #include <stdio.h> #include <time.h> #include <sys/timeb.h> #include <windows.h> char datestr[16]; char timestr[16]; char mss[4]; void log(char *s) {     struct tm *now;     struct timeb tb;      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,s); } VOID CALLBACK myTimerProc1(   HWND hwnd, // handle of window for timer messages   UINT uMsg, // WM_TIMER message   UINT idEvent, // timer identifier   DWORD dwTime // current system time ) {  log("In myTimerProc1\n"); } VOID CALLBACK myTimerProc2(   HWND hwnd, // handle of window for timer messages   UINT uMsg, // WM_TIMER message   UINT idEvent, // timer identifier   DWORD dwTime // current system time ) {  log("In myTimerProc2\n"); } int main() {     int i;     MSG msg;      SetTimer(NULL,0,1000,myTimerProc1);     SetTimer(NULL,0,2000,myTimerProc2);     for (i=0;i<20;i++) {         Sleep(500);         log("In main\n");         if (GetMessage(&msg,NULL,0,0)) {             TranslateMessage(&msg);             DispatchMessage(&msg);         }      }     return 0; } //2012-07-26 17:29:06.375 In main //2012-07-26 17:29:06.875 In myTimerProc1 //2012-07-26 17:29:07.375 In main //2012-07-26 17:29:07.875 In myTimerProc2 //2012-07-26 17:29:08.375 In main //2012-07-26 17:29:08.375 In myTimerProc1 //2012-07-26 17:29:08.875 In main //2012-07-26 17:29:08.875 In myTimerProc1 //2012-07-26 17:29:09.375 In main //2012-07-26 17:29:09.890 In myTimerProc2 //2012-07-26 17:29:10.390 In main //2012-07-26 17:29:10.390 In myTimerProc1 //2012-07-26 17:29:10.890 In main //2012-07-26 17:29:10.890 In myTimerProc1 //2012-07-26 17:29:11.390 In main //2012-07-26 17:29:11.890 In myTimerProc2 //2012-07-26 17:29:12.390 In main //2012-07-26 17:29:12.390 In myTimerProc1 //2012-07-26 17:29:12.890 In main //2012-07-26 17:29:12.890 In myTimerProc1 //2012-07-26 17:29:13.390 In main //2012-07-26 17:29:13.890 In myTimerProc2 //2012-07-26 17:29:14.390 In main //2012-07-26 17:29:14.390 In myTimerProc1 //2012-07-26 17:29:14.890 In main //2012-07-26 17:29:14.890 In myTimerProc1 //2012-07-26 17:29:15.390 In main //2012-07-26 17:29:15.890 In myTimerProc2 //2012-07-26 17:29:16.390 In main //2012-07-26 17:29:16.390 In myTimerProc1 //2012-07-26 17:29:16.890 In main //2012-07-26 17:29:16.890 In myTimerProc1 //2012-07-26 17:29:17.390 In main //2012-07-26 17:29:17.890 In myTimerProc2 //2012-07-26 17:29:18.390 In main //2012-07-26 17:29:18.390 In myTimerProc1 //2012-07-26 17:29:18.890 In main //2012-07-26 17:29:18.890 In myTimerProc1 //2012-07-26 17:29:19.390 In main //2012-07-26 17:29:19.890 In myTimerProc2

引用 1 楼 user-3 的回复:你在cmd环境里运行就好，  我想直接运行编译生成的那个exe文件，请问有办法让他支持鼠标的滚轮吗？？

引用 1 楼 user-3 的回复:你在cmd环境里运行就好，+1

你在cmd环境里运行就好，


Question: float 型变量到底可以提供几位有效数字？

感謝各位高手了解了解

float：    1bit（符号位） 8bits（指数位） 23bits（尾数位） 精度是由尾数的位数来决定的 float：2^23 = 8388608，一共七位，这意味着最多能有7位有效数字， 但绝对能保证的为6位，也即float的精度为6~7位有效数字；

顶楼上的，是这样

include\float.h ... #define FLT_DIG         6                       /* # of decimal digits of precision */ #define FLT_EPSILON     1.192092896e-07F        /* smallest such that 1.0+FLT_EPSILON != 1.0 */ #define FLT_GUARD       0 #define FLT_MANT_DIG    24                      /* # of bits in mantissa */ #define FLT_MAX         3.402823466e+38F        /* max value */ #define FLT_MAX_10_EXP  38                      /* max decimal exponent */ #define FLT_MAX_EXP     128                     /* max binary exponent */ #define FLT_MIN         1.175494351e-38F        /* min positive value */ #define FLT_MIN_10_EXP  (-37)                   /* min decimal exponent */ #define FLT_MIN_EXP     (-125)                  /* min binary exponent */ #define FLT_NORMALIZE   0 #define FLT_RADIX       2                       /* exponent radix */ #define FLT_ROUNDS      1                       /* addition rounding: near */ ... http://bbs.csdn.net/topics/390676437

7~8个 vc那个不是按float输出的

你这个结论不严谨吧, float是23位底数位, 换算成10进制不是能以整数对上的, 不是说一个数能精确到8位就所有数都能精确到8位.


Question: 关于一个插入算法的问题

C语言的基本语法要先搞会。这个算法不算难，再好好调试一下，尽量先不看别人的代码。

顶楼上一个吧，，，，

“多一少一”问题占程序员常犯错误的10%以上！ 避免“多一少一”问题的方法之一是将比如<10甚至<5的数代入程序片断，搬手指头心算验证一下程序到底应该写为 x、x-1、x+1中的哪个？ <、<=、==、>、>=中的哪个？

1. k[j+1]=k[j--]; 的各步骤顺序和执行结果在c标准中是未定义的，各编译器实现可能不一样。你使用某个编译器结果可能正确，但换一个编译器可能就错了。换成后面的写法结果是确定的。  2. c的数组下标是从0开始的，你的写法都是从1开始的 for (i = 1; i < n; i++)     while ( j >= 0 ...  insertsort(test,7);

仅供参考里面貌似有插入排序 http://pan.baidu.com/s/17yIcQ 突然发现我这代码好万能。。。


Question: 再发一个多线程的面试题

信号量的信号数量有意义，读写锁的共享数目一般没有意义  指的是信号量可以允许某个数量的线程同时访问（读，写） 读写锁分读锁和写锁，读锁可以允许无数线程同时去读（如果没有其它线程锁住写锁的话），写锁只允许一个线程去写（如果没有其它线程锁住读锁或写锁的话），所以数量没有意义。

有人知道吗？

引用 3 楼 my3439955 的回复:个人看法：  你没有把握到面试官要考察的点，他考察的点就是说信号量可以多线程同时获取，读写锁也可以多线程同时获取，看起来很类似，有什么区别？  可以从两点作答 1、信号的获得者是彼此平等的，读写锁的获得者有两类，读者和写者，不是平等的  2、信号量的信号数量有意义，读写锁的共享数目一般没有意义 2、信号量的信号数量有意义，读写锁的共享数目一般没有意义   “什么意义？ 是指多个线程可以拥有资源的访问权？  而读写锁不具备访问权概念？  是这样理解吗？”

不懂


Question: C语言实现的二叉树并显示，出不来结果啊，求解

引用 9 楼 truelance 的回复:这是你自己定义的 lz这代码是你自己写的吗

引用 7 楼 shenlei190810 的回复:[quote=引用 4 楼 truelance 的回复:] createBitaryTree(BinaryTree *binaryTree) 等价于 createBitaryTree(BinaryTreeNode **binaryTree) 要传入的是一个二重指针这里为什么要用二重指针[/quote] 这是你自己定义的

引用 4 楼 truelance 的回复:createBitaryTree(BinaryTree *binaryTree) 等价于 createBitaryTree(BinaryTreeNode **binaryTree) 要传入的是一个二重指针这里为什么要用二重指针

引用 2 楼 truelance 的回复:在main()里调用 createBitaryTree(&bt);为什么要用指向指针的指针呢？

引用 3 楼 shenlei190810 的回复:[quote=引用 2 楼 truelance 的回复:] 在main()里调用 createBitaryTree(&bt);为什么啊BinaryTree 不就是一个指针嘛[/quote]类型和你定义的不一样，你函数的形参是BinaryTree*，你传的实参是BinaryTree

引用 2 楼 truelance 的回复:在main()里调用 createBitaryTree(&bt);为什么啊BinaryTree 不就是一个指针嘛

在main()里调用 createBitaryTree(&bt);

输入ABC##D##E##输入的是对的啊，就是不出结果啊


Question: const 参数 C++11类型转换,编译不过

C++四个特定显式强制转换， 是各有用途的 不用在对应的地方，对了是凑巧 不对是正常  子类（指针，引用）转换成基类（指针，引用）不需要任何显式强制转换 反之需要 实际上，这个强制转换本来就是错误用法， 因为可以使用虚函数的地方，不需要强制转换  只有为了某种特殊用途（例如MFC框架），才需要dynamic_cast 如果你用了dynamic_cast 大部分情况是，你的设计有问题，而不是你的真的需要dynamic_cast

引用 1 楼 Jenf_Mu 的回复:inline void fun(const A* a) 	{ 		A* a1 = const_cast<A*>(a); 		const B* b = static_cast<B*>(a1); 		cout<<b<<endl; 	}  问一下  struct A 	{ 		int a; 	}; 	struct B : A 	{ 		int b; 		void display() const 		{ 			cout<<b<<endl; 		} 	}; 	struct C : A 	{  	};  	inline void fun(const A* a) 	{ 		const B* b = static_cast<const B*>(a); 		b->display(); 		cout<<b<<endl; 	}  	inline void test() 	{ 		B b; 		b.b = 100; 		fun(&b); 		C c; 		fun(&c); 	} 这种情况下,用 dynamic_cast会报错,因为类B没有虚函数,不是多态的. 但用static_cast的话,像struct C这里就错了,但它不能检测出来,怎么办呢?

const B* b = static_cast<const B*>(a);

引用 3 楼 oN5GrzoN 的回复:[quote=引用 1 楼 Jenf_Mu 的回复:] inline void fun(const A* a) 	{ 		A* a1 = const_cast<A*>(a); 		const B* b = static_cast<B*>(a1); 		cout<<b<<endl; 	}  问一下  struct A 	{ 		int a; 	}; 	struct B : A 	{ 		int b; 		void display() const 		{ 			cout<<b<<endl; 		} 	}; 	struct C : A 	{  	};  	inline void fun(const A* a) 	{ 		const B* b = static_cast<const B*>(a); 		b->display(); 		cout<<b<<endl; 	}  	inline void test() 	{ 		B b; 		b.b = 100; 		fun(&b); 		C c; 		fun(&c); 	} 这种情况下,用 dynamic_cast会报错,因为类B没有虚函数,不是多态的. 但用static_cast的话,像struct C这里就错了,但它不能检测出来,怎么办呢?[/quote]  基类加虚析构函数

//cout<<b<<endl(); cout<<b<<endl;

const B* b = reinterpret_cast<B const*>(a);


Question: ftok产生的key冲突了

用户a和b 文件i节点及程序调试查看ftok产生的key值如下 用户a： a-/home/a/etc/ipckey>ls -li 2097174 -rwxrw-r--. 1 a a    0 Sep 22  2013 comm 程序调试： 64		sprintf(strPath,"%s/etc/ipckey/comm",getenv("HOME")); (gdb) p strPath $1 = "/home/a/etc/ipckey/comm", '\000' <repeats 91 times> (gdb) n 67		if ((ilShareKey = ftok(strPath,1)) == (key_t)-1) (gdb) p ilShareKey $2 = 16908310  用户b： b-/home/b/etc/ipckey>ls -li 2228246 drwxr-xr-x. 2 b b 4096 Sep 22  2013 trnlog 程序调试： 64		sprintf(strPath,"%s/etc/ipckey/trnlog",getenv("HOME")); (gdb) p strPath $1 = "/home/b/etc/ipckey/trnlog", '\000' <repeats 89 times> (gdb) n 67		if ((ilShareKey = ftok(strPath,1)) == (key_t)-1) (gdb) p ilShareKey $2 = 16908310

亲，恭喜，恭喜啊！问题解决了！   赞一个！恩，不错！继续努力！

好吧，没人解答我来说说吧！ 翻看了ftok的实现源码，得知ftok就是通过文件的一些属性加上id值得到的key值，的确存在不同文件同一id值生成相同key值的可以，比如我遇到的这种情况。 先列出ftok的实现，精简如下： key = ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | ((proj_id & 0xff) << 24)); 用户a： a-/home/a/etc/ipckey>stat -c "%i %d" comm 2097174 64770 用户b： b-/home/b/etc/ipckey>stat -c "%i %d" trnlog 2228246 64770  按照ftok的实现经过计算，的确得出相同的结果。 所以说，ftok的使用不只是大家所说的，如果生成key值的文件在使用，不允许删除重建，否则会出现意想不到的问题；而且，相同的机器，我们也需要注意我遇到的这种情况。  通过以上，我明白了ftok产生的问题，让我纠结了几天的问题。 ～～～结贴～～～