C中的动态分配

Ker*_*y82 4 c memory-management

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

char *tmp;
sprintf (tmp,"%ld",(long)time_stamp_for_file_name);
Run Code Online (Sandbox Code Playgroud)

有人可以解释为字符串tmp分配多少内存.

有多少个字符是长变量?

谢谢,

我还希望能够获得有关此类信息的详尽资源.

谢谢

更新:

使用您的示例我遇到了以下问题:

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]$
Run Code Online (Sandbox Code Playgroud)

所以snprintf的len结果是-1,我使用标准编译器在Solaris 9上编译.

请帮我!

gnu*_*nud 6

如果您的编译器符合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();
}
Run Code Online (Sandbox Code Playgroud)

标准的相关部分(来自草案文件):

  • 7.19.6.5.2:如果n为零,则不写入任何内容,s可以是空指针.
  • 7.19.6.5.3:snprintf函数返回已经写入的字符数已足够大,不计算终止空字符,如果发生编码错误则返回负值.因此,当且仅当返回值是非负且小于n时,才完全写入以null结尾的输出.

如果这不起作用,我猜你的编译器/ libc不支持c99的这一部分,或者你可能需要明确启用它.我运行你的例子(使用gcc版本4.5.0 20100610(预发布),Linux 2.6.34-ARCH),我得到了

$./example
Lunghezza:di 12345678 8
Run Code Online (Sandbox Code Playgroud)


unw*_*ind 5

很难提前知道,但我想你可以推测将会有这将是最多64位,因而"18,446,744,073,709,551,615"应该是最大可能值.这是2 + 6*3 = 20位数,通常不包括逗号.负数是21.因此,请将32个字节作为一个漂亮的圆形大小.

更好的方法是将其与使用相结合snprintf(),因此如果您的估计已关闭,则不会出现缓冲区溢出.


Ste*_*sop 5

实际使用的字符数明显取决于值:如果time_stamp_for_file_name为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);
Run Code Online (Sandbox Code Playgroud)

注意实现,其中snprintf返回-1表示空间不足,而不是所需的空间.

正如Paul R所说,你可以根据实现的大小找出一个固定的上限long.这样就可以完全避免动态分配.例如:

#define LONG_LEN (((sizeof(long)*CHAR_BIT)/3)+2)
Run Code Online (Sandbox Code Playgroud)

(基于10的base-2 log大于3的事实).+2给出1为减号,1给出整数除法向下舍入的事实.你需要另外一个nul终结器.

要么:

#define STRINGIFY(ARG) #ARG
#define EXPAND_AND_STRINGIFY(ARG) STRINGIFY(ARG)

#define VERBOSE_LONG EXPAND_AND_STRINGIFY(LONG_MIN)
#define LONG_LEN sizeof(VERBOSE_LONG)

char tmp[LONG_LEN];
sprintf(tmp, "%ld", (long)time_stamp_for_file_name);
Run Code Online (Sandbox Code Playgroud)

VERBOSE_LONG可能是一个比你实际需要的更大的字符串.在我的编译器上它(-2147483647L-1).我不确定是否LONG_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
Run Code Online (Sandbox Code Playgroud)

但我怀疑这是值得的:更好的方法是在某种可移植头中定义它并为新平台手动配置它.