inz*_*nez -4 c arrays printf long-integer
我只是在阅读"C接口和实现".书中描述了一些非常有趣的概念.有时(在我看来)代码非常难看,但现在我有一个关于将整数/长转换为字符串(char数组)的问题.书中描述的是:
const char *Atom_int(long n) {
char str[43];
char *s = str + sizeof str;
unsigned long m;
if (n == LONG_MIN)
m = LONG_MAX + 1UL;
else if (n < 0)
m = -n;
else
m = n;
do
*--s = m%10 + '0';
while ((m /= 10) > 0);
if (n < 0)
*--s = '-';
return Atom_new(s, str + sizeof str - s);
}
Run Code Online (Sandbox Code Playgroud)
因为没有描述为什么使用这个函数的方式......我想知道为什么它不仅仅是简单的东西:
const char *Atom_int(long n)
{
char str[43];
char *s = str;
sprintf(str, "%ld", n);
return Atom_new(s, str + sizeof str - s);
}
Run Code Online (Sandbox Code Playgroud)
有什么区别吗?我错过了任何关于使用sprintf的"简单"方法的东西,它可能导致与书中的功能不同的结果?我的意思是,如果仅仅是为了展示如何将长片转换为不使用ltoa/sprintf/...的字符串,那就太好了.但如果这是唯一的原因,这是不必要的复杂,......
您为这两个函数发布的原始代码存在两个主要问题:
str
阵列并不'\0'
终止,传递给调用时未定义的行为printf
.s
具有自动存储的数组的指针str
也是不正确的.取消引用此返回值也将调用未定义的行为.关于你的问题,第一个函数的目的是显示一个整数到字符串转换器的实现.使用sprintf
失败了这个目的.请注意作者如何处理以下情况INT_MIN
:-n
由于大多数系统上的整数溢出,计算会调用未定义的行为,尽管结果在所有现代系统上都是正确的.但完全符合标准是一项困难的艺术:他的解决方案假定2s补充,否则将失败.
这是一个使用相同原型的改进解决方案.它更加便携,不需要特殊情况LONG_MIN
,减少了分区和模数操作.
const char *Atom_int(long n) {
char str[43];
char *s = str + sizeof str;
unsigned long m;
if (n < 0)
m = (unsigned long)-(n + 1) + 1;
else
m = n;
while (m >= 10) {
*--s = m % 10 + '0';
m /= 10;
}
*--s = m + '0';
if (n < 0)
*--s = '-';
return Atom_new(s, str + sizeof str - s);
}
Run Code Online (Sandbox Code Playgroud)
另请注意,您提出的替代方案不正确:您传递的错误长度为Atom_new()
.您应该传递sprintf
或返回的字节数snprintf
.这是一个改进版本:
const char *Atom_int(long n) {
char str[43];
return Atom_new(str, snprintf(str, sizeof str, "%ld", n));
}
Run Code Online (Sandbox Code Playgroud)