C编程-整数/长到字符串表示法

C编程-整数/长到字符串表示法,c,arrays,printf,long-integer,C,Arrays,Printf,Long Integer,我只是在读“C接口和实现”。书中描述了一些非常有趣的概念。代码有时很难看(在我看来),但现在我遇到了一个关于将整数/长字符转换为字符串(字符数组)的问题。书中描述的是: 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

我只是在读“C接口和实现”。书中描述了一些非常有趣的概念。代码有时很难看(在我看来),但现在我遇到了一个关于将整数/长字符转换为字符串(字符数组)的问题。书中描述的是:

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);
}

有什么区别吗?关于我使用sprintf的“简单”方法,我有没有遗漏任何可能导致与本书中的函数不同的结果?我的意思是,如果只是为了展示如何不使用ltoa/sprintf/将长字符串转换为字符串,那就太好了。但是如果这是唯一的原因,那么它就不必要复杂了,…

您为这两个函数发布的原始代码有两个主要问题:

  • str
    数组未
    '\0'
    终止,在传递到
    printf
    时调用未定义的行为
  • 将指针
    s
    返回到具有自动存储
    str
    的数组也是不正确的。取消引用此返回值也将调用未定义的行为
关于您的问题,第一个函数的目的是展示整数到字符串转换器的实现。使用
sprintf
无法达到此目的。注意作者如何处理
INT\u MIN
:计算
-n
会调用未定义的行为,因为大多数系统上都存在整数溢出,即使结果在所有现代系统上都是正确的。但是,完全符合标准操作系统是一门困难的艺术:他的解决方案假定是2s补充,否则将失败

这是一个使用相同原型的改进解决方案。它更便于携带,不需要特殊情况下的长时间,进行更少的除法和模运算

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);
}

同意,第一个函数不会0终止。这两个函数都返回指向自动存储的指针。丑陋的除此之外,只要看看“long-to-char-array”转换过程:任何能说明这个过于复杂的版本的东西?
snprintf
都比
sprintf
@a3f:好吧,那么你应该这么说。C不仅仅是PC、服务器和ARM。不管怎么说,这就是为什么我们有并需要。实际上,这些不完整的问题不应该回答,而是要求先完成。@a3f:我发布了一个更简单、更可移植的解决方案,可以处理2s补码表示的不对称范围。它只假定
long
类型的最大范围在128位左右。@artm:在原始代码中,return语句使用局部变量
s
s
被初始化为指向自动数组
str
的末尾,并且仅通过连续递减操作进行相对更新。编译器似乎不够聪明,无法确定
s
仍然指向自动存储。在这种情况下,这似乎是可行的,可惜的是,
gcc
无法做到这一点,但在一般情况下,这要困难得多,而且可能是不可能的。你不应该指望书中的
C接口和实现中的内置函数会违背这本书的目的。我的这本书已经
返回了Atom\u new,(str+sizeof str)-s)
而不是
返回s
。如果该函数真的是书中的1:1,则最终获得另一本书!它返回一个带有无效值的指针!是的,你是对的。也没有“printf”打印值。这只是出于测试目的,也就是删除返回的Atom_new…@inzanez:通过声明代码来自一本书,但实际上修改了它,并在破坏它的过程中,你以一种严重损害作者声誉的方式歪曲了这本书。如果我是你,我会编辑这本书如果我是作者,我现在会非常生气。
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);
}
const char *Atom_int(long n) {
    char str[43];
    return Atom_new(str, snprintf(str, sizeof str, "%ld", n));
}