Question: 字符串排序问题

// 哈哈，我是找来找岔的， // 这么多的高手，对题目的理解有问题！没仔细看题目的后果！ // 在这里只指出错误之处，上面的人已经指出了没有释放内存的错误，这里不再指出了！！！！ // 这里不对你的原程序的写法作出置评   #include<stdio.h> #include<string.h> #include<stdlib.h>  char *a[2000];  int main(void) {      char *p;      int i, k, n;       scanf("%d", &n);       for(i = 1; i < (n+1); i++){          a[i]=(char*)malloc(sizeof(char)*2000);          memset(a[i], 0, sizeof(char)*2000);      }       for(i = 1; i < (n+1); i++)          scanf("%s",a[i]);       for(i = 1; i < (n+1); i++)      {          for(k = i+1; k < (n+1); k++)              if(strcmp(a[i],a[k])>0)              {                  p       = a[k];                  a[k]    = a[i];                  a[i]    = p;              }      }       for(i = 1; i < (n+1); i++)              printf("%s\n",a[i]);  // Hi, 你忘记释放内存了！我就不帮你写了，你自己补上吧！                return 0;  }  程序在Ubuntu 14.04上测试通过， astron@ubuntu:~$ uname -a Linux ubuntu 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux  GCC Version: astron@ubuntu:~$ gcc -v gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)

来看看~表示学习学习。。。

引用 8 楼 u013951943 的回复:[quote=引用 6 楼 a515360208 的回复:] 你的代码除了动态申请后没有释放，没有其他问题 如果你做的是ACM的题目的话，估计就是超时或者内存的问题了，你把没有通过的原因贴出类 错误显示就是runtime error 有人说是内存的问题，可是我不知道问题出在什么地方，后面我释放了空间也不行[/quote] ACM题的话，就无能无力了，跟本身的的编译器有关系吧，我也不太懂

菜鸟路过，无能为力

1 #include<stdio.h>   2 #include<stdlib.h>   3 #include<string.h>   4 struct  node;   5 typedef  struct tree   6 {   7         struct  node *p_node;   8 }tree;   9 typedef struct node  10 {  11         struct  tree p_left;  12         struct  tree p_right;  13         char *p_data;  14 }node;  15 tree tr;  16 void init()  17 {  18         tr.p_node=NULL;  19 }  20 static tree *find_tree(tree *p_tree ,const char *str)  21 {  22         if(!p_tree->p_node||!strcmp(p_tree->p_node->p_data,str))  23         {  24                 return p_tree;  25         }  26         if(strcmp(p_tree->p_node->p_data,str)>0)  27         {  28                 return find_tree(&p_tree->p_node->p_left,str);  29         }  30         return find_tree(&p_tree->p_node->p_right,str);  31 }  32 void add_data(const char *str)  33 {  34         char *p_str=(char *)malloc(strlen(str)+1);  35         memcpy(p_str,str,strlen(str)+1);  36         node *p_node=(node *)malloc(sizeof(node));  37         p_node->p_left.p_node=NULL;  38         p_node->p_right.p_node=NULL;  39         p_node->p_data=p_str;  40         if(!tr.p_node)  41         {  42                 tr.p_node=p_node;  43                 return;  44         }  45         find_tree(&tr,str)->p_node=p_node;  46 }  47 void erg_tree(const tree *p_tree)  48 {  49         if(!p_tree->p_node)  50         {  51                 return;  52         }  53         erg_tree(&p_tree->p_node->p_left);  54         printf("%s\n",p_tree->p_node->p_data);  55         erg_tree(&p_tree->p_node->p_right);  56         free(p_tree->p_node->p_data);  57         free(p_tree->p_node);  58 }  59 int main()  60 {  61         init();  62         char buff[100];  63         size_t  i=0;  64         for(;i<10;i++)  65         {  66                 gets(buff);  67                 add_data(buff);  68         }  69         printf("*************************************\n");  70         erg_tree(&tr);  71         return 0;  72 } 二叉树实现了一下

不要假设malloc都能成功，不要假设N < 2000,不要假设2000个字节足够容纳一行内容。

引用 11 楼 u013951943 的回复:[quote=引用 9 楼 u012061345 的回复:] 字符串最长是多少？ 如果是2000的话，内存要开2001。 这个不要紧，原题对大小没有要求，2000只是我随便弄的[/quote]  这个说不定很要紧。你弄份AC的代码来看看。

引用 9 楼 u012061345 的回复:字符串最长是多少？ 如果是2000的话，内存要开2001。 这个不要紧，原题对大小没有要求，2000只是我随便弄的

引用 2 楼 yangyuyu77584 的回复:a[i]=(char*)malloc(sizeof(char)*2000);这里申请了内存，后面没有释放。指针一定要记住申请后不用时就将他释放。 恩 可是后来我释放了还是有问题

字符串最长是多少？ 如果是2000的话，内存要开2001。

引用 6 楼 a515360208 的回复:你的代码除了动态申请后没有释放，没有其他问题 如果你做的是ACM的题目的话，估计就是超时或者内存的问题了，你把没有通过的原因贴出类 错误显示就是runtime error 有人说是内存的问题，可是我不知道问题出在什么地方，后面我释放了空间也不行

qsort Performs a quick sort.  void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );  Routine Required Header Compatibility  qsort <stdlib.h> and <search.h> ANSI, Win 95, Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  None  Parameters  base  Start of target array  num  Array size in elements  width  Element size in bytes  compare  Comparison function  elem1  Pointer to the key for the search  elem2  Pointer to the array element to be compared with the key  Remarks  The qsort function implements a quick-sort algorithm to sort an array of num elements, each of width bytes. The argument base is a pointer to the base of the array to be sorted. qsort overwrites this array with the sorted elements. The argument compare is a pointer to a user-supplied routine that compares two array elements and returns a value specifying their relationship. qsort calls the compare routine one or more times during the sort, passing pointers to two array elements on each call:  compare( (void *) elem1, (void *) elem2 );  The routine must compare the elements, then return one of the following values:  Return Value Description  < 0 elem1 less than elem2  0 elem1 equivalent to elem2  > 0 elem1 greater than elem2    The array is sorted in increasing order, as defined by the comparison function. To sort an array in decreasing order, reverse the sense of “greater than” and “less than” in the comparison function.  Example  /* QSORT.C: This program reads the command-line  * parameters and uses qsort to sort them. It  * then displays the sorted arguments.  */  #include <stdlib.h> #include <string.h> #include <stdio.h>  int compare( const void *arg1, const void *arg2 );  void main( int argc, char **argv ) {    int i;    /* Eliminate argv[0] from sort: */    argv++;    argc--;     /* Sort remaining args using Quicksort algorithm: */    qsort( (void *)argv, (size_t)argc, sizeof( char * ), compare );     /* Output sorted list: */    for( i = 0; i < argc; ++i )       printf( "%s ", argv[i] );    printf( "\n" ); }  int compare( const void *arg1, const void *arg2 ) {    /* Compare all of both strings: */    return _stricmp( * ( char** ) arg1, * ( char** ) arg2 ); }   Output  [C:\code]qsort every good boy deserves favor boy deserves every favor good   Searching and Sorting Routines  See Also   bsearch, _lsearch

为什么不用qsort函数呢、

你觉得有什么不妥？或者运行会出错？


Question: ShellExecuteEx怎么动态调用？

参考 MSDN98\SAMPLES\VC98\SDK\WINUI\SHELL\FILEVIEW\FVTEXT.CPP Microsoft SDK\samples\SysMgmt\Msi\Tutorial.cpp Microsoft SDK\samples\winui\Shell\FileView\FVText.Cpp Microsoft SDK\samples\winui\Shell\SampView\ContMenu.Cpp

Contents  Index  Topic Contents   Previous Topic: ShellExecute Next Topic: SHFileOperation    ShellExecuteEx   WINSHELLAPI BOOL WINAPI ShellExecuteEx(     LPSHELLEXECUTEINFO lpExecInfo );	  Performs an action on a file.   Returns a nonzero value if successful, or zero otherwise. To get extended error information, call theGetLastError function.  lpExecInfo  Address of a SHELLEXECUTEINFO structure that contains and receives information about the application being executed.  If the function succeeds, it sets the hInstApp member of the SHELLEXECUTEINFO structure to the instance handle to the application that the function started. If the function fails, hInstApp is one of the SE_ERR_ error values indicating the cause of the failure. (An instance handle will always be greater than 32 and an error value less than 32.) Note that the SE_ERR_ error values are for compatibility with the ShellExecute function; use theGetLastError function to retrieve error information.   The error value returned byGetLastError corresponds to the SE_ERR_ values and may be one of the following: ERROR_FILE_NOT_FOUND  The specified file was not found.  ERROR_PATH_NOT_FOUND  The specified path was not found.  ERROR_DDE_FAIL  The DDE transaction failed.  ERROR_NO_ASSOCIATION  There is no application associated with the given file name extension.  ERROR_ACCESS_DENIED  Access to the specified file is denied.  ERROR_DLL_NOT_FOUND  One of the library files necessary to run the application can't be found.  ERROR_CANCELLED  The function prompted the user for the location of the application, but the user canceled the request.  ERROR_NOT_ENOUGH_MEMORY  There is not enough memory to perform the specified action.  ERROR_SHARING_VIOLATION  A sharing violation occurred.     --------------------------------------------------------------------------------   Top of Page  © 1997 Microsoft Corporation. All rights reserved. Terms of Use.      Contents  Index  Topic Contents   Previous Topic: SHDESCRIPTIONID Next Topic: SHELLFLAGSTATE    SHELLEXECUTEINFO   typedef struct _SHELLEXECUTEINFO{     DWORD cbSize;      ULONG fMask;      HWND hwnd;      LPCTSTR lpVerb;      LPCTSTR lpFile;      LPCTSTR lpParameters;      LPCTSTR lpDirectory;      int nShow;      HINSTANCE hInstApp;        // Optional members      LPVOID lpIDList;      LPCSTR lpClass;      HKEY hkeyClass;      DWORD dwHotKey;      HANDLE hIcon;      HANDLE hProcess;  } SHELLEXECUTEINFO, FAR *LPSHELLEXECUTEINFO;     Contains information used by the ShellExecuteEx function.   cbSize  Size of the structure, in bytes.  fMask  Array of flags that indicate the content and validity of the other structure members. This can be a combination of the following values: SEE_MASK_CLASSKEY  Use the class key given by the hkeyClass member.   SEE_MASK_CLASSNAME  Use the class name given by the lpClass member.   SEE_MASK_CONNECTNETDRV  Validate the share and connect to a drive letter. The lpFile member is a Universal Naming Convention (UNC) path of a file on a network.   SEE_MASK_DOENVSUBST  Expand any environment variables specified in the string given by the lpDirectory or lpFile member.   SEE_MASK_FLAG_DDEWAIT  Wait for the DDE conversation to terminate before returning (if the ShellExecuteEx function causes a DDE conversation to start).  SEE_MASK_FLAG_NO_UI  Do not display an error message box if an error occurs.   SEE_MASK_HOTKEY  Use the hot key given by the dwHotKey member.  SEE_MASK_ICON  Use the icon given by the hIcon member.  SEE_MASK_IDLIST  Use the item identifier list given by the lpIDList member.   SEE_MASK_INVOKEIDLIST  Use the item identifier list given by the lpIDList member to invoke an application. If this member is NULL, the function creates an item identifier list and invokes the application. This flag overrides the SEE_MASK_IDLIST flag.  SEE_MASK_NOCLOSEPROCESS  Leave the process running after the ShellExecuteEx function exits. The hProcess member receives the handle to the process.    hwnd  Window handle to any message boxes that the system may produce while executing this function.  lpVerb  Address of a string specifying the name of a verb. The verb specifies an action for the application to perform. This member defaults to Open if no verb is specified.  lpFile  Address of a null-terminated string that specifies the name of the file to open or print. The function can open an executable file or a document file, but it can only print a document file. If the path is not included with the name, the current directory is assumed.  lpParameters  Address of a null-terminated string containing the application parameters. The parameters must be separated by spaces. To include double quotation marks, you must enclose the marks in double quotation marks, as in the following example:  sei.lpParameters = "An example: \"\"\"quoted text\"\"\"";  In this case, the application receives three parameters: An, example:, and "quoted text".   If the lpFile member specifies a document file, this member should be NULL.   lpDirectory  Address of a null-terminated string that specifies the name of the working directory. If this member is not specified, the current directory is used as the working directory.  nShow  Show flags. Can be one of the SW_ values described for theShowWindow function. If the lpFile specifies an executable file, this member specifies how the application is to be shown when it is opened.  hInstApp  Receives a value greater than 32 if successful, or an error value that is less than or equal to 32 otherwise. Error values can be one of the following: SE_ERR_FNF  File not found.  SE_ERR_PNF  Path not found.  SE_ERR_ACCESSDENIED  Access denied.  SE_ERR_OOM  Out of memory.  SE_ERR_DLLNOTFOUND  Dynamic-link library not found.  SE_ERR_SHARE  Cannot share an open file.  SE_ERR_ASSOCINCOMPLETE  File association information not complete.  SE_ERR_DDETIMEOUT  DDE operation timed out.  SE_ERR_DDEFAIL  DDE operation failed.  SE_ERR_DDEBUSY  DDE operation is busy.  SE_ERR_NOASSOC  File association not available.   lpIDList  Address of an ITEMIDLIST structure to contain an item identifier list uniquely identifying the file to execute. This member is ignored if the fMask member is not set to SEE_MASK_IDLIST.  lpClass  Address of a null-terminated string specifying the name of a file class or a globally unique identifier (GUID).This member is ignored if fMask is not set to SEE_MASK_CLASSNAME.  hkeyClass  Handle to the registry key for the file class. This member is ignored if fMask is not set to SEE_MASK_CLASSKEY.  dwHotKey  Hot key to associate with the application. The low-order word is the virtual key code, and the high-order word is a modifier flag (HOTKEYF_). For a list of modifier flags, see the description of theWM_SETHOTKEY message. This member is ignored if fMask is not set to SEE_MASK_HOTKEY.  hIcon  Handle to the icon for the file class. This member is ignored if fMask is not set to SEE_MASK_ICON.  hProcess  Handle to the newly started application. This member is set on return and is always NULL if fMask is not set to SEE_MASK_NOCLOSEPROCESS.   --------------------------------------------------------------------------------   Top of Page  © 1997 Microsoft Corporation. All rights reserved. Terms of Use.


Question: 请帮帮忙，看下这段错在哪？

引用 3 楼 mcmay 的回复:#include <stdio.h> int maim() {     float x,y;     char op;      printf("Enter x,opration & y:");     scanf("%f%c%f",&x,&op,&y);     switch(op)     {         case'+'      //这里差一个冒号，你自己加上去吧         printf("%.2f%c%.2f=%.2f\n",x,op,y,x+y);         break;         case'-'  //同上         printf("%.2f%c%.2f=%.2f\n",x,op,y,x-y);         break;         case'*' //同上          printf("%.2f%c%.2f=%.2f\n",x,op,y,x*y);         break;         case'/' //同上             if(y==0.0)                 printf("error\n");             else                 printf("%.2f%c%.2f=%.2f\n",x,op,y,x/y);         //这里最好加上一个         //default:             //printf("Operation undefined.");         } //这里加一个       //return 0;  你的main函数的定义有个int返回值 } 勤劳的小蜜蜂

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

应该加入：，规范要求最好加上default

switch  [ case 常量表达式1 ：  语句1； case 常量表达式2 ：  语句2； case 常量表达式3 ：  语句3； 等等 default : 语句;  ]

编译错误，提示不是很清楚嘛- -

引用 8 楼 sholber 的回复:maim是个什么东西？ = =

