将数字转换为不同的表示法

时间:2012-01-17 04:40:37

标签: c pointers

这是将数字转换为八进制,十进制,十六进制等不同表示的程序。

    #include<stdio.h>

    char *convert(unsigned int num, int base)
    {
    static char buff[33];
    char *ptr;
    ptr=&buff[sizeof(buff)-1];
    *ptr='\0';
    do
    {
    *--ptr="0123456789abcdef"[num%base];
    num/=base;
    }while(num!=0);
    return(ptr);
    }

    int main(){

    puts(convert(65,8));
    puts(convert(65,10));
    puts(convert(65,16));
    return 0;
    }

输出给出101,65和41(即数字'65'分别以八进制,十进制和十六进制表示法表示)

我非常了解最新情况,但我从来没有遇到像

这样的事情
*--ptr="0123456789abcdef"[num%base]

我理解它的工作,但我不明白它是如何有效的符号。有人请在这里解释0123456789abcdef(文字字符数组)部分。

3 个答案:

答案 0 :(得分:9)

这是一件可怕的工作;任何写过它的人都应该在棚子的后面取出并被殴打,直到他们承诺永远不会再在IOCCC(国际混淆的C代码竞赛)的条目之外再写这样的代码。

表达式的右侧

*--ptr = "0123456789abcdef"[num%base];

正在利用字符串文字转换为指针的事实。如果你看到:

const char digit[] = "0123456789ABCDEF";
*--ptr = digit[num%base];
你不会担心。字符串文字的表达式与此相同。 (至少他们有不写的优雅:

*--ptr = (num % base)["0123456789ABCDEF"];

这也取决于以下关系:

a[i] <==> i[a] <==> *(a + i) <==> *(i + a)

其中双头箭头表示等效性。

*--ptr的使用是向后提取数字,从最小到最重要。它的工作原理是因为指针初始化为静态缓冲区的末尾(因为函数的返回值是指向该缓冲区的指针,所以它是静态的至关重要。)

但是,代码不是很有用,因为您无法保存呼叫中的值,并在以后再次打电话时打印它。你不能写:

printf("%s = %s = %sn", convert(65,8), convert(65,10), convert(65,16));

或者,更准确地说,你可以,但你会看到三次相同的值第一个位置的“101”,“164”或“140”之一,以及“01”或者对于其他两个位置为“64”或“40”,并且C标准没有定义您将看到的值。静态缓冲区还可以防止代码是线程安全的。

总而言之,这是一个奇怪的炫耀代码,用于挑逗初学者。它有效,但这就是关于它的所有可以说的。它也没有检查其基础的有效性,因此convert(65, 18)可能导致未定义的行为。 (最糟糕的是,基数为17会引用一个无意的'\0',导致混淆。)

答案 1 :(得分:4)

哇,这很简洁,难以阅读。我理解你的困惑,但我想我可以帮忙。

*--ptr =表示“递减此指针并在递减后为​​地址指定一些值。”

"0123456789abcdef"是一个文字char数组。

[num%base]正在订阅上一个char数组,下标为num modulo base

这一行包含几个东西,如果完全展开,将如下所示:

char arr[] = "0123456789abcdef";
int subscript = num % base;
ptr = ptr - 1;
*ptr = arr[subscript];

答案 2 :(得分:1)

它鬼鬼祟祟的短手 - 想想它更像这样

char array[]="0123456789abcdef";
*--ptr=array[num%base];