This is What Peak Hello World Looks Like

栏目: IT技术 · 发布时间: 5年前

内容简介:Everybody’s done a Hello World program before. But now that I’ve got a few years of experience with the language, I set out to ask one of the most pressing questions out there - how do we make Hello World in C as convoluted and hard to understand as possib

Everybody’s done a Hello World program before. But now that I’ve got a few years of experience with the language, I set out to ask one of the most pressing questions out there - how do we make Hello World in C as convoluted and hard to understand as possible? This post documents the final result of a sleep-deprived me trying to do exactly that.

I quickly realized I had to set a few ground rules first so there would be a sensible limit for lines of code that are “useless”:

  • Since we’re using pure C, we won’t have classes (so no HelloWorldFactoryFactoryFactorySingleton s)
  • All #include directives should be essential to the program (so no chaining a billion .h files)
  • Each function must do something essential to the program (so no functions that just call another or useless #defines )
  • The program takes no input, and writes Hello World! exactly to the terminal (so no other calculations are done)

With that, let’s start by building our string in a separate function with malloc instead:

#include <stdio.h>
#include <stdlib.h>

char* generate_words() {
  char* ret = malloc(13);

  ret[0] = 'H';
  ret[1] = 'e';
  ret[2] = 'l';
  ret[3] = 'l';
  ret[4] = 'o';
  ret[5] = ' ';
  ret[6] = 'W';
  ret[7] = 'o';
  ret[8] = 'r';
  ret[9] = 'l';
  ret[10] = 'd';
  ret[11] = '!';
  ret[12] = '\0'; // Can't forget our null operator!

  return ret;
}

int main() {
  char *ret = generate_words();
  printf(ret);
  free(ret);
  return 0;
}

That’s already much more complicated than before, but we can make it even worse! Replacing our direct assignments of letters to bitwise operations gets us this monstrosity:

#include <stdio.h>
#include <stdlib.h>

char* generate_words() {
  char* ret = malloc(12);
  char c = 0x01;

  ret[0] = (c << 6) | (c << 3); // H is 0x48
  ret[1] = c | (c << 2) | (c << 5) | (c << 6); // 'e' is 101
  ret[2] = ((c | (c << 1)) << 2) | ((c | (c << 1)) << 5); // 'l' is 108
  ret[3] = ((c | (c << 1)) << 2) | ((c | (c << 1)) << 5); // 'l' is 108
  ret[4] = (c | (c << 1)) | ((c | (c << 1)) << 2) | ((c | (c << 1)) << 5); // 'o' is 111
  ret[5] = (c << 5); // ' ' is 32
  ret[6] = c | (c << 2) | (c << 1) | (c << 1) << 3 | (c << 1) << 5; // 'W' is 87
  ret[7] = (c | (c << 1)) | ((c | (c << 1)) << 2) | ((c | (c << 1)) << 5); // 'o' is 111
  ret[8] = (c << 1) | ((c << 1) | (c << 2) | c) << 4; // 'r' is 114
  ret[9] = ((c | (c << 1)) << 2) | ((c | (c << 1)) << 5); // 'l' is 108
  ret[10] = (c << 2) | (c << 5) | (c << 6); // 'd' is 100
  ret[11] = (c << 5) | c; // '!' is 33

  return ret;
}

int main() {
  char *ret = generate_words();
  printf(ret);
  free(ret);
  return 0;
}

As you can see, I’ve added comments and some extra brackets for readability’s sake. However, what if we remove our c variable to save space and only depend on previously defined values in ret for our calculations?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

volatile u_int8_t a = 0 - 1;
volatile u_int8_t * z = NULL;

int main() {
    a == 0 - 1 ? z = aligned_alloc(sysconf(_SC_LEVEL1_DCACHE_LINESIZE), 1 * 10 + 3) : a != 1 * 10 + 3 ? z[a] = a == 0 ? z[a] = (1 << (a + 6)) | (1 << (a + 3)) : a == 1 ? (z[a - 1] & (1 << (a + 5))) | (z[a - 1] >> a) | (z[a - 1] >> (a + 5))  : a == 2 ? z[a - 2] | z[1] & ~(z[a - 2] >> (a + 4)) : a == 4 ? z[a - 2] | z[a - 3] | (z[a - 4] >> (a + 1)) : a == 5 ? (z[a - 4] & z[a - 3] & z[a - 5]) >> (a - 4) : a == 6 ? (z[a - 2] & ~z[a - 1] | (z[a - 6] >> (a - 4))) & ~(z[a - 6] >> (a - 2) << (a - 5)) : a == 8 ? (~z[a - 7] & z[a - 2]) | z[a - 3] | z[a - 3] << (a - 7) : a == 10 ? z[a - 9] & ~(z[a - 5] >> (a - 5)) : a == 11 ? z[a - 6] | ((z[a - 1] & z[a - 3]) >> (a - 5)) : a - a : 0; if(a == 1 * 10 + 3) {memcpy(z + 3, z + 2, 1);memcpy(z + 9, z + 3, 1);memcpy(z + 7, z + 4, 1);printf("%s", z);free(z);return 0;}a = a + 1;main();
}
u_int8_t* generate_words() {
  u_int8_t * ret = malloc(13);

  ret[0] = (1 << 6) | (1 << 3);
  ret[1] = (ret[0] & (1 << 6)) | (ret[0] >> 1) | (ret[0] >> 6);
  ret[2] = ret[0] | ret[1] & ~(ret[0] >> 6);
  ret[4] = ret[2] | ret[1] | (ret[0] >> 5);
  ret[5] = (ret[1] & ret[2] & ret[0]) >> 1;
  ret[6] = (ret[4] & ~ret[5] | (ret[0] >> 2)) & ~(ret[0] >> 4 << 1);
  ret[8] = (~ret[1] & ret[6]) | ret[5] | ret[5] << 1;
  ret[10] = ret[1] & ~(ret[5] >> 5);
  ret[11] = ret[5] | ((ret[10] & ret[8]) >> 6);
  ret[12] = 0;

  memcpy(ret + 3, ret + 2, 1);
  memcpy(ret + 9, ret + 3, 1);
  memcpy(ret + 7, ret + 4, 1);

  ret[12] = 0;

  return ret;
}

int main() {
  u_int8_t *ret = generate_words();
  printf("%s", ret);
  free(ret);
  return 0;
}

Now our code’s starting to look good (bad?). The only problem is that it takes way too long to run - my super-powerful laptop processor from two years ago took nearly 5 milliseconds to run it! Well, we could also optimize it to be cache-aligned for maximum performance :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zconf.h>

u_int8_t* generate_words() {
    u_int8_t * ret = aligned_alloc(sysconf(_SC_LEVEL1_DCACHE_LINESIZE), 13);

    ret[0] = (1 << 6) | (1 << 3);
    ret[1] = (ret[0] & (1 << 6)) | (ret[0] >> 1) | (ret[0] >> 6);
    ret[2] = ret[0] | ret[1] & ~(ret[0] >> 6);
    ret[4] = ret[2] | ret[1] | (ret[0] >> 5);
    ret[5] = (ret[1] & ret[2] & ret[0]) >> 1;
    ret[6] = (ret[4] & ~ret[5] | (ret[0] >> 2)) & ~(ret[0] >> 4 << 1);
    ret[8] = (~ret[1] & ret[6]) | ret[5] | ret[5] << 1;
    ret[10] = ret[1] & ~(ret[5] >> 5);
    ret[11] = ret[5] | ((ret[10] & ret[8]) >> 6);
    ret[12] = 0;

    memcpy(ret + 3, ret + 2, 1);
    memcpy(ret + 9, ret + 3, 1);
    memcpy(ret + 7, ret + 4, 1);

    ret[12] = 0;

    return ret;
}

int main() {
    u_int8_t *ret = generate_words();
    printf("%s", ret);
    free(ret);
    return 0;
}

Well, now we’ve got way too many lines. Let’s trim down on it by getting rid of the function and putting our code into a for loop:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main() {
    u_int8_t * ret = aligned_alloc(sysconf(_SC_LEVEL1_DCACHE_LINESIZE), 13);

    for (__auto_type i = 0; i < 13; i++) {
        if (i == 0)
            ret[i] = (1 << (i + 6)) | (1 << (i + 3));
        else if (i == 1)
            ret[i] = (ret[i - 1] & (1 << (i + 5))) | (ret[i - 1] >> i) | (ret[i - 1] >> (i + 5));
        else if (i == 2)
            ret[i] = ret[i - 2] | ret[1] & ~(ret[i - 2] >> (i + 4));
        else if (i == 4)
            ret[i] = ret[i - 2] | ret[i - 3] | (ret[i - 4] >> (i + 1));
        else if (i == 5)
            ret[i] = (ret[i - 4] & ret[i - 3] & ret[i - 5]) >> (i - 4);
        else if (i == 6)
            ret[i] = (ret[i - 2] & ~ret[i - 1] | (ret[i - 6] >> (i - 4))) & ~(ret[i - 6] >> (i - 2) << (i - 5));
        else if (i == 8)
            ret[i] = (~ret[i - 7] & ret[i - 2]) | ret[i - 3] | ret[i - 3] << (i - 7);
        else if (i == 10)
            ret[i] = ret[i - 9] & ~(ret[i - 5] >> (i - 5));
        else if (i == 11)
            ret[i] = ret[i - 6] | ((ret[i - 1] & ret[i - 3]) >> (i - 5));
        else
            ret[i] = i - i;
    }

    memcpy(ret + 3, ret + 2, 1);
    memcpy(ret + 9, ret + 3, 1);
    memcpy(ret + 7, ret + 4, 1);

    ret[12] = 0;
    printf("%s", ret);
    free(ret);
    return 0;
}

Wait, that for loop we added there could be written in an even more convoluted way! Let’s do so:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

volatile unsigned int a = 0 - 1;
volatile u_int8_t * z = NULL;

int main() {
    switch(a) {
        case 0 - 1:
            z = aligned_alloc(sysconf(_SC_LEVEL1_DCACHE_LINESIZE), 1 * 10 + 3);
            break;
        case 1 * 10 + 3:
            memcpy(z + 3, z + 2, 1);
            memcpy(z + 9, z + 3, 1);
            memcpy(z + 7, z + 4, 1);
            printf("%s", z);
            free(z);
            return 0;
        default:
            z[a] = a == 0 ? z[a] = (1 << (a + 6)) | (1 << (a + 3)) : a == 1 ? (z[a - 1] & (1 << (a + 5))) | (z[a - 1] >> a) | (z[a - 1] >> (a + 5))  : a == 2 ? z[a - 2] | z[1] & ~(z[a - 2] >> (a + 4)) : a == 4 ? z[a - 2] | z[a - 3] | (z[a - 4] >> (a + 1)) : a == 5 ? (z[a - 4] & z[a - 3] & z[a - 5]) >> (a - 4) : a == 6 ? (z[a - 2] & ~z[a - 1] | (z[a - 6] >> (a - 4))) & ~(z[a - 6] >> (a - 2) << (a - 5)) : a == 8 ? (~z[a - 7] & z[a - 2]) | z[a - 3] | z[a - 3] << (a - 7) : a == 10 ? z[a - 9] & ~(z[a - 5] >> (a - 5)) : a == 11 ? z[a - 6] | ((z[a - 1] & z[a - 3]) >> (a - 5)) : a - a;
    }

    a = a + 1;
    main();
}

Well, our switch there is taking quite a bit of space, isn’t it? Let’s fix that and clean up the code a bit:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

volatile u_int8_t a = 0 - 1;
volatile u_int8_t * z = NULL;

int main() {
    a==0-1?z=aligned_alloc(sysconf(_SC_LEVEL1_DCACHE_LINESIZE),1*10+3):a!=1*10+3?z[a]=a==0?z[a]=(1<<(a+6))|(1<<(a+3)):a==1?(z[a-1]&(1<<(a+5)))|(z[a-1]>>a)|(z[a-1]>>(a+5)):a==2?z[a-2]|z[1]&~(z[a-2]>>(a+4)):a==4?z[a-2]|z[a-3]|(z[a-4]>>(a+1)):a==5?(z[a-4]&z[a-3]&z[a-5])>>(a-4):a==6?(z[a-2]&~z[a-1]|(z[a-6]>>(a-4)))&~(z[a-6]>>(a-2)<<(a-5)):a==8?(~z[a-7]&z[a-2])|z[a-3]|z[a-3]<<(a-7):a==10?z[a-9]&~(z[a-5]>>(a-5)):a==11?z[a-6]|((z[a-1]&z[a-3])>>(a-5)):a-a:0;if(a==1*10+3){memcpy(z+3,z+2,1);memcpy(z+9,z+3,1);memcpy(z+7,z+4,1);printf("%s",z);free(z);return 0;}a=a+1;main();
}

And there we go - a program that prints Hello World , in just a single line of logic!

I’m sure there’s more ways to improve the unreadability of the project, so if you see something that could be improved, please let me know!


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

交易系统

交易系统

武剑锋 / 上海人民出版社 / 2011-1 / 32.00元

《交易系统:更新与跨越》是中国第一部研究证券交易系统的专业著作,填补了这一领域的学术空白。既回顾和总结了系统规划、建设和上线过程中,技术管理、架构设计、应用调优、切换部署、运行维护等方面的经验和教训,也从较为宏观的角度描述了独具中国特色的交易技术支撑体系,特别是,通过分析其他资本市场交易系统的近年来发展历程和后续的技术发展规划,探索了未来业务创新和技术创新的大致框架和可能的模式。相信《交易系统:更......一起来看看 《交易系统》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具