user-0 提问: 赵老师，一个C语言问题请教

回复:
user: user-1
content: C:\windows_2000_source_code\win2k\private\windows\base\client\lmem.c     133: HLOCAL     134: WINAPI     135: LocalReAlloc(     136:     HLOCAL hMem,     137:     SIZE_T uBytes,     138:     UINT uFlags     139:     )     140: {     141:     PBASE_HANDLE_TABLE_ENTRY HandleEntry;     142:     LPSTR p;     143:     ULONG Flags;     144:      145:     if ((uFlags & ~(LMEM_VALID_FLAGS | LMEM_MODIFY)) ||     146:         ((uFlags & LMEM_DISCARDABLE) && !(uFlags & LMEM_MODIFY))     147:        ) {     148: #if DBG     149:         DbgPrint( "*** LocalReAlloc( %lx ) - invalid flags\n", uFlags );     150:         BaseHeapBreakPoint();     151: #endif     152:         SetLastError( ERROR_INVALID_PARAMETER );     153:         return( NULL );     154:         }     155:      156:     Flags = 0;     157:     if (uFlags & LMEM_ZEROINIT) {     158:         Flags |= HEAP_ZERO_MEMORY;     159:         }     160:     if (!(uFlags & LMEM_MOVEABLE)) {     161:         Flags |= HEAP_REALLOC_IN_PLACE_ONLY;     162:         }     163:      164:     RtlLockHeap( BaseHeap );     165:     Flags |= HEAP_NO_SERIALIZE;     166:     try {     167:         if ((ULONG_PTR)hMem & BASE_HANDLE_MARK_BIT) {     168:             HandleEntry = (PBASE_HANDLE_TABLE_ENTRY)     169:                 CONTAINING_RECORD( hMem, BASE_HANDLE_TABLE_ENTRY, Object );     170:      171:             if (!RtlIsValidHandle( &BaseHeapHandleTable, (PRTL_HANDLE_TABLE_ENTRY)HandleEntry )) {     172: #if DBG     173:                 DbgPrint( "*** LocalReAlloc( %lx ) - invalid handle\n", hMem );     174:                 BaseHeapBreakPoint();     175: #endif     176:                 SetLastError( ERROR_INVALID_HANDLE );     177:                 hMem = NULL;     178:                 }     179:             else     180:             if (uFlags & LMEM_MODIFY) {     181:                 if (uFlags & LMEM_DISCARDABLE) {     182:                     HandleEntry->Flags |= BASE_HANDLE_DISCARDABLE;     183:                     }     184:                 else {     185:                     HandleEntry->Flags &= ~BASE_HANDLE_DISCARDABLE;     186:                     }     187:                 }     188:             else {     189:                 p = HandleEntry->Object;     190:                 if (uBytes == 0) {     191:                     hMem = NULL;     192:                     if (p != NULL) {     193:                         if ((uFlags & LMEM_MOVEABLE) && HandleEntry->LockCount == 0) {     194:                             if (RtlFreeHeap( BaseHeap, Flags | HEAP_NO_SERIALIZE, p )) {     195:                                 HandleEntry->Object = NULL;     196:                                 HandleEntry->Flags |= BASE_HANDLE_DISCARDED;     197:                                 hMem = (HANDLE)&HandleEntry->Object;     198:                                 }     199:                             }     200:                         else {     201: #if DBG     202:                             DbgPrint( "*** LocalReAlloc( %lx ) - failing with locked handle\n", &HandleEntry->Object );     203:                             BaseHeapBreakPoint();     204: #endif     205:                             }     206:                         }     207:                     else {     208:                         hMem = (HANDLE)&HandleEntry->Object;     209:                         }     210:                     }     211:                 else {     212:                     Flags |= HEAP_SETTABLE_USER_VALUE | BASE_HEAP_FLAG_MOVEABLE;     213:                     if (p == NULL) {     214:                         p = RtlAllocateHeap( BaseHeap, MAKE_TAG( LMEM_TAG ) | Flags, uBytes );     215:                         if (p != NULL) {     216:                             RtlSetUserValueHeap( BaseHeap, HEAP_NO_SERIALIZE, p, hMem );     217:                             }     218:                         }     219:                     else {     220:                         if (!(uFlags & LMEM_MOVEABLE) &&     221:                             HandleEntry->LockCount != 0     222:                            ) {     223:                             Flags |= HEAP_REALLOC_IN_PLACE_ONLY;     224:                             }     225:                         else {     226:                             Flags &= ~HEAP_REALLOC_IN_PLACE_ONLY;     227:                             }     228:      229:                         p = RtlReAllocateHeap( BaseHeap, MAKE_TAG( LMEM_TAG ) | Flags, p, uBytes );     230:                         }     231:      232:                     if (p != NULL) {     233:                         HandleEntry->Object = p;     234:                         HandleEntry->Flags &= ~BASE_HANDLE_DISCARDED;     235:                         }     236:                     else {     237:                         hMem = NULL;     238:                         SetLastError( ERROR_NOT_ENOUGH_MEMORY );     239:                         }     240:                     }     241:                 }     242:             }     243:         else     244:         if (!(uFlags & LMEM_MODIFY)) {     245:             hMem = RtlReAllocateHeap( BaseHeap, MAKE_TAG( LMEM_TAG ) | Flags, (PVOID)hMem, uBytes );     246:             if (hMem == NULL) {     247:                 SetLastError( ERROR_NOT_ENOUGH_MEMORY );     248:                 }     249:             }     250:         }     251:     except (EXCEPTION_EXECUTE_HANDLER) {     252:         hMem = NULL;     253:         BaseSetLastNTError( GetExceptionCode() );     254:         }     255:      256:     RtlUnlockHeap( BaseHeap );     257:      258:     return( (LPSTR)hMem );     259: }

user: user-1
content: 理解和讨论之前请先学会如何观察！  观察的具体办法：Linux下参考相关源代码。Windows下有源代码参考相关源代码，没源代码参考单步时执行过的汇编代码以及中途调用过的API。

user: user-1
content: new是new（≈alloc＋construct） alloc是alloc

user: user-0
content: 引用 32 楼 zhao4zhong1 的回复:不能使用new返回的指针！ 为毛

user: user-0
content: 引用 30 楼 zhao4zhong1 的回复:不过如果遇上realloc较原来大的一块内存，且无法在原地分配（后面紧挨着的内存以被分配）时，还真得在新位置分配新的，再将旧内容拷贝到新位置，然后“自动free掉旧的”。 看来某种程度上我也是二把刀啊！ 老赵，，刚才用代码试过了，WINDOWS下，当发生内存块移动时，以前的那个旧指针用_CrtIsValidHeapPointer函数检查不过，会导致程序挂掉的，或者用_msize函数检查也是一样的结果，，一个有效的地址用这两个检查都是通的过的，，所以是被自动给释放掉的，

user: user-1
content: 不能使用new返回的指针！

user: user-1
content: 以被分配→已被分配

user: user-1
content: 不过如果遇上realloc较原来大的一块内存，且无法在原地分配（后面紧挨着的内存以被分配）时，还真得在新位置分配新的，再将旧内容拷贝到新位置，然后“自动free掉旧的”。 看来某种程度上我也是二把刀啊！

user: user-2
content: realloc()  changes  the  size  of the memory block pointed to by ptr to        size bytes.  The contents will be unchanged to the minimum of  the  old        and new sizes; newly allocated memory will be uninitialized.  If ptr is        NULL, the call is equivalent to malloc(size); if size is equal to zero,        the  call is equivalent to free(ptr).  Unless ptr is NULL, it must have        been returned by an earlier call to malloc(),  calloc()  or  realloc().        If the area pointed to was moved, a free(ptr) is done.

user: user-1
content: realloc的语义是改变原内存块的大小，并没有生成一块新内存，所以就没必要free了。 至于哪个二把刀说“会自动free掉旧的”，权当笑话那么一听吧。  想从根本上理解，可参考Linux源代码中realloc的具体实现代码。

user: user-0
content: 引用 24 楼 zhao4zhong1 的回复:以下回复再次证明本ID只会复制粘贴MSDN内容： realloc Reallocate memory blocks.  void *realloc( void *memblock, size_t size );  Routine Required Header Compatibility  realloc <stdlib.h> and <malloc.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  realloc returns a void pointer to the reallocated (and possibly moved) memory block. The return value is NULL if the size is zero and the buffer argument is not NULL, or if there is not enough available memory to expand the block to the given size. In the first case, the original block is freed. In the second, the original block is unchanged. The return value points to a storage space that is guaranteed to be suitably aligned for storage of any type of object. To get a pointer to a type other than void, use a type cast on the return value.  Parameters  memblock  Pointer to previously allocated memory block  size  New size in bytes  Remarks  The realloc function changes the size of an allocated memory block. The memblock argument points to the beginning of the memory block. If memblock is NULL, realloc behaves the same way as malloc and allocates a new block of size bytes. If memblock is not NULL, it should be a pointer returned by a previous call to calloc, malloc, or realloc.  The size argument gives the new size of the block, in bytes. The contents of the block are unchanged up to the shorter of the new and old sizes, although the new block can be in a different location. Because the new block can be in a new memory location, the pointer returned by realloc is not guaranteed to be the pointer passed through the memblock argument.  realloc calls malloc in order to use the C++ _set_new_mode function to set the new handler mode. The new handler mode indicates whether, on failure, malloc is to call the new handler routine as set by _set_new_handler. By default, malloc does not call the new handler routine on failure to allocate memory. You can override this default behavior so that, when realloc fails to allocate memory, malloc calls the new handler routine in the same way that the new operator does when it fails for the same reason. To override the default, call   _set_new_mode(1)  early in your program, or link with NEWMODE.OBJ.  When the application is linked with a debug version of the C run-time libraries, realloc resolves to _realloc_dbg. For more information about how the heap is managed during the debugging process, see Using C Run-Time Library Debugging Support.  Example  /* REALLOC.C: This program allocates a block of memory for  * buffer and then uses _msize to display the size of that  * block. Next, it uses realloc to expand the amount of  * memory used by buffer and then calls _msize again to  * display the new amount of memory allocated to buffer.  */  #include <stdio.h> #include <malloc.h> #include <stdlib.h>  void main( void ) {    long *buffer;    size_t size;     if( (buffer = (long *)malloc( 1000 * sizeof( long ) )) == NULL )       exit( 1 );     size = _msize( buffer );    printf( "Size of block after malloc of 1000 longs: %u\n", size );     /* Reallocate and show new size: */    if( (buffer = realloc( buffer, size + (1000 * sizeof( long )) ))          ==  NULL )       exit( 1 );    size = _msize( buffer );    printf( "Size of block after realloc of 1000 more longs: %u\n",              size );     free( buffer );    exit( 0 ); }   Output  Size of block after malloc of 1000 longs: 4000 Size of block after realloc of 1000 more longs: 8000   Memory Allocation Routines  See Also   calloc, free, malloc 砖家，，这段文字从头到尾都没有明确的提到说realloc会自动将发生内存块移动时，将旧的内存块给释放掉啊，，，网上说会自动释放，但我想看看标准说明，，还有realloc函数的入参除了是calloc malloc realloc函数返回的结果外，可不可以是new返回的结果？？？？？我要标准说明，，，

user: user-0
content: 引用 23 楼 bug1190 的回复:[quote=引用 10 楼 zhao4zhong1 的回复:] [quote=引用 6 楼 bug1190 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] 严重怀疑楼主不会用realloc函数。 我干，，我暴露了，， 是要配合realloc才能完美解决，，，老赵，我好心给你分享答案，，你来揭我短儿，，[/quote] 用realloc要小心，参考下面： //文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; } [/quote] 老赵，，为什么用realloc分配成功时，不把此前的旧的内存给delete掉一次，不删除不会有内存泄漏吗[/quote] 刚才查资料说是会自动free掉旧的，，，MSDN上没见到有标准说明啊，能否给我引用一段，不要COPY没用的啊

user: user-1
content: free Deallocates or frees a memory block.  void free( void *memblock );  Function Required Header Compatibility  free <stdlib.h> and <malloc.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  Parameter  memblock  Previously allocated memory block to be freed  Remarks  The free function deallocates a memory block (memblock) that was previously allocated by a call to calloc, malloc, or realloc. The number of freed bytes is equivalent to the number of bytes requested when the block was allocated (or reallocated, in the case of realloc). If memblock is NULL, the pointer is ignored and free immediately returns. Attempting to free an invalid pointer (a pointer to a memory block that was not allocated by calloc, malloc, or realloc) may affect subsequent allocation requests and cause errors.  After a memory block has been freed, _heapmin minimizes the amount of free memory on the heap by coalescing the unused regions and releasing them back to the operating system. Freed memory that is not released to the operating system is restored to the free pool and is available for allocation again.  When the application is linked with a debug version of the C run-time libraries, free resolves to _free_dbg. For more information about how the heap is managed during the debugging process, see Using C Run-Time Library Debugging Support.  Example  /* MALLOC.C: This program allocates memory with  * malloc, then frees the memory with free.  */  #include <stdlib.h>         /* For _MAX_PATH definition */ #include <stdio.h> #include <malloc.h>  void main( void ) {    char *string;     /* Allocate space for a path name */    string = malloc( _MAX_PATH );    if( string == NULL )       printf( "Insufficient memory available\n" );    else    {       printf( "Memory space allocated for path name\n" );       free( string );       printf( "Memory freed\n" );    } }   Output  Memory space allocated for path name Memory freed   Memory Allocation Routines  See Also   _alloca, calloc, malloc, realloc, _free_dbg, _heapmin

user: user-1
content: 以下回复再次证明本ID只会复制粘贴MSDN内容： realloc Reallocate memory blocks.  void *realloc( void *memblock, size_t size );  Routine Required Header Compatibility  realloc <stdlib.h> and <malloc.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  realloc returns a void pointer to the reallocated (and possibly moved) memory block. The return value is NULL if the size is zero and the buffer argument is not NULL, or if there is not enough available memory to expand the block to the given size. In the first case, the original block is freed. In the second, the original block is unchanged. The return value points to a storage space that is guaranteed to be suitably aligned for storage of any type of object. To get a pointer to a type other than void, use a type cast on the return value.  Parameters  memblock  Pointer to previously allocated memory block  size  New size in bytes  Remarks  The realloc function changes the size of an allocated memory block. The memblock argument points to the beginning of the memory block. If memblock is NULL, realloc behaves the same way as malloc and allocates a new block of size bytes. If memblock is not NULL, it should be a pointer returned by a previous call to calloc, malloc, or realloc.  The size argument gives the new size of the block, in bytes. The contents of the block are unchanged up to the shorter of the new and old sizes, although the new block can be in a different location. Because the new block can be in a new memory location, the pointer returned by realloc is not guaranteed to be the pointer passed through the memblock argument.  realloc calls malloc in order to use the C++ _set_new_mode function to set the new handler mode. The new handler mode indicates whether, on failure, malloc is to call the new handler routine as set by _set_new_handler. By default, malloc does not call the new handler routine on failure to allocate memory. You can override this default behavior so that, when realloc fails to allocate memory, malloc calls the new handler routine in the same way that the new operator does when it fails for the same reason. To override the default, call   _set_new_mode(1)  early in your program, or link with NEWMODE.OBJ.  When the application is linked with a debug version of the C run-time libraries, realloc resolves to _realloc_dbg. For more information about how the heap is managed during the debugging process, see Using C Run-Time Library Debugging Support.  Example  /* REALLOC.C: This program allocates a block of memory for  * buffer and then uses _msize to display the size of that  * block. Next, it uses realloc to expand the amount of  * memory used by buffer and then calls _msize again to  * display the new amount of memory allocated to buffer.  */  #include <stdio.h> #include <malloc.h> #include <stdlib.h>  void main( void ) {    long *buffer;    size_t size;     if( (buffer = (long *)malloc( 1000 * sizeof( long ) )) == NULL )       exit( 1 );     size = _msize( buffer );    printf( "Size of block after malloc of 1000 longs: %u\n", size );     /* Reallocate and show new size: */    if( (buffer = realloc( buffer, size + (1000 * sizeof( long )) ))          ==  NULL )       exit( 1 );    size = _msize( buffer );    printf( "Size of block after realloc of 1000 more longs: %u\n",              size );     free( buffer );    exit( 0 ); }   Output  Size of block after malloc of 1000 longs: 4000 Size of block after realloc of 1000 more longs: 8000   Memory Allocation Routines  See Also   calloc, free, malloc

user: user-0
content: 引用 10 楼 zhao4zhong1 的回复:[quote=引用 6 楼 bug1190 的回复:] [quote=引用 5 楼 zhao4zhong1 的回复:] 严重怀疑楼主不会用realloc函数。 我干，，我暴露了，， 是要配合realloc才能完美解决，，，老赵，我好心给你分享答案，，你来揭我短儿，，[/quote] 用realloc要小心，参考下面： //文件1中的内容排序并去重,结果保存到文件2中 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCHARS 128      //能处理的最大行宽,包括行尾的\n和字符串尾的\0 int MAXLINES=10000,MAXLINES2; char *buf,*buf2; int c,n,hh,i,L; FILE *f; char ln[MAXCHARS]; int ignore_case=0; int icompare(const void *arg1,const void *arg2) {    return stricmp((char *)arg1,(char *)arg2); } int compare(const void *arg1,const void *arg2) {    return strcmp((char *)arg1,(char *)arg2); } int main(int argc,char **argv) {     if (argc<3) {         printf("Unique line. Designed by zhao4zhong1@163.com. 2012-08-20\n");         printf("Usage: %s src.txt uniqued.txt [-i]\n",argv[0]);         return 1;     }     if (argc>3) ignore_case=1;//若存在命令行参数3，忽略大小写     f=fopen(argv[1],"r");     if (NULL==f) {         printf("Can not find file %s!\n",argv[1]);         return 1;     }     buf=(char *)malloc(MAXLINES*MAXCHARS);     if (NULL==buf) {         fclose(f);         printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES,MAXCHARS);         return 2;     }     n=0;     hh=0;     i=0;     while (1) {         if (NULL==fgets(ln,MAXCHARS,f)) break;//         hh++;         L=strlen(ln)-1;         if ('\n'!=ln[L]) {//超长行忽略后面内容             printf("%s Line %d too long(>%d),spilth ignored.\n",argv[1],hh,MAXCHARS);             while (1) {                 c=fgetc(f);                 if ('\n'==c || EOF==c) break;//             }         }         while (1) {//去掉行尾的'\n'和空格             if ('\n'==ln[L] || ' '==ln[L]) {                 ln[L]=0;                 L--;                 if (L<0) break;//             } else break;//         }         if (L>=0) {             strcpy(buf+i,ln);i+=MAXCHARS;             n++;             if (n>=MAXLINES) {                 MAXLINES2=MAXLINES*2;                 if (MAXLINES2==1280000) MAXLINES2=2500000;                 buf2=(char *)realloc(buf,MAXLINES2*MAXCHARS);                 if (NULL==buf2) {                     printf("Can not malloc(%d LINES*%d CHARS)!\n",MAXLINES2,MAXCHARS);                     printf("WARNING: Lines >%d ignored.\n",MAXLINES);                     break;//                 }                 buf=buf2;                 MAXLINES=MAXLINES2;             }         }     }     fclose(f);     if (n>1) {         if (ignore_case) qsort(buf,n,MAXCHARS,icompare);         else qsort(buf,n,MAXCHARS,compare);     }     f=fopen(argv[2],"w");     if (NULL==f) {         free(buf);         printf("Can not create file %s!\n",argv[2]);         return 2;     }     fprintf(f,"%s\n",buf);     if (n>1) {         if (ignore_case) {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if (stricmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         } else {             hh=0;             L=MAXCHARS;             for (i=1;i<n;i++) {                 if ( strcmp((const char *)buf+hh,(const char *)buf+L)) {                     fprintf(f,"%s\n",buf+L);                 }                 hh=L;                 L+=MAXCHARS;             }         }     }     fclose(f);     free(buf);     return 0; } [/quote] 老赵，，为什么用realloc分配成功时，不把此前的旧的内存给delete掉一次，不删除不会有内存泄漏吗

user: user-3
content: 赵老师在哪里教书啊？

user: user-4
content: c是一个老生常谈的问题，好难

user: user-5
content: 不明觉厉啊！！我是Java系的菜鸟魔法师

user: user-6
content: 我不说话，就看着你们装逼

user: user-7
content: 引用 13 楼 bug1190 的回复:[quote=引用 11 楼 user-7 的回复:] c++中有, std::ostringstream, 再也不用操心这些事情了。 我日你亲哥，在MFC下面或者是在ATL下面，CString也能轻松完成这功能，而且格式都基本不用变，这说的是C好不，看清点[/quote] 难得理你，不要引用我。