C语言中的动态分配

C语言中的动态分配,c,memory-management,C,Memory Management,我正在写一个程序,我有以下问题: char *tmp; sprintf (tmp,"%ld",(long)time_stamp_for_file_name); root@-[/tmp]$cat test.c #include <stdio.h> int main() { int len; long time=12345678; char *tmp;

我正在写一个程序,我有以下问题:

char *tmp;
sprintf (tmp,"%ld",(long)time_stamp_for_file_name);
root@-[/tmp]$cat test.c

       #include <stdio.h>
       int
       main()
       {
            int len;
            long time=12345678;
            char *tmp;
            len=snprintf(NULL,0,"%ld",time);
            printf ("Lunghezza:di %ld %d\n",time,len);      
            return 0;
       }

root@-[/tmp]$gcc test.c
root@-[/tmp]$./a.out 
Lunghezza:di 12345678 -1
root@-[/tmp]$
有人能解释一下为字符串tmp分配了多少内存吗

一个长变量有多少个字符

谢谢,

我也希望能链接到这类信息的Exahusive资源

多谢各位

更新:

使用您的示例,我发现了以下问题:

char *tmp;
sprintf (tmp,"%ld",(long)time_stamp_for_file_name);
root@-[/tmp]$cat test.c

       #include <stdio.h>
       int
       main()
       {
            int len;
            long time=12345678;
            char *tmp;
            len=snprintf(NULL,0,"%ld",time);
            printf ("Lunghezza:di %ld %d\n",time,len);      
            return 0;
       }

root@-[/tmp]$gcc test.c
root@-[/tmp]$./a.out 
Lunghezza:di 12345678 -1
root@-[/tmp]$
root@-[/tmp]$cat test.c
#包括
int
main()
{
内伦;
长时间=12345678;
char*tmp;
len=snprintf(空,0,“%ld”,时间);
printf(“Lunghezza:di%ld%d\n”,时间,len);
返回0;
}
root@-[/tmp]$gcc test.c
root@-[/tmp]$./a.out
Lunghezza:di 12345678-1
根@-[/tmp]$
所以snprintf的len结果是-1,我使用标准编译器在solaris9上编译


请帮帮我

这取决于系统上的
长度有多大。假设最坏的情况是64位,那么您最多需要22个字符-这允许20位,一个前置
-
和一个终止
\0
。当然,如果你觉得自己太奢侈了,你可以多给点钱,让它成为一个很好的整数,比如32。

很难提前知道,尽管我猜你可以猜到它最多是64位,因此“18446744073709551615”应该是最大的可能值。即2+6*3=20位,通常不包括逗号。负数是21。因此,选择32字节作为一个漂亮的圆形大小


更好的做法是将其与使用
snprintf()
结合使用,这样如果估计值不正确,就不会出现缓冲区溢出。

实际使用的字符数显然取决于值:如果文件名的
时间戳为0,则实际上只需要2个字节。如果有任何疑问,您可以使用
snprintf
,它告诉您需要多少空间:

int len = snprinf(0, 0, "%ld", (long)time_stamp_for_file_name) + 1;
char *tmp = malloc(len);
if (tmp == 0) { /* handle error */ }
snprintf(tmp, len, "%ld", (long)time_stamp_for_file_name);
注意
snprintf
返回-1表示空间不足而不是所需空间的实现

正如Paul R所说,您可以根据实现的
long
的大小来确定一个固定的上限。这样可以完全避免动态分配。例如:

#define LONG_LEN (((sizeof(long)*CHAR_BIT)/3)+2)
(基于10的base-2对数大于3的事实)。+2表示负号为1,整数除法向下舍入为1。你需要为nul终结者再加一个1

或:

VERBOSE\u LONG
可能比实际需要的字符串稍大。在我的编译器上是
(-2147483647L-1)
。我不确定
LONG\u MIN
是否可以扩展到类似十六进制文字或编译器内部的内容,但如果是这样,那么它可能太短,而且这个技巧不会起作用。不过,单元测试很容易