#include <stdio.h> #include <stdlib.h> int main() { 	float x,y; 	char op; 	printf("Enter x,operation,y:\n"); 	scanf("%f%c%f",&x,&op,&y); 	switch(op) 	{ 	case '+': 		printf("%.2f%c%.2f=%.2f\n",x,op,y,x+y); 		break; 	case '-': 		printf("%.2f%c%.2f=%.2f\n",x,op,y,x-y); 		break; 	case '*': 		printf("%.2f%c%.2f=%.2f\n",x,op,y,x*y); 		break; 	case '/': 		if(y==0.0) 			printf("Division by zero!\n"); 		else 			printf("%.2f%c%.2f=%.2f\n",x,op,y,x/y); 		break; 	default: 		printf("Not supported yet!\n"); 	} 	system("pause"); 	return 0; }

maim是个什么东西？

要学会看编译器的报错提示啊

#include <stdio.h> int main()   //  maim()改成 main() { float x,y; char op; printf("Enter x,opration & y:"); scanf("%f%c%f",&x,&op,&y); switch(op) {case'+':  //少了  ： printf("%.2f%c%.2f=%.2f\n",x,op,y,x+y); break; case'-':   //同上  printf("%.2f%c%.2f=%.2f\n",x,op,y,x-y); break; case'*'://同上 printf("%.2f%c%.2f=%.2f\n",x,op,y,x*y); break; case'/'://同上 if(y==0.0) printf("error\n"); else printf("%.2f%c%.2f=%.2f\n",x,op,y,x/y); } }

好的，我试试。谢谢大家了

