Question: 通讯录是不是每一个malloc都有对应的free，如果是的话，那下面的代码是不是有错 head=shifang(head);是什么意思，把所有有错的地方找出来

/*****************************************************************  *  EXAMPLE  1                                                   *  *  This simple program illustrates the basic debugging features *  *  of the C runtime libraries, and the kind of debug output     *  *  that these features generate.                                *  *****************************************************************/  #include <stdio.h> #include <string.h> #include <malloc.h> #include <crtdbg.h>  // This routine place comments at the head of a section of debug output void OutputHeading( const char * explanation ) {    _RPT1( _CRT_WARN, "\n\n%s:\n**************************************\ ************************************\n", explanation ); }  // The following macros set and clear, respectively, given bits // of the C runtime library debug flag, as specified by a bitmask. #ifdef   _DEBUG #define  SET_CRT_DEBUG_FIELD(a) \             _CrtSetDbgFlag((a) | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) #define  CLEAR_CRT_DEBUG_FIELD(a) \             _CrtSetDbgFlag(~(a) & _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)) #else #define  SET_CRT_DEBUG_FIELD(a)   ((void) 0) #define  CLEAR_CRT_DEBUG_FIELD(a) ((void) 0) #endif   void main( ) {    char *p1, *p2;    _CrtMemState s1, s2, s3;     // Send all reports to STDOUT    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );    _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );    _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );    _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );     // Allocate 2 memory blocks and store a string in each    p1 = malloc( 34 );    strcpy( p1, "This is the p1 string (34 bytes)." );     p2 = malloc( 34 );    strcpy( p2, "This is the p2 string (34 bytes)." );      OutputHeading(        "Use _ASSERTE to check that the two strings are identical" );    _ASSERTE( strcmp( p1, p2 ) == 0 );     OutputHeading(        "Use a _RPT macro to report the string contents as a warning" );    _RPT2( _CRT_WARN, "p1 points to '%s' and \np2 points to '%s'\n", p1, p2 );     OutputHeading(        "Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations" );    _CrtMemDumpAllObjectsSince( NULL );     free( p2 );     OutputHeading(        "Having freed p2, dump allocation information about p1 only" );    _CrtMemDumpAllObjectsSince( NULL );     // Store a memory checkpoint in the s1 memory-state structure    _CrtMemCheckpoint( &s1 );     // Allocate another block, pointed to by p2    p2 = malloc( 38 );    strcpy( p2, "This new p2 string occupies 38 bytes.");     // Store a 2nd memory checkpoint in s2    _CrtMemCheckpoint( &s2 );     OutputHeading(        "Dump the changes that occurred between two memory checkpoints" );    if ( _CrtMemDifference( &s3, &s1, &s2 ) )       _CrtMemDumpStatistics( &s3 );     // Free p2 again and store a new memory checkpoint in s2    free( p2 );    _CrtMemCheckpoint( &s2 );     OutputHeading(        "Now the memory state at the two checkpoints is the same" );    if ( _CrtMemDifference( &s3, &s1, &s2 ) )       _CrtMemDumpStatistics( &s3 );     strcpy( p1, "This new p1 string is over 34 bytes" );    OutputHeading( "Free p1 after overwriting the end of the allocation" );    free( p1 );     // Set the debug-heap flag so that freed blocks are kept on the    // linked list, to catch any inadvertent use of freed memory    SET_CRT_DEBUG_FIELD( _CRTDBG_DELAY_FREE_MEM_DF );     p1 = malloc( 10 );    free( p1 );    strcpy( p1, "Oops" );     OutputHeading( "Perform a memory check after corrupting freed memory" );    _CrtCheckMemory( );     // Use explicit calls to _malloc_dbg to save file name and line number    // information, and also to allocate Client type blocks for tracking    p1 = _malloc_dbg( 40, _NORMAL_BLOCK, __FILE__, __LINE__ );    p2 = _malloc_dbg( 40, _CLIENT_BLOCK, __FILE__, __LINE__ );    strcpy( p1, "p1 points to a Normal allocation block" );    strcpy( p2, "p2 points to a Client allocation block" );     // You must use _free_dbg to free a Client block    OutputHeading(        "Using free( ) to free a Client block causes an assertion failure" );    free( p1 );    free( p2 );     p1 = malloc( 10 );    OutputHeading( "Examine outstanding allocations (dump memory leaks)" );    _CrtDumpMemoryLeaks( );     // Set the debug-heap flag so that memory leaks are reported when    // the process terminates. Then, exit.    OutputHeading( "Program exits without freeing a memory block" );    SET_CRT_DEBUG_FIELD( _CRTDBG_LEAK_CHECK_DF ); }  Output  Use _ASSERTE to check that the two strings are identical: ************************************************************************** C:\DEV\EXAMPLE1.C(56) : Assertion failed: strcmp( p1, p2 ) == 0   Use a _RPT macro to report the string contents as a warning: ************************************************************************** p1 points to 'This is the p1 string (34 bytes).' and  p2 points to 'This is the p2 string (34 bytes).'   Use _CRTMemDumpAllObjectsSince to check the p1 and p2 allocations: ************************************************************************** Dumping objects -> {13} normal block at 0x00660B5C, 34 bytes long  Data: <This is the p2 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 32 20 73  {12} normal block at 0x00660B10, 34 bytes long  Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73  Object dump complete.   Having freed p2, dump allocation information about p1 only: ************************************************************************** Dumping objects -> {12} normal block at 0x00660B10, 34 bytes long  Data: <This is the p1 s> 54 68 69 73 20 69 73 20 74 68 65 20 70 31 20 73  Object dump complete.   Dump the changes that occurred between two memory checkpoints: ************************************************************************** 0 bytes in 0 Free Blocks. 38 bytes in 1 Normal Blocks. 0 bytes in 0 CRT Blocks. 0 bytes in 0 IgnoreClient Blocks. 0 bytes in 0 (null) Blocks. Largest number used: 4 bytes. Total allocations: 38 bytes.   Now the memory state at the two checkpoints is the same: **************************************************************************   Free p1 after overwriting the end of the allocation: ************************************************************************** memory check error at 0x00660B32 = 0x73, should be 0xFD. memory check error at 0x00660B33 = 0x00, should be 0xFD. DAMAGE: after Normal block (#12) at 0x00660B10.   Perform a memory check after corrupting freed memory: ************************************************************************** memory check error at 0x00660B10 = 0x4F, should be 0xDD. memory check error at 0x00660B11 = 0x6F, should be 0xDD. memory check error at 0x00660B12 = 0x70, should be 0xDD. memory check error at 0x00660B13 = 0x73, should be 0xDD. memory check error at 0x00660B14 = 0x00, should be 0xDD. DAMAGE: on top of Free block at 0x00660B10. DAMAGED located at 0x00660B10 is 10 bytes long.   Using free( ) to free a Client block causes an assertion failure: ************************************************************************** dbgheap.c(1039) : Assertion failed: pHead->nBlockUse == nBlockUse   Examine outstanding allocations (dump memory leaks): ************************************************************************** Detected memory leaks! Dumping objects -> {18} normal block at 0x00660BE4, 10 bytes long  Data: <          > CD CD CD CD CD CD CD CD CD CD  Object dump complete.   Program exits without freeing a memory block: ************************************************************************** Detected memory leaks! Dumping objects -> {18} normal block at 0x00660BE4, 10 bytes long  Data: <          > CD CD CD CD CD CD CD CD CD CD  Object dump complete.

可以留下qq号私聊

//文件写入函数   void save(struct address_list *head)   {       FILE *fp;       struct address_list *p1;       char tong[30];       if(head==NULL)       {           printf("通讯录为空,无法存储!\n");           return;       }       printf("请输入保存后的文件名:");       gets(tong);       fp=fopen("tong.txt","w");       if(fp==NULL)       {           printf("cannot open file\n");           return;       }       p1=head;       fprintf(fp,"姓名    职业      手机     Email     通讯地址\n");       for(;p1!=NULL;)        {           fprintf(fp,"%s       %s       %s        %s       %s\n",p1->name,p1->work,p1->handset,p1->email,p1->address);           p1=p1->next;       }       printf("保存完毕!\n");       fclose(fp);   }      //文件读出函数   struct address_list *load(struct address_list *head)   {       FILE *fp;       char tong[30];       struct address_list *p1,*p2;       printf("请输入要输出的文件名:");       gets(tong);       fp=fopen("tong.txt","r");       if(fp==NULL)       {           printf("此通讯录名不存在,无法输出!\n");           return(head);       }       else       {           head=shifang(head);       }       p1=(struct address_list *)malloc(LEN);       fscanf(fp,"%s%s%s%s%s",&p1->name,&p1->work,&p1->handset,&p1->email,&p1->address);       if(feof(fp)!=0)       {           printf("文件为空,无法打开!\n");           return(head);       }       else       {           rewind(fp);           p2=p1;           head=p1;         //  n=0;           while(feof(fp)==0)           {               fscanf(fp,"%s%s%s%s%s",&p1->name,&p1->work,&p1->handset,&p1->email,&p1->address);               if(feof(fp)!=0)                   break;               p2->next=p1;               p2=p1;               p1=(struct address_list *)malloc(LEN);            //   n=n+1;           }           p2->next=NULL;           p1=head;           head=head->next;          // n=n-1;           free(p1);           print(head);           printf("打开完毕!\n");           return(head);       }       fclose(fp);   }      //综合操作函数   struct address_list *menu(struct address_list *head)   {       char num[10];       while(1)       {           printf("*********************\n");           printf("*** 1 姓名查找      ****\n");           printf("*** 2 增加          ****\n");           printf("*** 3 退出          ****\n");           printf("*********************\n");           printf("请输入您选择的操作:");           gets(num);           switch(*num)           {           case '1':               {                   head=search(head);                          //姓名查找                   print(head);               }               break;                 case '2':               {                   head=insert(head);                           //增加                   print(head);               }               break;           case '3':               return head;                  default:               printf("操作错误，此项不存在!\n");               break;           }                 // if(strcmp(num,"6")==0)             //  break;       }       return head;   }   //主函数   void main()   {       struct address_list *head=NULL;       char num[10];       printf("*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n");       printf("*=*               程序说明                *=*\n");       printf("*=*    请及时保存创建完毕的通讯录内容!    *=*\n");       printf("*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*\n");       while(1)       {           printf("************************\n");           printf("***     1 创建通讯录      ****\n");           printf("***     2 按名字排序      ****\n");           printf("***     3 综合操作        ****\n");           printf("***     4 保存            ****\n");           printf("***     5 打开            ****\n");            printf("***     6 删除            ****\n");           printf("***     7 退出            ****\n");           printf("************************\n");           printf("请输入您选择的操作:");           gets(num);           switch(*num)           {           case '1':               {                   if(head==NULL)                   {                       head=creat();                                //创建                       print(head);                   }                   else                   {                       head=shifang(head);                       head=creat();                                //重新创建                       print(head);                                        }               }               break;           case '2':               {                   head=paixu(head);                               //排序               }               break;           case '3':               {                   head=menu(head);                              //综合操作               }               break;           case '4':               {                   save(head);                                   //文件保存                   print(head);               }               break;           case '5':               {                   head=load(head);                              //文件输出               }               break;           case '6':               {                   head=delete_txl(head);                           //删除                   print(head);               }               break;           case '7':               head=shifang(head);               break;           default:               printf("操作错误，此项不存在!\n");               break;           }           if(strcmp(num,"7")==0)               break;       }   }

//输出函数   void print(struct address_list *head)      {       struct address_list *p;       if(head!=NULL)       {           p=head;           printf("本通讯录现在共有%d人:\n",n);           printf("---姓名-------职业--------手机-------Email-------通讯地址\n");           printf("==================================\n");           do           {               printf("== %s",p->name); printf("       ");               printf("%s",p->work); printf("       ");               printf("%s",p->handset); printf("       ");               printf("%s",p->email); printf("       ");               printf("%s",p->address); printf("       \n");               p=p->next;           }while(p!=NULL);           printf("==================================\n");       }       else           printf("通讯录为空,无法输出!\n");   }   //增加函数   struct address_list *insert(struct address_list *head)    {       struct address_list *p0,*p1,*p2;       char name[20];       p1=head;       printf("请输入增加的内容:\n");       printf("请输入姓名:");      gets(name);       if(strcmp(name,"0")==0)       {           printf("姓名不能为0,增加失败!\n");           return(head);       }       else       {           p0=(struct address_list *)malloc(LEN);           strcpy(p0->name,name);           printf("请输入职业:"); gets(p0->work);           printf("请输入手机:"); gets(p0->handset);           printf("请输入电子邮件:"); gets(p0->email);           printf("请输入通讯地址:");  gets(p0->address);           n=n+1;           if(head==NULL)           {               head=p0;               p0->next=NULL;               return head;           }           else           {               while(strcmp(p0->name,p1->name)>0&&(p1->next!=NULL))               {                   p2=p1;                   p1=p1->next;               }               if(strcmp(p0->name,p1->name)<0 || strcmp(p0->name,p1->name)==0)               {                   if(head==p1)                   {                       head=p0;  //第一次输入po                 }                   else                   {                       p2->next=p0; //不是第一次输入po                  }                   p0->next=p1;  //p1zhixiang head ,jiushi p2-p0-p1             }               else               {                   p1->next=p0;                   p0->next=NULL;               }               return head;           }       }   }   struct address_list *delete_txl(struct address_list *head)   {       struct address_list *p,*q;       char name[30];          if(head==NULL)       {           printf("通讯录为空,无法显示!\n");           return head;       }       p=head;       printf("请输入需要删除的人的姓名:");       gets(name);       if(strcmp(head->name,name)==0)       {           head=head->next;           free(p);           printf("删除操作成功！\n");          n--;          return head;       }       else       {           q=head,p=head->next;           while(p!=NULL)           {               if(strcmp(p->name,name)==0)               {                   q->next=p->next;                   free(p);                   printf("删除操作成功！\n");                   n--;                  return head;                                }               p=p->next;               q=q->next;           }             return head;       }   } //排序函数   struct address_list *paixu(struct address_list *head)   {       struct address_list *p1,*p2;       int i,j;       struct address_list1       {           char name[30];           char work[30];           char handset[30];           char email[30];           char address[30];       };       struct address_list1 px[200];       struct address_list1 temp;       if(head==NULL)       {           printf("通讯录为空,无法排序!\n");           return(head);       }       p1=head;       for(i=0;i<n,p1!=NULL;i++)       {           strcpy(px[i].name,p1->name);           strcpy(px[i].work,p1->work);           strcpy(px[i].handset,p1->handset);           strcpy(px[i].email,p1->email);           strcpy(px[i].address,p1->address);           p2=p1;           p1=p1->next;       }       head=shifang(head);       for(j=0;j<n-1;j++)       {           for(i=j+1;i<n;i++)           {               if(strcmp(px[i].name,px[j].name)<0)               {                   temp=px[i];                   px[i]=px[j];                   px[j]=temp;  //j=0，循环第一次后，，pj变成最小的             }           }       }       p1=(struct address_list *)malloc(LEN);       p2=p1;       strcpy(p1->name,px[0].name);      strcpy(p1->work,px[0].work);       strcpy(p1->handset,px[0].handset);       strcpy(p1->email,px[0].email);       strcpy(p1->address,px[0].address);          head=p1;       for(i=1;i<n;i++)       {           p1=(struct address_list *)malloc(LEN);           strcpy(p1->name,px[i].name);           strcpy(p1->work,px[i].work);           strcpy(p1->handset,px[i].handset);           strcpy(p1->email,px[i].email);           strcpy(p1->address,px[i].address);           p2->next=p1;           p2=p1;       }       p2->next=NULL;       printf("按姓名排序后为:\n");       print(head);       return(head);   }   //姓名查找函数   struct address_list *search(struct address_list *head)   {       struct address_list *p1,*p2;       int m;       char name[30];       if(head==NULL)       {           printf("通讯录为空,无法分类查找!\n");           return(head);       }       p1=head;       printf("********************\n");       printf("**  请输入需要查找的姓名  **\n");       printf("********************\n");       m=0;       gets(name);       while(p1!=NULL)       {           while(strcmp(p1->name,name)!=0&&p1->next!=NULL)           {               p2=p1;               p1=p1->next;           }           if(strcmp(p1->name,name)==0)           {               m++;               printf("你查找的内容是:\n");               printf("+++++++++++++++++++++++++++++++++++\n");               printf("++ %s        %s       %s       %s        %s\n",p1->name,p1->work,p1->handset,p1->email,p1->address);               printf("+++++++++++++++++++++++++++++++++++\n");           }           p1=p1->next;              if(m==0)           {               printf("此人未在本通讯录中!\n");           }           break;       }          return(head);   }      //释放内存函数   struct address_list *shifang(struct address_list *head)   {       struct address_list *p1;       while(head!=NULL)       {           p1=head;           head=head->next;           free(p1);       }       return(head);   }

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


