编程大神竟“玩”出了不像 C 的 C 程序

编程专家Brian Robert Callahan展示了如何用非典型C语法编写C程序,挑战C编译器,涉及Pascal、Algol元素及自定义PL/0语言。通过实验揭示C预处理器对非ASCII字符的理解,展示了编程语言的边界与可能性。

a19e8a042082c247ce3aa8316e0c0473.gif

作者 | Brian Robert Callahan

编译 | 张洁            责编 | 屠敏

出品 | 优快云(ID:优快云news)

为了让挑战变得有意思,Brian Robert Callahan(纽约州北部伦斯勒理工学院信息技术和网络科学的讲师) 决定编写一个看起来一点也不像 C 的 C 程序。如果把 C 语言变成另一种语言,然后用那种语言去编写程序,那么使用 C 编译器编译程序会怎样?

能编写出以下程序,Brian Robert Callahan 觉得是一件很光辉的事。

#include"cpaint.h"


var a, b, c, h, i, l, v, x, y, q, w, p size 65535 ,
packed n size 13 ꞉integer ;


procedure display(r,s,c) ;
begin
  LOOP
    call A(Z) ;
    call H(y,x) ;
    call B(Z)
  POOL ;


  y ꞉= r;
  x ꞉= s;


  call A(c) ;
  call H(y,x) ;
  call B(c) ;


  call refresh()
end ;


procedure fill(y,x,c,a) ;
begin
  if(y<0 or y>w-1 or x<0 or x>q-1 or c = a or Z <> a)fill꞉= -1 ;


  call draw(c) ;
  call fill(y+1,x,c,a) ;
  call fill(y-1,x,c,a) ;
  call fill(y,x-1,c,a) ;
  call fill(y,x+1,c,a)
end ;


procedure save(r,s) ;
begin
  i ꞉= 0 ;
  while(i<13)do
  begin
    n[i] ꞉= 0 ;
    i ꞉= i+1
  end ;


  call move(w>>1,(q>>1)-6) ;
  call printw("Save: ") ;
  call echo() ;
  call getnstr(n,12) ;
  call noecho() ;


  call open(n,"w+") ;
  call writeChar(83) ;
  call writeChar(w) ;
  call writeChar(q) ;


  LOOP
    call writeChar(Z)
  POOL ;


  y ꞉= r;
  x ꞉= s;


  call close ;
  call move(y,x)
end ;


procedure load(packed ʌ n) ;
begin
  call open(n,"r") ;
  call check ;


  LOOP
    readln(c);
    call draw(c)
  POOL ;


  c ꞉= 0;


  call close
end ;


procedure m() ;
begin
  l ꞉= 0 ;
  v ꞉= 1 ;


  call A(c) ;
  call H(0,0) ;
  call B(c) ;
  call refresh() ;


  while(v)do
  begin
    read(inp) ;
    '/':l ꞉= not l ; if(l)call draw(c) ; OK
    'k':y ꞉= y-1 ; if(y<0)y ꞉= 0 ; if(l)call draw(c) ; OK
    'j':y ꞉= y+1 ; if(y>w-1)y ꞉= w-1 ; if(l)call draw(c) ; OK
    'h':x ꞉= x-1 ; if(x<0)x ꞉= 0 ; if(l)call draw(c) ; OK
    'l':x ꞉= x+1 ; if(x>q-1)x ꞉= q-1 ; if(l)call draw(c) ; OK
    ' ':call draw(c) ; OK
    'c':c ꞉= c+1 ; if(c = M)c ꞉= 0 ; OK
    'd':call draw(15) ; OK
    'f':call fill(y,x,c,Z) ; OK
    's':call save(y,x) ; OK
    'q':v ꞉= 0 ; OK
    'v':c ꞉= c-1 ; if(c = N)c ꞉= M-1 ; CALL display(y,x,c)
  end
end ;


procedure main(I c,packed ʌ ʌ v) ;
begin
  call start ;
  call getmaxyx(stdscr,w,q) ;
  if(w>M)w ꞉= M ;if(q>M)q ꞉= M ;
  call start_color() ;


  while(x<M)do
  begin
    call init_pair(x,x,x) ;
    x ꞉= x+1
  end ;


  LOOP
    call draw(15)
  POOL ;


  if(c = 2)call load(v[c-1]) ; call display(0,0,0) ; call m() ; call endwin()
end ;


call main.

通过这段代码,也许有很多网友直言,这并非是 C 代码,而是包含 Pascal 语言的所有特征,用分号作为语句分隔符而不是语句结束符,用“:=”表示赋值,也许还有一些 Algol(一种指令式编程语言)的 LOOP……POOL 语法。它甚至有 Pascal 语言的返回赋值,即给函数分配一个值,就是它的返回值。

不过,Brian Robert Callahan 对此解释道,最近听说 A+、K 和 Q 语言(它们是 APL 和 J 之类的数组编程语言)的开发者 Arthur Whitney 会使用 C 预处理器来创建自己的语言,然后用这种自定的语言来实现他的语言。于是,他决定尝试一下这个有趣的实验。

Brian Robert Callahan 基于 PL/0 的自定义语言,编写了一个编译器。这个练习的亮点是 C 编译器将 UTF-8 字符理解为标识符的有效字符。Brian Robert Callahan 使用了很多看起来像 ASCII(美国信息交换标准代码)的字符,实际上并不是 ASCII,最终还是被接受为有效的标识符。C 预处理器能很好地将这些标识符转化为相对应的指令。在这里可以看到隐藏起来的头文件。

如果想查看 C 代码的真实外观,请尝试运行:

$ cc -E cpaint.c | clang-format | less

如果你感兴趣的话,不妨去试试上面的程序吧!

原文链接:https://briancallahan.net/blog/20220220.html

fabfa1aab5ae252aa2920e82f70a1740.gif

《新程序员001-003》全面上市,对话世界级大师,报道中国IT行业创新创造!

ac6815d78ee3135df1070e0e3738d86b.png


 

1cabb715cec58fbc786ce7085164d57c.gif


 

 

 

《程序员做饭指南》霸榜 GitHub!不仅有量筒、烧杯,还用上了数学公式?


 

永远不要辞职,除非……

☞乔布斯诞辰67周年,他的这些思想仍值得我们学习
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值