这是将数字转换为八进制,十进制,十六进制等不同表示的程序。
#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(文字字符数组)部分。
答案 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];