使用C中的无符号字符进行神奇打印

时间:2013-10-10 20:16:44

标签: c printing unsigned-char

上个学期我参加了一个操作系统课程。我并不感到惊讶的是,整个班级都是用C语言教授的,但是对它的大量使用似乎让一些人厌烦。当课程结束时,一些不喜欢语言的人正在提高他们的声音,他们不必再用C语言编程。这开始了学生(和老师)之间的一场小小辩论,最后得到了一位教授该课程的老师的回复。他的回答是用C代码写的:

#include <stdio.h>

unsigned char output[] = { 
0xe7, 0x3a, 0x1d, 0x2f, 0x01,
0x92, 0x42, 0x09, 0x48, 0x01,
0x92, 0x32, 0x09, 0x8e, 0x01,
0x92, 0x0a, 0x09, 0x48, 0x01,
0xe7, 0x73, 0xdd, 0x2f, 0x00,
};

int main() {
    unsigned char* wb;
    int i;
    for (wb = output; *wb; wb++) {

        if (*wb == 0x01) {
            printf("\n");
            continue;
        }

        for (i = 7; i >= 0; i--) {
            putchar((((*wb >> i) & 1) + 0x20));
        }
    }
    printf("\n");
    return 0;
}

打印:

!!!  !!!  !!! !    !!! !  ! !!!!
!  !  !  !    !     !  ! !  !   
!  !  !   !!  !     !  !!   !!! 
!  !  !     ! !     !  ! !  !   
!!!  !!! !!!  !!!! !!! !  ! !!!!

这是关于我一生中看到C C代码做过的最酷的事情! 谁能向我解释这是怎么做到的?

[编辑:为了清晰起见调整了缩进]

2 个答案:

答案 0 :(得分:1)

一个提示,请考虑数组output的二进制表示。这种技术出现的地方在于控制硬件寄存器中的位,就像在嵌入式系统中那样 - 这是C真正发光的地方。

答案 1 :(得分:1)

是的,我看到现在看起来很容易。

所以基本上他将char指针赋给输出并在for循环中运行它。 对于它击中的每个十六进制数,它将它向右移动i次,我从7开始,并且i> = 0

所以例如

./bits 0xe7 shift 7

============<<0xe7>>============
Decimal: 231 
Bits: [11100111] 

==========<<Shifted>>===========
Decimal: 1 
Bits: [00000001] >> 7
然后他继续和&amp; (和)结果为1,在这种情况下将返回

00000001
00000001
--------
       1

bang(!)字符的绘制取决于我们的结果,并且为结果提供'0'或'1',因为最后但并非最不重要的是他将shift /和结果添加到十六进制数0x20。

0x20是十进制数32,具有白色空格的字符表示,所以如果并且恰好返回0我们只是绘制一个空格,否则添加1个,我们得到十进制数33,它有一个字符爆炸的表现。

当然,有几点需要注意,比如你们都指出有终止值0x00和0x01来表示换行符。

在每行中,他打印32个字符,或4 * 8,因为他为每个十六进制值打印了8个字符。

感谢大家提出我自己的解决方案,因为这比获得答案更有趣;)