cpp:10: error: expected `:' before "printf" 10表示第10行，期待:在printf的前面 那它前面是什么呢？ 即上一行：case '+'  是照着数打的还是自己写的？少了个: 即 case '+':

case后面加冒号 case '+' 改成 case '+':

case是不是没加  ：

刚刚开始学，写其他的简单程序找一下就改过来了。这个怎么试都不行，如果知道说一下，谢谢了！


Question: 求思路

关键是表示方法：二元组选择较多，array，vector都可以，三元组及以上就用结构体。

谢谢了，暂时我找到办法解决了，非常感谢！

x'表示什么意思？ X*表示什么意思？  不是所有的人都明白线性代数。  所有的循环都是一样的：条件为真，执行循环体。 问题在于：如何描述条件？循环体是什么？


Question: memset和循环置位哪个花时间啊？

使用电脑计时有时误差会很大，因为待测程序段的运行会影响电脑时钟。 将待测程序段循环足够多次，手动掐秒表计时可能更准确。

无Profiler不谈效率。

memset是优化过的，从老赵贴的代码中可以看出它是这样优化的（当然这是针对特定的平台的优化）： 对于特殊的case（内存置0且buffer长度超过0x80），调用SSE2指令； 其它case，则是以dword为单位而不是byte为单位置内存，这就减少了memset中循环的次数。  至于 for (i = 0; i < N; i++) a[i] = 0; 有没有优化呢？就我个人知道的，这种简单的for循环，在多核的机器下，如果编译器做得好（很多前提条件，是吧） 是可以生成代码，使其能在多核上运行，大概是这个意思： for (i = 0; i < N/4; i++) a[i] = 0; // run on core1 for (i = N/4; i < N/2; i++) a[i] = 0; // run on core2 for (i = N/2; i < N*3/4; i++) a[i] = 0; // ... for (i = N*3/4; i < N; i++) a[i] = 0;  说这么多，想表达什么呢？ 1）先功能，后性能；  2）一句简单的“哪个花时间”，缺少条件的情况下，这问题没有任何意义； 如果一定要比较“哪个花时间”，那么请在你关心的上下文（你手头的机器，或者最终要跑的机器），反复多次运行并测量（不是运行一次并测量，这样误差太大），即 start = now(); 运行一万次（给数组置0） end = now(); 如果一万次的结果还不明显，比如只差一两秒，这样说明不了问题，请加大一万这个数目，并反复这个实验。 注意：机器不要跑其他的程序／服务⋯⋯，即尽量减少干扰  3）优化无处不在，但是都是针对特定的环境／平台，所以这就是为什么先性能，后功能的原因。

void *memset(void *s, int c, size_t count) 579 { 580         char *xs = s; 581  582         while (count--) 583                 *xs++ = c; 584         return s; 585 }  上层库也是用的循环搞定的。由于存在调用开销，有可能比直接用for循环要一丁点慢！ 如果是下面这个版本  static inline void *__memset_generic(void *s, char c, size_t count) 208 { 209         int d0, d1; 210         asm volatile("rep\n\t" 211                      "stosb" 212                      : "=&c" (d0), "=&D" (d1) 213                      : "a" (c), "1" (s), "" (count) 214                      : "memory"); 215         return s; 216 }  这个比较猛，这是linux内核中的代码，经个人测试很显然比for和memset API都要高效一些

我相信很难写出比memset更快的算法

数据量很少的话，用for多了用memset

可以把int换成char，看下时间，就知道效果了，自己写的for和memset的差距了（一般的memset都是4char的）  可以这么改一下，看看效率，这里的4就是4int版本的处理 for(i = 0;i < N; i+=4 ) {moreSum[i] = 0;moreSum[i+1] = 0;moreSum[i+2] = 0;moreSum[i+3] = 0;} for(;i < N; i++ ) moreSum[i] = 0;

不用讲,自然是memset效率高 汇编有一条指令是内存传送的 可以一次传送N个字节 你的程序也要翻译成汇编的 你自己看着办

引用 3 楼 majia2011 的回复:晕，刚回复完，lz就改了代码  第二个for竟然删除了 我自己失误了。再给我看看我2楼的回复。

引用 1 楼 majia2011 的回复:开玩笑吧，你  1是写了，n个int 2是写了，n个int[n]  你自己说哪个效率高  我改了下代码，再给我看看。多谢。

尽可能用memset  引用 楼主 middilestep 的回复:把一个数组置零， memset和循环置位哪个花时间啊？    #include <stdio.h>  #include <windows.h>  #define N 65535 int moreSum[N];  int main() { 	int i = 0; 	SYSTEMTIME sys; 	GetLocalTime(&sys); 	//printf("%4d/%02d/%02d %02d:%02d:%02d.%03d weekday:%1d\n",sys.wYear,sys.wMonth,sys.wDay,sys.wHour,sys.wMinute,sys.wSecond,sys.wMilliseconds,sys.wDayOfWeek); 	printf("#0 %02dm.%03dms\n",sys.wSecond,sys.wMilliseconds);  	for(i = 0;i < N; i++ ) moreSum[i] = 0; 	GetLocalTime(&sys); 	printf("#1 %02dm.%03dms\n",sys.wSecond,sys.wMilliseconds);  	 memset(moreSum,0,sizeof(moreSum)); 	GetLocalTime(&sys); 	printf("#2 %02dm.%03dms\n",sys.wSecond,sys.wMilliseconds);  	return 0; }      #0 00m.218ms #1 00m.218ms #2 00m.218ms

晕，刚回复完，lz就改了代码  第二个for竟然删除了

#define N 65535*10  #0 04m.118ms #1 04m.123ms #2 04m.123ms  ms 看出点来了

引用 12 楼 zhao4zhong1 的回复:千万别盲目崇拜linux： 先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装  再参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\intel\memset.asm         page    ,132         title   memset - set sections of memory all to one byte ;*** ;memset.asm - set a section of memory to all one byte ; ;       Copyright (c) Microsoft Corporation. All rights reserved. ; ;Purpose: ;       contains the memset() routine ; ;*******************************************************************************          .xlist         include cruntime.inc         .list  page ;*** ;char *memset(dst, value, count) - sets "count" bytes at "dst" to "value" ; ;Purpose: ;       Sets the first "count" bytes of the memory starting ;       at "dst" to the character value "value". ; ;       Algorithm: ;       char * ;       memset (dst, value, count) ;               char *dst; ;               char value; ;               unsigned int count; ;               { ;               char *start = dst; ; ;               while (count--) ;                       *dst++ = value; ;               return(start); ;               } ; ;Entry: ;       char *dst - pointer to memory to fill with value ;       char value - value to put in dst bytes ;       int count - number of bytes of dst to fill ; ;Exit: ;       returns dst, with filled bytes ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************          CODESEG      extrn   _VEC_memzero:near     extrn   __sse2_available:dword          public  memset memset proc \         dst:ptr byte, \         value:byte, \         count:dword          OPTION PROLOGUE:NONE, EPILOGUE:NONE          .FPO    ( 0, 3, 0, 0, 0, 0 )          mov     edx,[esp + 0ch] ; edx = "count"         mov     ecx,[esp + 4]   ; ecx points to "dst"          test    edx,edx         ; 0?         jz      short toend     ; if so, nothing to do          xor     eax,eax         mov     al,[esp + 8]    ; the byte "value" to be stored  ; Special case large block zeroing using SSE2 support     test    al,al ; memset using zero initializer?     jne     dword_align     cmp     edx,080h ; block size exceeds size threshold?     jb      dword_align     cmp     DWORD PTR __sse2_available,0 ; SSE2 supported?     je      dword_align      jmp     _VEC_memzero ; use fast zero SSE2 implementation     ; no return  ; Align address on dword boundary dword_align:          push    edi             ; preserve edi         mov     edi,ecx         ; edi = dest pointer          cmp     edx,4           ; if it's less then 4 bytes         jb      tail            ; tail needs edi and edx to be initialized          neg     ecx         and     ecx,3           ; ecx = # bytes before dword boundary         jz      short dwords    ; jump if address already aligned          sub     edx,ecx         ; edx = adjusted count (for later) adjust_loop:         mov     [edi],al         add     edi,1         sub     ecx,1         jnz     adjust_loop  dwords: ; set all 4 bytes of eax to [value]         mov     ecx,eax         ; ecx=0/0/0/value         shl     eax,8           ; eax=0/0/value/0          add     eax,ecx         ; eax=0/0val/val          mov     ecx,eax         ; ecx=0/0/val/val          shl     eax,10h         ; eax=val/val/0/0          add     eax,ecx         ; eax = all 4 bytes = [value]  ; Set dword-sized blocks         mov     ecx,edx         ; move original count to ecx         and     edx,3           ; prepare in edx byte count (for tail loop)         shr     ecx,2           ; adjust ecx to be dword count         jz      tail            ; jump if it was less then 4 bytes          rep     stosd main_loop_tail:         test    edx,edx         ; if there is no tail bytes,         jz      finish          ; we finish, and it's time to leave ; Set remaining bytes  tail:         mov     [edi],al        ; set remaining bytes         add     edi,1          sub     edx,1           ; if there is some more bytes         jnz     tail            ; continue to fill them  ; Done finish:         mov     eax,[esp + 8]   ; return dest pointer         pop     edi             ; restore edi          ret  toend:         mov     eax,[esp + 4]   ; return dest pointer          ret  memset  endp          end  崇拜？大婶真会开玩笑！迫于环境的问题，没有涉及windows相关资料。只是在linux下比较linux的几个接口性能差别！没有对对大婶的windows做任何妄言！


Question: 给变量赋一个超出表示范围的值，有没有可能影响其相邻的其他内存？

不过输出的时候需要注意  char a =128; 16 进制输出,可能是 FF80，FFFFFF80 而不是 80  char a =129;  16 进制输出,可能是 FF81，FFFFFF81 而不是 81

看你的方式， 如果强制转换地址为  指向更长数据的指针，通过指针解引用赋值，那是一定会的越界的。  如果赋值号左边的数据，是该变量本身（包括通过同一类型引用方式），用超长类型数据赋值， 或者会截断数据，或者转换为某个定值，或者产生一个异常， 或者因为不能转换,而产生编译错误---数据类型不能匹配。 这些时候，都不会越界。  //例如  unsigned char a =10000; unsigned char &b =a; b = 10000; //或者  b =100.12; //这些都不会越界  //如果这么做  int *pa = (int *)&a; *pa=1000;  //这么做会越界 //其实即使  *pa =0;  //也会越界的

不会的，变量本身的内存大小是固定的，系统不会让它越界存储的

无符号整形肯定不会，赋值中会被截断的。数组倒是经常越界

引用 楼主 skdjfsk 的回复:比如当一个8位的无符号数为0xFF时，再加1. 个人觉得不可能影响。 不会的，数据首先是通过寄存器，然后再送到内存的。

不会，只是表示的值出现了问题


Question: 怎么找数组中的最小值和次小值

怎么感觉刚讲的堆排序刚好可以使用，只不过有点大材小用 。。。 建议在照一次最小值（期间出现与第一次最小值相同的不算），然后将就可以交换了 思想应该就这样

不要每次取出一个值进行比较，这样比较的次数是2n-2, 而是一个取出2个值，首先进行比较，然后再与最小和次小比较，这样取出2个值比较的次数是3，最后整体的次数的3（n/2）. 比2n-2要少。

应该输出两个 printf("%d %d \n",min1,min2);

引用 35 楼 zxh707wk 的回复:可以直接用一次循环 代码： #include <stdio.h>  int main() { 	int i; 	int t; 	int a[]={2,3,4,2,0,5,8,6,1,8,4,3,7}; 	int min1=a[0]; 	int min2=a[1]; 	if(min1>min2) 	{ 		t=min1; 		min1=min2; 		min2=t; 	} /*到此，min和min2将数轴分成三段，其后的任一个a[i]只能是a[i]<=min1,   min1<a[i]<=min2, min2<a[1] 只需考虑前两种可能*/ 	for(i=2;i<sizeof(a)/sizeof(int);i++) 	{ 		if(a[i]<min2) 		{ 			min2=a[i]; 		} 		if(min1>min2) 		{ 			t=min1; 			min1=min2; 			min2=t; 		} /*按逻辑应该是-----即按数轴方向、一段一段考查*/           if(a[i]<=min1)          { min2=min1;            min1=a[i];          }         else if(a[i] <min2)         { min2=a[i];        }                 	} 	printf("%d\n",min1); 	return 0; }  在linux mint gcc上编译通过 上面某楼的 min1=min2=a[0];的假定初值，当a[0]就是该数组的最小值时，就找不到次小的了

一次扫描可以解决的问题 定义2个变量一个最小一个次小，分别给个很大的初始值  扫描，取出数Ai和次小比较，如果比次小大，则该数跳过 如果Ai比次小小，则Ai和最小比较，如果比最小小，则让次小=最小，最小=Ai，如果Ai比最小大，则，次小=Ai，最小不变；然后下一个，直到扫描完毕；要交换次小和最小，你们交换数据的时候，记得同时得交换序号

冒个泡   自己想

除了9楼、32楼和35楼 其他回答都很2B

忘了输出min2了。。。 min1为最小值 min2为次最小值

可以直接用一次循环 代码： #include <stdio.h>  int main() { 	int i; 	int t; 	int a[]={2,3,4,2,0,5,8,6,1,8,4,3,7}; 	int min1=a[0]; 	int min2=a[1]; 	if(min1>min2) 	{ 		t=min1; 		min1=min2; 		min2=t; 	} 	for(i=2;i<sizeof(a)/sizeof(int);i++) 	{ 		if(a[i]<min2) 		{ 			min2=a[i]; 		} 		if(min1>min2) 		{ 			t=min1; 			min1=min2; 			min2=t; 		} 	} 	printf("%d\n",min1); 	return 0; }  在linux mint gcc上编译通过

引用 12 楼 zyaiwx 的回复: 定义两个变量 submin和min 都初始化为极小值(你产生的是正整数，那就用0就好了) 每次从数组里面取两个数a和b a和b进行比较， 选出大的和submin比， 选出小的和min比。我也想了这个办法，可如果是负整数怎么办？ 负整数和正整数都有怎么办？ 怎么取极小值?

从大到小排序，不就可以了么？

引用 12 楼 zyaiwx 的回复: 定义两个变量 submin和min 都初始化为极小值(你产生的是正整数，那就用0就好了) 每次从数组里面取两个数a和b a和b进行比较， 选出大的和submin比， 选出小的和min比。++++++这个方法比较好

引用 15 楼 zhao4zhong1 的回复:怎么找出10个元素的值中只有两种时数组中的最小值和次小值？ 爱因斯坦好象说过：提出问题比解答问题更难！！！

引用 14 楼 zhao4zhong1 的回复:怎么找一个空数组和只有一个元素的数组中的最小值和次小值？ 爱因斯坦好象说过：提出问题比解答问题更难！ 不找，直接说没有。 你这个太极端，其实一个元素的数组，怎么定义最小值和次小值更有意义。 哈哈！！！！！！！！！！

这个方法似乎也可以用于选择问题

可以这么做：  定义两个整数，作为下标，表示最小元，次小元位置。  任取两个位置作为最小元，次小元位置，比较数据元素大小，让第一个为最小，第二个为次小   其他数据，每个数，跟次小比较，不小则什么也不做，小则替换之， 然后比较最小次小，依然保持 第一个为最小，第二个为次小。  最后互换最小元，次小元位置。 PS： 过程中，始终保持第一个为最小，第二个为次小。 对于重复数据，你这问题里，没有定义，最小元和次小元是否相同， 所以无法确定，能否直接使用这个方法

# include <stdio.h> # include <stdlib.h>  int main() {     int a[10];     int i;     int * p; // always point to min     int * q; // always point to second min     int tmp;      for (i = 0; i < 10; i++)         a[i] = rand() % 100;     for (i = 0; i < 10; i++)         printf("%d\n", a[i]);      if (a[0] < a[1]) // assume a[0] is min, a[1] is second min         p = a, q = a + 1;     else // otherwise, a[1] is min, a[0] is second min         p = a + 1, q = a;      for (i = 2; i < 10; i++)     {         if (a[i] < *p) // less than min         {             q = p; // old min is new second min             p = a + i; // a[i] is new min         }         else if (a[i] < *q) // greater than min but less than second min         {             q = a + i; // a[i] is new second min         }         else // greater than second min         {             ; // we do nothing here         }     }      printf("\nmin is: %d\n", *p);     printf("second min is: %d\n\n", *q);      tmp = *p;     *p = *q;     *q = tmp;      for (i = 0; i < 10; i++)         printf("%d\n", a[i]);      return 0; }

怎么找出10个元素值都一样的数组中的最小值和次小值？ 爱因斯坦好象说过：提出问题比解答问题更难！！

循环两次就行了，第一次记录数组中最小值的角标，再来循环一次（跳过第一次记录的角标）记录最小值的角标就是次小的


Question: 淘宝的手机版改触屏了，ie登陆好像不行了！谁有好办法吗？

我在推一下 说不定有人可以指点下呢！

有人可以指点一下吗？


Question: 急求 可编程16*64LED点阵显示屏程序

看规格书就明白时序了。  引用 楼主 fang6681 的回复:急求 可编程16*64LED点阵显示屏程序


Question: 过支付宝安全控件输入密码的方法，有知道的吗？

引用 4 楼 yimarong 的回复:[quote=引用 2 楼 yiyefangzhou24 的回复:] 当支付宝勾选安全控件输入的时候就不是一般的webbrowser了，是通过支付宝的安全平台在客户端做好加密之后的传输，不可能使用post直接发送，当然不使用安全控件的话应该可以，通过抓包看看发送的密码流程，通过post直接替换密码就行  具体的思路我也是了解的！ 就是如何去实现 比较困扰！  不知道从哪里下手！[/quote]思路我也说了啊，在非控件的情况下抓包->改包->发包

引用 6 楼 yimarong 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] http://www.autohotkey.com  你的意思是说 我下载这个软件，然后利用这个软件来自动输入支付宝密码吗？  有办法添加进软件内吗？[/quote] WinExec("autoinput.ahk",SH_HIDE);

引用 7 楼 user-4 的回复:[quote=引用 楼主 yimarong 的回复:] 我现在用的webbrowser控件，是焦点获取（模拟键盘输入）自动输入支付宝密码的！ 但是如果软件最小化之后 在聊qq或者写文本什么的时候，焦点就不在软件内了，支付宝密码会自动自动敲到当前的窗口去！  好几次qq和人聊天 发消息的时候 没注意 结果连支付密码都发出去了！  唉~郁闷！  我当前希望解决的难题： 1：我软件运行的时候，就算是最小化了，也可以自动完成支付流程！ 不会出现密码出现在外面（例如文本 qq聊天窗口等）的状况！ 2：希望实现支付宝支付全后台运行，目前好像是要post模式，不知道是不是还有别的什么好办法！  希望各位大牛可以指点一下！ 不胜感激！  你真敢用这个软件？[/quote]   这是什么意思？

引用 2 楼 yiyefangzhou24 的回复:当支付宝勾选安全控件输入的时候就不是一般的webbrowser了，是通过支付宝的安全平台在客户端做好加密之后的传输，不可能使用post直接发送，当然不使用安全控件的话应该可以，通过抓包看看发送的密码流程，通过post直接替换密码就行  具体的思路我也是了解的！ 就是如何去实现 比较困扰！  不知道从哪里下手！

不会的路过，接分

引用 楼主 yimarong 的回复:我现在用的webbrowser控件，是焦点获取（模拟键盘输入）自动输入支付宝密码的！ 但是如果软件最小化之后 在聊qq或者写文本什么的时候，焦点就不在软件内了，支付宝密码会自动自动敲到当前的窗口去！  好几次qq和人聊天 发消息的时候 没注意 结果连支付密码都发出去了！  唉~郁闷！  我当前希望解决的难题： 1：我软件运行的时候，就算是最小化了，也可以自动完成支付流程！ 不会出现密码出现在外面（例如文本 qq聊天窗口等）的状况！ 2：希望实现支付宝支付全后台运行，目前好像是要post模式，不知道是不是还有别的什么好办法！  希望各位大牛可以指点一下！ 不胜感激！  你真敢用这个软件？

有人可以指点一下吗？

引用 5 楼 zhao4zhong1 的回复:http://www.autohotkey.com  你的意思是说 我下载这个软件，然后利用这个软件来自动输入支付宝密码吗？  有办法添加进软件内吗？


Question: 发现了20G的c语言视频教程，可以去看看。

不如看书！


Question: 这题输出结果是什么

编译错误。

# include <stdio.h>  int main() ////////////// main { 	int x, y;////////// 	x = 2, y = 1; 	while(x-- != -1) 	{ 		do{ 		y *= x; 		 y++; /////////// 		} while(x--); 	}////////////////////////// 	printf("%d，%d/n",y,x);///////////// 	 	return 0; } 问题太多 关于自加自减，可以看置顶帖——http://bbs.csdn.net/topics/370153775

真是搞不懂哪来的这么多人为i++,++i的问题纠结，搞不清楚别这样写啊，折磨自己，更折磨别人 不知道什么叫代码风格吗？？？

引用 4 楼 starytx 的回复:没进来前就猜到是自增自减的问题（这个看看那个裘老的解释的置顶帖）。主函数名称也写错了这个置顶帖帮不了楼主  这代码 没涉及置顶帖讨论的问题

谁写的代码，丑的一比。错误百出

void main

编译出错，找不到函数入口。

x                y 1              2 0              1 -1 -2 所以最后的答案是 1， -2，考的是后--的运算，后--先比较再自减


Question: 大神 求帮助看以个程序，为何报错是死循环

引用 6 楼 ForestDB 的回复:LZ以截图而不是文本的方式给出代码，那么就失去了一次机会：“别人将代码存成文件并编译执行”。 方便了LZ自己，但是没有任何好处。  当然不乏热心人士将代码手动输入一遍，但这时的我，显然并不热心。 +1

LZ 的代码应该好好缩进下！

估计第二个循环  考试系统没有检查m-1的能力 所以认为m<=1的时候是死循环把

是一个考试的系统报的错误，运行出来是正确的

没看出问题，你执行了么

从一个名为 data.in 的文件中读取一个整数，将其值保存到变量 n 中。如果此值不在10到100之间(不含两个端点)，返回失败。 然后从1开始，计算出所有能整除此数的整数(包含此数本身)，并将这些数保存到一个数组 a 里面。 最后，将数组 a 里面的数都输出。

谁报的错？怎么报的？

用眼扫了一遍，感觉不存在使程序死循环的条件。


Question: 求大家帮帮忙！

#include “stdio.h"  int c;  //这里全局变量，初值为0  int jiafa(int a,int b,int c)  //这里的参数int c拷贝了main()传给它的全局变量c， {                    //所以无法改变main()传给它的那个c的值     c=a+b;     printf("%d\n",c);      return 0; //函数其实不需要返回数值，所以这个return 0没有必要 }  int main() {     int a,b;     jiafa(3,5,c);  //这个c是全局变量的那个c，jiafa()里的参数int c参数将这个c拷贝了一份     printf("%d\n",c);//所以无法改变，你需要将c的地址传给jiafa()，不过这也要改变jiafa()      return 0; }  这样改就ok了： #include <stdio.h>  int c;  void jiafa(int a,int b,int * c) {     *c = a+b;      printf("%d\n", *c); }  int main() {     int a,b;      jiafa(3, 5, &c);  //这里传c的地址给jiafa()，就可以改变c的值了     printf("%d\n", c);       return 0; }

int add(int a, int b) {     return a + b; }  int main() {     printf("%d\n", add(3, 5));      return 0; }

#include <stdio.h>  void jiafa(int a,int b,int c) { 	c=a+b;     printf("%d\n",c);     return ; }  int main(void) { 	int c;     jiafa(3,5,c); //printf("%d\n",c);//为什么没输出8，那么要输出8需要怎样改啊！     return 0; }

在主函数中定义一个c，然后写成c=jiafa（3,5，c）试试行不

jiafa(3,5,c);这行改成c = jiafa(3,5,c);看看这个.

我是需要在外面输出！引用可以吗？int &c

你都return 0了还要输出8？你直接return c也行啊。。


Question: Libevent下evhttp_set_cb和evhttp_set_gencb的区别是什么？

应该还是有很多人对此有疑问吧， 根据官方说明如下： 那么基本上就是对应特定的URI使用evhttp_set_cb注册回调那么就会流程会走到这里， 那么没有注册过的URI将会走到evhttp_set_gencb注册流程。   To use this capability, you need to include the <evhttp.h> header in your    program.  You create the server by calling evhttp_new(). Add addresses and    ports to listen on with evhttp_bind_socket(). You then register one or more    callbacks to handle incoming requests.  Each URI can be assigned a callback    via the evhttp_set_cb() function.  A generic callback function can also be    registered via evhttp_set_gencb(); this callback will be invoked if no other    callbacks have been registered for a given URI.         为了获得 HTTP 处理能力，需要包含头文件 <evhttp.h> 在你的应用程序中。你需要通过调用 evhttp_new() 来创建服务器，通过 evhttp_bind_socket() 来添加监听地址和端口号。然后你可以注册一个或者多个回调函数来处理收到的请求。 可以通过函数 evhttp_set_cb() 为每一个 URI 指定一个回调函数。 你同样可以使用函数 evhttp_set_gencb() 注册一个通用回调处理函数，在没有为指定 URI 注册回调函数的情况下，该回调函数会被调用。


Question: 【C语言】解压文件！

LZ还能搜索下？gzopen，……

引用 5 楼 ForestDB 的回复:Content-Encoding: gzip  zlib可以处理gzip没错，但是得用gz系列的函数； 而compress/uncompress是用来处理.Z格式的文件的。具体的GZ系列函数能告诉下吗？

引用 2 楼 zhao4zhong1 的回复:用 WinExec("命令行调用解压软件解压指定文件",SW_HIDE); 解压。 不要迷信API，有时WinExec更靠谱，更容易调试。不会用这个啊  我想用ZILB    这个UNCOMPRESS函数解压文件！

引用 1 楼 user-3 的回复:使用gzip压缩的，请搜索gzip相关函数不是用zilb吗？完事用uncomperss()函数

使用gzip压缩的，请搜索gzip相关函数


Question: collect2: ld returned 1 exit status

E:/FUdx_Android  我这里根本就没有这个文件夹

ios里成功调用了？？？ 理论上.a文件没问题

引用 2 楼 zhao4zhong1 的回复:undefined reference to 'CreateFastUdx()' 使用objdump或nm查看.a或.so中是否导出了名字CreateFastUdx  搜“Name Mangling in C++”  导出了  因为ios里就成功调用了

编译器 Cygwin

引用 3 楼 linux_hsylar 的回复:这个很可能是你的生成第三方静态库.a的编译器和你写的代码的编译器编译方式不同所导致，你可以把你的代码和是用的编译器发上来。  void IUdxMediaClientSink2::OnConnect(int erro)//与流媒体服务器联接成功或失败 { 	LOGE("OnConnect"); }  void IUdxMediaClientSink2::OnRecvData(BYTE* pData,int len)//回调接收数据 { 	LOGE("OnRecvData"); }  void IUdxMediaClientSink2::OnOperatorErro(int erro)//操作出错返回码 { 	LOGE("OnOperatorErro"); }  extern "C" jboolean Java_com_example_test_IUdxMediaClient_Bind (JNIEnv * env, jclass, jstring ip, jlong port) { LOGE("Bind");  	IUdxMediaClientSink2 iudS; 	IUdxMediaClient *iudc= CreateUdxMediaClient(); 	iudc->SetCB(&iudS); 	BOOL b = iudc->Bind(0, 0); 	return b; }

应该是编译选项

我编译时需要连接 使用第三方.a静态库文件 在编译的时候过不去


Question: vsprintf是线程安全的吗？

引用 26 楼 assembly 的回复:[quote=引用 25 楼 zhao4zhong1 的回复:] 谁说不操作全局变量的函数就是线程安全的？！ 我一直是这么认为的，难道不对？ 赵老师，能不能给个反例？谢谢了！[/quote]  倒也不能认为没引用全局变量就线程安全 如果你给两个线程两个指针指向同一个栈上分配的内存对象，不加锁仍然是线程不安全 又或者使用同一个资源，比如文件或者套接字  但是这里的vsprintf，恐怕在两个线程中撞车的可能性不大吧，如果不对同一个内存缓冲区操作的话 我想象不出一个现代的库实现，vsprintf内部还有什么必要共享某种资源，无论内存 还是文件、套接字等等等等 至于说vsprintf内部加锁，大家打个赌，谁找到有这样的实现就赠送个100分啥的，呵呵——不过不是我给哦

引用 24 楼 assembly 的回复:什么论坛啊，竟然不能修改自己的帖子！ 抱歉，我收回楼上的测试；因为发现了一个问题：  xusiwei1236: 你好！你的测试用例有问题，因为两个线程使用了相同的 char buf[1024]，因此而产生的字符混合，不能怪printf。 我修改了你的代码，把 char buf[1024] 分别挪到两个线程各自的函数内部，测试的结果是：没有混合  不妨你也测试一下。 我只是要证明“sprintf内没有加锁‘这一观点，因而使用了两个线程同时操作同一个str。如果两个线程同时用sprintf格式化两个不同的str，不会有任何问题。 如果sprintf内部加了锁，那么多个线程各自操作不同的字符串（刚才打错了）也会发生锁争用，而这种争用是没有必要的。

引用 24 楼 assembly 的回复:什么论坛啊，竟然不能修改自己的帖子！ 抱歉，我收回楼上的测试；因为发现了一个问题：  xusiwei1236: 你好！你的测试用例有问题，因为两个线程使用了相同的 char buf[1024]，因此而产生的字符混合，不能怪printf。 我修改了你的代码，把 char buf[1024] 分别挪到两个线程各自的函数内部，测试的结果是：没有混合  不妨你也测试一下。 我只是要证明“sprintf内没有加锁‘这一观点，因而使用了两个线程同时操作同一个str。如果两个线程同时用sprintf格式化两个不同的str，不会有任何问题。 如果sprintf内部加了锁，那么多个线程对各自操作不同的线程也会发生锁争用，而这种争用是没有必要的。

引用 25 楼 zhao4zhong1 的回复:谁说不操作全局变量的函数就是线程安全的？！ 我一直是这么认为的，难道不对？ 赵老师，能不能给个反例？谢谢了！

谁说不操作全局变量的函数就是线程安全的？！

xusiwei1236: 你好！ 我在Windows XP service pack3 + VC6的环境下，跑了你的代码，不过有一点点调整。测试的结果是这样的： 1.用CriticalSection把两个语句都包括进来，测试了几次，字符是干净的，没有发生混合  void thread_fun1(void *args) {     int i;     for(i=0; i<TESTN; i++) {         EnterCriticalSection (&critical_section);         sprintf(buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",                  "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#"                 );         printf("[thread 1] %03d | %s\n", i, buf); // printf 一般是线程安全的         LeaveCriticalSection (&critical_section);     } }   2.只用CriticalSection保护sprintf，结果：字符发生了混合；这说明：即使printf是安全的，但它保护的并不是整个字符串；猜测也许是一段一段保护的，当然只是猜测。  void thread_fun1(void *args) {     int i;     for(i=0; i<TESTN; i++) {         EnterCriticalSection (&critical_section);         sprintf(buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",                  "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#"                 );         LeaveCriticalSection (&critical_section);         printf("[thread 1] %03d | %s\n", i, buf); // printf 一般是线程安全的     } }   3.只用CriticalSection保护printf，结果：字符发生了混合；参考结果2，个人觉得，也许sprintf没保护；也许sprintf保护了，但不是整个字符串。  void thread_fun1(void *args) {     int i;     for(i=0; i<TESTN; i++) {         sprintf(buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",                  "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#",                 "#","#","#","#","#","#","#","#","#","#"                 );         EnterCriticalSection (&critical_section);         printf("[thread 1] %03d | %s\n", i, buf); // printf 一般是线程安全的         LeaveCriticalSection (&critical_section);     } }   4.不使用CriticalSection，当然发生了混合。

VC6： C:\Program Files\Microsoft Visual Studio\VC98\CRT\SRC\VSPRINTF.C

引用 11 楼 zhao4zhong1 的回复:为何不去看看vsprintf的源代码？ Windows： 先 http://www.microsoft.com/visualstudio/chs/downloads#d-2010-express 点开Visual C++ 2010 Express下面的语言选‘简体中文’，再点立即安装   在参考C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\vsprintf.c  Linux： 略

为何不去看看vsprintf的源代码？

引用 10 楼 xusiwei1236 的回复:正常的实现都不会使用全局变量（或static局部变量）， 也就是说，对于不同的str，是线程安全的。 如果有两个线程同时操作同一个str，是不安全的。  #include <stdio.h> #include <pthread.h>  #ifdef WIN32 	#include <windows.h> 	#define msleep(ms) Sleep((ms)) #else 	#include <unistd.h> 	#define msleep(ms) usleep((ms)*1000) #endif  #define TESTN 10 #define DELAY 100  char buf[1024]; pthread_t tid1, tid2;  void *thread_fun1(void *args) { 	int i; 	for(i=0; i<TESTN; i++) { 		sprintf(buf, "%s%s%s%s%s%s%s%s%s%s",  				"#","#","#","#","#","#","#","#","#","#" ); 		printf("[thread 1] %03d | %s\n", i, buf); // printf 一般是线程安全的 	} }  void *thread_fun2(void *args) { 	int i; 	for(i=0; i<TESTN; i++) { 		sprintf(buf, "%s%s%s%s%s%s%s%s%s%s",  					 ".",".",".",".",".",".",".",".",".","." );	 		printf("[THREAD 2] %03d | %s\n", i, buf); // printf 一般是线程安全的 	} }  int main(int argc, char *argv[]) { 	pthread_create(&tid1, NULL, thread_fun1, NULL); 	pthread_create(&tid2, NULL, thread_fun2, NULL); 	 	msleep(100); 	 	return 0; }  MinGW编译，连续运行10次，重定位到spts.txt:  for /L %i in (1,1,10) do @echo test %i...  & @a >> spts.txt  得到spts.txt（同一行内出现两种字符的就是因为sprintf内没有加锁）:  [thread 1] 000 | ########## [thread 1] 001 | ########## [thread 1] 002 | ########## [thread 1] 003 | ########## [thread 1] 004 | ########## [thread 1] 005 | ########## [thread 1] 006 | ########## [thread 1] 007 | ########## [thread 1] 008 | ########## [thread 1] 009 | ########## [THREAD 2] 000 | .......... [THREAD 2] 001 | .......... [THREAD 2] 002 | .......... [THREAD 2] 003 | .......... [THREAD 2] 004 | .......... [THREAD 2] 005 | .......... [THREAD 2] 006 | .......... [THREAD 2] 007 | .......... [THREAD 2] 008 | .......... [THREAD 2] 009 | .......... [thread 1] 000 | ########## [thread 1] 001 | ########## [thread 1] 002 | ########## [thread 1] 003 | ########## [thread 1] 004 | ########## [thread 1] 005 | ########## [thread 1] 006 | ########## [thread 1] 007 | ########## [thread 1] 008 | ########## [thread 1] 009 | ########## [THREAD 2] 000 | .......... [THREAD 2] 001 | .......... [THREAD 2] 002 | .......... [THREAD 2] 003 | .......... [THREAD 2] 004 | .......... [THREAD 2] 005 | .......... [THREAD 2] 006 | .......... [THREAD 2] 007 | .......... [THREAD 2] 008 | .......... [THREAD 2] 009 | .......... [thread 1] 000 | ########## [thread 1] 001 | ########## [thread 1] 002 | ########## [thread 1] 003 | ########## [thread 1] 004 | ########## [thread 1] 005 | ########## [thread 1] 006 | ########## [thread 1] 007 | ########## [thread 1] 008 | ########## [thread 1] 009 | ########## [THREAD 2] 000 | .......... [THREAD 2] 001 | .......... [THREAD 2] 002 | .......... [THREAD 2] 003 | .......... [THREAD 2] 004 | .......... [THREAD 2] 005 | .......... [THREAD 2] 006 | .......... [THREAD 2] 007 | .......... [THREAD 2] 008 | .......... [THREAD 2] 009 | .......... [thread 1] 000 | ########## [thread 1] 001 | ########## [thread 1] 002 | ########## [thread 1] 003 | ...####### [THREAD 2] 000 | ########## [thread 1] 004 | .......... [THREAD 2] 001 | ########## [thread 1] 005 | .......... [THREAD 2] 002 | ########## [thread 1] 006 | .......... [THREAD 2] 003 | ########## [thread 1] 007 | .......... [THREAD 2] 004 | ########## [thread 1] 008 | .......... [THREAD 2] 005 | ########## [thread 1] 009 | .......... [THREAD 2] 006 | .......... [THREAD 2] 007 | .......... [THREAD 2] 008 | .......... [THREAD 2] 009 | .......... [thread 1] 000 | ########## [thread 1] 001 | ########## [thread 1] 002 | ########## [thread 1] 003 | ########## [thread 1] 004 | ########## [thread 1] 005 | ########## [thread 1] 006 | ########## [thread 1] 007 | ########## [thread 1] 008 | ########## [thread 1] 009 | ########## [THREAD 2] 000 | .......... [THREAD 2] 001 | .......... [THREAD 2] 002 | .......... [THREAD 2] 003 | .......... [THREAD 2] 004 | .......... [THREAD 2] 005 | .......... [THREAD 2] 006 | .......... [THREAD 2] 007 | .......... [THREAD 2] 008 | .......... [THREAD 2] 009 | .......... [thread 1] 000 | ########## [thread 1] 001 | ########## [thread 1] 002 | ########## [thread 1] 003 | ########## [thread 1] 004 | ########## [thread 1] 005 | ########## [thread 1] 006 | ########## [thread 1] 007 | ########## [thread 1] 008 | ########## [thread 1] 009 | ########## [THREAD 2] 000 | .......... [THREAD 2] 001 | .......... [THREAD 2] 002 | .......... [THREAD 2] 003 | .......... [THREAD 2] 004 | .......... [THREAD 2] 005 | .......... [THREAD 2] 006 | .......... [THREAD 2] 007 | .......... [THREAD 2] 008 | .......... [THREAD 2] 009 | .......... [thread 1] 000 | ########## [thread 1] 001 | .......... [thread 1] 002 | ########## [THREAD 2] 000 | ########## [thread 1] 003 | .......... [THREAD 2] 001 | ########## [thread 1] 004 | .......... [THREAD 2] 002 | ########## [thread 1] 005 | .......... [THREAD 2] 003 | ########## [thread 1] 006 | .......... [THREAD 2] 004 | ########## [thread 1] 007 | .......... [THREAD 2] 005 | ########## [thread 1] 008 | .......... [THREAD 2] 006 | ########## [thread 1] 009 | .......... [THREAD 2] 007 | .......... [THREAD 2] 008 | .......... [THREAD 2] 009 | .......... [thread 1] 000 | ########## [thread 1] 001 | ########## [thread 1] 002 | ########## [thread 1] 003 | ########## [thread 1] 004 | ########## [thread 1] 005 | .......... [THREAD 2] 000 | ########## [thread 1] 006 | .......... [THREAD 2] 001 | ########## [thread 1] 007 | .......... [THREAD 2] 002 | ########## [thread 1] 008 | .......... [THREAD 2] 003 | ########## [thread 1] 009 | .......... [THREAD 2] 004 | .......... [THREAD 2] 005 | .......... [THREAD 2] 006 | .......... [THREAD 2] 007 | .......... [THREAD 2] 008 | .......... [THREAD 2] 009 | .......... [thread 1] 000 | ########## [THREAD 2] 000 | ########## [thread 1] 001 | .......... [THREAD 2] 001 | ########## [thread 1] 002 | .......... [THREAD 2] 002 | ########## [thread 1] 003 | .......... [THREAD 2] 003 | ########## [thread 1] 004 | .......... [THREAD 2] 004 | ########## [thread 1] 005 | .......... [THREAD 2] 005 | ########## [thread 1] 006 | .......... [THREAD 2] 006 | ########## [thread 1] 007 | .......... [THREAD 2] 007 | ########## [thread 1] 008 | .......... [THREAD 2] 008 | ########## [thread 1] 009 | .......... [THREAD 2] 009 | .......... [thread 1] 000 | ########## [thread 1] 001 | #######... [thread 1] 002 | ########## [THREAD 2] 000 | ########## [thread 1] 003 | .......... [THREAD 2] 001 | ########## [thread 1] 004 | .......... [THREAD 2] 002 | ########## [thread 1] 005 | .......... [THREAD 2] 003 | ########## [thread 1] 006 | .......... [THREAD 2] 004 | ########## [thread 1] 007 | .......... [THREAD 2] 005 | ########## [thread 1] 008 | .......... [THREAD 2] 006 | ########## [thread 1] 009 | .......... [THREAD 2] 007 | .......... [THREAD 2] 008 | .......... [THREAD 2] 009 | ..........   顶分析！

mujiok2003的图片启发了我，去找了一下，发现一个问题：你的图片是IAR 5.4版本中所附文档《EWARM_DevelopmentGuide.ENU.pdf》中第290页上的一段文字； 然后我找了IAR 6.5版本中，相同的文档《EWARM_DevelopmentGuide.ENU.pdf》中叙述REENTRANCY的章节，这次是在第390页上，而且，内容也发生了有趣的变化：   而这也意味着，某些代码，在IAR 5.4上没有问题，而用IAR 6.5却有问题。  这些　没有明确规范　而必须依赖编译器和库具体实现　的细节，在　多线程　或者　中断　的应用环境下，有必要仔细考虑，甚至使用自己的实现。

你可以先看看编译器的手册。 至少sprintf可以放心使用。   引用 15 楼 assembly 的回复:VC6是有源码的，但IAR的没看到。更换开发环境和编译器的时候，总是要面对这个问题。  如akirya所言，vsprintf内部使用了errno，而且C的标准库并没有对线程安全做强制的要求，那么不同的编译器的C库，就存在着使用其它全局量的可能，尽管只是可能，但这也是件让人纠结的事情。  我自己在ARM上写了一个多线程调度的核，用IAR编译。这样就要面对这个问题：线程代码如何放心地使用编译器提供的C库，包括string.h math.h stdlib.h。在编译器厂家不提供C库源码的情况下，该如何确认这些C库中的函数“没有使用全局量”？如果使用这些库函数的时候都拿锁来保护，对于一个C开发者来说，这是不可理喻的。  除非，使用自己的代码。但有。。那些经过底层优化的代码，不是那么容易折腾的，所以还是使用编译器自带的要明智些。  现在我决定这样做： 1.相信 string.h math.h 里的函数是不操作全局量的。 2.其它的函数，需要的时候，用自己的代码，包括vsprintf；不用的函数，就不包括。

以前VC的CRT有单线程与多线程版之分，现在只有多线程版了, 线程安全应该可以保证。

这个核是我自己写的，创建线程的函数都是自己的。不怕大家笑话，就贴几句在这里，可以看到，是非常简陋的：  void k_thread_create_context (struct _thread *p, void*(*proc)(void*), void *para) {     ul cpsr;     int i;      cpsr = get_cpsr ();     cpsr &= ~0x80; //enable IRQ, keep sys mode     p->ctx.cpsr = cpsr;      p->ctx.pc = (ul)proc;     for (i=0; i<CTX_REG_NUM; i++) {         p->ctx.r[i] = 0;     }     p->ctx.r[0] = (ul)para;     p->ctx.sp = (ul)(&(p->stack[USR_STACK_SIZE-1]));     p->ctx.lr = 0; }  int pthread_create (pthread_t *t, const pthread_attr_t *ta, void *(*proc)(void *), void *para) {     struct _thread *p;      if (0 == pthread_idle) {         return -1;     }      enter_critical ();      p = pthread_idle;     pthread_idle = pthread_idle->pnext;     *t = (pthread_t)p;     p->pnext = 0;      k_thread_create_context (p, proc, para);     k_thread_appand_ready (p);      exit_critical ();     return 0; }  _beginthread内部是alloc了内存，给每个线程开辟了C库所需全局量的存储区；而相应的，C库的入口代码也需要相应的调整，比如说引用errno，可能就要写成这样：pthis_thread->errno。  如果开发者使用编译器提供的C库，那么C库里的errno可能就是errno，而不是pthis_thread->errno，因为C库的作者不知道开发者会如何创建线程以及线程的数据结构。

引用 15 楼 assembly 的回复:VC6是有源码的，但IAR的没看到。更换开发环境和编译器的时候，总是要面对这个问题。  如akirya所言，vsprintf内部使用了errno，而且C的标准库并没有对线程安全做强制的要求，那么不同的编译器的C库，就存在着使用其它全局量的可能，尽管只是可能，但这也是件让人纠结的事情。  我自己在ARM上写了一个多线程调度的核，用IAR编译。这样就要面对这个问题：线程代码如何放心地使用编译器提供的C库，包括string.h math.h stdlib.h。在编译器厂家不提供C库源码的情况下，该如何确认这些C库中的函数“没有使用全局量”？如果使用这些库函数的时候都拿锁来保护，对于一个C开发者来说，这是不可理喻的。  除非，使用自己的代码。但有。。那些经过底层优化的代码，不是那么容易折腾的，所以还是使用编译器自带的要明智些。  现在我决定这样做： 1.相信 string.h math.h 里的函数是不操作全局量的。 2.其它的函数，需要的时候，用自己的代码，包括vsprintf；不用的函数，就不包括。 看你的编译器提供怎样的创建线程函数，应该有文档说明。 像VC提供的_beginthreadex就为每个线程提供一个errno，就没有线程安全的问题。

竟然编辑不了自己的帖子。补充一下： 1.相信string.h math.h里的某几个函数是不操作全局量的。例如：memcpy strcpy sin cos等

个人愚见：不认为vsprintf的实现需要全局变量，LZ可以看看代码中有无static变量或者其它全局变量，一般如果实现中使用了static这样的变量或者是全角变量是会在文档中提及的；但显然vsprintf的文档没有说 所以如果传给它的buffer是两个不同的buffer，个人认为vsprintf是线程安全的。


Question: 二叉树的创建和输出，提示0错误，0警告，可是为什么输入后没反应？

求解~~

大家帮忙看看啊，刚看到这里，自己想写一写，就发现问题了，实在没办法解决了呢~

如上，由于要p=(BTNode *)malloc(sizeof(BTNode)); 所以 用了形参*&p，采用了c++的引用来方便处理，为什么我输入无法结束，按回车时应该被当做一个字符处理了，才不能结束输入，所以不能输出吧，这里应该如何处理？  还是说程序本 身有问题？

引用 18 楼 wangyang745 的回复:楼主这样输入12^3^^4^^然后敲回车，注意字符之间没有空格也没有回车.测试过可以运行，仅供参考。 lz是前序创建二叉树，注意树的结构。 oh  my  god  ！ 知道了。   只管输入了，没考虑树的结构。多谢，多谢。成功了，居然不能乱输入。。。╮(╯▽╰)╭ 第一次写二叉树的程序，都不知道，原来输入都有要求。。。太感谢了！！！！！！

引用 15 楼 u010412073 的回复:#include<stdio.h> #include<stdlib.h> #include<malloc.h> typedef struct BTNode//定义结点类型 { char data; struct BTNode *lchild; struct BTNode *rchild; }BTNode;   void create(BTNode **p)//创建二叉树，输入'^'表示空 { char a; getchar(); scanf("%c",&a); if(a=='^') p=NULL; else { *p=(BTNode *)malloc(sizeof(BTNode)); (*p)->data=a; create(&((*p)->lchild)); create(&((*p)->rchild)); } return; }  void output(BTNode *p)//先序输出二叉树的内容 { if(p) { printf("%c\n",p->data); output(p->lchild); output(p->rchild); } }  int main()//主函数 { BTNode *p; printf("please input data:"); create(&p); output(p); return 0;  }   这个还有个小错误18行应该是*p=NULL;

引用 18 楼 wangyang745 的回复:楼主这样输入12^3^^4^^然后敲回车，注意字符之间没有空格也没有回车.测试过可以运行，仅供参考。 lz是前序创建二叉树，注意树的结构。我的确这样敲的，为什么我按回车后，就换行了，按n次了，都是换行。。。

要调试一下 并且你没有分析下你自己的代码吧 并不是不会结束 而是在输入第一个^之前一直是在左孩子上加节点 这样你如果想真正的结束输入需要输入N+1个^才能完全结束输入过程。 这个N是你在输入第一个^之前输入的字符的数量

引用 15 楼 u010412073 的回复:#include<stdio.h> #include<stdlib.h> #include<malloc.h> typedef struct BTNode//定义结点类型 { char data; struct BTNode *lchild; struct BTNode *rchild; }BTNode;   void create(BTNode **p)//创建二叉树，输入'^'表示空 { char a; getchar(); scanf("%c",&a); if(a=='^') p=NULL; else { *p=(BTNode *)malloc(sizeof(BTNode)); (*p)->data=a; create(&((*p)->lchild)); create(&((*p)->rchild)); } return; }  void output(BTNode *p)//先序输出二叉树的内容 { if(p) { printf("%c\n",p->data); output(p->lchild); output(p->rchild); } }  int main()//主函数 { BTNode *p; printf("please input data:"); create(&p); output(p); return 0;  }   我改成了c语言标准的，依然是同样的问题啊

引用 13 楼 shlvshe00 的回复:[quote=引用 5 楼 u010412073 的回复:] [quote=引用 4 楼 gongheguoyingpai11 的回复:] 没有什么大问题 你可以在getchar()那个语句后加上一句fflush(stdin)将输入缓冲区中'\n'清空掉 这样就不会读入\n了 因为之前\n总是会被读入 所以当输入一个^符号 使得将一个节点的左孩子置为NULL时 其右孩子总是读入\n作为自己的值 所以这样下去是无法结束输入的 a=getchar(); fflush(stdin); 修改后，输入结束后，按回车时，依旧把回车作为字符处理，一直按回车都没反应，一直换行.......[/quote] 你一直换行的原因是在等待你输入^，你只设定了^为结束条件[/quote] 我输入^了，依旧是那样。。。^不算是结束条件吧，只是遇到^表示为空~

引用 5 楼 u010412073 的回复:[quote=引用 4 楼 gongheguoyingpai11 的回复:] 没有什么大问题 你可以在getchar()那个语句后加上一句fflush(stdin)将输入缓冲区中'\n'清空掉 这样就不会读入\n了 因为之前\n总是会被读入 所以当输入一个^符号 使得将一个节点的左孩子置为NULL时 其右孩子总是读入\n作为自己的值 所以这样下去是无法结束输入的 a=getchar(); fflush(stdin); 修改后，输入结束后，按回车时，依旧把回车作为字符处理，一直按回车都没反应，一直换行.......[/quote] 你一直换行的原因是在等待你输入^，你只设定了^为结束条件

#include<stdio.h> #include<stdlib.h> #include<malloc.h> typedef struct BTNode//定义结点类型 { 	char data; 	struct BTNode *lchild; 	struct BTNode *rchild; }BTNode;  char get_char() { 	char a; 	scanf("%c",&a); 	fflush(stdin); 	return a; } void create(BTNode *&p,char a)//创建二叉树，输入'^'表示空，这里用了c++的引用，方便修改p { 	if(a=='^') 		p=NULL; 	else 	{ 		p=(BTNode *)malloc(sizeof(BTNode)); 		p->data=a; 		create(p->lchild,get_char()); 		create(p->rchild,get_char()); 	} }  void output(BTNode *p)//先序输出二叉树的内容 { 	if(p) 	{ 		printf("%c\n",p->data); 		output(p->lchild); 		output(p->rchild); 	} }  int main()//主函数 { 	BTNode *p; 	printf("please input data:"); 	create(p,get_char()); 	printf("pertrave:"); 	output(p); 	return 0; }

引用 9 楼 liuhengxiao 的回复: void create(BTNode *&p)//如果说要在函数里面给P申请动态空间，那你也可以传一个指针的指针呀 { char a; a=getchar(); if(a=='^') p=NULL; else { p=(BTNode *)malloc(sizeof(BTNode)); p->data=a; create(p->lchild); create(p->rchild); } }  就是觉得指针的指针麻烦，所以才利用*&P这样的操作。。

引用 8 楼 liuhengxiao 的回复: void create(BTNode *&p)//这里一个引用的指针是什么意思？ 要么引用要么指针，很是不理解                                              //要修改P的内容指针和引用都可以修改啊。。。 { char a; a=getchar(); if(a=='^') p=NULL; else { p=(BTNode *)malloc(sizeof(BTNode)); p->data=a; create(p->lchild); create(p->rchild); } } 这里是利用了c++的一些语法，可以直接在函数中修改指针本身，因为要动态申请。这样方便点。 可以避免指针的指针，那样会觉得有点儿麻烦~

来人啊。。。。

看了程序N遍了，依旧不知道问题出在哪里。。。


Question: 关于锁的问题---cpu对同一硬件接口寄存器访问

这相当于是一个原子操作，加锁或者是进入临界区，操作完成后，再解锁或者是退出临界区。  引用 楼主 nadleeh123 的回复:很多人可能都遇到过这样的情景: 1个设备,有一个按键，一个灯，一个外部io口，他们都是接到同一gpio组的不同位上的。 然后按键处于中断模式，可能随时被按下，需要cpu需要清除gpio的对应位。 灯一直按照遇到的频率闪烁，一般不会被改变。 外部io接口会在特定的情况切换gpio对应位的io模式。 3个线程独立控制3个设备。  好吧，问题来了，他们都属于同一组gpio，也就是说对cpu来说，3个设备在io空间内部这3个设备都是在同一个io空间，也就是说属于共享资源，但是属于该io空间的不同位上。每次操作都是各设各的位，互不影响。 这种情况下，多核cpu是否需要加锁，单核cpu是否需要禁抢占？

哦靠，难道赵老师要独吞200分了  来人啊！！！！！！！！

要加锁或临时关闭中断


Question: 关于const的问题求大神解答

这个应该是c++编译器自动优化的结果！在编译时将num替换为10再编译。如果用c编译，应该两个都是100

最近怎么这么多同样的问题，常量折叠

如果上帝当初编写的DNA永远正确的话，试问能进化出人类吗？

引用 6 楼 zyaiwx 的回复:[quote=引用 4 楼 zhao4zhong1 的回复:] 不要纠结各种常量了，这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢！ 赵老师的话很没意思。不纠结怎么搞懂？不搞懂咋保证写出正确的[/quote] 你知道不？根本就不存在正确的代码。 SSH不是很正确吗？咋HeartBleed了呢？  程序员要做的不是尽力避免错误，而是聚焦在快速发现并改正错误。真正以快速方式轻易解决错误，“快速的失败”远胜过“预防错误”。Fred George

引用 4 楼 zhao4zhong1 的回复:不要纠结各种常量了，这个世界上唯一不变的就是变化。用API WriteProcessMemory还能修改正运行的其它进程的内存里面的所谓常量呢！ 赵老师的话很没意思。不纠结怎么搞懂？不搞懂咋保证写出正确的

借一楼的话哦

0x400b14	push   rbp 0x400b15	mov    rbp,rsp 0x400b18	sub    rsp,0x10 0x400b1c	mov    DWORD PTR [rbp-0xc],0xa 0x400b23	lea    rax,[rbp-0xc] 0x400b27	mov    rsi,rax 0x400b2a	mov    edi,0x602080 0x400b2f	call   0x400960 <_ZNSolsEPKv@plt> 0x400b34	mov    esi,0x400980 0x400b39	mov    rdi,rax 0x400b3c	call   0x400970 <_ZNSolsEPFRSoS_E@plt> 0x400b41	lea    rax,[rbp-0xc] 0x400b45	mov    QWORD PTR [rbp-0x8],rax 0x400b49	mov    rax,QWORD PTR [rbp-0x8] 0x400b4d	mov    DWORD PTR [rax],0x64 0x400b53	mov    esi,0xa 0x400b58	mov    edi,0x602080 0x400b5d	call   0x4008d0 <_ZNSolsEi@plt> 0x400b62	mov    esi,0x40101d 0x400b67	mov    rdi,rax 0x400b6a	call   0x400940 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 0x400b6f	lea    rdx,[rbp-0xc] 0x400b73	mov    rsi,rdx 0x400b76	mov    rdi,rax 0x400b79	call   0x400960 <_ZNSolsEPKv@plt> 0x400b7e	mov    esi,0x400980 0x400b83	mov    rdi,rax 0x400b86	call   0x400970 <_ZNSolsEPFRSoS_E@plt> 0x400b8b	mov    rax,QWORD PTR [rbp-0x8] 0x400b8f	mov    eax,DWORD PTR [rax] 0x400b91	mov    esi,eax 0x400b93	mov    edi,0x602080 0x400b98	call   0x4008d0 <_ZNSolsEi@plt> 0x400b9d	mov    esi,0x40101d 0x400ba2	mov    rdi,rax 0x400ba5	call   0x400940 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> 0x400baa	mov    rdx,QWORD PTR [rbp-0x8] 0x400bae	mov    rsi,rdx 0x400bb1	mov    rdi,rax 0x400bb4	call   0x400960 <_ZNSolsEPKv@plt> 0x400bb9	mov    esi,0x400980 0x400bbe	mov    rdi,rax 0x400bc1	call   0x400970 <_ZNSolsEPFRSoS_E@plt> 0x400bc6	mov    eax,0x0 0x400bcb	jmp    0x400bd5 <main()+193> 0x400bcd	mov    rdi,rax 0x400bd0	call   0x4009a0 <_Unwind_Resume@plt> 0x400bd5	leave 0x400bd6	ret  http://blog.csdn.net/yby4769250/article/details/7359278


Question: 寻找采样数据处理程序（计算频率，振幅，等）

你级别这么高了，这点分算隔靴搔痒。本来希望送新手的

LZ可以送分了。

没有就算了，怎么也来个人应一声，我好送分啊

顶起。肯定有人用过，比如数字示波器的处理程序


Question: C语言更改当前目录问题

_getcwd, _wgetcwd Get the current working directory.  char *_getcwd( char *buffer, int maxlen );  wchar_t *_wgetcwd( wchar_t *buffer, int maxlen );  Routine Required Header Compatibility  _getcwd <direct.h> Win 95, Win NT  _wgetcwd <direct.h> or <wchar.h> Win NT    For additional compatibility information, see Compatibility in the Introduction.  Libraries  LIBC.LIB Single thread static library, retail version  LIBCMT.LIB Multithread static library, retail version  MSVCRT.LIB Import library for MSVCRT.DLL, retail version    Return Value  Each of these functions returns a pointer to buffer. A NULL return value indicates an error, and errno is set either to ENOMEM, indicating that there is insufficient memory to allocate maxlen bytes (when a NULL argument is given as buffer), or to ERANGE, indicating that the path is longer than maxlen characters.  Parameters  buffer  Storage location for path  maxlen  Maximum length of path in characters: char for _getcwd and wchar_t for _wgetcwd  Remarks  The _getcwd function gets the full path of the current working directory for the default drive and stores it at buffer. The integer argument maxlen specifies the maximum length for the path. An error occurs if the length of the path (including the terminating null character) exceeds maxlen. The buffer argument can be NULL; a buffer of at least size maxlen (more only if necessary) will automatically be allocated, using malloc, to store the path. This buffer can later be freed by calling free and passing it the _getcwd return value (a pointer to the allocated buffer).  _getcwd returns a string that represents the path of the current working directory. If the current working directory is the root, the string ends with a backslash ( \ ). If the current working directory is a directory other than the root, the string ends with the directory name and not with a backslash.  _wgetcwd is a wide-character version of _getcwd; the buffer argument and return value of _wgetcwd are wide-character strings. _wgetcwd and _getcwd behave identically otherwise.  Generic-Text Routine Mappings  TCHAR.H Routine  _UNICODE & _MBCS Not Defined _MBCS Defined _UNICODE Defined  _tgetcwd _getcwd _getcwd _wgetcwd    Example  // GETCWD.C /* This program places the name of the current directory in the   * buffer array, then displays the name of the current directory   * on the screen. Specifying a length of _MAX_PATH leaves room   * for the longest legal path name.  */  #include <direct.h> #include <stdlib.h> #include <stdio.h>  void main( void ) {    char buffer[_MAX_PATH];     /* Get the current working directory: */    if( _getcwd( buffer, _MAX_PATH ) == NULL )       perror( "_getcwd error" );    else       printf( "%s\n", buffer ); }   Output  C:\code   Directory Control Routines  See Also   _chdir, _mkdir, _rmdir

_chdir, _wchdir Change the current working directory.  int _chdir( const char *dirname );  int _wchdir( const wchar_t *dirname );   Example  /* CHGDIR.C: This program uses the _chdir function to verify  * that a given directory exists.  */  #include <direct.h> #include <stdio.h> #include <stdlib.h>  void main( int argc, char *argv[] ) {    if( _chdir( argv[1] )   )       printf( "Unable to locate the directory: %s\n", argv[1] );    else       system( "dir *.wri"); }   Output   Volume in drive C is CDRIVE  Volume Serial Number is 0E17-1702   Directory of C:\write  04/21/95  01:06p                 3,200 ERRATA.WRI 04/21/95  01:06p                 2,816 README.WRI                2 File(s)          6,016 bytes                              71,432,116 bytes free

chdir() Change the current working directory  Synopsis: #include <unistd.h>  int chdir( const char* path );Arguments: path  The new current working directory.  Library: libc  Use the -l c option to qcc to link against this library. This library is usually included automatically.   Description: The chdir() function changes the current working directory to path, which can be relative to the current working directory or an absolute path name.  Returns: 0  Success.  -1  An error occurred (errno is set).  Errors: EACCES  Search permission is denied for a component of path.  ELOOP  Too many levels of symbolic links or prefixes.  ENAMETOOLONG  The path argument is longer than PATH_MAX, or a pathname component is longer than NAME_MAX.  ENOENT  The specified path doesn't exist, or path is an empty string.  ENOMEM  There wasn't enough memory to allocate a control structure.  ENOSYS  The chdir() function isn't implemented for the filesystem specified in path.  ENOTDIR  A component of path is not a directory.  Examples: #include <stdio.h> #include <stdlib.h> #include <unistd.h>  int main( int argc, char* argv[] ) {     if( argc != 2 ) {         fprintf( stderr, "Use: cd <directory>\n" );         return EXIT_FAILURE;     }      if( chdir( argv[1] ) == 0 ) {         printf( "Directory changed to %s\n", argv[1] );         return EXIT_SUCCESS;     } else {         perror( argv[1] );         return EXIT_FAILURE;     } }

不懂windows编程~


Question: 用ffmpeg-20140503-git-719e72c-win32-dev + eclipse + mingw 搭建开发环境

以为自己走错地方了，再重新看一下，原来楼主发错地方了

引用 楼主 dongms_7 的回复:我想做一套封装了ffmpeg的api，供自己的项目中使用，首先我是做java的，网上也有类似的api和开源项目，发现效率一般，所以想jni自己写一套。  碰到的第一个问题就是如何搭建标题所示环境，请各位帮忙啊。  你先把开源的你说“效率一般”的代码看懂再说。


Question: 在自定义的函数中加输出代码，结果才正确，否则最终结果错误！！求解

我知道原因了，不是s被释放的原因，是str1被释放的原因。返回的指针找不到内容了。不过还是谢谢你！！

你的s是函数里的局部变量，出了函数体，s就被释放了，s的内容就不能保证还是原来那些了。


Question: 关于排列组合的一个小算法

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

//qplw.cpp #include <stdio.h> #include <string.h> #include <stdlib.h> int v=0; int w=0; int m;//记录字符串长度 int n;//记录字符串中的字符种类数 char map[256];//记录是哪几种字符 int count[256];//记录每种字符有多少个 int stack[1000];//递归用的栈，并记录当前生成的排列 void Make_Map(char *str) {//统计字符串的相关信息     int s[256];     int i;     memset(s,0,sizeof(s));     memset(count,0,sizeof(count));     m=strlen(str);     if (w<1 || m<w) w=m;     while(*str) {         s[*str]++;         str++;     }     n=0;     for (i=0;i<256;i++)         if (s[i]) {             map[n]=i;             count[n]=s[i];             n++;         } } void Find(int depth) {//递归式回溯法生成全排列     if (depth==w) {         int i;         for (i=0;i<depth;i++) putchar(map[stack[i]]);         putchar('\n');     } else {         int i;         if (v && depth>0) {             for (i=0;i<depth;i++) putchar(map[stack[i]]);             putchar('\n');         }         for (i=0;i<n;i++)             if (count[i]) {                 stack[depth]=i;                 count[i]--;                 Find(depth+1);                 count[i]++;             }     } } void main(int argc,char**argv) {     if (argc<2) {         printf("%s 要产生全排列的字符串 [限定长度|-1]\n",argv[0]);         return;     }     if (argc>=3) w=atoi(argv[2]);     if (-1==w) v=1;     Make_Map(argv[1]);     Find(0); } //C:\test>qplw //qplw 要产生全排列的字符串 [限定长度|-1] // //C:\test>qplw 123 //123 //132 //213 //231 //312 //321 // //C:\test>qplw 123 2 //12 //13 //21 //23 //31 //32 // //C:\test>qplw 122333 3 //122 //123 //132 //133 //212 //213 //221 //223 //231 //232 //233 //312 //313 //321 //322 //323 //331 //332 //333 // //C:\test>qplw 123 -1 //1 //12 //123 //13 //132 //2 //21 //213 //23 //231 //3 //31 //312 //32 //321 //

引用 1 楼 caozhy 的回复:int n = 3; for (int i = 0; i < (1 << n); i++) {      int t = i;     for (int j = 0; j < n; j++)     {         printf("%c ", t % 2 == 0 ? '#' : '*');         t /= 2;     }     printf("\n"); } 写完自己的发现和你的思路是一样的，在实现上还是相差有点距离啊，要向大牛学习啊

你将#看成0，*看成1，输入一个数N,公有2^N种情况，相当于就是用N位的2进制数从0到2^N-1表示, # include <stdio.h>  void numConvert(int (*p)[10], int n, int data);  int main() { 	int i, j, col, row = 1; 	int arr[1024][10];	//假设输入的 N <= 10 	printf("input number N:"); 	scanf("%d", &col);  	j = col; 	while (j > 0) 	{ 		row *= 2; 		j--; 	} 	for (i = 0; i < row; i++) 	{ 		numConvert(arr + i, col, i);	//进制转换 	}  	for (i = 0; i < row; i++) 	{ 		for (j = 0; j < col; j++) 		{ 			if (arr[i][j] == 0) 				printf("#"); 			else 				printf("*"); 		} 		printf("\n"); 	}  	return 0; }  void numConvert(int (*p)[10], int n, int data) { 	int i;  	for (i = n - 1; i >= 0; i--) 	{ 		p[0][i] = data % 2; 		data = data / 2;  	} }

为了能够让用户输入N，承接1楼的实现：   #include <stdio.h> #include <stdlib.h> #include <ctype.h>  #define MAX_INPUT_LENGTH 10  int is_numeric(const char *p) {     if (*p)     {         char c;         while ((c=*p++))         {             if (!isdigit(c))                 return 0;         }         return 1;     }     return 0; }  int main() {     char str[MAX_INPUT_LENGTH];     printf ("Enter N: ");     scanf("%s", str);     if (0 == is_numeric(str))     {         printf("Please enter an integer!\n");         return 1;     }     int n = atoi(str);      for (int i = 0; i < (1 << n); i++)     {         int t = i;         for (int j = 0; j < n; j++)         {             printf("%c ", t % 2 == 0 ? '#' : '*');             t /= 2;         }         printf("\n");     }  	return 0; }

递归解法，你可以自行改成迭代的。  #include <stdio.h> #include <stdlib.h>  void perm(int n, int level, int* v) {   int i, loop;   for(loop = 0; loop < n; ++loop)   {     v[level] = loop;     if(level == n-1)     {      printf("[%d", v[0]);      for(i =1; i < n; ++i)      {        printf(",%d", v[i]);      }       puts("]");     }else     {       perm(n, level+1,v);       }   } }  int main() {   int n, *v;   if(1 == scanf("%d", &n) && n > 0)   {      v = (int*)malloc(sizeof(int)* n);       if(v)      {        perm(n, 0, v);        free(v);      }   } }  //输入:3 /*输出: [0,0,0] [0,0,1] [0,0,2] [0,1,0] [0,1,1] [0,1,2] [0,2,0] [0,2,1] [0,2,2] [1,0,0] [1,0,1] [1,0,2] [1,1,0] [1,1,1] [1,1,2] [1,2,0] [1,2,1] [1,2,2] [2,0,0] [2,0,1] [2,0,2] [2,1,0] [2,1,1] [2,1,2] [2,2,0] [2,2,1] [2,2,2] */


Question: 如何将FB 中的内容，按屏幕旋转的方向进行显示. ( 0 90 180 270 度进行显示

换一个思路吧.

GUI_BitString_8bppDrawEx(FB* fb,int x0, int y0)  函数可将 FB 中的字符 正确显示到 LCD 屏幕上, 现在需要将 LCD 屏幕旋转90度 或 180度， GUI_BitString_8bppDrawEx函数应要修改，请提示一下. 谢谢

int  GUI_BitString_8bppDrawEx(FB* fb,int x0, int y0) {     int Ret         = 0;     int Height      = fb->size.height;     int Width       = fb->size.width;     int  y, BytesPerLine , tmp_y;     int LCDXSize = 0; 	int LCDYSize = 0;     U8 *pDest = NULL; 	const U8 * pSrc = (const U8 *)fb->addr[0];  	 	GUI_LOCK();     if((Screen_Context.LCDDirection[GUI_Context.SelLayer] == GUI_SCNDIR_ROTATE90)        ||(Screen_Context.LCDDirection[GUI_Context.SelLayer] == GUI_SCNDIR_ROTATE270))     {         LCDXSize = Screen_Context.LCDYSize[GUI_Context.SelLayer]; 		LCDYSize = Screen_Context.LCDXSize[GUI_Context.SelLayer];     }     else     {         LCDXSize = Screen_Context.LCDXSize[GUI_Context.SelLayer]; 		LCDYSize = Screen_Context.LCDYSize[GUI_Context.SelLayer];     }  	if(x0 >= LCDXSize) 	{ 		GUI_UNLOCK(); 		return EPDK_FAIL; 	}	 	tmp_y = y0 + Height; 	if(tmp_y > LCDYSize) 	{ 		Height =  LCDYSize - y0; 	}	 	     pDest = (unsigned char *)(orange.fbaddr[GUI_Context.SelLayer]) + (y0 *LCDXSize) + (x0);     BytesPerLine = Width;     for (y=0; y < Height; y++)      {         memcpy(pDest, pSrc, Width);         pSrc += BytesPerLine;         pDest = (U8*)(pDest +LCDXSize); 	     } 	 	GUI_UNLOCK(); 	return Ret; }


Question: (m => m.answercount > 0)代表什么？

LINQ TO SQL 么？啊？ 你发错栏目了吧？

不是LINQ？

Lambda表达式，这是C#，不是C/C++

不明觉厉


Question: 结构体排序问题

31                         *t=*(student_t*)data[end]; 改成 t=(student_t*)data[end];


Question: 请大家帮帮忙!

刚才那句话是:擅用

_fstat, _fstati64 Get information about an open file.  int _fstat( int handle, struct _stat *buffer );  __int64 _fstati64( int handle, struct _stat *buffer );  Function Required Header Compatibility  _fstat <sys/stat.h> and <sys/types.h> Win 95, Win NT  _fstati64 <sys/stat.h> and <sys/types.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  _fstat and _fstati64 return 0 if the file-status information is obtained. A return value of –1 indicates an error, in which case errno is set to EBADF, indicating an invalid file handle.  Parameters  handle  Handle of open file  buffer  Pointer to structure to store results  Remarks  The _fstat function obtains information about the open file associated with handle and stores it in the structure pointed to by buffer. The _stat structure, defined in SYS\STAT.H, contains the following fields:  st_atime  Time of last file access.  st_ctime  Time of creation of file.  st_dev  If a device, handle; otherwise 0.  st_mode  Bit mask for file-mode information. The _S_IFCHR bit is set if handle refers to a device. The _S_IFREG bit is set if handle refers to an ordinary file. The read/write bits are set according to the file’s permission mode. _S_IFCHR and other constants are defined in SYS\STAT.H.  st_mtime  Time of last modification of file.  st_nlink  Always 1 on non-NTFS file systems.  st_rdev  If a device, handle; otherwise 0.  st_size  Size of the file in bytes.  If handle refers to a device, the st_atime, st_ctime, and st_mtime and st_size fields are not meaningful.   Because STAT.H uses the _dev_t type, which is defined in TYPES.H, you must include TYPES.H before STAT.H in your code.  Example  /* FSTAT.C: This program uses _fstat to report  * the size of a file named F_STAT.OUT.  */  #include <io.h> #include <fcntl.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <stdlib.h> #include <string.h>  void main( void ) {    struct _stat buf;    int fh, result;    char buffer[] = "A line to output";     if( (fh = _open( "f_stat.out", _O_CREAT | _O_WRONLY |                                   _O_TRUNC )) ==  -1 )    _write( fh, buffer, strlen( buffer ) );     /* Get data associated with "fh": */    result = _fstat( fh, &buf );     /* Check if statistics are valid: */    if( result != 0 )       printf( "Bad file handle\n" );    else    {       printf( "File size     : %ld\n", buf.st_size );        printf( "Time modified : %s", ctime( &buf.st_ctime ) );    }    _close( fh ); }   Output  File size     : 0 Time modified : Tue Mar 21 15:23:08 1995   File Handling Routines  See Also   _access, _chmod, _filelength, _stat

system("dir /b /a-d c:\\*.* >d:\\allfiles.txt"); //读文件d:\\allfiles.txt的内容即C:\\下所有文件的名字 system("dir /b /a-d /s c:\\*.* >d:\\allfilesinsub.txt"); //读文件d:\\allfilesinsub.txt的内容即C:\\下所有文件的名字包含子目录 system("dir /b /ad  c:\\*.* >d:\\alldirs.txt"); //读文件d:\\alldirs.txt的内容即C:\\下所有子目录的名字 请记住，能用shell命令获取文件、文件夹信息或者操作文件、文件夹最好用shell命令获取或者操作，而不要用各种API获取或者操作，因为当遇到非法文件夹名或非法文件名或非法文件长度、非法文件日期、压缩文件、链接文件、稀疏文件……等各种意料之外的情况时，API会处理的不全面或陷入死循环，而shell命令不会。


Question: 求助 将unsign char数组中的字符转化为16进制

void HexDump(char *buf,int len,int addr) {     int i,j,k;     char binstr[80];      for (i=0;i<len;i++) {         if (0==(i%16)) {             sprintf(binstr,"%08x -",i+addr);             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         } else if (15==(i%16)) {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);             sprintf(binstr,"%s  ",binstr);             for (j=i-15;j<=i;j++) {                 sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');             }             printf("%s\n",binstr);         } else {             sprintf(binstr,"%s %02x",binstr,(unsigned char)buf[i]);         }     }     if (0!=(i%16)) {         k=16-(i%16);         for (j=0;j<k;j++) {             sprintf(binstr,"%s   ",binstr);         }         sprintf(binstr,"%s  ",binstr);         k=16-k;         for (j=i-k;j<i;j++) {             sprintf(binstr,"%s%c",binstr,('!'<buf[j]&&buf[j]<='~')?buf[j]:'.');         }         printf("%s\n",binstr);     } }

unsign char aes_128_cbc_plain_text[AES_128_CBC_LEN]={'a','b','c','d','a','b','c','d','a','b','c','d','a','b','c','d'}; unsign char  aes_128_cbc_plain_text1[AES_128_CBC_LEN]; memcpy((void *)aes_128_cbc_plain_text1,(void *)aes_128_cbc_plain_text,AES_128_CBC_LEN);

引用 1 楼 user-2 的回复:引用unsign char aes_128_cbc_plain_text[AES_128_CBC_LEN]={'a','b','c','d','a','b','c','d','a','b','c','d','a','b','c','d'}; 怎样才能把上面的数组转为unsign char  aes_128_cbc_plain_text1[AES_128_CBC_LEN]={0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64} 这两个是一样的，不需要转。   我知道是一样的，但是在运行的时候，我如果按照unsign char aes_128_cbc_plain_text[AES_128_CBC_LEN]={'a','b','c','d','a','b','c','d','a','b','c','d','a','b','c','d'};就会出错误。 转化成unsign char  aes_128_cbc_plain_text1[AES_128_CBC_LEN]={0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64}就不会出错了。

但是我运行的时候会有错误，我这个利用openssl加密的例子里明文就是： unsigned char aes_128_cbc_plain_text[AES_128_CBC_LEN] = \ 									{0x6b,0xc1,0xbe,0xe2,0x2e,0x40,0x9f,0x96,\ 									 0xe9,0x3d,0x7e,0x11,0x73,0x93,0x17,0x2a}; 所以我想转化一下


Question: 现在的ANSI C指C89还是c99还是c11？

把有限的生命浪费在品尝/品鉴无穷多种的新鲜、靓丽、添加很多香精的语法糖中，我认为不值当也不健康。  这是人生哲学

引用 2 楼 incident_a 的回复:现在都2014年了，C编译器不说支持C11，也应该都自动支持C99了吧，为什么我现在看到的还是支持ANSI C的编译器呢？ 因为现在很多比如银行、航空、税务、通讯……系统的源代码仍是C89 我猜。  把有限的生命浪费在品尝/品鉴无穷多种的新鲜、靓丽、添加很多香精的语法糖中，我认为不值当也不健康。

引用 4 楼 mujiok2003 的回复:[quote=引用 2 楼 incident_a 的回复:] 现在都2014年了，C编译器不说支持C11，也应该都自动支持C99了吧，为什么我现在看到的还是支持ANSI C的编译器呢？  不要以为自动支持。 看看你自己的编译器是否支持。[/quote] 那现在大家编程序用到的什么标准比较多？是c89还是c99还是c11？

引用 2 楼 incident_a 的回复:现在都2014年了，C编译器不说支持C11，也应该都自动支持C99了吧，为什么我现在看到的还是支持ANSI C的编译器呢？  不要以为自动支持。 看看你自己的编译器是否支持。

ANSI C指C89， 之后的版本应该是ISO C

ANSI C指的是C89，GCC要看版本号。  引用 楼主 incident_a 的回复:我认为应该是c11，但我记得去年我用VS2010的时候，C语言不支持布尔类型，（可能是我没包含头文件吧），那照这样看来vs2010用的甚至是c89，到底怎么回事？ 还有第二个问题，现在的GCC用的是C11吗？


Question: 结构体内部申请的空间会随着结构体空间而释放吗？

不会，应先释放st_a->s，再释放st_a  引用 楼主 u013354393 的回复:typedef struct AAA {   char *s; } A;  void main() {   A *st_a = NULL;   st_a = (A *)malloc(sizeof(A));   st_a->s = (char *)malloc(20);   free(st_a); }  st_a->s的空间会相应的释放掉吗？

不会。。。。。


Question: WINDOWS控制台下,使用什么来避免类似fgets函数的阻塞，急！！

Windows 下以非阻塞方式读取标准输入一般采取什么方式，只能用通过多线程实现吗？

windows select不支持non-socket 引用10038: 在一个非套接字上尝试了一个操作

除了多线线程还有没有其他方式；能确定window下select不能用于stdin吗？

用多线程？


Question: 高速路车流量监测怎样实现报警？

这个就和地图的 实时路况一个概念嘛~~你自己瞧瞧嘛~

首先应该有一个检测装置来采集车流量数据，然后根据要求，不同的车流量数据段就显示不同的字体颜色就完了

什么方面的建议阿，是界面设计还是车流检测阿

#include <windows.h> #include <stdio.h>  void ConPrint(char *CharBuffer, int len); void ConPrintAt(int x, int y, char *CharBuffer, int len); void gotoXY(int x, int y); void ClearConsole(void); void ClearConsoleToColors(int ForgC, int BackC); void SetColorAndBackground(int ForgC, int BackC); void SetColor(int ForgC); void HideTheCursor(void); void ShowTheCursor(void);  int main(int argc, char* argv[]) {    HideTheCursor();    ClearConsoleToColors(15, 1);    ClearConsole();    gotoXY(1, 1);    SetColor(14);    printf("This is a test...\n");    Sleep(5000);    ShowTheCursor();    SetColorAndBackground(15, 12);    ConPrint("This is also a test...\n", 23);    SetColorAndBackground(1, 7);    ConPrintAt(22, 15, "This is also a test...\n", 23);    gotoXY(0, 24);    SetColorAndBackground(7, 1);    return 0; }  //This will clear the console while setting the forground and //background colors. void ClearConsoleToColors(int ForgC, int BackC) {    WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);    //Get the handle to the current output buffer...    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    //This is used to reset the carat/cursor to the top left.    COORD coord = {0, 0};    //A return value... indicating how many chars were written    //not used but we need to capture this since it will be    //written anyway (passing NULL causes an access violation).    DWORD count;     //This is a structure containing all of the console info    // it is used here to find the size of the console.    CONSOLE_SCREEN_BUFFER_INFO csbi;    //Here we will set the current color    SetConsoleTextAttribute(hStdOut, wColor);    if(GetConsoleScreenBufferInfo(hStdOut, &csbi))    {       //This fills the buffer with a given character (in this case 32=space).       FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);        FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       //This will set our cursor position for the next print statement.       SetConsoleCursorPosition(hStdOut, coord);    } }  //This will clear the console. void ClearConsole() {    //Get the handle to the current output buffer...    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    //This is used to reset the carat/cursor to the top left.    COORD coord = {0, 0};    //A return value... indicating how many chars were written    //   not used but we need to capture this since it will be    //   written anyway (passing NULL causes an access violation).    DWORD count;    //This is a structure containing all of the console info    // it is used here to find the size of the console.    CONSOLE_SCREEN_BUFFER_INFO csbi;    //Here we will set the current color    if(GetConsoleScreenBufferInfo(hStdOut, &csbi))    {       //This fills the buffer with a given character (in this case 32=space).       FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);       //This will set our cursor position for the next print statement.       SetConsoleCursorPosition(hStdOut, coord);    } }  //This will set the position of the cursor void gotoXY(int x, int y) {    //Initialize the coordinates    COORD coord = {x, y};    //Set the position    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); }  //This will set the forground color for printing in a console window. void SetColor(int ForgC) {    WORD wColor;    //We will need this handle to get the current background attribute    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    CONSOLE_SCREEN_BUFFER_INFO csbi;     //We use csbi for the wAttributes word.    if(GetConsoleScreenBufferInfo(hStdOut, &csbi))    {       //Mask out all but the background attribute, and add in the forgournd color       wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);       SetConsoleTextAttribute(hStdOut, wColor);    } }  //This will set the forground and background color for printing in a console window. void SetColorAndBackground(int ForgC, int BackC) {    WORD wColor = ((BackC & 0x0F) << 4) + (ForgC & 0x0F);;    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wColor); }  //Direct console output void ConPrint(char *CharBuffer, int len) {    DWORD count;    WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), CharBuffer, len, &count, NULL); }  //Direct Console output at a particular coordinate. void ConPrintAt(int x, int y, char *CharBuffer, int len) {    DWORD count;    COORD coord = {x, y};    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);    SetConsoleCursorPosition(hStdOut, coord);    WriteConsole(hStdOut, CharBuffer, len, &count, NULL); }  //Hides the console cursor void HideTheCursor() {    CONSOLE_CURSOR_INFO cciCursor;    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if(GetConsoleCursorInfo(hStdOut, &cciCursor))    {       cciCursor.bVisible = FALSE;       SetConsoleCursorInfo(hStdOut, &cciCursor);    } }  //Shows the console cursor void ShowTheCursor() {    CONSOLE_CURSOR_INFO cciCursor;    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if(GetConsoleCursorInfo(hStdOut, &cciCursor))    {       cciCursor.bVisible = TRUE;       SetConsoleCursorInfo(hStdOut, &cciCursor);    } }   #pragma comment(lib,"user32") #pragma comment(lib,"gdi32") #include <stdlib.h> #include <conio.h> #include <windows.h> HWND WINAPI GetConsoleWindow(); void HideTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = FALSE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } void ShowTheCursor() {     CONSOLE_CURSOR_INFO cciCursor;     HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);     if (GetConsoleCursorInfo(hStdOut, &cciCursor)) {         cciCursor.bVisible = TRUE;         SetConsoleCursorInfo(hStdOut, &cciCursor);     } } int main() {     HWND  hwnd;     HDC   hdc;     HFONT hfont;     HBITMAP hbm;     HDC hdcBits;     BITMAP bm;      system("color F0");     system("cls");     HideTheCursor();     hwnd  = GetConsoleWindow();     hdc   = GetDC(hwnd);     hbm=LoadImage(0,"C:\\Windows\\Soap Bubbles.bmp",IMAGE_BITMAP,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE);     if (hbm) {         hdcBits = CreateCompatibleDC(hdc);         GetObject (hbm, sizeof(BITMAP), &bm);         SelectObject(hdcBits,hbm);         BitBlt(hdc,200,10,bm.bmWidth, bm.bmHeight,hdcBits,0,0,SRCCOPY);         DeleteDC(hdcBits);         DeleteObject(hbm);     }     hfont = CreateFont(24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "华文楷体");     SelectObject(hdc,hfont);     SetTextColor(hdc,RGB(255,255,255));     SetBkMode(hdc,TRANSPARENT);     TextOut(hdc,210,30,"这个背景是泡泡",14);     DeleteObject(hfont);     ReleaseDC(hwnd,hdc);     getch();     system("color 07");     system("cls");     ShowTheCursor();     return 0; }

学习百度的实时交通信息表示


Question: c++ 关于try catch

工程里设置启用捕获SEH异常就啥都能抓到了

得先throw， cache才有效。 没抛出异常，还cache啥。 scanf本身没有抛出异常。

throw try  catch

引用 7 楼 mujiok2003 的回复:if (scanf("%d",&a[i]) == 1) { //ok }else{ //ng } 这输入是输入了 可是数组越界没办法判断 这个要怎么做

scanf也许会“出错”，但是它又不“触发异常”，这个不是一码事。

为什么 try catch捕捉不到错误

数据类型错误，  catch什么也不填就是捕获所有错误数据类型

接收所有类型的错误 catch (...) { }


Question: 哪个好心人能帮我详细解释下，这个R树的源代码。万分感激！

http://blog.csdn.net/n_sev7/article/details/19364757  以前写的R-Tree的总结

代码这么多这么乱没注释没说明怎么看？

谢谢，就是没有注释，看不懂啊，所以才求助的。求大神，求高手。


Question: [SWU]数组越界???

strlen所作的仅仅是一个计数器的工作，它从内存的某个位置（可以是字符串开头，中间某个位置，甚至是某个不确定的内存区域）开始扫描，直到碰到第一个字符串结束符'\0'为止，然后返回计数器值。

引用 楼主 u012789847 的回复:1 #include <stdio.h>   2 #include <stdlib.h>   3 #include <string.h>   4   5 void randchar(char str1[100])   6 {   7         int i, j;   8         srand((int)time(0));   9  10         for(i=0; i<100; i++){  11                 j       = 1+(int)(62.0*rand()/(RAND_MAX+1.0));  12                 if(j<=26&&j>=1){  13                         str1[i]='a'+j-1;  14                 }else if(j>26&&j<=52){  15                         str1[i]='A'+j-27;  16                 }else if(j>52&&j<=62){  17                         str1[i]='0'+j-53;  18                 }  19         }  20 }  21 void main()  22 {  23         char str[100];  24         randchar(str);  25         int i, num;  26         num     = strlen(str);  27         printf("%d\n", num);  28         for(i=0; i<100; i++){  29                 printf("%c", str[i]);  30         }  31         printf("\n");  32 }  33 为何输出的结果是 112 8DuuS4toM9MZyMjf5kv5NLOIcxyx41Z3vjodeHsQH4F6GPbB0xxD8cbazAyurnnMxCQC98jH2PDzuF1k2oO0qQ1QgpayDob0QRsQ 112？是怎么回事？？？  num = = 112

字符串都需要\0结尾. 比较好的习惯是; char str[100] = {0};  定义时即初始化为全0

函数用错了///

令str[99] = '\0'； strlen返回的是字符串的长度，不是字符数组的长度。


Question: c语言将txt文件数据存到一个数组(需要读取txt里面的数据完成算法)

求大神！！！急

求大神！！！急求大神！！！急

求大神！！！急


Question: 请问如何修改下列指令，让程序正常运行，使得用户能够禁用cpu缓存机制

0级权限就可以的 要绕过系统的安全检查

CPU缓存可以让用户操作的吗？


Question: c语言局部变量怎样分配存储空间

[b]引用 14 楼 Sforforforfor 的回复:非常感谢你的答案，解开了我的困惑。我可不可以这样理解：函数源代码被编译后，它的最开始会有移动栈指针的指令，效果就是在栈中分配空间，移动多少是编译器在编译期间计算好了，作为立即数存在于指令中。  就是这样子的，不过不一定是在开头，中间也可以 C语言可以在 {} 大括号内部的 语句组， --也有翻译成分程序的--内部定义变量； C++可以在随时，定义变量； 所以具体有几次移动栈指针，看编译器如何实现了； 和定义的变量大小，多少并无多少的关系。 编译器，只要保证使用变量的时候，有内存可用就行了。

不用在可执行文件中记录。  编译器一般，至少分两步编译代码。 一步编译生成目标代码，一步链接目标代码，生成 可执行文件。  编译的时候，编译器，有个表，专门记录每个函数自动变量的空间大小。 编译成代码的时候，只是把按照表中的大小数数而已。 需要增加减小内存，则安排指令移动堆栈指针（加减对应的寄存器）  编译器，按照需要为变量，安排偏移量，则在编译器的表里，找到，算出来， 写入目标代码中的指令中，是个立即数（对应于C，C++ 就相当于常数） 立即数是指令的一部分，是指令的操作数，所以，一般不需要表来储存。  编译器最后，把各个目标代码文件，链接成可执行文件 linux,unix 目标代码是xxx.o, 缺省可执行文件，编译后为 xxx.out dos,window 目标代码是xxx.obj,缺省可执行文件，编译后为xxx.exe

引用 12 楼 lm_whales 的回复:可执行文件，一般只有符号的重定位表； 还有一些操作系统，或者编译器，实现某些特别功能的专用表格、 这个符号，一般不包含函数内部的自动变量。 因为自动变量的位置，在每次函数调用过程中，是相对固定的，没有必要使用一个表格。  即便是静态变量，全局变量； 一般也只是有个初始值，需要表记录； 除非需要重定位，否则不需要额外，安排一个表，记录变量的位置。  C++函数内部的静态变量，因为需要保证，按照第一次调用的顺序初始化； 倒是可能，有个表记录一下。 非常感谢你的答案，解开了我的困惑。我可不可以这样理解：函数源代码被编译后，它的最开始会有移动栈指针的指令，效果就是在栈中分配空间，移动多少是编译器在编译期间计算好了，作为立即数存在于指令中。

这个应该是编译器管理的吧

引用 4 楼 lm_whales 的回复:[quote=引用 楼主 Sforforforfor 的回复:]        c语言的函数内的局部变量在栈中分配空间，而且是当它所在的函数被调用时才分配，这个过程是自动的还是由系统来管理的？在函数被调用的时候是根据什么来确定要分配多大的空间？  这是编译器安排好的代码，自动管理的。  分配回收，只是栈指针寄存器的加减操作。 变量在栈帧中的相对位置，基本上是固定的不变的；  只是函数调用时候，栈指针的初始化位置不同，所以变量地址不同。 每个自动变量的偏移量是固定的。   [/quote] 貌似明白一些了，不过还有个问题就是可执行文件中有个表专门记录每个函数自动变量的空间大小吗？否则栈指针怎么知道加减多少？

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

这是自动管理的吧~

看汇编结果。

稍微学一点汇编，就不会有这种疑问了

变量占用空间是固定的，每个变量一经定义； 在栈中占用的空间就固定了； 因为C同一类型的变量，占用相同的栈空间。

引用 楼主 Sforforforfor 的回复:c语言的函数内的局部变量在栈中分配空间，而且是当它所在的函数被调用时才分配，这个过程是自动的还是由系统来管理的？在函数被调用的时候是根据什么来确定要分配多大的空间？  这是编译器安排好的代码，自动管理的。  分配回收，只是栈指针寄存器的加减操作。 变量在栈帧中的相对位置，基本上是固定的不变的；  只是函数调用时候，栈指针的初始化位置不同，所以变量地址不同。 每个自动变量的偏移量是固定的。

分配的大小是由你定义时确定的，分配和回收的过程是由系统来处理的

自动分配，大小是由局部变量决定的

都是自动分配的啊，你分配多少个字节，是你定义决定的，退出函数自动释放。不知道你是不是要问这个，还是问函数执行的空间


Question: C语言急需要一种“子函数”

发明新东西之前请先了解、学习已有的东西。

引用 楼主 screen12 的回复:我们知道，Ｃ语言现在不存在“子函数”，各个函数尽管代码多少可能不同，但地位是平等的。  但是实际上，Ｃ语言急需要一种“子函数”，就是在一个函数内部定义，内部使用，在外部无效的函数。这种”子函数“可以继承父函数的局部变量。  因为在工作中，我经常在一个函数内部，有好几个地方需要用到同一段代码，如果复制过去，不仅代码量大，而且修改起来还得把所有地方一起修改，太麻烦。但是如果定义一个函数吧，也不好办。因为这段代码需要用到函数中的局部变量，如果把这些局部变量用参数传递过去，可以是可以，但是参数多的时候极为麻烦。  迫切需要一种”子函数“，在函数内部定义，仅限于内部使用，可以自动继续父函数的局部变量。  static inline

参数多，能把参数弄成一个结构体，然后传指针么？

楼主可以考虑一下全局静态变量和函数，它们的作用域仅限于本文件内。

闭包不是什么语言都有的。

虽然你描述的好像C++能解决，但是C++是无解的。C++也不能在函数内部再定义函数。你为什么不尝试使用宏？参数多的时候，你为什么不抽象成对象？

楼主的想法实现起来稍微有点麻烦，因为局部变量是用堆栈指针相对引用的，子函数内部的变量要用堆栈基址，子函数外部的局部变量要参考不同的堆栈基址，这样嵌套层级多的时候，实现有点麻烦， 这个问题的处理上PASCAL编译器实现有讲解，C通常用的入栈和出栈方法和PASCAL还不同。 理论上来说，应该也能实现，可能也会增加一些限制，编译器也会复杂不少。  函数参数传递的问题建议多用结构体，用结构指针传递， 你只需要一个变量即可。

换C++试试

宏定义 + 指针

GCC对标准C有所扩展，允许在函数中定义函数----在CSDN中找一下GCC扩展吧

就用参数传递啊，有什么麻烦？copy+paste, 看着有三四行参数就不爽？ 不行就定义类。

如果宏不能满足楼主所需，请结合google protobuf学习研究代码生成（code generation）技术。

为什么不用宏呢？

2楼正解。 要么换种语言。

楼主需要的只是一个 #define而已

内联函数从源代码层看，有函数的结构，而在编译后，却不具备函数的性质。内联函数不是在调用时发生控制转移，而是在编译时将函数体嵌入在每一个调用处。编译时，类似宏替换，使用函数体替换调用处的函数名。一般在代码中用inline修饰，但是能否形成内联函数，需要看编译器对该函数定义的具体处理。 http://baike.baidu.com/link?url=QhIPmgOarhWYlCBLztV3XQF55ABcD5j8CZiH9BO_3NH3wnAdj69m-saFPN2Qncf5

C++11，lambda表达式。C语言估计是不会有了

你说的应当是，内联函数。


Question: 一个程序编译改名字复制一份，为什么两个在gdb中输出一样实际运行结果不一样？输出一个变量的地址

9楼真正达人一枚啊！

linux从2.6.12开始支持Address space layout randomization ，ASLR 进程用户空间的栈起始于STACK_TOP， 每个体系结构都必须定义STACK_TOP, 大多数都设置为TASK_SIZE, 即用户地址空间中最高的可用地址，在x86_32上该值为0XC0000000。如果内核设置了PF_RANDOMIZE，则起始点会减少一个小的随机量，使得栈的起始地址成为一个随机值，这样的话使用缓冲区溢出进行攻击就更加困难。  所以在内核开启了ALSR的情况下，你的程序别说换个名字，就是同一个程序连续运行两遍，其结果也不一样。  而gdb在运行时，fork之后，exec之前，会使用personality(orig_personality|ADDR_NO_RANDOMIZE)系统调用来关闭进程的ASLR，所以在gdb里运行输出值是一样的。

这不一样很正常啊，打印的是变量在栈上的地址，不同的进程栈是不一样的啊。

就像在饭店，你点两份相同的菜，并不能保证在后厨是同一个厨师在同一个煤具上做的一样。 你的程序运行在存储器的哪个区域、数组具体分配的地址，是由操作系统+编译系统等动态完成的，输出的地址相同也好、不同也好你没有必要去深究----有限的精力用在真正有用的地方吧

研究Linux加载可执行文件相关源代码。

debug 和released版本是不一样的

输出的是a的地址，这得看运行的时候是怎么分配的。不一样很正常吧。

比如我gdb中看到输出都是-6916，而不是gdb运行test 和test01不一样。

引用 4 楼 zhao4zhong1 的回复:研究Linux加载可执行文件相关源代码。 好的，谢谢

引用 2 楼 u012061345 的回复:输出的是a的地址，这得看运行的时候是怎么分配的。不一样很正常吧。 不加g编译的时候输出的地址是虚拟地址吗？ 加g后的了？


Question: 有关自动售糖机的问题，包括了编译原理部分的有穷自动机 有编译错误，自己思路捋不出来错误

step by step debug.

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

编译没错，是内容写的不对。。自己顺自己思路看不出来

编译错误，一般都告诉你是哪行


Question: 几句难懂的C语句，求解释

地址减地址，没意义的，null；

谢谢

是的，地址减地址

是啊是啊 应该等于0吧 因为数组地址就是数组首元素的地址啊


Question: c/c++编程软件

最好一开始就用Visual Studio 2010以上的，以后进入企业了，适应性好些。

发过去了。。。。。

引用11楼 哈我也是菜鸟，刚学不久，他们推荐我使用DEV C/C++ 5。也不大，给个邮箱号我给你发过去。就10M大小。 2215232001@qq.com谢谢啦

引用7楼 我可以说QtCreator吗 VS对我的老爷机来说实在太沉重了 闻所未闻

c-free挺适合新手的，一些比较简单那的程序！推荐下

引用2楼 我觉得C-Free也可以吧！ 先下个，试试

我可以说QtCreator吗 VS对我的老爷机来说实在太沉重了

引用5楼 Visual Studio 2013 我只会C语言，但vs2013不能用scanf，printf,感觉好不舒服，是不是我太落后了

Visual Studio 2013

code::blocks简单好用

windows上首选VS系列，linux上可以有code::blocks, eclipse CDT

我觉得C-Free也可以吧！

DEV C++ 或者CodeBlock


Question: 任何一个自然数n的立方可以写成n个连续奇数的和

引用 2 楼 lm_whales 的回复:第一个奇数设为a 根据等差数列求和公式有 n^3 = a*n + n*(n-1) 于是 a = n^2 - n+1; 这个式子对正整数成立 会数学真可怕。

#include <stdio.h> #include <stdlib.h> #include <math.h>  int main(){ 	int n, sum, i,x; 	printf("Please enter n大于10.\n"); 	scanf("%d", &n); 	sum = (int)pow((float)n, (float)3);//总和  	x = (int)pow((float)n, (float)2) - n + 1;//第一项  	for(i = 0; i < n; i++){ 		printf("%d\t", x + i * 2); 	} 	printf("\n");  	system("pause"); }

连续奇数的和 有公式的


Question: 单链表问题,求高手讲解!

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

野指针~ 楼主的程序我拿来用用 ！

引用 6 楼 qq597955169 的回复:[quote=引用 2 楼 user-6 的回复:] q是一个指针而没有给它分配空间 所以你使用q->pNext，q此时是没有pNext成员的所以就会出现错误 请问我是否可以这样理解.   PNODE q;只是定义了,可以指向结构体的指针变量q,    q->pNext(并不存在),但是如果使用它的话,就会出现使用了非法的内存?[/quote] q->pNext是存在的，只是它指向的是一块不可用的内存

引用 2 楼 user-6 的回复:q是一个指针而没有给它分配空间 所以你使用q->pNext，q此时是没有pNext成员的所以就会出现错误 请问我是否可以这样理解.   PNODE q;只是定义了,可以指向结构体的指针变量q,    q->pNext(并不存在),但是如果使用它的话,就会出现使用了非法的内存?

关于野指针请查看博文：http://blog.csdn.net/ventry/article/details/765554

q是个野指针，它没有经过初始化，不知道它指向内存的何处。然后，你的代码中那个应该注释掉的语句却引用了这个结构体指针的一个成员，这是非法的。

结构体和一般类型变量不同，你只是声明了一个节点指针q，没有分配空间，所以无法使用next成员指针。

// q->pNext = NULL;     //为什么该行不注释掉,就出错?望高手解答下...    不注释 掉,就出错.


Question: C中函数的调用次数和处理时间

引用 11 楼 zhao4zhong1 的回复:7楼内容请不要无视。 而且大侠，我用的事VS，你说的是VC

引用 11 楼 zhao4zhong1 的回复:7楼内容请不要无视。 英语不好 可不可以来点简单的中文翻译？

7楼内容请不要无视。

引用 9 楼 ADF1230 的回复:推荐 Luke Stackwalker    其实自己写也成： 1，利用vs或者gcc编译，并生成pdb等符号文件； 2，解析符号文件，得到 tuple<function_name,begin_line,end_line>； 3，运行目标程序，每隔x ms中断该进程，采样程序计数器位置，采样点多一点； 4，分析所有函数的执行次数，这个就代表函数总共执行时间了。 好像好难啊，大侠，我是初学，有没有比较简单的方法？就比如VS中的profiler怎么用？

引用 5 楼 mujiok2003 的回复:[quote=引用 2 楼 u013220057 的回复:] 用VS编译的，可以用吗？ VS有自己的profiler.[/quote] 怎么用啊？怎么打开VS的profiler?能不能说的详细点？

VC6   Enable Profiling Home |  Overview |  Details  Feature Only in Professional and Enterprise Editions   Profiling is supported only in Visual C++ Professional and Enterprise Editions. For more information, see Visual C++ Editions.  Before using the profiler, you must build the current project with profiling enabled (equivalent to the command line setting LINK /PROFILE). If you want to perform function profiling only in the current project, you only need to enable profiling for the linker.  If you want to do line profiling, you also need to include debugging information.  To build your project for function profiling   On the Build menu, click Settings to display the Project Settings dialog box.   Click the Link tab.   In the Category drop-down list box, click General.   Select the Enable Profiling check box.   Click OK.   On the Build menu, click Build projectname.exe.  Note   Selecting the Enable Profiling check box turns off incremental linking. To re-enable incremental linking, clear the Enable Profiling option.  To build your project for line profiling   Perform the procedure to enable function profiling described earlier in this topic.   Select the Generate Debug Info check box.   Click the C/C++ tab.   In the Category drop-down list box, click General.   In the Debug Info drop-down list box, click Program Database or Line Numbers Only.   Click OK.   On the Build menu, click Build projectname.exe.  When the build is complete, the project is ready to be profiled.

可以在函数总定义一个static int count = 0；由于是静态变量，因此只会在第一次调用时初始化，而后在函数末尾对count++；即可实现计数。

引用 2 楼 u013220057 的回复:用VS编译的，可以用吗？ VS有自己的profiler.

函数调用次数很简单，设置一个全局变量Count = 0，在要计算次数的函数后面加一句 Count++; 最后输出Count就搞定了。 运行时间的话可以利用clock()函数（百度一下用法吧）。在要计算时间的函数前后分别clock一次，做差就得到函数调用消耗的时间了。

windows自带的GetTickCount

用VS编译的，可以用吗？

你在windows上用的什么编译器，如果用gcc，应该可以使用。


Question: 关于fread和fwrite读取有管理员权限的exe问题

引用 11 楼 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;  //... } 类似的例子还可以举很多。 果然是大神啊，太厉害了，这个方法管用！！！

引用 8 楼 xy505188 的回复:[quote=引用 5 楼 mujiok2003 的回复:] 引用CopyFile复制的文件可以正常打开的，代码只是凑合着用 会多拷贝一个字节，这是个bug while(!feof(in)) { char c3; fread(&c3,1,1,in); fwrite(&c3,1,1,o); }如果系统加的1个字节不知道的话，即使获取了文件的长度，整长度复制后，系统还是会在后面加1个字节；或者按文件长度-1复制，系统自己加上一个未知的字节，那文件复制多次后不是整个文件都变了？[/quote] 你看看你的文件大小就知道了。

引用 7 楼 xy505188 的回复:[quote=引用 5 楼 mujiok2003 的回复:] 引用CopyFile复制的文件可以正常打开的，代码只是凑合着用 会多拷贝一个字节，这是个bug while(!feof(in)) { char c3; fread(&c3,1,1,in); fwrite(&c3,1,1,o); }不懂，是读写完毕后，执行fclose前，系统会在后面加一个字节吗？[/quote] 读到最后一个字节后， feof（in)还是false,所以继续循环， 执行fread， fread失败， c3的值应该没有改变，此后就不该再执行fwrite了。

引用 5 楼 mujiok2003 的回复:引用CopyFile复制的文件可以正常打开的，代码只是凑合着用 会多拷贝一个字节，这是个bug while(!feof(in)) { char c3; fread(&c3,1,1,in); fwrite(&c3,1,1,o); }如果系统加的1个字节不知道的话，即使获取了文件的长度，整长度复制后，系统还是会在后面加1个字节；或者按文件长度-1复制，系统自己加上一个未知的字节，那文件复制多次后不是整个文件都变了？

引用 5 楼 mujiok2003 的回复:引用CopyFile复制的文件可以正常打开的，代码只是凑合着用 会多拷贝一个字节，这是个bug while(!feof(in)) { char c3; fread(&c3,1,1,in); fwrite(&c3,1,1,o); }不懂，是读写完毕后，执行fclose前，系统会在后面加一个字节吗？

引用 1 楼 zhao4zhong1 的回复:关闭杀毒软件。把杀软全关了，复制后的文件和原来的文件大小一模一样，但是一打开就出现：XXX is not a valid value，等错误，我把这个文件上传到网盘里了，是个教学视频，大神可以测试一下，我的电脑是WIN7 64位，复制后不行，但是若用CopyFile这个API，完全可以正常打开，不会报错。不知道怎么回事 链接如下：http://pan.baidu.com/s/1bny6UHx

引用 3 楼 buyong 的回复:in=fopen(c1,"rb"); 没判断返回值吧。 而且这样也太低效，你不会先吧输入文件长度求出，然后一起读取和复制呀  还不如调用系统命令copyCopyFile复制的文件可以正常打开的，代码只是凑合着用，没想到先去求文件长度，反正最后效果也一样，简单一点，出错了也好查

程序运行需要管理员权限，复制可以不用管理员权限吧？

关闭杀毒软件。