あのオブファスケが帰ってきたそうだ。どれだけ「わかりにくい」Cプログラムを作成できるかを競うコンテスト IOCCC (International Obfuscated C Code Contest)が5年ぶりに開催される (マイナビ)。自然体で普通にコード書くとオブファスケなみんな! それ行け、出番だ!
Q: How did the IOCCC get started? A: One day (23 March 1984 to be exact), back Larry Bassel and I (Landon Curt Noll) were working for National Semiconductor's Genix porting group, we were both in our offices trying to fix some very broken code. Larry had been trying to fix a bug
第1回からして難しい (スコア:3, 参考になる)
過去の受賞作品 [ioccc.org]を見ると、第1回の作品ですでに相当難解です。
このへんに解説を見つけたけど [hatena.ne.jp]。
Re:第1回からして難しい (スコア:1)
> 第1回の作品
install: all [ioccc.org]
@echo are you kidding'??'
ふいた
わかりやすさは賛否両論なのに、わかりにくさだと意見が一致するのはなぜか? (スコア:2)
Re: (スコア:0)
理解に必要な知識量と方法論は人それぞれなのに対して、
理解出来ない状態は万人共通だからでしょう。
Re: (スコア:0)
Re: (スコア:0)
再帰呼び出しや三項演算子をうまく使えば、繰り返しや条件判断も表現できるから、
任意のプログラム全体を1つの式で表現できないでしょうか。
つまり、セミコロン使用禁止とか。
ついでにカンマ演算子も使用禁止にできるかな。
Re: (スコア:0)
Lisp でも使ってろよ。いや、使ってください。使いましょう。
Re: (スコア:0)
三項演算子はコーディング規約で使用禁止にしてる所なんかも事もあって、若い開発者は解読不能だったりするんですよね。
わかりにくいというよりも、(使う機会が無いから)存在すら知らないor忘れてるという。
Re: (スコア:0)
日常的にエクセルを使って、セルに条件判断式を入力したりする人のほうが、三項演算子になじみやすいかもね。
Re: (スコア:0)
Subjectを本文の一行目として使用するのは最高にわかりにくい
一番困ったは・・・ (スコア:1)
中途半端に実装されたオリジナルインタプリタが、コード中にハードコーディングされたオリジナルバイナリデータを逐次解釈しながら実行するってプログラムだった。やってることが単純な割に大量のコードが書き散らされていて、中には一度も実行されない処理も多数で、何が何だかさっぱりだったよ。作った当人は「バイナリデータを変更すればプログラムの動作を変更できるから、仕様変更にも強いし、柔軟性も高い。俺様凄い」と思って作ったらしい。条件分岐するうまい方法を思いつかなかったらしく、実行中にバイナリデータを書き換えたりするという・・・。
Re:一番困ったは・・・ (スコア:1)
そういうソフトをいただいた事もありますが、一応メリットはあるんですけどね。
仕様との合致を確認しやすいとか、簡単な仕様変更には対応しやすいとか。
一方でデメリットはインタプリタ部分の変更が必要となる場合に泣きが入ることですか。
非対応の入力が増えるとが、オペコード部分のビット数が足りなくなったとか。
オリジナルを作った人はいいんです。最初は小さいのを作ってこつこつ増設ですから。
でも引き継いだ人はすでに建て増し済みの温泉旅館を受け取るので何が何だか分からないという。
まぁ条件次第ですが、それほど悪い考えじゃないと思いますよ。
でも、バイナリコードの書き換えは反則です。
Re: (スコア:0)
じつはそのバイナリデータとはZ80のコードだったとか。
あるいは、マイクロプロセッサを作る仕事したくて挫折した人が、
俺仕様のマイクロプロセッサを作った気分になりたくてやったとか。
どちらにせよ迷惑に違いないことには合意。
せめてそのオリジナルバイナリデータを作成するためのアセンブラなり
コンパイラを用意してもらわないと。(そういう問題ではない)
コレジャナイ感 (スコア:0)
C言語AA大会やないか
使用言語はPHP の方が向いてる? (スコア:0)
http://codepad.org/Nn0TbhNk [codepad.org]
# 解り辛い挙動、ではないのか。
優勝はもらった (スコア:0)
#define FALSE -1
Re:優勝はもらった (スコア:2)
#define END ;}
Re: (スコア:0)
オイオイV7 UNIXの真似をして優勝はないだろう?
http://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h [tuhs.org]
Re: (スコア:0)
> V7 UNIXの真似
せっかくcまでこれたものを、アセンブラに戻してどうする
しかし、これわかりやすいかも MASMみたいでなついよ
Re: (スコア:0)
Pascalかも。
Re: (スコア:0)
ALGOL です(ALGOL 68 だったかな)。
というか、IOCCC 開催のきっかけとなったのが、そのマクロを用いて書かれた Bourne Shell のソースコードなわけですが、ここスラドにおいてももはや UNIX 文化はコモンセンスではないのですね。
IOCCC FAQ [ioccc.org] からの引用:
Re: (スコア:0)
どうせなら、逆に定義しろ
Re: (スコア:0)
プリプロセッサ系は卑怯な気がするなぁ。
#define car <st
#define id .h>
で、
#include cardioid
#include carringid
とかやられたら、誰にも読めない。
Re:優勝はもらった (スコア:4, 参考になる)
「プリプロセッサ系は卑怯」なんてことは全然ありませんが、審査するのは人間ですから、ありきたりな手を使っても良い評価は得られません。実際、ガイドライン [ioccc.org]の Our Likes and Dislikes の節に
と書いてある通り、マクロを使って読みにくくしていることしか見るべきところがないようなエントリーは古臭いというのが評価基準です。
ちなみに、 #2052882 [srad.jp] の人も書いている通り、 #2052871 のコードはコンパイルエラーだと思いますけど……。マクロ展開は字句解析の後で起こるので、 car というマクロが定義されていても cardioid というトークンには影響を与えません。 (なんてのは当たり前過ぎる話なので、何か引っかけがあるのかと思いますが、わかりません。)
Re: (スコア:0)
プリプロセッサを手動で反復適用するとかすれば、あるいは。
ああ、でも、n 回目のプリプロセスのためのディレクティブが n - 1 回まではエスケープされるように書かなきゃならなくなるのか。
Re: (スコア:0)
あなたの望むようには展開されない
Re: (スコア:0)
真面目にやってこそアレゲ [pro.or.jp]
たとえ本人にその意志がなかったとしても
Re:優勝はもらった (スコア:2)
Re: (スコア:0)
もう「CとしてもFortran 77としてもシェルスクリプトとしても正しいプログラム」とか「シェルスクリプトとして実行すると自分自身をMakefileとして自分自身をコンパイルするプログラム」はあるよねw
Re:優勝はもらった (スコア:3)
言語1のプログラムが言語2のプログラムを出力して、言語2のプログラムが言語3のプログラムを出力して、言語3のプログラムが最初の言語1のプログラムを出力するというような循環的な自己出力プログラムは一般化されています [sigfpe.com]。
Fnxyは言語xで書かれたプログラム(関数)であるとする。
Fnxyはn個の文字列G1, ..., Gnを引数として取り、言語yによるプログラムYを出力する。
Yはn個の文字列G2, G3, ..., Gn, G1に対して言語yで書かれた関数G2を適用するものであるとする。
このとき、言語xによるプログラムF3xy(F3xy, F3yz, F3zx)は言語yによるプログラムF3yz(F3yz, F3zx, F3xy)を出力する。
F3yz(F3yz, F3zx, F3xy)はF3zx(F3zx, F3xy, F3yz)を出力し、F3zx(F3zx, F3xy, F3yz)はF3xy(F3xy, F3yz, F3zx)を出力するので元に戻る。
これを応用して、各言語での関数定義の構文などを定義すると、循環的な自己出力プログラムを出力するプログラム [sigfpe.com]が書けます。
Re:優勝はもらった (スコア:1)
//から始まる形式のコメントを使っていいのなら、コンパイラがShift_JISに対応しているか否かで挙動が変わるプログラムが書ける……ってのも、既出?
1を聞いて0を知れ!
Re: (スコア:0)
マシン語で、エントリポイントを変えると別のプログラムになる、ってのが昔あったような。
オペコードとオペランドが交互に並んでいて、それを逆に解釈するみたいなイメージ。
関数の引数に (スコア:0)
俺の三重ポインタが火を噴く時が来たようだな……
#引き継いだソースにあってキレそうになった
Re:関数の引数に (スコア:2)
良く"ポインタのポインタ"で混乱している人がいるけど
typedef 使えば理解もコーディングも楽になりますよ.
こんな感じです.
typedef int T;
typedef T* PT; // "int" のポインタ
typedef PT* PPT; // "intのポインタ" のポインタ
typedef PPT* PPPT; // "intのポインタのポインタ" のポインタ
変数宣言時はこんな感じ
T t = 1;
PT pt = &t;
PPT ppt = &pt;
PPPT pppt = &ppt;
関数の引数で3重ポインタ(?)を使う場合はこんな感じ.
void hogehoge( PPPT *pppt)
{
PPT ppt = ....;
*pppt = &ppt;
}
これなら,次に引継いだ人もキレないでしょう.
Re: (スコア:0)
「P」を「*」と脳内変換しながら読まないといけない分だけ、よけいに分かりにくくなっています。
Re: (スコア:0)
確かに意味がないですよね。どうせなら、
とやってもらった方が、配列の先頭のポインタなのか、要素のポインタなのかが判別しやすい。前者ならARR_ARR_PT、後者ならARR_PT*と宣言することで、一目瞭然。
Re: (スコア:0)
多重ポインタって、指す先がポインタなのか(多次元)配列なのか、メモリ確保状況はどうなっているのかが
管理しきれなくなってくるというのが混乱の元だと思います。
そういう区別をtypedefを使ってうまく表現すれば、読みやすさに大きく貢献しますね。
Cのポインタの表記法そのものは(多重になっても)単純明快でややこしくないし、仮に*の数を間違っても
コンパイラが指摘してくれるから、あまり問題ではないと思います。
# 10重とか100重くらいになると*の並びを読むだけで目がくらむでしょうけど。
# 数千重くらいになると画面全体が「*」で埋め尽くされて、画面をスクロールしても分からない
# なんてことになりそう。
# どういうところに10重とか100重とか数千重のポインタを使うと効果的なのか、見当もつかないけど。
アドレス渡しのためなのか配列のためなのか? (スコア:0)
そうそう。
void sub( int *a) とかみたとき、
配列として使うためにポインタになってるか
アドレス渡しで値を取り出すためのポインタなのか、
意図がわからないと判断つかない。
Re: (スコア:0)
配列として使うのであればサイズを渡すべきとは思いますけどね。
何度も修正した結果、当初の想定から外れて
配列の範囲外アクセスとかありえますから。
サイズを渡せば疎結合になりますし。
Re: (スコア:0)
Cの学習初期にポインタと配列が同じようなものだと覚えた人が、
多次元配列とポインタの相性の悪さを受け入れられなくて挫折するみたいな感じじゃないでしょうか。
Re:関数の引数に (スコア:1)
つ津
Re:関数の引数に (スコア:1)
3重ポインタ使いはポインタの魔術師と呼ばれていた
他に、マクロを多用するマクラーレンと呼ばれる奴もいた
Re: (スコア:0)
魔術師なら「関数の配列へのポインタを返す関数へのポインタの配列へのポインタ」くらいは使ってみたりするのでしょうか。
私には無理だけど。
Re:関数の引数に (スコア:1)
Re: (スコア:0)
古いコードでは文字列の配列だけで二重(?)で、さらに可変長で…
Re: (スコア:0)
何重のポインタを作ったところで、ややこしくなっていくのは確かですが、アイディアとしては同じだと思うのです。
可変重ポインタとかって、できないでしょうか。
void hogehoge(int n)
{
double (*)na;
:
:
}
みたいな。実現方法も分からないし、実現したところで有効な使い方があるのかどうかも分からないけど。
Re: (スコア:0)
上の議論とかもまとめてそうだけれど、型の検証がほしいから何重だろうがきちんと宣言するのであって、それが面倒だというなら void * にして、リファデリファの局面でキャストすればいいだけじゃん。
C++プログラマが書いたCプログラム (スコア:0)
古典的だけど、
int* a,b;
とか。
Re: (スコア:0)
C++は文法が壊れているので仕方ありません。
Re:C++プログラマが書いたCプログラム (スコア:2)
C++ での int* a; と書く習慣がどういう経緯によるものかは知りませんが、 C++ を考案した Bjarne Stroustrup はそっちの書き方のほうが好きみたいですね (C++ Style and Technique FAQ [libjingu.jp]、日本語訳 [libjingu.jp])。