Question: C语言实现：集成音乐到EXE里边问题？

引用 18 楼 my_xxh 的回复:[quote=引用 4 楼 Saleayas 的回复:] MAKEINTRESOURCE 谢谢大家积极的分享知识！问题解决了；代码修改为： #include"resource.h" #pragma  comment(lib,"winmm.lib") void MyplayMusic(void) { PlaySoundA(MAKEINTRESOURCE(WaveID),GetModuleHandle(NULL), SND_ASYNC|SND_RESOURCE);  } 自己第一次用VC6.0写这样的程序，犯了个错误，忘了把.rc文件导入到工程中，导致编译通过，能运行，就是播放不了音乐； 再次感谢大家了哈！[/quote] 恭喜解决问题。 我也学到了东西。

MAKEINTRESOURCE

使用临时文件不会死人的。 GetTempFileName The GetTempFileName function creates a name for a temporary file. The filename is the concatenation of specified path and prefix strings, a hexadecimal string formed from a specified integer, and the .TMP extension.  The specified integer can be nonzero, in which case, the function creates the filename but does not create the file. If you specify zero for the integer, the function creates a unique filename and creates the file in the specified directory.  UINT GetTempFileName(   LPCTSTR lpPathName,  // pointer to directory name for temporary                         // file   LPCTSTR lpPrefixString,  // pointer to filename prefix   UINT uUnique,        // number used to create temporary filename   LPTSTR lpTempFileName                         // pointer to buffer that receives the new                         // filename );   Parameters lpPathName  Pointer to a null-terminated string that specifies the directory path for the filename. This string must consist of characters in the ANSI character set. Applications typically specify a period (.) or the result of the GetTempPath function for this parameter. If this parameter is NULL, the function fails.  lpPrefixString  Pointer to a null-terminated prefix string. The function uses the first three characters of this string as the prefix of the filename. This string must consist of characters in the ANSI character set.  uUnique  Specifies an unsigned integer that the function converts to a hexadecimal string for use in creating the temporary filename.  If uUnique is nonzero, the function appends the hexadecimal string to lpPrefixString to form the temporary filename. In this case, the function does not create the specified file, and does not test whether the filename is unique.   If uUnique is zero, the function uses a hexadecimal string derived from the current system time. In this case, the function uses different values until it finds a unique filename, and then it creates the file in the lpPathName directory.   lpTempFileName  Pointer to the buffer that receives the temporary filename. This null-terminated string consists of characters in the ANSI character set. This buffer should be at least the length, in bytes, specified by MAX_PATH to accommodate the path.  Return Values If the function succeeds, the return value specifies the unique numeric value used in the temporary filename. If the uUnique parameter is nonzero, the return value specifies that same number.   If the function fails, the return value is zero. To get extended error information, call GetLastError.   Remarks The GetTempFileName function creates a temporary filename of the following form:  path\preuuuu.TMP  The following table describes the filename syntax:   Component Meaning  path Path specified by the lpPathName parameter  pre First three letters of the lpPrefixString string  uuuu Hexadecimal value of uUnique    When the system shuts down, temporary files whose names have been created by this function are not automatically deleted.   To avoid problems resulting when converting an ANSI string, an application should call the CreateFile function to create a temporary file.   If the uUnique parameter is zero, GetTempFileName attempts to form a unique number based on the current system time. If a file with the resulting filename exists, the number is increased by one and the test for existence is repeated. Testing continues until a unique filename is found. GetTempFileName then creates a file by that name and closes it. When uUnique is nonzero, no attempt is made to create and open the file.   QuickInfo   Windows NT: Requires version 3.1 or later.   Windows: Requires Windows 95 or later.   Windows CE: Unsupported.   Header: Declared in winbase.h.   Import Library: Use kernel32.lib.   Unicode: Implemented as Unicode and ANSI versions on Windows NT.  See Also File I/O Overview, File Functions, CreateFile, GetTempPath

引用 楼主 my_xxh 的回复:程序思路描述：把turn.wav音乐文件插入到VC6.0某个工程的资源文件中，获取音乐文件的ID号：IDR_WAVE1；利用      PlaySoundA播放这个音乐文件；          程序的目的：把音乐文件集成到exe文件中来。不用把turn.wav音乐文件放到指定目录下，那样很麻烦！程序怎么改能做到？  主要代码如下： ps:GetModuleHandle(NULL) 是为了获取资源所在模块的句柄；  #include"resource.h" #pragma  comment(lib,"winmm.lib") void MyplayMusic(void) { 	PlaySoundA(IDR_WAVE1,GetModuleHandle(NULL),SND_ASYNC|SND_RESOURCE); }  vc++6.0编译报错： error C2664: 'PlaySoundA' : cannot convert parameter 1 from 'const int' to 'const char *' 但是，vc2008里却能编译通过呢？   求解惑！谢谢大家！ playsound的参数要求是文件名（路径），你提供一个ID肯定是不行。可以把这个ID的资源存储成文件。然后再播放。

引用 4 楼 Saleayas 的回复:MAKEINTRESOURCE 谢谢大家积极的分享知识！问题解决了；代码修改为： #include"resource.h" #pragma  comment(lib,"winmm.lib") void MyplayMusic(void) { PlaySoundA(MAKEINTRESOURCE(WaveID),GetModuleHandle(NULL), SND_ASYNC|SND_RESOURCE);  } 自己第一次用VC6.0写这样的程序，犯了个错误，忘了把.rc文件导入到工程中，导致编译通过，能运行，就是播放不了音乐； 再次感谢大家了哈！

http://msdn.microsoft.com/en-us/library/windows/desktop/dd743680(v=vs.85).aspx 13楼的用法是对的，我就是觉得我的第二个参数是不是出错了？我是这样用的 PlaySound(MAKEINTRESOURCE(IDR_WAVE1),GetModuleHandle(NULL), SND_ASYNC|SND_RESOURCE);

引用 14 楼 my_xxh 的回复:[quote=引用 11 楼 zjq9931 的回复:] [quote=引用 10 楼 my_xxh 的回复:] [quote=引用 5 楼 u013491662 的回复:] 我以前是这么用的  PlaySound((LPCWSTR)IDR_WAVE1,NULL,SND_ASYNC|SND_RESOURCE);  PlaySound函数的第二个参数为NULL，不需要获取包含资源的模块句柄嘛？我试了哈PlaySound((LPCWSTR)IDR_WAVE1,NULL,SND_ASYNC|SND_RESOURCE); 也是能通过编译，运行的起来，就是不能正常播放声音！MSDN上的描述如下图：可我这样写的：PlaySound(MAKEINTRESOURCE(IDR_WAVE1),GetModuleHandle(NULL), SND_ASYNC|SND_RESOURCE);   能运行，就是不能正常执行播放音乐，返回true; 错在？ [/quote] 用这个：MAKEINTRESOURCE(IDR_WAVE1) 和用这个，“IDR_WAVE1”没有本质的区别。是一样的。 肯定是不行的，要文件名，你个我个字符串，又不是文件名，有什么用呢？[/quote] 类型转换的作用；查的MSDN ； PlaySound函数,有这个用法！[/quote] 用我在13楼发的那个用法。那个是正宗的msdn上的用法。把你找的那个用法的原文贴过来一下，看看。

引用 11 楼 zjq9931 的回复:[quote=引用 10 楼 my_xxh 的回复:] [quote=引用 5 楼 u013491662 的回复:] 我以前是这么用的  PlaySound((LPCWSTR)IDR_WAVE1,NULL,SND_ASYNC|SND_RESOURCE);  PlaySound函数的第二个参数为NULL，不需要获取包含资源的模块句柄嘛？我试了哈PlaySound((LPCWSTR)IDR_WAVE1,NULL,SND_ASYNC|SND_RESOURCE); 也是能通过编译，运行的起来，就是不能正常播放声音！MSDN上的描述如下图：可我这样写的：PlaySound(MAKEINTRESOURCE(IDR_WAVE1),GetModuleHandle(NULL), SND_ASYNC|SND_RESOURCE);   能运行，就是不能正常执行播放音乐，返回true; 错在？ [/quote] 用这个：MAKEINTRESOURCE(IDR_WAVE1) 和用这个，“IDR_WAVE1”没有本质的区别。是一样的。 肯定是不行的，要文件名，你个我个字符串，又不是文件名，有什么用呢？[/quote] 类型转换的作用；查的MSDN ； PlaySound函数,有这个用法！

第二个参数： hmod  Handle of the executable file that contains the resource to be loaded. This parameter must be NULL unless SND_RESOURCE is specified in fdwSound.   第三个参数： SND_RESOURCE 这样就可以了。

第三个参数，或上这个SND_RESOURCE，似乎是就可以播放资源里面的但是，还不知道具体怎么用。

引用 10 楼 my_xxh 的回复:[quote=引用 5 楼 u013491662 的回复:] 我以前是这么用的  PlaySound((LPCWSTR)IDR_WAVE1,NULL,SND_ASYNC|SND_RESOURCE);  PlaySound函数的第二个参数为NULL，不需要获取包含资源的模块句柄嘛？我试了哈PlaySound((LPCWSTR)IDR_WAVE1,NULL,SND_ASYNC|SND_RESOURCE); 也是能通过编译，运行的起来，就是不能正常播放声音！MSDN上的描述如下图：可我这样写的：PlaySound(MAKEINTRESOURCE(IDR_WAVE1),GetModuleHandle(NULL), SND_ASYNC|SND_RESOURCE);   能运行，就是不能正常执行播放音乐，返回true; 错在？ [/quote] 用这个：MAKEINTRESOURCE(IDR_WAVE1) 和用这个，“IDR_WAVE1”没有本质的区别。是一样的。 肯定是不行的，要文件名，你个我个字符串，又不是文件名，有什么用呢？

引用 5 楼 u013491662 的回复:我以前是这么用的  PlaySound((LPCWSTR)IDR_WAVE1,NULL,SND_ASYNC|SND_RESOURCE);  PlaySound函数的第二个参数为NULL，不需要获取包含资源的模块句柄嘛？我试了哈PlaySound((LPCWSTR)IDR_WAVE1,NULL,SND_ASYNC|SND_RESOURCE); 也是能通过编译，运行的起来，就是不能正常播放声音！MSDN上的描述如下图：可我这样写的：PlaySound(MAKEINTRESOURCE(IDR_WAVE1),GetModuleHandle(NULL), SND_ASYNC|SND_RESOURCE);   能运行，就是不能正常执行播放音乐，返回true; 错在？

引用 5 楼 u013491662 的回复:我以前是这么用的  PlaySound((LPCWSTR)IDR_WAVE1,NULL,SND_ASYNC|SND_RESOURCE);  这样可以？

引用 6 楼 my_xxh 的回复:[quote=引用 4 楼 Saleayas 的回复:] MAKEINTRESOURCE PlaySound(MAKEINTRESOURCE(IDR_WAVE1),GetModuleHandle(NULL), SND_ASYNC|SND_RESOURCE); 编译能通过，程序也能运行起来，就是这个wav格式的音乐文件不能正常播放，测试了哈，PlaySound的返回值为0，莫能正常执行，问题出在什么地方？没有获得包含资源的模块句柄吗？新手学习。谢谢了！[/quote] 这个MAKEINTRESOURCE，只是返回资源的名称。而playsound要求的是文件名。。。肯定是不行的。

直接双击wav文件能否播放。

引用 4 楼 Saleayas 的回复:MAKEINTRESOURCE PlaySound(MAKEINTRESOURCE(IDR_WAVE1),GetModuleHandle(NULL), SND_ASYNC|SND_RESOURCE); 编译能通过，程序也能运行起来，就是这个wav格式的音乐文件不能正常播放，测试了哈，PlaySound的返回值为0，莫能正常执行，问题出在什么地方？没有获得包含资源的模块句柄吗？新手学习。谢谢了！


Question: C语言新手问题

2楼正解，传递给函数的是数组元素，不是数组的地址，如果传递&iShuZu[i],那么这样就是把数组的每个元素的地址传递给函数，函数的参数类型应该声明为指向int的指针类型(int * p)，并且printf时要使用各式说明符(%p)，而不是%d指针指向的是一个存储某些数值的地址，对指针取值(*)，即是取出存储在指针指向的地址中存储的值，重在理解

自己把代码打一遍就知道那个是正确的了

计算机组成原理→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=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495

引用 楼主 Cristiano001 的回复: 我的问题是: 书上说：当数组作为函数实参时候，只传递数组的地址，而不是将整个数组赋值到函数中； 那main函数中Aaa（iShuzu[i]）中的iShuzu[i]传递到被调用函数的时候应该就是iShuzu[i] 的地址啊 既然是地址那最后printf输出的也应该是数组的地址啊。 为什么在被调用程序中输出的却是每个数组元素的值，而不是数组元素的地址呢？求解  我在数组和指针上要蒙圈了 因为形参的类型，限定了实参的类型，你传入的是数组中的一个元素，所以，和形参的类型一样，所以正常啊。

iShuzu[i]是数组吗？iShuzu[i]是一个数组元素，不是数组。  你没有搞清楚数组和它们元素的关系

数组（准确点讲应该叫“数组名”）和数组元素是两个不同的概念。数组名是一个地址(即指针)，它指向数组中的第一个元素的地址；而数组元素本质上就是一个个变量。  就拿楼主的例子来说，数组(名)是iShuzu(不带有中括号)，而数组元素则是iShuzu[i]。楼主可以试着打印*iShuzu，它的结果应该是第一个数组元素0.

iShuze作为参数时才会作为指针，加上下标运算符[]后的iShuze[i]返回的是一个右值

iShuzu[i] 代表的是值，你Aaa传入的是一个int值，而不是数组呀。 比如i=0，iShuzu[i]=0，你传入的是0这个值。  你的Aaa函数需要的只是一个int型实参，而不是一个数组啊

牛B的勇士你在哪


Question: 数组{1,3,5,7}为什么输出的是扑克牌符号

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

引用 4 楼 maple_LE 的回复:orz，这个程序写的好绕啊= = 首先这段代码  for (i=0;i<5;i++) num[i]=&a[i];  这让int指针数组的每个指针分别指向了数组的每个元素，也就是说现在*num[i]==a[i] 而接下来的  for (i=0;i<5;i++) { p=num+i; printf("%s",*p); }  这里的第一行代码相当于p=&num[i]也就是说p指向了num数组中的指针，现在它是一个指向指针的指针，但下面的printf语句非常的有问题 *p只对指针p解除了一级引用，现在的它相当于num[i]==&a[i]，也就是说它相当于和a数组中i号元素地址 接下来是格式说明符%s，这是输出字符串，也就是说printf函数将会不断输出以i号元素为起点，下一个空字符为终点的区间内的所有字符 所以接下来输出的结果就看你这个编译器的编码类型和空字符在内存中的位置了= = 以上属于个人的理解，如果有错误的话请提出来，谢谢= =  感谢详细的讲解！书上没怎么说，分别给了2个写法，我在win8上用的vc++6.0，只能用%d对应**p。回复晚了不好意思

引用 1 楼 T5500 的回复:printf("%s",*p); //这里的格式控制符应该是%d吧，是不是抄错了？  没抄错，p是指向指针的指针。  printf("%d",**p);这个就没错，不知道为什么

p存储的是指针数组的元素的地址，指针数组的每个元素都是一个指向int数组的单个元素的地址，即指针数组的单个元素对应int数组的单个元素的地址;对p取值(*)取出的是指针数组中的指向int数组单个元素的地址，即(*p)是一个指针数组元素，这个元素指向int数组元素，再次对*p取值，得到的才是int数组的元素的值

引用 1 楼 T5500 的回复:printf("%s",*p); //这里的格式控制符应该是%d吧，是不是抄错了？+1

嗯，是输出格式的问题，你是想%d还是%p啊，如果是%s就会出现这种情况


Question: 代码提示segment fault

int arr[] = {};  一没有size,二是如果arr[]里如果不指定大小 ，那么一定要在中括号里赋值

引用 1 楼 u012421456 的回复:数组没有初始化，里边是些什么东西就不知道了， 你初始化数组后试试+1

引用 16 楼 chireice 的回复:[quote=引用 10 楼 amoyman 的回复:] int arr[]={} 改成 int arr[15]={0}; 在 i < 15 就不会越界了。 我是想试试在不确定数组长度的情况下该如何处理，C是不支持动态分配内存的是吧[/quote] malloc+free

其实电脑开机后物理内存的每个字节都是可读写的，从来不会因为所谓的new、delete或malloc、free而被创建、销毁。区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

变量定义未开辟空间，只开辟了一个内存地址，这个地址的空间到底多大只有电脑知道。

引用 15 楼 chireice 的回复:我不明白的是，为何既然是越界了，却还可以往数组中写入？ 你的代码可以写入任何地址，没人帮你检查越界，完全靠程序员自己检查。 就像很大一片空地，没有围墙和栅栏，你想去哪就去哪，但是很多地方都有钉子甚至地雷，踩上了后果自负。

引用 10 楼 amoyman 的回复:int arr[]={} 改成 int arr[15]={0}; 在 i < 15 就不会越界了。 我是想试试在不确定数组长度的情况下该如何处理，C是不支持动态分配内存的是吧

引用 4 楼 zysnet 的回复:数组没有定义长度，那么在编译的时候在栈中不会给它分配空间，那么在使用这个数组时，当然后访问访问越界了。  这种用法不对，定义数组必须要使用编译器知道数组的大小，这样才能组它分配空间，这是C语言的规矩（动态分配内存和这个机制不一样），所以应该有以下几做定义：  int arr[] = {1, 2, 3, 4};     //这样编译器是知道数组的大小的  int arr[4];                        //这样编译器也是知道数组的大小的，虽然没有初始化 我不明白的是，为何既然是越界了，却还可以往数组中写入？而且长短没有限制，一定是到最后一个循环结束后才会提示错误

引用 8 楼 brookmill 的回复:我用的是cygwin，gcc 4.8.2 楼主用的什么系统和编译器？  系统：Linux version 2.6.32-431.el6.x86_64 编译器：gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)

