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上编译.
请帮我!
如果您的编译器符合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)
标准的相关部分(来自草案文件):
如果这不起作用,我猜你的编译器/ libc不支持c99的这一部分,或者你可能需要明确启用它.我运行你的例子(使用gcc版本4.5.0 20100610(预发布),Linux 2.6.34-ARCH),我得到了
$./example
Lunghezza:di 12345678 8
Run Code Online (Sandbox Code Playgroud)
很难提前知道,但我想你可以推测将会有这将是最多64位,因而"18,446,744,073,709,551,615"应该是最大可能值.这是2 + 6*3 = 20位数,通常不包括逗号.负数是21.因此,请将32个字节作为一个漂亮的圆形大小.
更好的方法是将其与使用相结合snprintf(),因此如果您的估计已关闭,则不会出现缓冲区溢出.
实际使用的字符数明显取决于值:如果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)
但我怀疑这是值得的:更好的方法是在某种可移植头中定义它并为新平台手动配置它.