我正在编写程序,我遇到以下问题:
char *tmp;
sprintf (tmp,"%ld",(long)time_stamp_for_file_name);
有人可以解释为字符串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]$
因此snprintf的len结果为-1,我使用标准编译器在Solaris 9上编译。
请帮助我!
答案 0 :(得分: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();
}
标准的相关部分(来自draft document):
如果这不起作用,我猜你的编译器/ libc不支持c99的这一部分,或者你可能需要明确启用它。我运行你的例子(使用gcc版本4.5.0 20100610(预发布),Linux 2.6.34-ARCH),我得到了
$./example
Lunghezza:di 12345678 8
答案 1 :(得分:5)
事先很难说,虽然我猜你可以猜测它最多只能是64位,因此“18,446,744,073,709,551,615”应该是最大的可能值。这是2 + 6 * 3 = 20位数,通常不包括逗号。负数是21。所以,将32个字节作为一个漂亮的圆形大小。
最好将其与使用snprintf()
结合使用,这样如果您的估算已关闭,则不会出现缓冲区溢出。
答案 2 :(得分: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);
注意snprintf
为空间不足而返回-1的实现,而不是所需的空间。
正如Paul R所说,你可以根据实现中long
的大小确定一个固定的上限。这样就可以完全避免动态分配。例如:
#define LONG_LEN (((sizeof(long)*CHAR_BIT)/3)+2)
(基于10的base-2 log大于3的事实)。 +2给出1为减号,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);
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
但我怀疑这是值得的:更好的方法是在某种可移植头中定义它并为新平台手动配置它。
答案 3 :(得分:3)
这取决于系统中long
的大小。假设64位的最坏情况,则最多需要22个字符 - 这允许20个数字,前面的-
和终止\0
。当然,如果你感觉奢侈,你可以总是允许一点点额外的东西,并使它成为一个很好的圆形数字,如32。
答案 4 :(得分:2)
以log 2 10(~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 */
“+2”表示符号和0终结符。
答案 5 :(得分:1)
八进制每三位需要一个字符。打印到10的基数,对于相同的数字,它从不给出比八进制更多的数字。因此,为每三位分配一个字符。
sizeof(long)在编译时为您提供字节数。乘以8得到位。在除以3之前添加两个,这样你就可以获得天花板而不是地板。请记住,C字符串需要最后的零字节,因此在结果中添加一个字节。 (另一个是否定的,如评论中所述)。
char tmp[(sizeof(long)*8+2)/3+2];
sprintf (tmp,"%ld",(long)time_stamp_for_file_name);
答案 6 :(得分:0)
3*sizeof(type)+2
是将整数类型type
格式化为十进制字符串所需的字节数的安全通用规则,原因是3是log10(256)
的上限并且n
字节整数是base-256中的n
个数字,因此基数为10的ceil(log10(256^n))==ceil(n*log10(256))
个数字。+2
用于说明终止NUL字节和可能的减号如果type
非常小。
如果你想成为迂腐的人并且使用CHAR_BIT!=8
支持DSP等,那么请使用3*sizeof(type)*((CHAR_BIT+7)/8)+2
。 (请注意,对于POSIX系统,这是无关紧要的,因为POSIX需要UCHAR_MAX==255
和CHAR_BIT==8
。)