楼上所言极是！

内存就是公厕，你不预定，清洁工是不会清洁前任拉过的屎的

int arr[] = {};　请问你到底想要开个多大的数组？编译器直接默认开0个数据大小的内存；会给出： error C2466: 不能分配常量大小为 0 的数组（VS2010）。 如果不确定的话，试试用vector吧。

int arr[] = {};　　这样没有意义

我用的是cygwin，gcc 4.8.2 楼主用的什么系统和编译器？

从楼主的描述来看，Segmentation fault很可能是main函数返回的时候发生的。函数的返回地址是保存在栈上的，如果局部变量越界覆盖(改动)了返回地址，覆盖的时候不会出事，return的时候就会返回到一个错误的地址，就挂掉了。 但是楼主的代码虽然读取了越界的内容，但是没有做任何修改，所以栈没被破坏，按理也就不应该挂。我运行楼主的代码就没事，但是做了以下改动之后就会出现和楼主类似的现象。     for( i = 0; i < 15; i ++) {         printf( "%d -> %d \n", i, arr[i] );         arr[i] = i;  // 加上这一行     }     printf("12345\n");  // 加上这一行     sleep(2);  // 加上这一行     return 0;

进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令

下标越界


Question: 操作系统的进程堵塞概念

引用 楼主 u012879806 的回复:问题1：   现代操作系统 这本书上提到进程堵塞概念：  即使cpu不空闲，也不会执行进程，  这就是堵塞。  好了， 我们结合具体的一款操作系统windows， 请问 sleep函数， 会让进程堵塞吗？   如果不会，为什么？   windows也是一操作系统，所以它的堵塞概念，也得和 操作系统书本保持一致。   sleep这个时间段内，进程没法运行， 所以也叫堵塞。  线程没法运行，也叫堵塞。  同理waitforsingleobject等函数，也是如此。  以上是我对进程，线程堵塞理解。    问题2： windows 有很多堵塞函数，比如网络库函数recv等，也会让线程堵塞。  可是有的函数堵塞会消耗cpu，有的则不会。 什么原因导致这么大的差异？   还有既然堵塞了进程。 进程就没有cpu，没有cpu，何来 消耗cpu一说呢？ sleep的作用就是让直行线程加入等待队列,合适的时候唤醒,以下情况使用sleep就醒不来了, 硬中断上下文, 某些情况软中断上下文.

所有真正的阻塞都不会占用CPU， 如果非说占用一点的话就是进程切换或者进入内核的开销， 这个可能会有点差异吧    有些人写程序用无意义的循环做阻塞，这是个人问题而且那不符合阻塞的定义， 进程是照常跑的， 只是这部分执行的代码无意义而已

引用 13 楼 u012879787 的回复:[quote=引用 12 楼 zhao4zhong1 的回复:] C:\windows_2000_source_code\win2k\private\net\sockets\winsock2\dll\winsock2\recv.cpp      43: int WSAAPI      44: recv(      45:      IN SOCKET s,      46:      OUT char FAR * buf,      47:      IN int len,      48:      IN int flags      49:      )      50: /*++      51: Routine Description:      52:       53:     Receive data from a socket.      54:       55: Arguments:      56:       57:     s     - A descriptor identifying a connected socket.      58:       59:     buf   - A buffer for the incoming data.      60:       61:     len   - The length of buf.      62:       63:     flags - Specifies the way in which the call is made.      64:       65: Returns:      66:       67:     The  number  of  bytes  received.   If  the  connection has been gracefully      68:     closed,  the  return  value  is  0.   Otherwise, a value of SOCKET_ERROR is      69:     returned, and a specific error code is stored with SetErrorCode().      70:       71: --*/      72:       73: {      74:     INT             ErrorCode;      75:     PDSOCKET        Socket;      76:     LPWSATHREADID   ThreadId;      77:       78:       79:     ErrorCode = TURBO_PROLOG_OVLP(&ThreadId);      80:     if (ErrorCode==ERROR_SUCCESS)      81:     {      82:         Socket = DSOCKET::GetCountedDSocketFromSocket(s);      83:         if(Socket != NULL){      84:             INT             ReturnValue;      85:             PDPROVIDER      Provider;      86:             DWORD           BytesReceived;      87:             WSABUF          Buffers;      88:       89:             Buffers.len = len;      90:             Buffers.buf = buf;      91:       92:             Provider = Socket->GetDProvider();      93:             ReturnValue = Provider->WSPRecv(s,      94:                               &Buffers,      95:                               1,      96:                               &BytesReceived,      97:                               (LPDWORD)&flags,      98:                               NULL,                 // lpOverlapped      99:                               NULL,                 // lpCompletionRoutine     100:                               ThreadId,     101:                               &ErrorCode);     102:             Socket->DropDSocketReference();     103:             if (ReturnValue==ERROR_SUCCESS) {     104:                 if ((flags & MSG_PARTIAL)==0) {     105:                     return (INT)BytesReceived;     106:                 }     107:                 ErrorCode = WSAEMSGSIZE;     108:             }     109:      110:             assert (ErrorCode!=NO_ERROR);     111:             if (ErrorCode==NO_ERROR)     112:                 ErrorCode = WSASYSCALLFAILURE;     113:      114:         }     115:         else {     116:             ErrorCode = WSAENOTSOCK;     117:         }     118:     }     119:      120:     SetLastError(ErrorCode);     121:     return SOCKET_ERROR;     122: }    这2000的代码 和我想象的不一样。我还以为是内部开辟个线程，然后等待线程返回，  所以给用户造成一种现象：等待。  感谢你的参与。    问题2： windows 有很多堵塞函数，比如网络库函数recv等，也会让线程堵塞。  可是有的函数堵塞会消耗cpu，有的则不会。 什么原因导致这么大的差异？   还有既然堵塞了进程。 进程就没有cpu，没有cpu，何来 消耗cpu一说呢？   这问题，是错误的，需要更正，更正为： 一些网络函数，被堵塞后， 未必进程会堵塞，比如你放在一个子线程里，  所以这种，不算进程堵塞， 但是算线程堵塞。 这些函数，会消耗 cpu。   原因，目前没有能力彻底搞清楚， 跳过。   最后一个问题，  有没有工具，可以查看某个 进程处于：运行，就绪，堵塞 的状态？   任务管理器无法胜任此项工作。  [/quote]   windows下没有进程调度的说法， 所以不存在进程堵塞、运行、等待 这种状态。

引用 6 楼 u012879806 的回复:[quote=引用 4 楼 max_min_ 的回复:] 即使cpu不空闲，也不会执行进程  sleep是在只执行进程的，只是这个进程在sleep而已！<不考虑线程>  windows下 sleep是针对线程而言  如果程序只有一个线程，恰好该线程里调用 sleep， getch ,getchar等函数，  我感觉 进程就会堵塞。  此时， 系统分配cpu给 该进程，那么程序也不会继续执行，  因为等待某个事件发生，比如：输入事件， 或者sleep时间到了，才会 继续。   我好奇的是：   为什么有的阻塞函数会消耗cpu，有的则不会，  有高手指导吗？  [/quote] 有的虽然阻塞了，但还是在执行汇编指令，例如while(1),但sleep不会，sleep让线程主动放弃时间片，CPU不会去执行任何代码，当然不消耗CPU了

引用 4 楼 max_min_ 的回复:即使cpu不空闲，也不会执行进程  sleep是在只执行进程的，只是这个进程在sleep而已！<不考虑线程>  windows下 sleep是针对线程而言  如果程序只有一个线程，恰好该线程里调用 sleep， getch ,getchar等函数，  我感觉 进程就会堵塞。  此时， 系统分配cpu给 该进程，那么程序也不会继续执行，  因为等待某个事件发生，比如：输入事件， 或者sleep时间到了，才会 继续。   我好奇的是：   为什么有的阻塞函数会消耗cpu，有的则不会，  有高手指导吗？

建议精读Linux源代码中有关线程调度的源代码。 《深入解析Windows操作系统-Windows Internals》 《30天自制操作系统》

引用 12 楼 zhao4zhong1 的回复:C:\windows_2000_source_code\win2k\private\net\sockets\winsock2\dll\winsock2\recv.cpp      43: int WSAAPI      44: recv(      45:      IN SOCKET s,      46:      OUT char FAR * buf,      47:      IN int len,      48:      IN int flags      49:      )      50: /*++      51: Routine Description:      52:       53:     Receive data from a socket.      54:       55: Arguments:      56:       57:     s     - A descriptor identifying a connected socket.      58:       59:     buf   - A buffer for the incoming data.      60:       61:     len   - The length of buf.      62:       63:     flags - Specifies the way in which the call is made.      64:       65: Returns:      66:       67:     The  number  of  bytes  received.   If  the  connection has been gracefully      68:     closed,  the  return  value  is  0.   Otherwise, a value of SOCKET_ERROR is      69:     returned, and a specific error code is stored with SetErrorCode().      70:       71: --*/      72:       73: {      74:     INT             ErrorCode;      75:     PDSOCKET        Socket;      76:     LPWSATHREADID   ThreadId;      77:       78:       79:     ErrorCode = TURBO_PROLOG_OVLP(&ThreadId);      80:     if (ErrorCode==ERROR_SUCCESS)      81:     {      82:         Socket = DSOCKET::GetCountedDSocketFromSocket(s);      83:         if(Socket != NULL){      84:             INT             ReturnValue;      85:             PDPROVIDER      Provider;      86:             DWORD           BytesReceived;      87:             WSABUF          Buffers;      88:       89:             Buffers.len = len;      90:             Buffers.buf = buf;      91:       92:             Provider = Socket->GetDProvider();      93:             ReturnValue = Provider->WSPRecv(s,      94:                               &Buffers,      95:                               1,      96:                               &BytesReceived,      97:                               (LPDWORD)&flags,      98:                               NULL,                 // lpOverlapped      99:                               NULL,                 // lpCompletionRoutine     100:                               ThreadId,     101:                               &ErrorCode);     102:             Socket->DropDSocketReference();     103:             if (ReturnValue==ERROR_SUCCESS) {     104:                 if ((flags & MSG_PARTIAL)==0) {     105:                     return (INT)BytesReceived;     106:                 }     107:                 ErrorCode = WSAEMSGSIZE;     108:             }     109:      110:             assert (ErrorCode!=NO_ERROR);     111:             if (ErrorCode==NO_ERROR)     112:                 ErrorCode = WSASYSCALLFAILURE;     113:      114:         }     115:         else {     116:             ErrorCode = WSAENOTSOCK;     117:         }     118:     }     119:      120:     SetLastError(ErrorCode);     121:     return SOCKET_ERROR;     122: }    这2000的代码 和我想象的不一样。我还以为是内部开辟个线程，然后等待线程返回，  所以给用户造成一种现象：等待。  感谢你的参与。    问题2： windows 有很多堵塞函数，比如网络库函数recv等，也会让线程堵塞。  可是有的函数堵塞会消耗cpu，有的则不会。 什么原因导致这么大的差异？   还有既然堵塞了进程。 进程就没有cpu，没有cpu，何来 消耗cpu一说呢？   这问题，是错误的，需要更正，更正为： 一些网络函数，被堵塞后， 未必进程会堵塞，比如你放在一个子线程里，  所以这种，不算进程堵塞， 但是算线程堵塞。 这些函数，会消耗 cpu。   原因，目前没有能力彻底搞清楚， 跳过。   最后一个问题，  有没有工具，可以查看某个 进程处于：运行，就绪，堵塞 的状态？   任务管理器无法胜任此项工作。

recv函数所在线程不消耗CPU，但recv函数需要完成的功能这个接力棒被传给socket底层对应线程继续消耗CPU了。我猜。

我是新人, 我很好奇 sleep 不是 sleep 线程吗?

引用 7 楼 bigbaldy 的回复:[quote=引用 6 楼 u012879806 的回复:] [quote=引用 4 楼 max_min_ 的回复:] 即使cpu不空闲，也不会执行进程  sleep是在只执行进程的，只是这个进程在sleep而已！<不考虑线程>  windows下 sleep是针对线程而言  如果程序只有一个线程，恰好该线程里调用 sleep， getch ,getchar等函数，  我感觉 进程就会堵塞。  此时， 系统分配cpu给 该进程，那么程序也不会继续执行，  因为等待某个事件发生，比如：输入事件， 或者sleep时间到了，才会 继续。   我好奇的是：   为什么有的阻塞函数会消耗cpu，有的则不会，  有高手指导吗？  [/quote] 有的虽然阻塞了，但还是在执行汇编指令，例如while(1),但sleep不会，sleep让线程主动放弃时间片，CPU不会去执行任何代码，当然不消耗CPU了[/quote]  看9楼。

引用 8 楼 zhao4zhong1 的回复:举例来讲：recv阻塞了，但其底层实现对应的通过网卡接收字节的线程不能阻塞，仍需消耗cpu。 说的不对的话，请楼下高手拍砖。   《Windows编程启示录》 19.6 为什么有些进程在被终止之后还停留在任务管理器中     当某个进程结束时（可能是正常结束，也可能是因为调用了像TerminateProcess之类的函数），这个进程的用户态模块将被删除。但内核态模块只有在与线程相关的所有驱动程序执行完成之后才会被删除。     例如，如果某个线程正处于I/O操作中，那么将会给负责I/O的驱动程序发送一个内核信号来取消这个操作。     如果驱动程序的行为是良好的，那么它将清除与这个未完成I/O相关的一些信息并且释放线程。     如果驱动程序的行为是不好的（可能是因为驱动程序管理的硬件表现出奇怪的行为），那么可能需要花很长的时间来清除这个未完成的I/O。在这段时间里，驱动程序将不会释放这个线程（以及这个线程所在的进程）。实际的情况要更复杂一些，但这里的简单模型对于我们的讨论已经足够。    ……    换句话说，如果你终止了某个进程后还能在任务管理器中看到这个进程，那么实际上这个进程已经停止运行了，只不过还有些残留的信息保留在系统中，只有当与这个进程相关的所有驱动程序都完成了清除操作并且指向这个进程的句柄都已经关闭，进程才会完全消失。   我给你跟更正一下。。  recv 对用户来说只是一个api， 它自身内部，是否用while这种循环，没看过反汇编源码，  所以我不得而知。  一个api的内部实现， 哪怕它是用循环语句，或者内部再次开辟一个子线程，然后再傻等待这个子线程结束。  对用户来说，我们是不会管他怎么实现的。  用户只会关心，该函数堵塞的时候，是否会消耗cpu ,  很明显 recv 是会消耗， 会消耗的说法，是来自网络，我没有发自验证它。  既然会消耗，那么其内部 不应该是：  recv () { HANDLE hThread = _beingthreadex(...); if(!hThread ) return; waitforsingleobject(hThread, -1); }  sleep， wait.. 等函数，均不会消耗cpu。  只会让出cpu来。

高手额？ ？？

路过。。。学知识。。


Question: c#和c++的相互调用

不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件，或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如： A将请求数据写到文件a.txt，写完后改名为aa.txt B发现aa.txt存在时，读取其内容，调用相应功能，将结果写到文件b.txt，写完后删除aa.txt，改名为bb.txt A发现bb.txt存在时，读取其内容，读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境，B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢？  共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多，下面仅列出我现在能想到的： ·进程之间松耦合 ·进程可在同一台机器上，也可跨机，跨操作系统，跨硬件平台，甚至跨国。 ·方便调试和监视，只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务，只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务，而且几乎不可能发生队列满的情况（除非硬盘空间满） ·……

“这个func函数中的for循环每循环一次，就会返回一个值给c#，请问应该怎么实现~~~。” 不要说C#啦， 就是C++自己也做不到啊， 一个函数只能返回一个值啊。。。。

这个不是C++\c#的问题，A函数调用B函数，B函数有for循环，每次for循环会有返回值。哪里来的这种B函数？

看看这个有帮助没——http://www.cnblogs.com/liping13599168/archive/2011/03/31/2000320.html


Question: 大神帮我看下动态库.so有没有加载上

应该是你代码写的有问题。

libcurl.so 是否还依赖其他的库

引用 3 楼 zhao4zhong1 的回复:进程意外退出会在当前目录下产生‘core’文件或形如‘core.数字’的文件比如‘core.1234’ 使用命令 gdb 运行程序名 core或core.数字 进入gdb然后使用bt命令 可以查看进程意外退出前函数调用的堆栈，内容为从上到下列出对应从里层到外层的函数调用历史。 如果进程意外退出不产生core文件，参考“ulimit -c core文件最大块大小”命令后来发现把 gcc 参数 -shared 去掉就可以了 但好奇怪，我链接的就是动态库亚  其实整个过程是这样的： 我需要curl库，curl库的编译需要cyassl库，限于嵌入式下不允许安装这2者（太大，浪费资源）： 我们这么做： 1.只make cyassl， 把得到的*.h和*.so找到，拉出来整理在一起 2.在make curl的时候需要cyassl动态库，我们给其*.so的目录，就把curl make好了 3.程序中需要curl，我们把*.h 和 *.so提取出来，整理在一起 4.在gcc 参数中链接那些curl *.so目录

引用 2 楼 zmlovelx 的回复:应该是你代码写的有问题。问题基本解决了，和代码无关，Makefile写的有问题

引用 1 楼 user-3 的回复:libcurl.so 是否还依赖其他的库依赖cyassl库


Question: 能看看这个 为什么不可以么

仅供参考#include <stdio.h> int main() {     int IP[4];     int i;     char c;      printf("请输入一个ip地址:");fflush(stdout);     while (1) {         rewind(stdin);         if (5==scanf("%d.%d.%d.%d%c",&IP[0],&IP[1],&IP[2],&IP[3],&c)) {             if (0<=IP[0] && IP[0]<=255              && 0<=IP[1] && IP[1]<=255              && 0<=IP[2] && IP[2]<=255              && 0<=IP[3] && IP[3]<=255              && '\n'==c) {                 break;             } else printf("输入的ip地址格式不对!\n请重新输入:\n");         } else printf("输入的ip地址格式不对!\n请重新输入:\n");     }     for (i=0;i<4;i++) {         printf("IP[%d]=%d\n",i,IP[i]);     }     return 0; }

一般也没什么问题，只是最好不要这么用，你这个程序可以试试强制类型转换

恩恩 好的 谢谢了  可是关键我需要输入的不仅仅是整数啊，那么应该怎么办呢？

去掉那个分号，还有，其实scanf("%lf",&Fahrenheit))==1并不是很好，因为在计算机中浮点数无法准确存储，即使你输入1.0，那也可能是保存为0.999999或1.00000001什么的

scanf %lf有格式控制的，所以你的输入无法停止。可以改成！=1能够触发退出循环

while后面的分号

while条件写错了，改后为while((scanf("%lf",&Fahrenheit)==1));


Question: C语言数组和指针问题求助

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

数组最好不要加减 先赋值给指针后在进行加减，不容易错 int* p = count;

#include<stdio.h> void Aaa(int bbb);  int main() { 	int iShuzu[10]; 	int i; 	for(i=0;i<10;i++) 	{ 		iShuzu[i]=i; 	} 	for(i=0;i<10;i++) 	{ 		Aaa(iShuzu[i]); 	} 	return 0; } 	void Aaa(int bbb) 	{ 		printf("%d\n",bbb); 	} 书上说数组作为实参是数组的地址 那么这个main函数在调用Aaa的时候 为什么可以直接写iShuzu呢 我觉得应该是*iShuzu啊 否则就不能输出想要的元素而是输出每个数组的地址啊 但是结果输出的确实 0 1 2 3 4 5 6 7 8 9这些元素啊 为什么？？？？

楼主可以看一下——http://blog.csdn.net/mbh_1991/article/details/9079463

估计是书上写的有误，*的意思就是解引用，count 和 &country[0]是一样的，*count 和 count[0]是一样的

Count是第一个元素的地址，自然*Count是第一个元素，Count+1表示数组的第二个元素的地址，依次类推

Count内为数组首地址也是第一个元素的地址。。。


Question: 读写文件问题

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

安装win8.1中。。。，暂时无法查看

没看明白你的程序意图是什么 加入a里面是“gfedcba”，你是希望执行完程序后变成“fedcba”还是“fghijkl”？ 如果是后者，你的代码可以实现，但如果是前者，这个代码就不对了

这个我不是太清楚，测试了一会，在fwrite后加个fflush之后好像能用。

#include <stdio.h> #include <stdlib.h> int main() {     FILE *fp;     if ((fp = fopen("a", "rb+")) == NULL)     {         printf("error");         exit(0);     }     char temp;     fseek(fp, 0, 2);     int length = ftell(fp);     rewind(fp);     while (ftell(fp) < length)     {         fread(&temp, 1, 1, fp);         temp++;         fseek(fp, -1, 1);         fwrite(&temp, 1, 1, fp);     }     fclose(fp);     return 0; }


Question: HBase 启动Failed to start master

没结贴，没解决嘛

楼主您好！我也遇到着这个问题！！好几天了解决不好~请问您是怎么解决的呢？先感谢了

引用 1 楼 liuhengxiao 的回复:你发错板块了吧！？这里是开发板块 哪个版块合适呢？？

你发错板块了吧！？这里是开发板块


Question: 【请问一个数组指针的问题】大侠请进

引用 13 楼 zhao4zhong1 的回复:要么忍，要么滚。这个屌

引用 12 楼 zxh707wk 的回复:[quote=引用 8 楼 zhao4zhong1 的回复:] [quote=引用 7 楼 wangjun403 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] 不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);又比如cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。 不懂汇编怎么办[/quote] 学[/quote]不学怎么办[/quote] 要么忍，要么滚。

引用 7 楼 wangjun403 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] 不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);又比如cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。 不懂汇编怎么办[/quote] 学

引用 8 楼 zhao4zhong1 的回复:[quote=引用 7 楼 wangjun403 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] 不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);又比如cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。 不懂汇编怎么办[/quote] 学[/quote]不学怎么办

引用 5 楼 zhao4zhong1 的回复:不要企图依赖输出指针相关表达式...的值【比如printf("%p\n",...);又比如cout<<...】来理解指针的本质， 而要依赖调试时的反汇编窗口中的C/C++代码【比如void *p=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。 不懂汇编怎么办

在int a[4]={1,2,3,4};这个定义中：  a 是数组名，也是数组的首地址；  &a是数组首地址的地址，这样理解，a为一个指针，而&a是a这个指针的指针。  有点绕，但是可以通过这个例子来理解：  a[0] = 1;  *a = 1;  *(*(&a)) = 1;

应该用 == 表示等价

*a =a[0]; *&a=a; 这么理解就可以了

引用 3 楼 user-7 的回复:[quote=引用 1 楼 zjq9931 的回复:] [quote=引用 楼主 daida2008 的回复:]  int a[4]={1,2,3,4}; cout<<a<<" "<<&a<<endl; //两个输出是相等的！！ cout<<*a<<" "<<*(&a)<<endl; //这两个输出是不等的！！ 数组名代表数组的首地址，那么&a返回的也是数组的地址，既然都是数组的地址那么对这个地址进行解引用就应该是第一个元素的值，为什么不是呢？ 这样就相等了  	int a[4]={1,2,3,4}; 	cout<<a<<" "<<&a<<endl; //两个输出是相等的！！ 	cout<<*a<<" "<<*(*(&a))<<endl; //这两个输出是不等的！！  a是数组名，可以代表数组的首地址，但他不是数组的首地址，a是一个变量，不是一个地址。如果是地址，那么它就无法&a。 [/quote] a并非变量，不能对其进行++或--操作。如果是变量，就能够&a[/quote] 确实，我的说法有误。

引用 1 楼 zjq9931 的回复:[quote=引用 楼主 daida2008 的回复:]  int a[4]={1,2,3,4}; cout<<a<<" "<<&a<<endl; //两个输出是相等的！！ cout<<*a<<" "<<*(&a)<<endl; //这两个输出是不等的！！ 数组名代表数组的首地址，那么&a返回的也是数组的地址，既然都是数组的地址那么对这个地址进行解引用就应该是第一个元素的值，为什么不是呢？ 这样就相等了  	int a[4]={1,2,3,4}; 	cout<<a<<" "<<&a<<endl; //两个输出是相等的！！ 	cout<<*a<<" "<<*(*(&a))<<endl; //这两个输出是不等的！！  a是数组名，可以代表数组的首地址，但他不是数组的首地址，a是一个变量，不是一个地址。如果是地址，那么它就无法&a。 [/quote] a并非变量，不能对其进行++或--操作。如果是变量，就能够&a

数组名仅仅是相当于指针，它并不是真正意义的指针，而是一个const的数，它的值等于指针的值 其实a和 &a结果都是数组的首地址，但他们的类型是不一样。 a表示&a[0],也即对数组首元素取地址，a+1表示首地址+sizeof(元素类型)。 &a虽然值为数组首元素地址，但类型为：类型 (*)[数组元素个数],所以&a+1大小为：首地址+sizeof(a)。

引用 楼主 daida2008 的回复: int a[4]={1,2,3,4}; cout<<a<<" "<<&a<<endl; //两个输出是相等的！！ cout<<*a<<" "<<*(&a)<<endl; //这两个输出是不等的！！ 数组名代表数组的首地址，那么&a返回的也是数组的地址，既然都是数组的地址那么对这个地址进行解引用就应该是第一个元素的值，为什么不是呢？ 这样就相等了  	int a[4]={1,2,3,4}; 	cout<<a<<" "<<&a<<endl; //两个输出是相等的！！ 	cout<<*a<<" "<<*(*(&a))<<endl; //这两个输出是不等的！！  a是数组名，可以代表数组的首地址，但他不是数组的首地址，a是一个变量，不是一个地址。如果是地址，那么它就无法&a。


Question: -----------------在linux下使用C语言操作数据库有哪些方法？-----------------

引用 13 楼 Zidane_2014 的回复:顶！ 能否只使用相应的库而不一定安装客户端吗？ 安装客户端的本质是拷贝和注册几个dll

顶！ 能否只使用相应的库而不一定安装客户端吗？

自顶！！

引用 10 楼 zhao4zhong1 的回复:这个是oracle文件夹下的demo文件夹下的例子代码。我想实现对远程数据库的增删改，那么我本地必须安装客户端才能使用例如OCI、 PRO*C、 ODBC吗？

这个是oracle文件夹下的demo文件夹下的例子代码。

引用 5 楼 zhao4zhong1 的回复:请楼主打开demo目录下的例子代码亲自查看之： Program Name                              Features Illustrated cdemo81.c                                 Using basic SQL processing with release 8 and later functionality. cdemo82.c                                 Performing basic processing of user-defined objects. cdemocor.c                                Using complex object retrieval (COR) to improve performance. cdemodr1.c,cdemodr2.c,cdemodr3.c          Using INSERT/UPDATE/DELETE statements with RETURNING clause used with basic datatypes, LOBs and REFs. cdemodsa.c                                Describing information about a table. cdemodsc.c                                Describing information about an object type. cdemofo.c                                 Registering and operating application failover callbacks. cdemolb.c                                 Create and insert LOB data and then read, write, copy, append and trim the data. cdemolb2.c                                Writing and reading of CLOB/BLOB columns with stream mode and callback functions. cdemolbs.c                                Writing and reading to LOBs with the LOB buffering system. cdemobj.c                                 Pinning and navigation of REF object. cdemorid.c                                Using INSERT, UPDATE, DELETE statements and fetches to get multiple rowids in one round-trip. cdemoses.c                                Using session switching and migration. cdemothr.c                                Using the OCIThread package. cdemosyev.c                               Registering predefined subscriptions and specifying a callback function to be invoked for client notifications (for more information about Advanced Queuing, see Oracle Streams Advanced Queuing User’s Guide and Reference). ociaqdemo00.c,ociaqdemo01.c,ociaqdemo02.c Advanced queuing. cdemodp.c,cdemodp_lip.c                   Loading data with the direct path load functions. cdemdpco.c                                Loading a column object with the direct path load functions. cdemdpno.c                                Loading a nested column object with the direct path load functions. cdemdpin.c                                Loading derived type (inheritance) - direct path. cdemdpit.c                                Loading an object table with inheritance - direct path. cdemdpro.c                                Loading a reference with the direct path load functions. cdemdpss.c                                Loading SQL strings with the direct path load functions. cdemoucb.c,cdemoucbl.c                    Using static and dynamic user callbacks. cdemoupk.c,cdemoup1.c,cdemoup2.c          Using dynamic user callbacks with multiple packages. cdemodt.c                                 Datetime and interval example. cdemosc.c                                 Scrollable cursor. cdemol2l.c                                Accesses LOBs using the LONG API. cdemoin1.c                                Inheritance demo which modifies an inherited type in a table and displays a record from the table. cdemoin2.c                                Inheritance demo to do attribute substitutability. cdemoin3.c                                Inheritance demo that describes an object, inherited types, object tables, and a sub-table. cdemoanydata1.c                           Anydata demo. Inserts and selects rows to and from anydata table. cdemoanydata2.c                           Anydata demo. Creates a type piecewise using OCITypeBeginCreate() and then describes the new type created. cdemosp.c                                 Session pooling. cdemocp.c                                 Connection pooling. cdemocpproxy.c                            Connection pooling with proxy functionality. cdemostc.c                                Statement caching. cdemouni.c                                Program for OCI UTF16 API. nchdemo1.c                                Shows nchar implicit conversion feature and codepoint feature. 能说详细点吗？不是太懂。

引用 6 楼 Oringe_new 的回复:oci odbc Proc*c? 引用 7 楼 mayday_xin 的回复:直接操作的话，oci就可以了我想实现的是远程对数据库的增删改，能否不安装oracle客户端，直接使用你们所建议的方法操作？

直接操作的话，oci就可以了

oci odbc Proc*c?

引用 3 楼 cheng7068 的回复:可以采用odbc底层接口函数，或者直接采用oci进行开发都可以还需要下载相应的库吗？

可以采用odbc底层接口函数，或者直接采用oci进行开发都可以

引用 1 楼 u012421456 的回复:什么数据库？oracle

什么数据库？


Question: C语言强制类型转换优先级问题，请高手解答，多谢啦。

建议括号，代码风格问题~

建议楼主看看C语言运算符优先级表，那样就OK了

查一下运算符优先级表就知道了，成员选择运算符优先级高于强制类型转换，这里加不加括号没影响

大神们指点，不是大婶们。

//C++ Operators //  Operators specify an evaluation to be performed on one of the following: //    One operand (unary operator) //    Two operands (binary operator) //    Three operands (ternary operator) //  The C++ language includes all C operators and adds several new operators. //  Table 1.1 lists the operators available in Microsoft C++. //  Operators follow a strict precedence which defines the evaluation order of //expressions containing these operators.  Operators associate with either the //expression on their left or the expression on their right;    this is called //“associativity.” Operators in the same group have equal precedence and are //evaluated left to right in an expression unless explicitly forced by a pair of //parentheses, ( ). //  Table 1.1 shows the precedence and associativity of C++ operators //  (from highest to lowest precedence). // //Table 1.1   C++ Operator Precedence and Associativity // The highest precedence level is at the top of the table. //+------------------+-----------------------------------------+---------------+ //| Operator         | Name or Meaning                         | Associativity | //+------------------+-----------------------------------------+---------------+ //| ::               | Scope resolution                        | None          | //| ::               | Global                                  | None          | //| [ ]              | Array subscript                         | Left to right | //| ( )              | Function call                           | Left to right | //| ( )              | Conversion                              | None          | //| .                | Member selection (object)               | Left to right | //| ->               | Member selection (pointer)              | Left to right | //| ++               | Postfix increment                       | None          | //| --               | Postfix decrement                       | None          | //| new              | Allocate object                         | None          | //| delete           | Deallocate object                       | None          | //| delete[ ]        | Deallocate object                       | None          | //| ++               | Prefix increment                        | None          | //| --               | Prefix decrement                        | None          | //| *                | Dereference                             | None          | //| &                | Address-of                              | None          | //| +                | Unary plus                              | None          | //| -                | Arithmetic negation (unary)             | None          | //| !                | Logical NOT                             | None          | //| ~                | Bitwise complement                      | None          | //| sizeof           | Size of object                          | None          | //| sizeof ( )       | Size of type                            | None          | //| typeid( )        | type name                               | None          | //| (type)           | Type cast (conversion)                  | Right to left | //| const_cast       | Type cast (conversion)                  | None          | //| dynamic_cast     | Type cast (conversion)                  | None          | //| reinterpret_cast | Type cast (conversion)                  | None          | //| static_cast      | Type cast (conversion)                  | None          | //| .*               | Apply pointer to class member (objects) | Left to right | //| ->*              | Dereference pointer to class member     | Left to right | //| *                | Multiplication                          | Left to right | //| /                | Division                                | Left to right | //| %                | Remainder (modulus)                     | Left to right | //| +                | Addition                                | Left to right | //| -                | Subtraction                             | Left to right | //| <<               | Left shift                              | Left to right | //| >>               | Right shift                             | Left to right | //| <                | Less than                               | Left to right | //| >                | Greater than                            | Left to right | //| <=               | Less than or equal to                   | Left to right | //| >=               | Greater than or equal to                | Left to right | //| ==               | Equality                                | Left to right | //| !=               | Inequality                              | Left to right | //| &                | Bitwise AND                             | Left to right | //| ^                | Bitwise exclusive OR                    | Left to right | //| |                | Bitwise OR                              | Left to right | //| &&               | Logical AND                             | Left to right | //| ||               | Logical OR                              | Left to right | //| e1?e2:e3         | Conditional                             | Right to left | //| =                | Assignment                              | Right to left | //| *=               | Multiplication assignment               | Right to left | //| /=               | Division assignment                     | Right to left | //| %=               | Modulus assignment                      | Right to left | //| +=               | Addition assignment                     | Right to left | //| -=               | Subtraction assignment                  | Right to left | //| <<=              | Left-shift assignment                   | Right to left | //| >>=              | Right-shift assignment                  | Right to left | //| &=               | Bitwise AND assignment                  | Right to left | //| |=               | Bitwise inclusive OR assignment         | Right to left | //| ^=               | Bitwise exclusive OR assignment         | Right to left | //| ,                | Comma                                   | Left to right | //+------------------+-----------------------------------------+---------------+

加点括号不是很好的行为么。

多谢各位的指点啦。 不过我说的C语言中的优先级。不过，我明白了， 多谢各位啦。

[quote=引用 楼主 liudiancun 的回复:] 小弟初学C语言，对于强制类型转化有一个小小的问题，还请大神们指点一二。 int a; a  =  (int) father->age;  问题就在这里，里面的强制类型转化优先级是怎么算的？ 我知道一般都是加括号，像是a  =  (int) （father->age）;但是不加括号，等同于 a=(int) (father->age),  解释见楼上

结构有类型么？将结构强制转换有什么意义么？或者说，你使用的指向结构的指针，那是一个地址；所以，强制转换的对象是结构的成员。可以将father->age看作一个整体，相当于你在main中定义的一个float类型变量，然后将这个变量进行强制转换为int类型

成员访问运算符->的优先级高于强制类型转换运算符(type)。  C++ 运算符优先级列表：http://www.cppblog.com/aqazero/archive/2012/11/10/8284.html


Question: 请问这段将FILE文件转化为char类型的代码有什么问题？ffile为什么总是-1？

引用 6 楼 jiangdianqin 的回复:[quote=引用 5 楼 zhao4zhong1 的回复:] ffile=new char[filesize]; size_t sz = fread(ffile,sizeof(char),filesize,fp);话说写入char字符数组的话不是还需要预留一个字节存放‘/0’吗？[/quote] jpg和asciiz没有关系。  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……

引用 11 楼 adlay 的回复:引用 10 楼 jiangdianqin 的回复:[quote=引用 8 楼 adlay 的回复:] FILE 是一个结构，你说的 -1 不晓得是指里面哪个成员为 -1？ 还是指针的值是 -1？是写入的char变量的值为-1 这... new 如果出错要么返回 NULL， 要么抛出异常，怎么会是 -1，你的调试器没问题？ 直接把值打印出来看呢[/quote] 我现在觉得可能是我写数据库的那段代码有问题 ，同样的代码写进sqlite中没有问题，但是写进mongodb中就有问题了

引用 10 楼 jiangdianqin 的回复:引用 8 楼 adlay 的回复:FILE 是一个结构，你说的 -1 不晓得是指里面哪个成员为 -1？ 还是指针的值是 -1？是写入的char变量的值为-1 这... new 如果出错要么返回 NULL， 要么抛出异常，怎么会是 -1，你的调试器没问题？ 直接把值打印出来看呢

引用 8 楼 adlay 的回复:FILE 是一个结构，你说的 -1 不晓得是指里面哪个成员为 -1？ 还是指针的值是 -1？指针的值为-1，所以存进去的就是-1

引用 4 楼 adlay 的回复:那把 error 变量打出来，看错误码是什么，对应什么样的错误信息哦 我在另一个数据库中 也写入了同样的操作 但是确实把图片写入了  而且ffile同样为-1 这是什么情况？

引用 5 楼 zhao4zhong1 的回复:ffile=new char[filesize]; size_t sz = fread(ffile,sizeof(char),filesize,fp);话说写入char字符数组的话不是还需要预留一个字节存放‘/0’吗？

那把 error 变量打出来，看错误码是什么，对应什么样的错误信息

引用 1 楼 adlay 的回复:文件名写错了， "F:/ceshi/iphoto.jpg" 改成 "F:\\ceshi\\iphoto.jpg" 事实上 我在做一个mongodb的东西，将图片文件插图数据库，但是他不支持直接将FILE插入，我就先将其转化为char类型，再插入，可是不知道什么原因，插入的ffile总是int32的值

引用 1 楼 adlay 的回复:文件名写错了， "F:/ceshi/iphoto.jpg" 改成 "F:\\ceshi\\iphoto.jpg"改过来也不对，也是-1

引用 13 楼 zhao4zhong1 的回复:[quote=引用 6 楼 jiangdianqin 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] ffile=new char[filesize]; size_t sz = fread(ffile,sizeof(char),filesize,fp);话说写入char字符数组的话不是还需要预留一个字节存放‘/0’吗？[/quote] jpg和asciiz没有关系。  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息…… [/quote]哦 这样啊 我研究了半天 发现应该与这段代码无关 与数据库写入的方式有关  谢谢赵老师了

引用 13 楼 zhao4zhong1 的回复:[quote=引用 6 楼 jiangdianqin 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] ffile=new char[filesize]; size_t sz = fread(ffile,sizeof(char),filesize,fp);话说写入char字符数组的话不是还需要预留一个字节存放‘/0’吗？[/quote] jpg和asciiz没有关系。  推荐使用WinHex软件查看硬盘或文件或内存中的原始字节内容。  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息…… [/quote] 这个还是有用的


Question: popen和system都会让父进程等待子进程结束吗

引用 6 楼 liupeng_wolf 的回复:用system执行脚本的时候，加上&，让脚本后台执行，这样system就可以立即返回了 引用 6 楼 liupeng_wolf 的回复:用system执行脚本的时候，加上&，让脚本后台执行，这样system就可以立即返回了   请问这种方法，system的返回值是多少呢？会一直返回0吗？

用 fork + exec， 你不 wait 就不会等子进程结束，搜使用 fork 的代码很多吧

那有类似代码吗？我看到网上的代码都是父进程等待子进程结束的

用多线程试试

还可在线程中执行。  或者system中后台执行。

引用 1 楼 adlay 的回复:用 fork + exec， system 这些函数内部也是用这两个系统调用来实现的 +1


Question: c语言关于函数指针里面用void*传参数的问题

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

引用 4 楼 ParsifalC 的回复:int (*comp)(void*,void*) int intGreater(int *x,int *y)  这是两种不同的函数指针类型。 一楼说的方法是正确的做法。 在具体的回调函数内部进行类型转换，这样才能发挥回调函数的优势。 在不更改调用方的代码情况下，实现不同的功能。  嗯，一楼方法是可以的，但是就是我要有DOUBLE类型比较，方法的参数都是void*，只能再函数体里面转换，4楼的方法比较好

引用 3 楼 lovesmiles 的回复:typedef  int (*func)(void*,void*)  insertionSort((func)intGreater);//强制类型转换  谢谢大神，应该强转一下，测试是没问题的。

引用 1 楼 r_Jimy 的回复:可以将 int intGreater(int *x,int *y){     return *x-*y; } 定义为 int intGreater(void *x,void *y){          return *(int*)x-*(int*)y; } --------------------- 可以是可以，但是比如要要比较double类型的话，函数也是int doubleGreater(void *x,void *y),只能靠函数名区别了，我想传入参数的时候就限定。


Question: 求指教！为什么这个程序vc可以输出结果在Dev-cpp运行到scanf那里就不走了

引用 13 楼 brookmill 的回复:我觉得可能是unsigned int和%d不匹配造成的问题。楼主可以试试这两个改动： 1. unsigned int a=0; scanf("%u",&a); 2. int a=0; scanf("%d",&a); 一般情况下unsigned int和%d混用都问题不大，dev-cpp不知道有什么不一样。  顺便说一句，我刚入行的时候曾经这么干过： short a; scanf("%d", &a); 结果就把栈弄崩了，自己还不知道是怎么回事。从那以后就觉得scanf太危险了（其实该说指针太危险了）  非常感谢 不过我试过了不是这个原因 原因是就是上面所说的 还是很感谢

引用 14 楼 zhao4zhong1 的回复:pow Calculates x raised to the power of y.  double pow( double x, double y );  Routine Required Header Compatibility  pow <math.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  pow returns the value of xy. No error message is printed on overflow or underflow.   Values of x and y Return Value of pow   x < > 0 and y = 0.0 1  x = 0.0 and y = 0.0 1  x = 0.0 and y < 0 INF    Parameters  x  Base  y  Exponent  Remarks  The pow function computes x raised to the power of y.   pow does not recognize integral floating-point values greater than 264, such as 1.0E100.  Example  /* POW.C  *  */  #include <math.h> #include <stdio.h>  void main( void ) {    double x = 2.0, y = 3.0, z;     z = pow( x, y );    printf( "%.1f to the power of %.1f is %.1f\n", x, y, z ); }   Output  2.0 to the power of 3.0 is 8.0   Floating-Point Support Routines  See Also   exp, log, sqrt http://bbs.csdn.net/topics/390676437    非常感谢！！ 我看了Dev有关math.h里面有关pow的定义发现pow的参数必须是float 或者 long double型 如下： /* 7.12.7.4 The pow functions. Double in C89 */ extern float __cdecl powf (float, float); #ifndef __NO_INLINE__ __CRT_INLINE float __cdecl powf (float x, float y)   {return (float) pow (x, y);} #endif extern long double __cdecl powl (long double, long double); 改过来就好了

gcc下执行的确没问题 我的C-Free执行的确出不来结果，我单步时发现n在i等于2时变成了99而不是100，不知道是不是编译器问题—— 楼主不妨单步一下VC6和dev试试，看看有什么不同

引用 10 楼 T5500 的回复:汗，没看仔细你的问题，帮不上忙了 还是很感谢！

汗，没看仔细你的问题，帮不上忙了

好吧。。。 我去看看Dev和其他编译器有什么不同

gcc 4.9.0

引用 5 楼 T5500 的回复: 执行没问题啊 哦？兄弟你用的也是Dev吗？

[img=https://img-bbs.csdn.net/upload/201408/13/1407938524_155258.png][/img 在vc里就是这样可以出来 在Dev里就蛋疼了。。。。 不知道怎么弄了

执行没问题啊

是不是死循环了？？

走到这就不走了

正在等你输入一个正整数


Question: 基于C 的 一个API 包如何使用？

根据我的经验，一般这种提供源代码，可以使用make（不是NMAKE）编译的，一般都是支持跨平台的。 如果你以前没研究过这种编译方式，最好还是找个熟悉的人来帮你。 总的来说： 1.它应该是可以在WINDOWS下跑的； 2.WINDOWS下，一般应该需要MinGW(Windows 下的GCC）支持。这些东西文档中应该包含有才对。 3.WINDOWS下默认不会有make这个工具，这个需要你自己搞定。  引用 6 楼 zhai__chi 的回复:[quote=引用 3 楼 super_admi 的回复:] 文档不是说了吗？ 分三步走： 1.下载好源代码做好准备； 2.运行配置脚本进行配置； 3.运行批处理工具进行编译（一般使用make)；  话说，一般这玩意都会直接有二进制程序提供吧？  您好！感谢您的回答。我对电脑是外行，是不是要下载个GCC什么的对这个软件configure？可不可以在windows下用这个软件?[/quote]

这种开源的东西，最好的方式看文档（即使是英文，也要克服），一步步执行。 make的话，有cmake软件和linux下的make，看源码的支持方式，有的通过Cmake可以生成Windows下的工程，然后打开工程编译链接即可。

引用 3 楼 super_admi 的回复:文档不是说了吗？ 分三步走： 1.下载好源代码做好准备； 2.运行配置脚本进行配置； 3.运行批处理工具进行编译（一般使用make)；  话说，一般这玩意都会直接有二进制程序提供吧？  您好！感谢您的回答。我对电脑是外行，是不是要下载个GCC什么的对这个软件configure？可不可以在windows下用这个软件?

lib库，引入lib库和相应的头文件就行了；linux下编译工程后引用头文件

执行./configure 配置， make编译， 再make install 大部分的source都是这样的， 当然一般也会有binary提供， 可能是so加头文件。

文档也想别人帮你翻译吗？

看它的Documentation和Examples啊。。。http://multifario.sourceforge.net/


Question: 救助C语言需要N个数，但是要输入N+1个数之后按确定键才会执行下面的命令

引用 2 楼 u011761982 的回复:[quote=引用 1 楼 lisong694767315 的回复:] scanf("%d ",&q.data[q.tail]);将输入格式%d后面的空格去掉，即改成"%d"  scanf("%d",&q.data[q.tail]);  加了空格表示什么意思？[/quote] 非常谢谢您了，这个大概是不小心打进去的，非常感谢您解决了我的疑惑。

引用 1 楼 lisong694767315 的回复:scanf("%d ",&q.data[q.tail]);将输入格式%d后面的空格去掉，即改成"%d"  scanf("%d",&q.data[q.tail]); +1

引用 2 楼 u011761982 的回复:[quote=引用 1 楼 lisong694767315 的回复:] scanf("%d ",&q.data[q.tail]);将输入格式%d后面的空格去掉，即改成"%d"  scanf("%d",&q.data[q.tail]);  加了空格表示什么意思？[/quote] 跳过输入后面的空白字符

引用 1 楼 lisong694767315 的回复:scanf("%d ",&q.data[q.tail]);将输入格式%d后面的空格去掉，即改成"%d"  scanf("%d",&q.data[q.tail]);  加了空格表示什么意思？


Question: 在ubuntu终端 编译c程序之后  生成不了可执行文件。。

引用 28 楼 u014262884 的回复:linux是没有exe(可执行文件的). 默认条件下, 只要没有后缀的程序它都把它视为可执行文件来处理没有后缀名的也可能是文本文件

你加了-c？？？

引用 24 楼 xzc29312 的回复:你加了-c？？？ 加-c干吗？不用加啊，-c是之编译不链接

引用 23 楼 Dobzhansky 的回复:加个  -v 看看 -v  不是查勘gcc版本的么？

引用 22 楼 lovesmiles 的回复:你这那里是运行不了，是输出的文件不知道到那里去了。指定输出路径试试看 怎么指定啊？有没有一劳永逸的方法？

加个  -v 看看

引用 3 楼 zmlovelx 的回复:gcc -c main.c -o main.o   这种是不能生成可执行文件的 直接gcc main.c就可以生成a.out不好意思  昨天没上，我这可能是终端的事  生成不了可执行文件  不管是gcc   main.c  还是gcc  -o  main   main.c都生成不了

引用 2 楼 zjq9931 的回复:[quote=引用 楼主 leee7338 的回复:] 在ubuntu终端 编译c程序之后  生成不了可执行文件。。 编译之后，还要链接，才行。虽然我不知道ubuntu下怎么用链接，但编译之后肯定是要链接的。[/quote] 不好意思  昨天没上，我这可能是终端的事  生成不了可执行文件  不管是gcc   main.c  还是gcc  -o  main   main.c都生成不了

引用 1 楼 lovesmiles 的回复:你是如何判断出它是不可执行的？另外这个代码有没有main函数？ 不好意思  昨天没上，我这可能是终端的事  生成不了可执行文件  不管是gcc   main.c  还是gcc  -o  main   main.c都生成不了

你这那里是运行不了，是输出的文件不知道到那里去了。指定输出路径试试看

引用 19 楼 lovesmiles 的回复:话说，你知道在Linux上面怎么运行程序吧？别这么小看我行么？ [zhang:~/hello]$gcc hello.c [zhang:~/hello]$ls hello.c [zhang:~/hello]$gcc hello.c -o hello [zhang:~/hello]$ls hello.c [zhang:~/hello]$

是需要交叉编译吧！

话说，你知道在Linux上面怎么运行程序吧？

生成了什么新文件

引用 16 楼 lovesmiles 的回复:[quote=引用 15 楼 leee7338 的回复:] [quote=引用 3 楼 zmlovelx 的回复:] gcc -c main.c -o main.o   这种是不能生成可执行文件的 直接gcc main.c就可以生成a.out不好意思  昨天没上，我这可能是终端的事  生成不了可执行文件  不管是gcc   main.c  还是gcc  -o  main   main.c都生成不了[/quote] 那生成了什么样的文件？生不成总得有个提示什么的吧？[/quote] 没有提示，gcc完就没变化

引用 15 楼 leee7338 的回复:[quote=引用 3 楼 zmlovelx 的回复:] gcc -c main.c -o main.o   这种是不能生成可执行文件的 直接gcc main.c就可以生成a.out不好意思  昨天没上，我这可能是终端的事  生成不了可执行文件  不管是gcc   main.c  还是gcc  -o  main   main.c都生成不了[/quote] 那生成了什么样的文件？生不成总得有个提示什么的吧？

引用 7 楼 zxh707wk 的回复:引用 4 楼 qq_18283689 的回复:承上，直接gcc main.c就可以生成a.out,如果不想用默认的a.out想自己定义，可以在gcc main.c后面加上-o main，形如：gcc main.c -o main .然后直接./main（注意是 " ./  "）就可以执行了+1，另外，如果没有指定输出路径的话，可执行文件默认生成在当前用户主目录里

有人还错误地以为天下的可执行文件都带exe扩展名的。

还有编译器,不会是交叉编译器吧...


Question: huffman编码问题，剑桥大学Julian Seward的Huffman解码程序

我走了几遍，没看出来它跟原理有什 么关系，也跟一般的哈夫曼解码方式不一样，所以才拿出来，希望做过的前辈能帮忙指点一下

http://blog.csdn.net/ns_code/article/details/19174553 http://blog.csdn.net/abcjennifer/article/details/8020695

引用 1 楼 god_vigoss 的回复:具体代码可以看这里http://www.newxing.com/S7D457EA44664/huffman.c 首先，需要明白huffman编码解码的原理，即，用自然语言来怎么表达。 然后，自己试着写一下伪代码，理清流程思路，再看代码就会相当的容易。 以上两点是否做到呢？

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


Question: 麻烦帮忙看下哪里有错！

引用 1 楼 lisong694767315 的回复:你声明了一个str指针，又没有给它分配内存。输入的字符串存哪呢？？  应该给str分配内存：  char *str = (char*)malloc(20*sizeof(char));  // 分配20个char的内存  谢谢了，怪不得呢！

引用 4 楼 Baoge_leopard 的回复:[quote=引用 楼主 pf4919501 的回复:] #include "stdio.h" #include "conio.h" main() {   int len;   char *str;   printf("please input a string:\n");   scanf("%s",str);   int length(char *p);   len=length(str);   printf("the string has %d characters.",len);   getch(); } int length(char *p) {   int n;   n=0;   while(*p!='\0')   {     n++;     p++;   }   return n; } 检查了几遍，也没找到哪里的问题，麻烦有人帮忙指正下！  还要在main（）上面声明int length(char *p)； main()前少了int[/quote] 给str分配内存

引用 楼主 pf4919501 的回复:#include "stdio.h" #include "conio.h" main() {   int len;   char *str;   printf("please input a string:\n");   scanf("%s",str);   int length(char *p);   len=length(str);   printf("the string has %d characters.",len);   getch(); } int length(char *p) {   int n;   n=0;   while(*p!='\0')   {     n++;     p++;   }   return n; } 检查了几遍，也没找到哪里的问题，麻烦有人帮忙指正下！  还要在main（）上面声明int length(char *p)； main()前少了int

楼上说的对~

#include "stdio.h" #include "conio.h" main() {                 int len; 		char str[100]; 		printf("please input a string:\n"); 		scanf("%s",str); 		len=length(str); 		printf("the string has %d characters.",len); 		getch(); } int length(char *p) {   int n;   n=0;   while(*p!='\0')   {     n++;     p++;   }   return n; }


Question: 跳马问题

引用 12 楼 zxh707wk 的回复:路过，lz要结帖了。。。 谢谢，我想学习些调试技巧。

.....  解答的很好啊

路过，lz要结帖了。。。

引用 10 楼 livvve 的回复:[quote=引用 9 楼 zjq9931 的回复:] [quote=引用 8 楼 livvve 的回复:]  嗯。我题目没有看仔细。 蛮感谢你的，你怎么发现的错误的调试很久都没发现[/quote] 熟能生巧吧，多调试，似乎没有别的招。

引用 9 楼 zjq9931 的回复:[quote=引用 8 楼 livvve 的回复:]  嗯。我题目没有看仔细。 蛮感谢你的，你怎么发现的错误的调试很久都没发现

引用 8 楼 livvve 的回复:[quote=引用 5 楼 zjq9931 的回复:] [quote=引用 3楼 livvve 的回复:] 恩恩，感觉思想是不是出了问题，做出来告诉我一下 已经改好。[/quote] 谢谢，t3&&t4,不然运行结果是马跳到（8，0）::(8,4)了。[/quote] 嗯。我题目没有看仔细。

引用 5 楼 zjq9931 的回复:[quote=引用 3楼 livvve 的回复:] 恩恩，感觉思想是不是出了问题，做出来告诉我一下 已经改好。[/quote] 谢谢，t3&&t4,不然运行结果是马跳到（8，0）::(8,4)了。

马跳日时好像不需要输入的，不过您说的其他溢出蛮有用

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

引用 3 楼 livvve 的回复:恩恩，感觉思想是不是出了问题，做出来告诉我一下 已经改好。

改好了。  #include<iostream> using namespace std;   const int TARGET_X=8; const int TARGET_Y=4; const int MAXSTEP=100;   int Num; int path[MAXSTEP+1][2]; int dx[]={0,1,2,2,1}; int dy[]={0,2,1,-1,-2}; int mk[9];   void jump(int x,int y,int step) { 	int k,i; 	int t1,t2,t3,t4; 	int x1,y1;  	for(k=1;k<=4;k=k+1) 	{ 		x1=x+dx[k]; 		y1=y+dy[k]; 		if(x1>TARGET_X || y1>TARGET_Y) 			continue; 		t1=(x1>=0) && (x1<=TARGET_X); 		t2=(y1>=0) && (y1<=TARGET_Y); 		t3=(x1==TARGET_X) && (y1!=TARGET_Y); 		t4=(x1==TARGET_X) && (y1==TARGET_Y); 		if( (t1) && (t2) ) 		{ 			path[step][0]=x1; 			path[step][1]=y1; 			mk[step]=k; 			if(t4 || t3)			//t3也是算的 			{ 				Num=Num+1; 				cout<<"方案："<<Num<<":"; 				for(i=0;i<=step;i++) 				{ 					cout<<"("<<path[i][0]<<","<<path[i][1]<<")";	//path[i][i]，改为path[i][1]，这里是引起输出结果错误的地方。 				} 				cout<<"\n"; 			} 			else 			{   				jump(x1,y1,step+1); 			} 		} 	} } int main(int argc, char* argv[]) { 	mk[0]=0; 	Num=0; 	path[0][0]=0; 	path[0][1]=0; 	jump(0,0,1); 	cout<<"总方案数："<<Num<<endl; 	return 0; }

恩恩，感觉思想是不是出了问题，做出来告诉我一下

还有一部分是1,2--2,3这个跳的就有问题了。

还没有仔细看程序，不过你的结果似乎有点怪，都结束在（8,0）


Question: 一道compile error题 (POJ 1002)

引用 8 楼 lovesmiles 的回复:typedef int (*func)(const void*, const void*); qsort(ph,nph,9,(func)strcmp);//强制类型转换 在CPP中编译成功了。谢谢！

引用 6 楼 gojoy_x13 的回复:这个不知道，可以跟一下头文件，觉得像是dev-c的头文件有问题。第一个在dev-c里也能编过吗 两个在devcpp里都编译不通过。但是示例程序能AC

#include<stdio.h> #include<stdlib.h> #include<string.h>  char ph[100000][9], buf[1000]; char map[26]={'2','2','2','3','3','3','4','4','4','5','5','5','6', 	'6','6','7',0,'7','7','8','8','8','9','9','9',0};  int nph; int main(){ 	int i, j; 	int x=1,z=0; 	memset(ph, 0, sizeof(ph)); 	scanf("%d", &nph);  	for(i=0; i<nph; i++){ 		int x = 0; 		scanf("%s", buf);  		for(j=0; buf[j]; j++) { 			if(buf[j]=='-') continue; 			if((buf[j]>='A'&&buf[j]<'Z')|| 				(buf[j]>=0&&buf[j]<=9)) 				buf[j]=map[buf[j]-'A']; 			ph[i][x++]=buf[j]; 			if(x==3) ph[i][x++]='-'; 		} 	} 	qsort(ph,nph,9, strcmp);  	x = 1; 	z = 0;  	for(i=1;i<nph;++i){ 		if(strcmp(ph[i-1],ph[i])){ 			if(x>1)    {    				printf("%s %d\n",ph[i-1],x); 				z=1; 			} 			x=1; 		} 		else x++; 	} 	if(x>1){ 		printf("%s %d\n",ph[i-1],x); 		z=1; 	} 	if(!z)  printf("No duplicates.\n"); }  具体代码意思不懂，c里面的变量申明放在 代码块首。

scanf(" %s",&buf);  // 这里不应该用& 用gcc编译通过，不过关于qsort和strcmp有个warning

引用 1 楼 brookmill 的回复:#include string.h要放到stdlib.h前面 不对，不是这个问题，刚才糊涂了

typedef int (*func)(const void*, const void*); qsort(ph,nph,9(,func)strcmp);//强制类型转换

应该是qsort参数类型的问题。qsort函数声明里面，最后一个参数应该是int (*)(const void*, const void*)，但是strcmp是int (__attribute__((__cdecl__)) *)(const char*, const char*) 用gcc编译有个警告，Dev-cpp 5.6.1就不知道了。

应该是scanf("%s",&buf)那一句不该加&号了。还有一个问题，就是为什么在Dev-cpp 5.6.1环境中编译会提示strcmp那一行出现下列错误？ [Error] invalid conversion from 'int (__attribute__((__cdecl__)) *)(const char*, const char*)' to 'int (*)(const void*, const void*)' [-fpermissive]

#include string.h要放到stdlib.h前面


Question: 为什么scanf()输入已声明长度字符串数组时，可以超过定义的长度呢？

引用 7 楼 modyaj 的回复:[quote=引用 4 楼 sinat_19278443 的回复:] [quote=引用 1 楼 modyaj 的回复:] 先看看scanf 的第二个参数   再看看printf输出字符串的方式 估计就知道了 还是木有清楚[/quote] 第二个参数说明  你操作的是一个内存地址  你在地址上写入的数据超过你你原本计划的大小  对于系统还说 她根本不知道 举个简单的例子：你要在本子上写一行字 你说你写入的是8个字  我现在告诉你   你可以从本子的第二行的第一个位置开始写  结果你写了10个字 作为本子  它哪里会知道你写的10字有问题啊！如果你运气不好 ，刚好写第九个或者第十个字的时候那个位置本子上已经有字了  那么你写了后影响别人（因为你给人家覆盖了嘛）。不知道怎么说恰当不？ 同样的  输出函数 从某个地址开始输出，直到遇到结束符才停止！因为你连续输入的字符里面没有结束符 所以都给你输出来了，至于什么时候遇到结束符 那要看运气了（所以有可能会多输出一些意外的字符）[/quote] 懂了懂了

其实电脑开机后物理内存的每个字节都是可读写的，区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。 #include<stdio.h> int main(void){     char mytal[8];        //已经申明长度为8     scanf("%7s",mytal);     printf("%s\n",mytal);     return 0; }

引用 4 楼 sinat_19278443 的回复:[quote=引用 1 楼 modyaj 的回复:] 先看看scanf 的第二个参数   再看看printf输出字符串的方式 估计就知道了 还是木有清楚[/quote] 第二个参数说明  你操作的是一个内存地址  你在地址上写入的数据超过你你原本计划的大小  对于系统还说 她根本不知道 举个简单的例子：你要在本子上写一行字 你说你写入的是8个字  我现在告诉你   你可以从本子的第二行的第一个位置开始写  结果你写了10个字 作为本子  它哪里会知道你写的10字有问题啊！如果你运气不好 ，刚好写第九个或者第十个字的时候那个位置本子上已经有字了  那么你写了后影响别人（因为你给人家覆盖了嘛）。不知道怎么说恰当不？ 同样的  输出函数 从某个地址开始输出，直到遇到结束符才停止！因为你连续输入的字符里面没有结束符 所以都给你输出来了，至于什么时候遇到结束符 那要看运气了（所以有可能会多输出一些意外的字符）

引用 5 楼 zjq9931 的回复:[quote=引用 楼主 sinat_19278443 的回复:] 代码： #include<stdio.h> int main(void){     const char mytal[8];        //已经申明长度为8     scanf("%s",mytal);     printf("%s\n",mytal);     return 0; } 运行结果：  输入了10个字符，超过了8个了，也显示了10个，不应该只显示7个吗？ 求解答 不少黑客的攻击就是利用这个导致越界，然后入侵系统的。[/quote] 这么厉害啊，学习了 万分感谢！！

引用 楼主 sinat_19278443 的回复:代码： #include<stdio.h> int main(void){     const char mytal[8];        //已经申明长度为8     scanf("%s",mytal);     printf("%s\n",mytal);     return 0; } 运行结果：  输入了10个字符，超过了8个了，也显示了10个，不应该只显示7个吗？ 求解答 不少黑客的攻击就是利用这个导致越界，然后入侵系统的。

引用 1 楼 modyaj 的回复:先看看scanf 的第二个参数   再看看printf输出字符串的方式 估计就知道了 还是木有清楚

引用 楼主 sinat_19278443 的回复:代码： #include<stdio.h> int main(void){     const char mytal[8];        //已经申明长度为8     scanf("%s",mytal);     printf("%s\n",mytal);     return 0; } 运行结果：  输入了10个字符，超过了8个了，也显示了10个，不应该只显示7个吗？ 求解答 C语言是不会检查越界行为的，这个需要自己控制。 所以要小心。

正常,mytal[7]里面本来放的是'\0',你这样输入之后将mytal[7]改成了'8',而printf输出的时候要一直要遇到'\0'才停止的.

引用 3 楼 zjq9931 的回复:C语言是不会检查越界行为的，这个需要自己控制。 所以要小心。+1


Question: 关于指针输出字符串

还能再基础点吗

指针只能存字符串的地址，而不能存字符串

你那样写只是声明了个指针变量，没有实际的数据存储空间，new一下或者malloc一下才行

楼上们的都是正解！

引用 3 楼 Intel0011 的回复:char *string; -->只分配了指针变量string的内存 #include <stdio.h> int main(void) {     char *string;     string = malloc(sizoef(char) * 80); //使string指向分配的内存     scanf("%s",string);     printf("\n%s\n",*string);     free(strng); //释放之前分配的内存     return 0; }[/quote  [quote=引用 2 楼 u012421456 的回复:] 字符串可以表达为char*的形式	  但是char*不一定是字符串	 char*本意是指向字符的指针，可能指向的是字符 的数组（就像int*一样）	  只有它所指的字符数组有结尾的\0，才能说它 所指的是字符串没有用。

崩溃的时候在弹出的对话框按相应按钮进入调试，按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。  其实电脑开机后物理内存的每个字节都是可读写的，区别仅在于操作系统内存管理模块在你读写时是否能发现并是否采取相应动作而已。操作系统管理内存的粒度不是字节而是页，一页通常为4KB。

使用指针前要初始化。初始化来源可以是栈地址、堆地址或者全局变量的那个地址。

补充一点，如果输入的里面有各种字符建议用gets，不用scanf("%s", &str);

引用 楼主 chlth007 的回复:#include <stdio.h> main() { 	char *string; 	scanf("%s",string); 	printf("\n%s\n",*string); } 运行后如图所示  指针没有分配内存空间。 在scanf前加上： string = (char*)malloc(1024);

char *str =  (char*)malloc( 256*sizeof(char) ); 	memset(str,0,256*sizeof(char)); 	scanf("%s",str);  	printf("%s",str); 	free(str);

把第六行的*去掉还是一样

程序中只定义了一个char *的指针变量string， 是没有空间来存储所输入的字符串的， 可以修改成这样：  int main(int argc, char *argv[]) {     char *string = NULL;     char str[128]={0};     /*定义一个数组，并进行初始化*/      string = str;     scanf("%s", string);     printf("the string is: %s !\n", string);     return 0; }


Question: 请高手指点一下！！！！C程序的问题

*string 代表的是地址string里面的内容也就是hello mingri，但是输出%s的时候需要的是这个字符串的首地址，也就是string.

引用 3 楼 Cristiano001 的回复:我是新手 刚学几天以下是代码 #include<stdio.h> main() {   char *string="hello mingri";   printf("%s",string);   return 0; } 我的问题是 这个printf("%s",string);输出的应该是hello mingri这个字符串的地址啊，为什么会输出hello mingri字符串呢，应为string是一个地址不是变量啊!  为什么？  printf中双引号内的%后面跟的字母决定后面变量输出的内容，如果输出的是printf（“%d”,string），那么输出的就是字符串的地址以10进制的数值，格式化输出中%s的意思是从字符串首地址的第一个字符，然后字符串首地址自增，直到遇到的地址存放的是字符串结束符，也就是‘\0’，表示此次字符串读取完成  建议你去看看C语言的格式化输入输出，这是学习C一定要熟练掌握的一些函数

引用 12 楼 zhao4zhong1 的回复:理解和讨论之前请先学会如何观察！  计算机组成原理→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=(void *)(...);】及其对应汇编指令以及内存窗口中的内存地址和内存值来理解指针的本质。  这辈子不看内存地址和内存值；只画链表、指针示意图，画堆栈示意图，画各种示意图，甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗？本人深表怀疑！ 这辈子不种麦不收麦不将麦粒拿去磨面；只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头，压面条，烤面包，……能从本质上理解面粉、理解面食吗？本人深表怀疑！！  提醒： “学习用汇编语言写程序” 和 “VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化，这样过一遍不就啥都明白了吗。 （Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。） 想要从本质上理解C指针，必须学习C和汇编的对应关系。” 不是一回事！  不要迷信书、考题、老师、回帖； 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实！  有人说一套做一套，你相信他说的还是相信他做的？ 其实严格来说这个世界上古往今来所有人都是说一套做一套，不是吗？  不要写连自己也预测不了结果的代码！  电脑内存或文件内容只是一个一维二进制字节数组及其对应的二进制地址； 人脑才将电脑内存或文件内容中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、汇编指令、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……  十字链表交换任意两个节点C源代码（C指针应用终极挑战）http://download.csdn.net/detail/zhao4zhong1/5532495 赵老师，看了你神一般的回复，我膜拜了

char* cstr = "hello world"; printf("%p\n",&cstr);   //这样得到的才是cstr字符串的存储地址  printf("%s",string) ;//这样得到的才是cstr字符串的内容，即hello world  printf("%c",*string) ;//这样得到的才是cstr字符串的第一个字符h，即h  printf("%s",*string) ;//这样得不到任何东西，会运行错误的，%s是输出字符串的，而*string是一个char类型字符

引用 3 楼 Cristiano001 的回复:我是新手 刚学几天以下是代码 #include<stdio.h> main() {   char *string="hello mingri";   printf("%s",string);   return 0; } 我的问题是 这个printf("%s",string);输出的应该是hello mingri这个字符串的地址啊，为什么会输出hello mingri字符串呢，应为string是一个地址不是变量啊!  为什么？  你是没有理解printf("%s")这个函数，当里面是使用%s时，它就是需要一个指针。你不给它指针反而会出错。

加了个*,只能取到一个char，1个字符  printf("%c",*string);  这样用，打印一个字符

你把你的指针看成数组就好啦。。。。。。。。其实就相当于一个常量数组

%s是输出一个字符串，所以应该提供一个字符串的首地址，即string。  而*string是字符串的第一个字符，输出字符应该使用%c，printf("%c",*string);  它会输出h

输出或输出字符串的时候的参数是字符串的首地址


Question: 关于预编译的问题

用“gcc -dM -E test.c”测试了下输出，发现使用-std=c++0x的时候，是没有linux宏定义的，而不加-std=c++0x的时候，是有的。 看来是c++11给改了。  感谢各位。

引用 3 楼 lisong694767315 的回复:在ANSI标准确定前，类似unix和vax这样的符号被用做在编译时确定目标平台。那时还没有C语言的官方标准。所以对变量的使用没有通用规则，编译器的作者们通常会在编译器的实现中使用unix, linux这些作为预定义宏的符号，并假定开发者在自己的代码中会避开它们。  1989年ANSI C标准出台后，限制了编译器对符号的使用，编译器中预定义宏的符号只能以两个下划线开头，或者一个下划线后紧接着大写字母。于是，那些默认使用旧预定义符号（例如unix、linux）的编译器就变得不合法了，GCC就是其中之一（最早一版的GCC是1987年发布的）。在编译器的实现中，它将linux当成1。  不过，通过类似gcc/g++ -std=c++11，可以让GCC遵循新规范。 我编译的时候 加了-std=c++0x

先创建一个空文件test.c $ touch test.c $ gcc -dM -E test.c


Question: c语言全局指针变量释放问题

计算机组成原理→DOS命令→汇编语言→C语言（不包括C++）、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言（包括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对应的汇编并单步执行观察相应内存和寄存器变化。）

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

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

执行那个函数后，两点 i保存了a数组的地址，直到程序执行结束  但是a数组本身会在函数执行完成后释放自己的内存

程序运行结束，什么都没了，全部销毁。 即使你new的没有delete，程序结束也会被OS收回。

引用 楼主 beiyuexianren 的回复:这个运行结束之后肯定是要释放b[6]所占的内存的，但是是否释放a[5]呢？ a[5]也和其他局部变量一样，也是要释放的。

引用 楼主 beiyuexianren 的回复:如果释放，那么i将来若在别的地方使用，则i所指的值可能会错误 完全正确。aa返回之后，a的地址不再有效，使用i有可能出问题。这是一个常见的错误。有时候编译器会有警告的。 结论：不要在函数返回之后使用局部变量的地址。


Question: 这个代码错在哪里？

不要在函数里面包含头文件

#if defined(linux) #include<stdio.h> #endif  int main() {   #if defined(linux)     printf("hello"); #endif       return 0;   }

在centos下面跑


Question: 老问题，关于for里面关于打印i的问题

引用 24 楼 fxbszj 的回复:[quote=引用 23 楼 misskissC 的回复:] C++里面++i比i++高效； C里无区别。 为什么在C语言里没有区别[/quote]   用一个变量，

引用 24 楼 fxbszj 的回复:[quote=引用 23 楼 misskissC 的回复:] C++里面++i比i++高效； C里无区别。 为什么在C语言里没有区别[/quote]   gcc  -g  double_plus.c  -o double_plus objdump -dS double_plus   不知道这样可不可以说明这个...

引用 23 楼 misskissC 的回复:C++里面++i比i++高效； C里无区别。 为什么在C语言里没有区别

C++里面++i比i++高效； C里无区别。

所以运行结果是这样的：

在for里面没区别 不用分析

计算机组成原理→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对应的汇编并单步执行观察相应内存和寄存器变化。）

i++ 和 ++i 副作用完全一样 而这里只用到了 题目的副作用 所以没有区别

引用 3 楼 u012501633 的回复:C/C++语言定义（语言的参考手册）明确定义了顺序点的概念。顺序点位于： 1. 每个完整表达式结束时。完整表达式包括变量初始化表达式，表达式语句，return语句的表达式，以及条件、循环和switch语句的控制表达式（for头部有三个控制表达式）； for里面没有顺序点，那打印的结果是不是意味着可能是0-9也可能是1-10呢？ for 成吨的序列点 你怎么会觉得for 没序列点呢

引用 7 楼 Baoge_leopard 的回复:结果一样，只是前置加加效率比后置加加效率高一点 这是何解？？

引用 5 楼 u012501633 的回复:[quote=引用 2 楼 lisong694767315 的回复:] 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9  C/C++语言定义（语言的参考手册）明确定义了顺序点的概念。顺序点位于： 1. 每个完整表达式结束时。完整表达式包括变量初始化表达式，表达式语句，return语句的表达式，以及条件、循环和switch语句的控制表达式（for头部有三个控制表达式）； [/quote]  for的执行顺序是一定的  for（A ; B ; C) {   D; }  它的执行顺序就是 A； B; D; C; A; B; D; C; .... 如果B为假就跳出。 你把你的函数带入上面看看会不会有区别。 只不过是C一个是i++一个是++i 对于一个单独的语句这两个的结果没有区别。

引用 9 楼 qq_16696537 的回复:[quote=引用 7 楼 Baoge_leopard 的回复:] 结果一样，只是前置加加效率比后置加加效率高一点 这是何解？？[/quote]   i++和++i的不同

没有区别的！ 他们两个相当于~ int i = 0; for(;i<10;){   printf("%d'n", i);  ++i;     //  a } 单独一条语句 前++ 和 后++ 没有任何区别！ int i = 10; int a = i++; int b = ++i; 结果就是 a = 10, i = 12, b = 12; 就是这种用法 ~~~

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

引用 15 楼 u011362822 的回复:打印结果没区别，不过效率就有点区别了，++i 比 i++ 效率高点。 因为在i++情况下，编译器会用一个临时变量保存i的值，而++i就不会。 不过现在的很多编译器会优化，使这两种用法效率没区别。 详见：http://stackoverflow.com/questions/24886/is-there-a-performance-difference-between-i-and-i-in-c 对学习编程者的忠告： 眼过千遍不如手过一遍！ 书看千行不如手敲一行！ 手敲千行不如单步一行！ 单步源代码千行不如单步Debug版对应汇编一行！ 单步Debug版对应汇编千行不如单步Release版对应汇编一行！

调试跟踪可以解开你的疑问，实在不行看汇编代码。真正能搞明白，确实得如赵老师说的那样。

打印结果没有区别，但是，眼里看见的有区别。

结果一样，只是前置加加效率比后置加加效率高一点

引用 5 楼 u012501633 的回复: 可怜的娃，你是怎么了


Question: 关于归并排序的问题

问题是不是出现在这一句？tmp = (int *) malloc((high - low) * sizeof(int)); 假设 high =2 ；low =1 ；实际上你只申请了4字节内存，事实上应该申请 2*int 内存。

谢谢各位了，我知道问题怎么解决了

谢邀，有人解答了，我就围观吧，大脑有些不想动了。。。

我以前写的，你可以参考一下：  #include"stdio.h" #include"stdlib.h"  int *B;  // 全局的临时数组 void Merge_Array(int A[], int low, int mid, int high)   {       int i, j, k;   	for(k=low; k<=high; ++k)           B[k] = A[k];             // 将A中所有元素复制到B       for(i=low,j=mid+1,k=i; i<=mid&&j<=high; ++k)       {           if(B[i] <= B[j])      // 比较B的左右两段序列中的元素               A[k] = B[i++];    // 将较小值复制到A中           else               A[k] = B[j++];       }       while(i<=mid)  A[k++] = B[i++];   // 若第一个表未检测完，复制       while(j<=high) A[k++] = B[j++];   // 若第二个表未检测完，复制 }      void Merge_Sort(int A[], int low, int high)   {       if(low < high)       {           int mid = (low + high)/2;           Merge_Sort(A, low, mid);       // 对左侧子序列进行递归排序           Merge_Sort(A, mid+1, high);    // 对右侧子序列进行递归排序           Merge_Array(A, low, mid, high);     // 归并       }   }   int main() { 	int i; 	int A[9] = {1,5,4,3,7,2,6,8,0};  // 待排序数组 	B = (int*)malloc(9*sizeof(int)); // 分配空间  	/*输出排序前数组*/ 	printf("The squence of numbers:\n"); 	for(i=0; i<9; ++i) 		printf("%d ", A[i]); 	printf("\n");  	/*输出排序后数组*/ 	Merge_Sort(A, 0, 8); 	printf("The sorted data is:\n"); 	for(i=0; i<9; ++i) 		printf("%d ", A[i]); 	printf("\n");  	return 0; }

虽然不知道，还是顶一下

问题出在 Merge_Sort 中 Merge_Sort(A, low, mid); Merge_Sort(A, mid+1, high); 这两条语句中。在运行时取不到 mid 不知道如何改是好


Question: 一道笔试题

#include<stdio.h>  int main(int  argc, char  *argv[]) { 	int a[5]={1,2,3,4,5}; 	int *p = a; 	 	//*(p++) += 100;  	*(++p) += 100;  	 	printf("%d,%d,%d", *p, *(p+1), *(p+2)); 	return 0; }     把题目变一下

简单的指针题啊，直接234

引用 楼主 hotdog008 的回复:int a[5]={1,2,3,4,5}; int *p = a;  *(p++) += 100;  printf("%d,%d,%d", *p, *(p+1), *(p+2));  输出结果？  234

学习了，谢谢楼主分享。

直接在草稿纸上演算不就可以了吗

笔试搞完可以自己拿编译器调试测试啊

输出结果：2,3,4  *(p++) += 100;这一句等同于下面两句：  *p += 100; p++;   即先将a[0]加100，然后地址加1。所以*p, *(p+1), *(p+2)输出的是a[1], a[2], a[3]


Question: 写了一个蛋疼的排序程序，请大家看来吐槽一下提出一点建议或问题

顺便~~发代码是可以使用代码格式的。

这是按你的思路写的：  #include <stdio.h> #include <malloc.h>  #define SIZEOFINT sizeof(int) #define DATAFLAGS 1008611  void mysort(int *data_array, int len_array);  int main(void) { 	int len_array=0, i; 	int *data_array = NULL;  	printf("输入数组长度："); 	while(!scanf("%d", &len_array) || len_array < 0){ 		printf("数组长度只能是大于0的正整数\n"); 		printf("输入数组长度："); 	}  	data_array = (int *)calloc(len_array, SIZEOFINT);  	printf("输入数组中的数据：\n"); 	for(i=0; i<len_array; ++i){ 		scanf("%d", &data_array[i]); 	}  	mysort(data_array, len_array);  	printf("从小到大排序结果：\n"); 	for(i=0; i<len_array; ++i){ 		printf("%d  ", data_array[i]); 	}  	return 0; }  void mysort(int *data_array, int len_array) { 	int i, j, ps; 	int *temp_array = NULL;  	temp_array = (int *)calloc(len_array, SIZEOFINT);  	for(i=0; i<len_array; ++i) 	{ 		temp_array[i] = DATAFLAGS; 		for(j=0; j<len_array; ++j) 		{ 			if(temp_array[i] > data_array[j]) 			{ 				temp_array[i] = data_array[j]; 				ps = j; 			} 		} 		data_array[ps] = DATAFLAGS; 	} 	for(i=0; i<len_array; ++i){ 		data_array[i] = temp_array[i]; 	} 	free(temp_array); }

新人，打酱油，路过……

引用 6 楼 zhao4zhong1 的回复:各种排序算法动画演示http://www.webhek.com/misc/comparison-sort/  ＜1000个元素，冒泡排序 ＜100000个元素，qsort函数 ＜10000000个元素，放数据库中，建索引，（B+树排序） ≥10000000个元素，没用到过。

lz你想用这个程序实现什么功能呢？

引用 1 楼 maple_LE 的回复:我的思路是先撸出数组最小值，然后把最小值放入到临时数组，再撸出剩下的数组最小值，再按顺序放入到临时数组，最后临时数组填满了，同时也是有序的，再把临时数组的数据写回到原数组 时间复杂度和空间复杂度疑似有点高  你这个思路跟简单选择排序有点像，但简单选择排序不需要临时数组。  简单选择排序的算法思想很简单，假设序列为L[n]，第i趟排序即从L[i...n]中选择关键字最小的元素与L(i)交换，每一趟排序可以确定一个元素的最终位置。经过n-1趟排序就可以使得序列有序了。   void SelectedSort(int A[], int n)   {       for(int i=0; i<n-1; ++i)  // 一共进行n-1趟       {           int minPos = i;  // 记录最小元素的位置              for(int j=i+1; j<n; ++j)               if(A[j] < A[minPos])                   minPos = j;              if(minPos != i)  // 与第i个位置交换           {               int tmp = A[i];             A[i] = A[minPos];             A[minPos] = tmp;         }       }   }


Question: 请教关于SMTP发html内嵌图片邮件的问题：Hotmail、iclould等邮箱不能正常显示图片。。

求解答

试试你的html部分Content-Transfer-Encoding:quoted-printable改成Content-Transfer-Encoding:8bit，quoted-printable编码的话，不可打印的ascii变成=XX，原=号变=3D，就像你说在foxmail看到的那个样子...

引用 3 楼 zhao4zhong1 的回复:将=3D"全部替换为="  哪个是能正常显示图片的邮件源码。。。我自己的是没有3D的

将=3D"全部替换为="

引用 1 楼 lovesmiles 的回复:我觉得你这个问题应该移到web前端开发那边。 额，以前没来过这里，不知道这里的版块怎么分。。我程序是用C语言写的。。所以在这里问了，哈哈

我觉得你这个问题应该移到web前端开发那边。