如果您想要一个严格的上限来覆盖标准中的所有可能性,达到某个极限,您可以尝试以下方法:

#if LONG_MAX <= 2147483647L
    #define LONG_LEN 11
#else
    #if LONG_MAX <= 4294967295L
        #define LONG_LEN 11
    #else
        #if LONG_MAX <= 8589934591L
            ... etc, add more clauses as new architectures are
                     invented with bigger longs
        #endif
    #endif
#endif

#如果LONG_MAX如果您的编译器符合C99,您应该能够执行以下操作:

char *tmp;
int req_bytes = snprintf(NULL, 0, "%ld",(long)time_stamp_for_file_name);
tmp = malloc(req_bytes +1); //add +1 for NULL
if(!tmp) {
    die_horrible_death();
}
if(snprintf(tmp, req_bytes+1, "%ld",(long)time_stamp_for_file_name) != req_bytes) {
    die_horrible_death();
}
本标准的相关部分(摘自):

  • 7.19.6.5.2:如果n为零,则不写入任何内容,s可以是空指针
  • 7.19.6.5.3:snprintf函数返回本应写入的字符数 n是否足够大,不包括终止的空字符或负数 值(如果发生编码错误)。因此,空终止的输出已被删除 完全写入当且仅当返回值为非负且小于n时
如果这不起作用,我猜您的编译器/libc不支持c99的这一部分,或者您可能需要显式地启用它。当我运行您的示例时(使用gcc版本4.5.0 20100610(预发行版),Linux 2.6.34-ARCH),我得到


八进制要求每三位有一个字符。你们打印到10的底部,对于同一个数字,它的位数永远不会超过八进制。因此,每三位分配一个字符

sizeof(long)提供编译时的字节数。将其乘以8得到位。在除以三之前加上二,这样你得到的是天花板而不是地板。请记住,C字符串的末尾需要最后一个零字节,因此在结果中添加一个。(另一个表示否定,如评论中所述)

它需要log210(~3.32)位来表示十进制数字;因此,您可以这样计算位数:

#include <limits.h>
#include <math.h>

long time;
double bitsPerDigit = log10(10.0) / log10(2.0); /* or log2(10.0) in C99 */
size_t digits = ceil((sizeof time * (double) CHAR_BIT) / bitsPerDigit);

char *tmp = malloc(digits+2); /* or simply "char tmp[digits+2];" in C99 */
#包括
#包括
长时间;
双位sperdigit=log10(10.0)/log10(2.0);/*或C99中的log2(10.0)*/
size_t digits=ceil((时间大小*(双)字符位)/bitsPerDigit);
char*tmp=malloc(数字+2);/*或者在C99中简单地“char tmp[digits+2];”*/
“+2”表示符号和0终止符

3*sizeof(type)+2
是将整数类型
type
格式化为十进制字符串所需字节数的安全通用规则,原因是3是
log10(256)
的上限,而
n
字节整数是
n
基数256中的数字,因此
ceil(log10(256^n))==ceil(n*log10(256))
以10为底的数字。如果
类型
非常小,则
+2
用于说明终止的NUL字节和可能的减号


如果你想学究气,支持DSP之类的
CHAR\u位=8
然后使用
3*sizeof(type)*((字符位+7)/8)+2
。(注意POSIX系统这是不相关的,因为POSIX需要<代码> UCHARORMAX=255 和<代码> CARYBIT==8 )。重要注意事项:微软Visual C++编译器(MSVC)不符合C99。我不知道是否实现了这个特殊功能,但它并不正式支持1999年的标准;仍然有一些古怪的平台使用8以外的字节大小。这太疯狂了。你能给我找一些这样的平台吗?我认为一些PIC平台可能包含byt的其他位宽度
#include <limits.h>
#include <math.h>

long time;
double bitsPerDigit = log10(10.0) / log10(2.0); /* or log2(10.0) in C99 */
size_t digits = ceil((sizeof time * (double) CHAR_BIT) / bitsPerDigit);

char *tmp = malloc(digits+2); /* or simply "char tmp[digits+2];" in C99 */