■掲示板に戻る■ ■過去ログ倉庫めにゅーに戻る■
トリッキーなコード
1 名前: 投稿日: 2001/02/26(月) 21:51
独りよがりのためのスレッド
大体トリッキーなコードを書く奴に限って
致命的なバグを出したりするんだけど、
書きたいもんはしょうがない。


2 名前: 投稿日: 2001/02/26(月) 21:51
サンプルまでに有名な奴を1つ

#define swap(a,b) a^=b^=a^=b


3 名前: デフォルトの名無しさん 投稿日: 2001/02/26(月) 22:06
>>2
すげー! あ、いやまじで。メモッとこ



4 名前: デフォルトの名無しさん 投稿日: 2001/02/26(月) 22:11
そして3は浮動小数点演算に上記のマクロを使用して氏んだ


5 名前: 投稿日: 2001/02/26(月) 22:30
>>3

それと、以下のようなコードに注意
int a=9;
swap(a,a);
ASSERT(a==0);



6 名前: デフォルトの名無しさん 投稿日: 2001/02/26(月) 22:32
if(A) B; の代わりにA&&B
if(!A) B; の代わりにA||B


7 名前: デフォルトの名無しさん 投稿日: 2001/02/26(月) 22:59
>>6
Perlだと普通じゃない?



8 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 01:00
>>7
Bは条件判断文じゃなくて
実行したい関数とか命令であることに注意
うちの会社でそんなコード書いたら書き直しだな



9 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 01:03
>if(!A) B; の代わりにA||B
やっぱA or Bでしょう。

open(IN, "hoge.dat") or die;
日本語訳「hoge.datを開け、さもなくば逝ってよし」


10 名前: 3 投稿日: 2001/02/27(火) 01:07
>>4
またまたお得情報! うん、確かに使えない

>>5
ASSERTって何? namcoの戦車ゲーム? でもスペル違うな〜
あ、いやまじで疑問。


11 名前: 8 投稿日: 2001/02/27(火) 01:12
確かにperlじゃ普通かも
ごめん宇津だし脳


12 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 01:23
>>10

ASSERTの使い方については、
『Writing Solid Code』という本を読むといいよ。


13 名前: 10 投稿日: 2001/02/27(火) 01:31
>>12
えーとswap(a,a)だとaが0になっちゃうってこと?
でaが0なもんでエラーになっちゃうってこと?
ちょっと実験してみます。

http://www.microsoft.com/japan/developer/library/vccore/_core_the_assert_macro.htm
とかですか? 他の言語でもきっと大差ないよね?


14 名前: 13 投稿日: 2001/02/27(火) 01:40
実験してわかったぴょん
swap(a,a)のように本マクロで同一変数を使用した場合、
a^a の結果が a に代入されるため、結果 a==0 になってしまう
Cって奥が深いぴょん


15 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 01:47
お礼になるか分からないけど最近作った駄作だぴょん
#define bitchack(a,b) (a>>b)&1
aのb番目(0〜)のbitが勃っていたら1、勃っていなかったら0



16 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 02:09
bitcheck?
>>15


17 名前: 15 投稿日: 2001/02/27(火) 02:26
>>16
bitcheckぴょん
ついでに出てきた駄作ぴょん
#define bitset(a,b) a|=(1<<b)
#define bitreset(a,b) a&=~(1<<b)
代入したくなかったら=を捨てるぴょん


18 名前: 投稿日: 2001/02/27(火) 09:26
意外とトリッキーなのが出てこないな。

最近書いたもっともトリッキーなコードはswitch文かな。
default以外の各case毎に同じ2〜3行の処理をさせたいが、
だからといって関数を作るほどではない。
そういうときにあなたならどうする?ちょっと考えてみそ

一番あり得そうなのは、

switch(c)
{
case 0:
case 1:
switch(c)
{
case 0:
/*0*/
break;
case 1:
/*1*/
break;
}
/*0,1*/
....;
break;
default:
/*others*/
break;
}

これを綺麗に書くにはどうすれば?


19 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 09:30
まずインデントを入れること。


20 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 09:34
case (n) 文の代わりに、

result =
(n == 0 ? 0処理 :
n == 1 ? 1処理 :
n == 2 ? 2処理 :
デフォルト処理)

ってやつ。
見やすいけど条件文に不慣れな人には理解しにくいかも。



21 名前: 投稿日: 2001/02/27(火) 09:52
>>20
あ、なるほど
?:の優先順位のバグがちょっと気になるけど、
簡単なswitchを書くならこちらの方が見やすいかもね。
効率が悪くなるのが残念だけど。


22 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 10:09
>21
コンパイラの最適化を信じなさい(笑)



23 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 10:31
>>1
キボーンは、こんな感じでちゅか。

switch(c) {
  case 0:
    /* 0 */
    ....;
    if (0)
    case 1:
      /* 1 */
      ....;
    /* 0,1 */
    ....;
    break;
  default:
    /* others */
    break;
}


24 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 10:37
トリッキーなコードに浸っているようでは所詮厨房


25 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 10:52
トリッキーコードに浸って厨房っぷりをはっきするスレッドでは。


26 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 11:32
>>24
いいから、なんか出せ!


27 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 11:34
大昔・・・、
FORTRANで、いかに短い行数(=パンチカードの枚数)で、万年カレンダー等の
プログラムを作れるかを競ってたなぁ〜。

結構ロジック・アルゴリズムの勉強にはなったよ。


28 名前: 投稿日: 2001/02/27(火) 11:35
>>23
exactly!だだ出来ればブロックで囲むとなお可。

>>24
25の言うとおり、厨房ぶり満載のスレッド。
1で書いたけど、実際仕事でトリッキーなコードを書く奴に
ろくな奴がいないのは承知。でも書きたいんだよ


29 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 11:35
Z80のアセンブラで最速かつ最短の乗除算ルーチンを…


30 名前: 投稿日: 2001/02/27(火) 11:37
>>27
それと、N88BASICで1行プログラミングとかね。



31 名前: 名無しさん@お腹いっぱい。 投稿日: 2001/02/27(火) 12:29
>>31
1 end


32 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 14:41
>>23
申し訳ないけどif(0)のあたりが意味不明だぴょん
誰か解説お願いだぴょん
てゆーか、今まさにそのコードを使ってみたいぴょん

・・・あ、やっぱ四の五の言わずに実験してみるぴょん


33 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 14:51
>>32ぴょん
実験しても、理解しにくいと思いまちゅ。

gotoだと見た目にトリッキーさに欠けるから、if(0)を使ってるだけでちゅ。
使うのは、砂場のお遊びまでにしといてくだちゃい。


34 名前: 24 投稿日: 2001/02/27(火) 16:16
ポインタから0か1のbool型に変換したい時に普通
b = (ptr != NULL)
なんて書くところを
b = !!ptr
と書くのはどう?
トリッキーでもないけど読みやすさの点から結構気に入った書き方


35 名前: 投稿日: 2001/02/27(火) 16:19
>>33
でも結局、gotoを使ってるんだよね。
switch文ってのがつまりgotoな訳で。

>>32
正規表現のメタキャラクタのエスケープを例にあげやう。
動作を追っていって理解してくれ

for(i=0;strSrc[i]!='\0';i++)
{
  switch(strSrc[i])
  {
  case '$':
    if(strSrc[i+1]!='\0' && strSrc[i+1]!='\n')  break;
    if(0)
  case '^':
    if(i!=0 && strSrc[i-1]!='\n')  break;
  case '.':
  case '[':
  case ']':
  case '|':
  case '*':
  case '+':
  case '?':
  case '(':
  case ')':
    result+="\\";
  }
  result+=strSrc[i];
}



36 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 16:40
>>23
うわ、面白い!!
テストしてみよ、どう動くんだろう。

俺厨房。糞コードマンセー


37 名前: 24 投稿日: 2001/02/27(火) 16:52
assert(ptr && "スタック異常")
assert(i<N && "インデックス範囲外")
アサート発動時にコメントを付加する方法
でも全然トリッキーじゃねーな


38 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 16:55
MSBとLSBの入れ替え

n = ((n >> 1) & 0x55555555) | ((n << 1) & 0xaaaaaaaa);
n = ((n >> 2) & 0x33333333) | ((n << 2) & 0xcccccccc);
n = ((n >> 4) & 0x0f0f0f0f) | ((n << 4) & 0xf0f0f0f0);
n = ((n >> 8) & 0x00ff00ff) | ((n << 8) & 0xff00ff00);
n = ((n >> 16) & 0x0000ffff) | ((n << 16) & 0xffff0000);



39 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 16:59
トリッキなコードを書くヤツは厨房だが
トリッキなコードも書けないヤツはもっと厨房。



40 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 17:09
トリッキーなコードを書ける知識があればこそ、
実務においてそれらを正しく避けることができるのだ。

とか言ってみるテスト


41 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 17:23
むかしグラフィックが異様に遅い初代PC88での話し。
画面クリアをなんとか高速にできないか?とおもいZ80のインストラクション表をみながら
これなら16bit単位で書き込めて、メモリ書き込みとアドレス更新が一発じゃんと思ったのが
 LD SP,xxxx
 LD BC,0
 PUSH BC
アドレスがディクリメントされていくのでケツからクリアされていくが
効果はあった。

でも後で気がついた話し。
DMAとめてクリアしてDMA再起動させたほうが早かったんだよね。


42 名前: 36 投稿日: 2001/02/27(火) 17:24
ちゃんと動くじゃん、仕事で使ってみたいな。
やっぱ、書き直しか?

つーか、上司が糞だから通りそうで嫌だな。


43 名前: 投稿日: 2001/02/27(火) 17:30
>>41
をを、目から鱗。
既に今の時代では使えないのがなおさらトリッキーでgood!


44 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 17:59
IF(0) ってどういう動作になるんですか?
>>42



45 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 18:08
>>41
Oh! FMで似たようなコード見た気がするよ。
もちろん6809だけど。


46 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 18:15
>>39
ごめん。Pascalだとあんまりトリッキーなのは、書かせてもらえないの(藁


47 名前: 投稿日: 2001/02/27(火) 18:28
42ではないが>>44
if(0)で次の1文がとばせるんですが、
switchのcaseで飛んできたものは実行される、という訳です。
上から順次実行してきた場合はとばされるけど、
case宛にjumpしてきたコードは実行される。
言葉にすると難しいな。やっぱ42さんお願い


48 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 18:39
>>44
普通に>>35でわかりやすい例が挙がってるじゃん。読めよ


49 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 18:39
>>47
ありがとうございました。
解かりました。
if(0)を FOR文等に変えてみてもトリッキ−な事できますね。


50 名前: 投稿日: 2001/02/27(火) 18:45
>>49
まさにそれこそトリッキーだが、動くのかな?
動いたところで実用価値が無いがそこはそれ、トリッキーであれば許可。

誰かfor文の中にgotoするテストをしてみて。
予想では、初期化は実行されないが、終了条件などはチェックされそうだな。


51 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 18:47
for(;0;)


52 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 18:52
>>50
できました。
繰り返しが0だったらIf(0)と同じ効果ですね。


53 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 19:26
Life with UNIXにのっていた最悪プログラムコンテストのグランプリはすごいとおもった。

int main[] = {VAXのマシンコード};



54 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 19:31
>>53
ベーマガの投稿プログラムかよ(ワラ


55 名前: 投稿日: 2001/02/27(火) 19:31
>>53
そんな事出来るの?コンパイラ依存でなくて?
実験実験。ブルースクリーン出そうだが。


56 名前: 53 投稿日: 2001/02/27(火) 19:35
昔の話しで環境依存だとおもう。
最近のはデータセクションにコードは置けないだろうから。


57 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 19:40
>>56
たぶん、エントリーポインタ書き換えればいけるよъ( ゚ー^)


58 名前: 投稿日: 2001/02/27(火) 19:42
>>56
考えてみればそうだね。
今エントリポイントを操作して頑張ってたけど、
どうあがいてもプログラムロード即死亡。
コードセクションにデータをおければいいんだが。


59 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 20:05
コードってゆうか
#define "debug.c"
debug.cの中にはデバッグ用のソースが入っている。



60 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 20:13
>>59

#include じゃなくて?


61 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 21:05
#if _UNIX_
#include </dev/tty>
#elsif _DOS_
#include <con>
#endif



62 名前: デフォルトの名無しさん 投稿日: 2001/02/27(火) 23:47
#define "整数"  int
#define "始まり" main
#define "終わり" return
#define "表示"  printf

"整数" "始まり"()
{
  "表示"("%s" , "ハローCワールド");
  "終わり" 0;
}




63 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 00:19
なんか、このスレに一人だけ素の厨房がいるな


64 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 02:00
キミのことかね?


65 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 04:20
#define駆使してMindもどきがつくれそうだな


66 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 10:46
もっと面白いの期待age


67 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 11:54
unsigned char main[] = {0xc3 /* ret */};
とりあえず動きました。
環境:Win98, VC++98


68 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 14:27
>>67
Win2kでは無理だろ。……多分だけど。


69 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 15:05
>>53
知る人ぞ知る、MAZE BATTLEみたいなもんか。


70 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 15:12
>>68
win2000動作確認しました。
動いた。


71 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 15:23
>>62
error C2007: #define の後に識別子が必要です。


72 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 15:27
>>70
隣家オプション求む


73 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 15:29
>67
cygwin gcc on win98se でも動いた。

main=195;
の方がかっこいいかも。



74 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 15:45
>>72
む、VC++6.0のデフォでOKだと思って、
新規で作ったら通らなくなった。

でも、古いプロジェクトファイルのほうはリンク通る。
ちと調べましゅ。

お馬鹿でスマン


75 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 16:09
あで??何が違うんだろう・・T-T;
鬱だ。


76 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 22:18
char main=-61;

動いちゃったぴょん
Linuxならふつーに動くッぽいぴょん


77 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 22:44
トリッキーの極みと言えば、やっぱり(67の様な)オブジェクトコードの埋め込みや、
自己書き換えだと思うけど、誰か本格的にやってる人いない?


78 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 23:05
>>41 >>43

2人とも、まだまだあま〜いじょ。

0クリアするコードも含めて0クリアして、はじめて
トリッキーと言えるのっ。 もちっと考えてみそっ!


79 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 23:26
関数の実体のコピーは合法でしょうか?
func1() {
/* ... */
}
func2() {
/* ... */
}

/*
関数のサイズは、コンパイラが出力するMAPファイルやアセンブラ出力で関数の
位置関係から算出します。
この場合、func2のアドレスとfunc1のアドレスの差を関数のサイズとみなします。
*/
typedef (*tclosure)();
#define FUNCMAXSIZE 8192;
test() {
 static char closure_code[FUNCMAXSIZE];
 tclosure closure;
 memcopy(closure_code, func1, (size_t)(func2 - func1));
 closure = (closure_code)closure_code;
 closure(); /* 実行 */
}


80 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 23:35
>>79
何に使うの。具体例を。

 if ( 用途が無い ) return 屑コード;


81 名前: 79 投稿日: 2001/02/28(水) 23:39
これができて何が嬉しいかというと、普通のファイルに関数そのものを置ける事。
DOSのsmallモデルとかの、実行ファイルのサイズに制限のある環境で、
擬似的にオーバレイが可能になるとか。
他に利点無かったかな・・・


82 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 23:45
  ∩ ∩
 (゜∇゜) ピョピョ
 (   )
  ⊥⊥



83 名前: 79 投稿日: 2001/02/28(水) 23:46
まあ、処理系依存なんだけど、大抵の環境で同じ様な事が出来る筈。
TEXTセグメントに納まらなくなった場合とかに、アセンブラで書いて小さくする手間が省ける。
アセンブラを直接弄らない事で、ある意味移植性は高くなる。(藁


84 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 23:46
(cond
((用途が無い?) '屑コード)
((実用にはならないけど面白い?) 'そうだね)
(else '何かあるの?))


85 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 23:47
>>79
func2()がfunc1()よりも後ろに置かれてるという保証はあるの?



86 名前: 85 投稿日: 2001/02/28(水) 23:49
ごめん。わかってるみたいね。


87 名前: デフォルトの名無しさん 投稿日: 2001/02/28(水) 23:49
>>85
引き算したり比較したりしてうまいことやる。

if ( func1 < func2 )
{
...
}
else
{
...
}


88 名前: 79 投稿日: 2001/02/28(水) 23:51
>>85
だからー、79で
>関数のサイズは、コンパイラが出力するMAPファイルやアセンブラ出力で関数の
>位置関係から算出します。
と書いてあるだろが。
ちゃんと読んでね。


89 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 00:00
if文などの条件演算におけるXOR表現
(a < 0 != b < 0)
…この程度常識っすかね?


90 名前: 79 投稿日: 2001/03/01(木) 00:01
まあ、今となってはあまり意味が無いか。
ゲームボーイなどの携帯ゲーム機ではいまだに有効な筈・・。


91 名前: >89 投稿日: 2001/03/01(木) 00:05
たしかその式はC言語では違法だった様な。コンパイラが警告ださない?
非ゼロ同士が一致するかは保障されてない筈。
でも大抵の環境で有効かな?
アセンブラ出力見ればはっきりするけど。


92 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 00:11
>>84
面白い=トリッキーコード≠屑コード。

"The International Obfuscated C Code Contest"なんて
どこが面白いでちゅか?


93 名前: >91 投稿日: 2001/03/01(木) 00:11
んなわけねーだろ。
関係演算子の値は、常に0か1だ。


94 名前: 91>93 投稿日: 2001/03/01(木) 00:15
あ、そうかも。式の値に対しての真偽値のことと間違えてた。
しまん


95 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 00:36
// MSVC has for scope bug.
#if defined(_MSC_VER)
# define for if(0);else for
#endif


96 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 01:05
多分トリツキーなことになると思うのでここで質問。

printfをあちこちに埋め込んでデバグ用出力をよくするんだけど
#ifdef DBG_FLG
printf("hoge:a=%d",a);
#endif
などとあちこちに書くのはとても面倒。そこで、マクロで
debug_printf("hoge:a=%d",a);
などと1行ですますマーベラスなアイディア、あります?


97 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 01:12
>>96
いつも使ってる奴のコピペ
ほんとはdprintf((式))一個だけでも良いんだけど、
引数チェック付きprintfということで・・
#ifdef DEBUG
#define dprintf(a) printf(a)
#define dprintf0(a) printf(a)
#define dprintf1(a,b) printf(a,b)
#define dprintf2(a,b,c) printf(a,b,c)
/* ... */
/* 条件付き出力 */
#define d1printf(t, a) do { if (t) {dprintf(a);} } while (0)
#define d1printf0(t, a) do { if (t) {dprintf(a);} } while (0)
#define d1printf1(t, a,b) do { if (t) {dprintf1(a,b);} } while (0)
#define d1printf2(t, a,b,c) do { if (t) {dprintf2(a,b,c);} } while (0)
/* ... */
#else
#define dprintf(a)
#define dprintf0(a)
#define dprintf1(a,b)
#define dprintf2(a,b,c)
/* ... */
#define d1printf(t, a)
#define d1printf0(t, a)
#define d1printf1(t, a,b)
#define d1printf2(t, a,b,c)
/* ... */
#endif



98 名前: >96 投稿日: 2001/03/01(木) 01:20
ごくあたりまえの手段だが・・・。

#ifdef DEBUG
#define debug_printf printf
#else
#define debug_printf 1 ? (void) 0 : printf
#endif



99 名前: 96 投稿日: 2001/03/01(木) 01:23
>>97
やはり、printfの引数の数が鬼門ですね・・・
引数の数にあわせてdefineを代えるのも面倒(ごめんなさい)。
ここをトリックで切り抜ける方法がなんかないもんでしょかね。


100 名前: 97>99 投稿日: 2001/03/01(木) 01:26
だからー、全体を括弧で囲めば、dprintf一個でも良いの。
dprintf(("p:%lx ->n:%lx\n", (long)p, (long)n));


101 名前: 96 投稿日: 2001/03/01(木) 01:28
>>98
素ゥ晴らしい! 君は英雄だ!
ありがとう! 2chって素敵


102 名前: 97>98 投稿日: 2001/03/01(木) 01:33
負けた。
実行されないコードがコンパイラによって削除されるかが鍵だなー。


103 名前: 97 投稿日: 2001/03/01(木) 01:37
あ、普通削除されるか・・


104 名前: 96 投稿日: 2001/03/01(木) 01:38
>>102
コンパイラの最適化で消えてなくなるようです。
(今 .s を出力して確かめてみた)
まさに実用的なマーベラストリックですね。


105 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 01:43
>>97
Cよちよちの初心者です。お世話になります。

#define d1printf(t, a)

上の','とaの間にある半角スペースは、ある種のトリックでしょうか。
「コピペ」の言葉が、ちょっと気になったものですから・・・。


106 名前: 97>105 投稿日: 2001/03/01(木) 01:49
空白は全然、なんの関係もないです。
みたまんまのマクロです。


107 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 01:53
97じゃないけど、()のなかの空白は気にしなくてもいいよ。


108 名前: 襴様 投稿日: 2001/03/01(木) 01:54
>>105
定説です。


109 名前: 105 投稿日: 2001/03/01(木) 01:57
>>97
ありがとうございます。出直してきます。


110 名前: 外付けSCSI 投稿日: 2001/03/01(木) 02:32
#ifndef DEBUG
#define DB(x)
#else
#define DB(x) x



111 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 03:24
>>98
うわーかっこいい!サイコーだぴょん。
ん?・・・ちょっと待つぴょん

#ifdef DEBUG
#define debug
#else
#define debug 1?(void)0:
#endif

とすると、printfだけじゃななくてもどんな関数
(一時的なロギング関数とか)でもオッケーだぴょん。
こんな感じだぴょん
debug hoge();


112 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 06:52
>>111
110さんのが、トリックを使わずに、可読性・汎用性も高く
副作用も少ない、すばらしい書き方の見本ではないのかな。

トリックをすべて否定している訳では無いよ。


113 名前: デフォルトの名無しさん 投稿日: 2001/03/01(木) 10:28
98のは昔のDOS処理系のLSI-C試食版やTurboCでも期待通り展開される。


114 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 08:44
>>110
括弧つけるのが面倒だぴょん
生意気言ってごめんだぴょん


115 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 11:59
>>114
デバッグ用のコードがシンプルでなければ・・・、
 デバッグ用のコードのデバッグをやるはめになる恐れがある。

まーふぃー(嘘)


116 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 16:28
今でもよく使うトリック。

char* GetHogehogeFilename()
{
static char filename[_MAX_PATH + 1];
.....(hoge hoge).....
return filename;
}


117 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 16:53
>>116
これはトリックというのか?
リエントラントでないのでsage


118 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 16:56
トリックというより、単なる糞コードだな。


119 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 17:57
>>117
> リエントラントでないのでsage
うむ。でも便利。Windowsだと怖いが。


120 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 18:12
Windowsだとなぜ怖い?
どんなOSだろうと使い方間違えればすぐにバグの原因になるコードだと
思うけど。



121 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 18:20
>>120
Windowsだと、いつリエントラントが要求されるようになるか
わからん。
DOSでリエントラントが要求されるケースはかなり特殊。


122 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 19:19
再帰呼び出しでなくても、

char *a,*b;

a = GetHogeHogeFileName();
b = GetHogeHogeFileName();

fp = fopen(a,"r");

で動作保証されないよね?
使い方に注意する必要があるというのはそういうことです。



123 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 20:59
スレッドを多用したプログラムから対策無しに利用した時点で
中身の保証が出来なくなってアウトってことだろ。
でもそれだけなら他のOSでも言える事だと思うけど・・・Windowsでは
何か違うの?


124 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 21:03
最近のは知らないんだけど
昔のstrtokとかいうのも、そんな実装じゃなかったっけ?


125 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 21:12
私にはレベルが高すぎて理解できないので、
どなたか教えてください。

>>98さんの
#define debug_printf 1 ? (void) 0 : printf
>>111さんの
#define debug 1?(void)0:
の行と、

#define debug
の違いを詳しく。


126 名前: 125 投稿日: 2001/03/02(金) 21:15
↑失礼、記入漏れあり。訂正いたします。

#define debug
の違いを詳しく。
   ↓
#define debug_printf
#define debug
の違いを詳しく。


127 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 22:40
自分でcppだけ実行して展開してみろ>125


128 名前: 125 投稿日: 2001/03/02(金) 23:00
今、Cの本しか無いんです。
ヒントだけでもいいですから、教えてください。>>127さん


129 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 23:27
自分で調べることが大切だ、ということを教えているのだよ。


130 名前: デフォルトの名無しさん 投稿日: 2001/03/02(金) 23:56
>>128
b=( a>0 ? 3 : 0 );
たとえばこれ、分かりますか?
多分Cの本には載ってるぴょん


131 名前: 125 投稿日: 2001/03/02(金) 23:57
>>129
それはわかります。
Cの本で"プリプロセッサ”の章も調べた上でお聞きしているのです。

例えば、その本の中で、
グローバル変数の実体宣言と外部宣言のマクロを使った説明があるのですが、
(以下、引用)
#ifdef  GLOBAL_VALUE_DEFINE
#define  GLOBAL
#else
#define  GLOBAL extern
#endif

でマクロ定義して、GLOBAL_VALUE_DEFINEの定義/未定義によって、
GLOBALの置換文字列を空文字列またはexternにします。(以下、略)

つまり、上記での「空文字列」のやり方と何が違うのかと。お願い致します。


132 名前: 125 投稿日: 2001/03/03(土) 00:07
>>130
3項演算子ですね。
代入演算子より優先順位は高いので、括弧は不要でしょう。


133 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 00:10
>>131
あんまり変わらないぴょん
なんであんなふうになってるかというと
printfには引数があるからだぴょん


134 名前: 125 投稿日: 2001/03/03(土) 00:20
>>133
ふむふむ、なんとなく。ありがとう。


135 名前: 125 投稿日: 2001/03/03(土) 00:41
>>133
じゃあ、これでもいいって事ですか?

#ifdef DEBUG
#define debug
#else
#define debug //
#endif


136 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 00:49
>#define debug //
"//"自体が#define行のコメント子になっちゃうでしょ。


137 名前: 125 投稿日: 2001/03/03(土) 01:05
>>136
コメント>マクロ という事ですか。ふーむ。奥が深い。


138 名前: 125 投稿日: 2001/03/03(土) 01:31
もう少しおつきあい下さい。
これなら、どぉ?

#ifdef DEBUG
#define debug
#else
#define debug /##/
#endif


139 名前: 125 投稿日: 2001/03/03(土) 01:33
やっぱ、だめ臭いな。


140 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 01:48
もうこのスレから出てってくれ>125


141 名前: フォルトの名無しさん 投稿日: 2001/03/03(土) 02:21
>>96
VC++6.0ならこれでOKみたい。
#ifdef DEBUG
#define debug_printf printf
#else
#define debug_printf
#endif


142 名前: >141 投稿日: 2001/03/03(土) 02:31
それが通らないコンパイラは存在しないだろう。
ただし引数が評価されるために副作用があるけどな。


143 名前: >138 投稿日: 2001/03/03(土) 02:37
まあ好き好きだから、それを使っとけ。
このようなコードでも、君の書いた通りには動くことだし。

if (...)
 debug ...;
...;


144 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 02:44
>>98
bccでは
「エラー E2468 : void 型の値は許されない」
となってコンパイルが通りません。
なぜにああいう形にする必要があるのか知りたいです。
(だいたい、A?B:Cは BとCが同じ型の必要があると思うのだが・・・)
debug_printfの引数部分に副作用があるものがあるときには
>>141 のほうが評価されて正しい結果になると思います。
まあ、もしdebug_printfの返り値を使用していたり、
debug_printfの引数の評価順に依存した副作用とかがあると
141のやつでもだめだとは思いますが・・・

>>140
理由は良くわかりませんが、厳しいですね。。。

>>142
引数評価されたほうが、debug版との動作の差がなくなると思うのだが・・・
(なんの副作用もなければ最適化で消えると思うし)


145 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 03:30
#ifdef DEBUG
#define debug
#else
#define debug 1? 0:
#endif

gccで問題なく実行できたぴょん


146 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 03:32
四の五の言わずにまずトライ&エラーの精神を持つべきだぴょん
失敗は成功のおっぱいだぴょん


147 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 03:36
ちょっと感動。
http://www.flipcode.com/cgi-bin/msg.cgi?showThread=Tip-MSVCFor&forum=totd&id=-1


148 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 03:42
>>146
トライアンドエラーもよいけど、
たまには言語の仕様とか勉強して
理論的にプログラム書こうね!


149 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 03:51
>>147 はどうやらVC++で
for ( i = 0; ... )
{
}
と書けるようにするテクニックを紹介してるみたいだ。



150 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 03:55
>>149
for (int i = 0; ...) でしょ.
Watcom もこれできないんだよな−


151 名前: 138>143 投稿日: 2001/03/03(土) 04:51
もう一回だけチャンスを。

#ifdef DEBUG
#define debug
#else
#define debug if(0)
#endif

>>140
なんかすごいの出してくれたら、そうします。


152 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 05:08
>>151
すばらしいぴょん
それが正道っぽいぴょん
いつのまにかそんなにトリッキーじゃなくなってるぴょん・・・


153 名前: 151 投稿日: 2001/03/03(土) 05:13
>>152
全てはあなたのお陰です。ありがとう。


154 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 05:25
>>151
なんだ、まだやってたのか。
この場合は三項演算子を使うのが定石であって、
それ以外の解は存在しないんだって。
151ではこれが正しく動かないだろ?

if (...)
 debug printf(...);
else
 ...


155 名前: 151 投稿日: 2001/03/03(土) 05:36
>>154
机上では、動くはずなんですけど。それより、
定石を破るのが「トリック」なのでは・・・?


156 名前: 151 投稿日: 2001/03/03(土) 05:37
だめだね。ごめん>>155


157 名前: 151 投稿日: 2001/03/03(土) 05:38
訂正:
だめだね。ごめん>>154


158 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 05:44
これだったらどうだろう?

#define debug if(1) ; else


159 名前: 151 投稿日: 2001/03/03(土) 05:51
「どっか逝け」の声は、もう十分に聞こえております。 が、
まだ煮え切らないので。

if-else のネストだけが問題なら、

#define debug while(0)

で、だめ?


160 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 06:03
>>158-159
moe ? printf("ハァハァ") : debug printf("逝ってよし!");
だめだめ。


161 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 06:36
あと、
debug printf("ヽ(´ー`)ノ") , debug printf("やっぱり氏のう");
だめだめ。


162 名前: !151 投稿日: 2001/03/03(土) 07:20
3項演算子でなくても
#define debug_printf 0 && printf
でどう?


163 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 07:30
1 + debug_printf("だめだめ\n");


164 名前: 151 投稿日: 2001/03/03(土) 08:17
>>163
ちょっと一眠りして、ひとつ考えてみたんですけど
まだつきあってくれます?


165 名前: 151 投稿日: 2001/03/03(土) 08:23
とりあえず書きますので、また駄目出しお願いします。

#ifdef DEBUG
#define debug
#else
#define debug 0 &&
#endif


166 名前: 151 投稿日: 2001/03/03(土) 09:20
>>163さん以外の方でも結構ですので、どなたか
>>165の「だめだめパターン」を教えてください。


167 名前: 151 投稿日: 2001/03/03(土) 10:38
もやもや感が残るので、友達の使ってないPC-9821noteを借りてきました。
それで、MS-DOS6.2 + TurboC 2.0 で検証しました。
>>143,>>154,>>160-161,>>163 は全てOKでした。

それより、
3項演算子を使うやり方で、>>163のパターンを検証すると、
#define DEBUG

#ifdef DEBUG
#define debug
#else
#define debug 1 ? (void)0 :
#endif


int i;
i = 1 + debug 3; /* error ! */


と書くと、/* error ! */の所で、コンパイラがエラーを返すんですけど・・・。
"Not an allowed type in function main"ってメッセージです。
環境のせいでしょうか。


168 名前: 151 投稿日: 2001/03/03(土) 10:48
訂正:

上記、#define DEBUG の記述をコメントアウトしたときに、
コンパイラがエラーを返します。 ごめんなさい。


169 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 11:17
もうこのスレ 151 にあげるから気が済むまでおやりなさい


170 名前: 投稿日: 2001/03/03(土) 11:25
さすがにかなりウザいと思い始めたり。

仕方ないので新しいネタ。
自分自身をファイルなどで読み込むことなく、
自分自身を表示するプログラムを書いてみそ。

ちなみに「可能です」。
わからない人は下の答え(たぶんすぐ誰かが書くだろう)を見ないで、
しばらく考えてみてはどうでしょう。面白い(かもしれない)よ

ちなみにN88BASICなら
10 LIST
ですね。


171 名前: 投稿日: 2001/03/03(土) 11:31
>>170
#include "hoge.h"

--hoge.h
int main(void){printf("#include \"hoge.h\"");return 0;}

こういうのはやめてね(涙)。


172 名前: 151 投稿日: 2001/03/03(土) 12:04
振り返ってみると、確かに「荒らし」のごとくの連続書き込み。

151は、これをもちまして永遠に2chから去ることとなりました。
ご迷惑をおかけしました皆様方には、お詫び申し上げます。さようなら。


173 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 15:56
>>170
> 10 LIST

system .... cat .... "What?" .... finish->face


174 名前: 好評なのに絶版 投稿日: 2001/03/03(土) 16:42
printf("main=0x%x\n",main);



175 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 17:23
なんか有澤誠が出てきそうなネタだな>不動点プログラム



176 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 17:43
ttp://www.sail.t.u-tokyo.ac.jp/~hidaka/break-j.html


177 名前: 好評なのに絶版 投稿日: 2001/03/03(土) 23:06
>>176
これって何か役に立つの?
取り立ててすごいわけでもなく、毒にも薬にもならない。
たとえば、自分の中の関数名一覧をとりだせちゃうとか、
そういうのだったらいろいろ応用(?)も効くと思う。


178 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 23:24
>>170
ネタが高度すぎてだれも付いてこられないもよん。


179 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 23:36
>>170
子プロセスでシェルを起動して、ソースファイルを
typeとかcatに渡すってのは?


180 名前: デフォルトの名無しさん 投稿日: 2001/03/03(土) 23:39
>>179
ファイルを読んじゃ駄目ってんだから、たぶん反則だとおもうぴょん


181 名前: 投稿日: 2001/03/04(日) 01:03
>>178
高度なパズルで、トリッキーなコードとは無関係だったからかも。
昔ソースコードに感染するウィルスを考えていたときに作ったんだけどね。

>>179
180さんの言われるとおり反則ですね〜。頑張って下さい。


182 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 01:40
埋め込みオブジェクトコードの話題キボン


183 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 01:58
文字コードを利用する奴はなんか反則っぽいのでいや。
昔、FORTRANですごいの見たことあるんだけど思い出せない。


184 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 02:48
void call_func(void *func, ...)
{
func(...);
}
というような関数は実装できますか?


185 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 03:00
キャストしておしまい>184


186 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 03:01
>>184
だいたい出来るぴょん


187 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 03:03
>184
関数ポインタ使え!


188 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 03:12
>>184
void mick( int a )
{ printf("%d\n",a); }
void jack( void b() ,int a)
{ b(a); }
main()
{ jack( mick, 8 ); }

もっとかっこよく実装できるはずだがそこは諸兄に任せるぴょん


189 名前: 投稿日: 2001/03/04(日) 03:17
どういうときに効果的に使えるんだろう。
関数を引数に渡したくなったことはないけど、
もしかしたら綺麗にプログラミングするときに便利かもね

>>183
とりあえず文字コード(0x22とか)に頼らなくても作れます。
現在printfを使わないでやるのに挑戦中です。
(要するにcoutなどを使ってみる)


190 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 03:34
>>189
>関数を引数に渡したくなったことはないけど
基本的に関数に引渡す値は、構造体に入れておけば
引数を渡しまわせるので、実地においてその辺りで
悩むケースは稀だと思うぴょん


191 名前: 投稿日: 2001/03/04(日) 03:45
>>190
悩むことは無くても、効果的に使用できる状況は知っておきたいね。
知らなくても美しく(かつ読みやすく(笑))書くことは出来ると思うけど。


192 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 07:15
>>191
引数を渡すパターンも>>188で示してるつもりだぴょん
でも可変引数はこのパターンだと確かにちょっときついぴょん
トリッキーでも美しくもないのでsageるぴょん


193 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 07:41
>>170
>自分自身をファイルなどで読み込むことなく、
>10 LIST
ワラタヨ! イイカラスーパートリッキナコタエダシテミセロ サイテンシテヤッカラ


194 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 08:29
大して面白くはないな

#define X(x) #x
char x[]=X(main(){puts(X(#define X(x) #x));printf(X(char x[]=)X(X(%s);),x);printf(X(%s),x);});main(){puts(X(#define X(x) #x));printf(X(char x[]=)X(X(%s);),x);printf(X(%s),x);}


195 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 08:38
訂正。無駄なことをしていた。

#define X(x) #x
char x[]=X(main(){puts(X(#define X(x) #x));printf(X(char x[]=X(%s);%s),x,x);});main(){puts(X(#define X(x) #x));printf(X(char x[]=X(%s);%s),x,x);}


196 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 09:37
>>195
デタウンコ、マタコンパイルシテミタノカー
ウンコノゲンリョウト、コンペアシテミタノカー
..... < 10 LIST


197 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 10:27
>>170
イイカラ、ハヤクコタエダシテミセロ


198 名前: Ken 投稿日: 2001/03/04(日) 11:19
やあみんな。
http://www.acm.org/classics/sep95/
の Stage I なんか、どうだい?



199 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 12:12
>>198
ヘイ!ケン ソンナノココニカクト スキールヨリモラールガオチール


200 名前: 投稿日: 2001/03/04(日) 12:14
>>194-195
なるほど、文字列化演算子を使う方法ですか。思いつかなかった。
#xはコンパイラによってはサポートされていないんだけど、
ほとんどのコンパイラでコンパイルできるし、これくらいは可でしょう。

>>197
答えですか。そんじゃ文字コードに依存しない物を
int main(){char c='"',*text="int main(){char c='%c',*text=%c%s%c;printf(text,c,c,text,c);return 0;}";printf(text,c,c,text,c);return 0;}



201 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 12:47
>>200
イイヨ リカイシヤスイ イイコタエ
モスコシ トリッキナモンダイ ダシテクレ


202 名前: 投稿日: 2001/03/04(日) 13:27
>>201
問題考えるの簡単じゃないんだよ。
もう少し引っ張れると良かったんですが。

アセンブラレベルとかだったらトリッキーなコード多そうだけど、
ついてこれない人が大部分だろうし。

ちょっと考えてみます。誰かネタふって(笑)
c=a++ + + + + + ++a;


203 名前: 投稿日: 2001/03/04(日) 13:46
ちょっと思いついた問題。休日の午後だというのに厨房だな俺。

ビット数を求める最短のプログラムを書け、ってのはどうでしょう。
32bitの問題として、例えば5ならビット数は2(0101)って感じです。

あ〜ちなみにこのスレッドは
「こんなトリッキーなコードを書いたよ」
とか、
「この冗長なコードをトリッキーに出来ないかな」
とか、そういった話題も大歓迎です。
本来はそっちが目的だったし。


204 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 13:54
>>189
SPMDプログラミングモデルで他ノードに対して関数呼び出しさせるときとか。
あ、クラスタなどでの並列プログラミングの話ね。



205 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 14:23
>>202
ワルイコトシタ... スマンナ ジカンガ アレバ キョウリョクスル
c=a++ + + + + + ++a;

maximal munch ノ モンダイダナ
...ト コタエテシマウト マタワルイノデ オイトク


206 名前: 投稿日: 2001/03/04(日) 14:24
>>204
なるほど、並列プログラミングとかだったら意味があるな。
みずからそんなコードを書くことはしばらく無いと思うけど、
頭の片隅に置いておきます。tnx


207 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 14:46
>>203
ビット数って立っているビットの数? それとも任意の数を表すのに必要なビット数?
とりあえず両方出しておくよ。

int b; // 答えのビット数
DWORD d; // 入力データ

//立っているビットの数を求める(dが例えば5ならbに2を格納)
for(b=32;(int)d>=0&&b>0;b--,d=d<<1);

//任意の数を表すのに必要なビット数を求める(dが例えば5ならbに3を格納)
for(b=0;d!=0;b+=d&1,d=d>>1);


208 名前: 207 投稿日: 2001/03/04(日) 14:52
補足のコメントが逆だった。

//任意の数を表すのに必要なビット数を求める(dが例えば5ならbに3を格納)
for(b=32;(int)d>=0&&b>0;b--,d=d<<1);
//立っているビットの数を求める(dが例えば5ならbに2を格納)
for(b=0;d!=0;b+=d&1,d=d>>1);


209 名前: 投稿日: 2001/03/04(日) 14:55
>>208
立っているビットを想定していました。
言葉足らずですみません。

で、for文を使った一般的な方法だけれど、
それをトリッキーに書いてみてはどうでしょう。
有名なのに↓があります。
int numofbits(long bits)
{
  bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
  bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
  bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
  bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
  return (bits & 0x0000ffff) + (bits >>16 & 0x0000ffff);
}
これは自分で考えるとすると結構ハードだと思うのですが。
かくいう俺も独自で思いついたのはありません。


210 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 15:13
>>209
条件から「最短のプログラムを書け」を削除しなきゃ。



211 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 15:22
ライシュウマデ モーコラレナイノデ マァ'スゴーク'カンタンナヤツヲ ヒトツ オワビニ

Z80アセンブラデ ジサツプログラムヲ ツクレ
 メモリクウカンハ 0-FFFFh スベテ RAM
 ソノルーチンヲ ヨブト RAMエリア スベテ 0クリア
 ルーチンハ リロケータブル デアルコト
 スグ コタエラレルヤツハ カクナ

Z80ナラ ニーモニックヒョウグライ ナントカナルダロ


212 名前: 投稿日: 2001/03/04(日) 15:30
>>210
exactry。時間最短にしときましょか(笑)

>>211
Z80じゃなきゃ無理なのかな?
x86で出来ないかなぁ。


213 名前: 投稿日: 2001/03/04(日) 15:32
>>212
>exactry
ウツダシノウ


214 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 16:26
>x86で出来ないかなぁ。

z80だと00hがNOPなので全クリアでぐるぐる状態になるのですが
x86で00hって何の命令でしたっけ?
add [ebx+esi],alかな?


215 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 17:56
>>214
00hだけで完結する命令はないみたいね。

ちなみに add [ebx+esi],al のアセンブル結果は 00h,04h,33h


216 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 17:58
と思ったらあったね。add [eax],al が 00h,00h


217 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 19:01
>>215, 216
16bitモードの時、[bx+si]のModR/Mが00だったので
32ビットモードだとレジスタに'e'が付くだけだと思い込んでました
鬱だ


218 名前: 投稿日: 2001/03/04(日) 20:18
>>215
eaxとesiが0だったら、メモリを荒らすことなく
ずっとぐるぐる動き続けることができるのでは?
状況がわかりにくいので「自殺プログラム」って
何をするべきなのかわからないのですが。


219 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 21:49
>>203

int numofbits(unsigned int n)
{
static const int bits[] = {
0, 1, 1, 2,
(途中省略)
30, 31, 31, 32,
};

return bits[n];
}

すいません。くだんねーのでsageます。


220 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 22:04
>>218
自分のプログラムも含めてクリアする。つまり自殺。って事では。

>>219
一番最速!しかも、たぶん一番最小(34byte程度のテーブルなら)。
しかし、スレ趣旨から外れてるのは確かに。でもよく使うよね。


221 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 22:09
>>220
ゴメソ。テーブルの数はまちがいじゃん。鬱・・・。


222 名前: 投稿日: 2001/03/04(日) 22:21
>>219
いや素晴らしい、ワラタ
マジで最速ですな。

>>220
自分のプログラムをクリアするだけ?
他のアドレスもクリアするんでしょ?
自分自身を先のアドレスへコピーして、
今までの自分を0でクリアする、そういうプログラムの事なのかな?
この場合はメモリが循環していないと駄目だよね。むーん


223 名前: デフォルトの名無しさん 投稿日: 2001/03/04(日) 23:53
>>203
int count(int a)
{
int ret=0;
for(;a;a>>=1)ret+=a&1;
return ret;
}
挑戦してみたぴょん。でももうちょっと削れそうだぴょん


224 名前: 223 投稿日: 2001/03/04(日) 23:57
致命的なバグを発見したぴょん
でも秘密にしとくぴょん


225 名前: 投稿日: 2001/03/05(月) 00:05
>>223
サンクス。限度まで削って……
int ret=a&1;
while(a) ret+=(a>>=1)&1;
return ret;
あまりかわらんなぁ。



226 名前: 投稿日: 2001/03/05(月) 00:07
>>224
言われて気付いた ^^;
トリッキーなコードは書くべきじゃないね(笑)


227 名前: デフォルトの名無しさん 投稿日: 2001/03/05(月) 00:36
>>225
気のせいか処理が長くなってる気がするぴょん


228 名前: 投稿日: 2001/03/05(月) 00:37
>>223
最終案
do ret+=a&1;
while(a>>=1);
これだと可読性もあるし、ベストかもしれない。

テーブルもループも使わず、>>209の様な形で
かっこよくかつ短くビット数を得るトリッキーなコード
誰か考えてくれないかなぁ。


229 名前: デフォルトの名無しさん 投稿日: 2001/03/05(月) 00:46
>>228
渋くて速くてかっこいいぴょん
で、答が落ち着いたところでデバッグしとくぴょん
int count( unsigned int a )

つーか、この時間たぶん誰も見てないぴょん・・・


230 名前: デフォルトの名無しさん 投稿日: 2001/03/05(月) 01:56
うむ。処理系によってはちゃんと動く場合もあるかもね。


231 名前: デフォルトの名無しさん 投稿日: 2001/03/05(月) 01:59
>>230
処理系依存の処理ってどこ?
っていうか何に対してコメントしてるの?


232 名前: デフォルトの名無しさん 投稿日: 2001/03/05(月) 02:07
>>231
unsignedについてのコメントと思われるぴょん
右シフト時、処理系によって符号の扱いが違うかもしれない
ということ(0埋めか符号そのままか)だぴょん
unsignedにしとけば符号は関係ないので常に0埋めとなるぴょん


233 名前: お手軽な奴をひとつ 投稿日: 2001/03/05(月) 03:46
int numofbits(unsigned bits) {
return bits ? numofbits(bits / 2) + bits % 2 : 0;
}


234 名前: 投稿日: 2001/03/05(月) 06:26
>>233
いいねぇ。いかにもfc.comp.lang.cっぽい書き方が通っぽい。
たかがbitcheckでスタックを結構喰うのが難点だけど、
読みやすくていいんじゃないでしょうか。

>>230
unsigned/signedの右シフトなら、ANSI-Cではしっかりと仕様が決まってます。
signedの場合、最上位ビットは必ずそのまま設定されるはずですよ。


235 名前: デフォルトの名無しさん 投稿日: 2001/03/05(月) 06:27
ttp://www.aya.or.jp/~sanami/peace/


236 名前: デフォルトのアセンブラ屋さん 投稿日: 2001/03/05(月) 06:41
あんま出番がないのでさみしいから・・・。

>>222
>他のアドレスもクリアするんでしょ?
Yes

>自分自身を先のアドレスへコピーして、
そんな事はしなくていいですよ。

>今までの自分を0でクリアする
一番最後にね。ヒント。

>この場合はメモリが循環していないと駄目だよね。
そう。処理中にNMI要求もない事が条件。


237 名前: 投稿日: 2001/03/05(月) 07:05
>>236
なるほど、意外と複雑じゃ無いみたいですね。
書けないこともなさそう。98emuでも入れて、
その中で試しに書いてみようかな。
俺はx86系アセンブリをあまり書いたことがないから
トリッキーに美しく書くのは無理だろうけど。

俺はライフゲームの無限生成パターンみたいなのを
想像していて、例えば mov [next eip],code みたいに
次々と自分自身を変更するコードを考えてた。


238 名前: デフォルトの名無しさん 投稿日: 2001/03/05(月) 07:23
自己書き換えは実行のみ可能なセグメントではエラーになるよ
>237


239 名前: 投稿日: 2001/03/05(月) 07:29
>>238
だからPC-9801(というかdos)を想定してました。
(確かにeipという書き方で誤解を生みますね)
code/dataセグメントが分かれてしまう環境では
自殺プログラムって原理的に不可能ですよね?

自殺プログラムが作れる条件は多分
・メモリが巡回している
・全ての領域に書き込み可能
なんじゃないのかな?


240 名前: デフォルトの名無しさん 投稿日: 2001/03/05(月) 08:35
>>239
Winだろうが別にdataセグメントにコード置いたってかまわないし
codeセグメントにwrite属性付けることも可能ですよ


241 名前: 投稿日: 2001/03/05(月) 12:23
>>240
へえ、知らなかった、tnxっす。
実はセグメント周りは弱いんだよね。
コンパイラオプションでも調べてみます。
さすがにメモリ巡回はしていないよね?


242 名前: デフォルトの名無しさん 投稿日: 2001/03/05(月) 12:44
http://remus.rutgers.edu/~rhoads/Code/bitcount3.c
>>209 を速くしたやつ。


243 名前: 投稿日: 2001/03/05(月) 12:54
>>242
なるほど。同じアルゴリズムなのかな?後でチェックしてみよう。
209の可読性を失わせるなら、代入が減る分こちらの方が早いかも。
int numofbits(unsigned int bits)
{
bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
bits = (((bits >> 4) + bits) & 0x0f0f0f0f;
bits += bits >> 8;
return (bits + (bits >> 16)) & 0xff;
}
某本からの転載です


244 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 00:51
>>243
基本原理はおんなじっぽいぴょん
disasしたら0xaaaaaaaaとか出てきたから
割り算とかはこれらの数字を作るためのトリックっぽいぴょん


245 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 17:50
CSVファイル(とか)を作るコード。

do{
   /* なんか処理する */
}while(!((終了条件) || (fputc(',', fp), 0)));


246 名前: 職人志願 投稿日: 2001/03/06(火) 18:43
#define START_A 0x101
#define END_B 0x102
#define STOP_C 0x103
というような定義文がたくさんあり、
stringという文字列を読み込んで
if(strcmp(string,"START")==0) hoge(START);

のようなif文を定義文の数だけずらっと並べてたんですが、
スマートに美しくコーディングできるでしょうか?



247 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 18:53
定数宣言に#defineなんて使うのですか?
constじゃなくて?


248 名前: こういうのじゃ駄目ですか? 投稿日: 2001/03/06(火) 19:07
>>246
struct _tbl { int id;
char* name;
} tbl[] = { {0,"START"},
       {1,"END"},
       {2,"STOP"},
  {-1,""}};

for(int i=0;tbl[i].id != -1;i++){
 if(strcmp(string,tbl[i].name)==0){
  hoge(tbl[i].id)
  break;
 }
}



249 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 19:55
>>246
enumで定義しろ。enumで。



250 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 20:10
> 定数宣言に#defineなんて使うのですか?
> constじゃなくて?
フツーでしょ。
constは、このデータはいじりません宣言でしかないだけでしょ。
定数宣言じゃないですよ。
と言うか、もしかして君、そうしてるの?


251 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 21:05
247じゃないけど、const派だなぁオレは。デバッガでも追いやすいし。
つか、普通は最適化で直埋めされるから速度も問題ないし…。


252 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 21:22
読みにくいコードコンテストみたくなってきたな


253 名前: coder 投稿日: 2001/03/06(火) 21:27
gotoを使わないための苦肉の策。

while(0)
{
...
if (...) break;
...
if (...) break;
...
}

割と普通?

gotoは使わない!ってんじゃないけど、
インデント的に嫌いなもんで。



254 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 21:31
>>246
職人への道のりは、かなり遠く感じるぞ。
まずは言語より、考え方の勉強だな。


255 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 21:42
>>253
coderさん、Pro? それともネタ?


256 名前: coder 投稿日: 2001/03/06(火) 21:47
>>255
間違えた。
これじゃ何もしないじゃん。(苦笑)

じゃあ、こんな感じかな。

while(1) {
 ...
 if (...)break;
 ...
 break;
};

一応、Proです。^o^v



257 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 21:56
>>256
プロのcoderさんなので、お聞きします。
ネストが2重以上になった時のいい方法、教えて。


258 名前: 246 投稿日: 2001/03/06(火) 21:58
>>248
どうもすみません。
数字の部分は既に定義が決められているので
tbl[] = { {START_A,"START_A"},
       {END_B,"END_B"},
       {STOP_C,"STOP_C"},
としてやってみます。

>>254
すみません。精進します。


259 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 22:03
>>256
無限ループは危険だと思うぴょん。有限ループがいいと思うぴょん。
do{}while(0);とかはどうかぴょん。


260 名前: coder 投稿日: 2001/03/06(火) 22:10
>>257
break(2);
ってやりたくなる時ですか?

基本的には2重以上にネストしないように見直しますが、
どうしても必要になったのなら、ためらいなくgotoを使います。
もしくは、ネストの内側でreturn。(←あまり薦められない)
あ、やっぱり別関数にするかな。

要するに状況に応じて対処します。(あたりまえ)

ちなみに、Proって言ってもGAME関係です。
納期・効率が優先される世界なので、一般的ではないかも。
#故に「トリッキー」に惹かれてきたわけですが。



261 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 22:13
できれば個性は語尾ではなく、内容で示していただけると幸いです。
全く内容のない書き込みなら、語尾だけで個性を表すことも仕方ないと
思いますが、わりと良い内容を書かれているだけに残念です。

老婆心によるお節介なので、sage。


262 名前: coder 投稿日: 2001/03/06(火) 22:14
>>259さん
コードを見直してみたらそのようにやっていました。^_^;;

それで、while(0)って。。(恥&言い訳)



263 名前: 79 投稿日: 2001/03/06(火) 22:34
昔、こんな感じの事やってました。(今もたまに・・)
(TurboC)
static char csetcode[] =
"\x55" /* push bp */
"\x8b\xec" /* mov bp,sp */
"\xb4\x02" /* mov ah,2 */
"\xb7\x00" /* mov bh,0 */
"\x8a\x76\x08" /* mov dh,[bp+8] */
"\x8a\x56\x06" /* mov dl,[bp+6] */
"\xcd\x10" /* int 10h */
"\x5d" /* pop bp */
"\xcb" /* retf */
/* "\xc3" */
;
typedef void (far *tcset)(int, int);
#define cset(x,y) (*(tcset)csetcode)(x,y)
/* test */
int main() {
cset(40,13);
return 0;
}


264 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 22:34
>>259
初心者ですが、・・・do{}while(0); は、有限ループなの?
do先に一回{}無条件実行、while(継続条件式)って思ってましたが。説明お願い。


265 名前: 259 投稿日: 2001/03/06(火) 22:53
>>264
有限ループである。
何故ならば、継続条件式が偽であるため、
継続せずに終わるからである。   だぴょん


266 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 23:02
>>265
回らない条件ループ。シュール。だったら、while(0)をタイプする意味はなあに?

>>261なんか無視していいよ。だってここは2chだもの みつを


267 名前: 259 投稿日: 2001/03/06(火) 23:09
>>266
while(0)を入れないとコンパイル通らないからだぴょん
てゆーかそもそも do{〜;}while() ってゆー構文だし、
一度だけ回るループとか思ってほしいぴょん


268 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 23:19
ああ、261が言ってるのって'ぴょん'とかって発言してるやつ(ら?)のことか・・だもん


269 名前: SAGE 投稿日: 2001/03/06(火) 23:21
1回しか通らないんじゃループとは言わねぇ!

…という突っ込みは無しですか?(^^;)


270 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 23:31
ループには展開されないよ。>269
アセンブラの出力でも見れば?


271 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 23:36
switch(val)
{
 case 0:
  return TRUE;
  break;
 case 1:
  return FALSE;
  break;
}

return する場合でも break を入れる律儀な俺。
break 入れてる?

スレ違い?



272 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 23:37
警告出るから入れない>271


273 名前: デフォルトの名無しさん 投稿日: 2001/03/06(火) 23:44
>>263
こういうのってfar呼出しになるからDOSだと効率悪いね。
特にポインタ渡すような関数は。
コードをheapにコピーして置けばnearで呼べるかな?


274 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 00:07
>>263
素直にインラインアセンブラ使えばいいんでないの?


275 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 00:19
DSEGにコード追い出せるのが利点とか。>274
あと実行時に変更ができる?
まあ、inline-asmでもできるか。


276 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 03:24
あたりまえすぎるが

bool f = false ;
:
if(pushed)
foo = !foo ;
:

マジでこれ仕事で使っていたが上司に「鳥キーな事してるね」
いわれたアル. フツーあるよね!?



277 名前: 投稿日: 2001/03/07(水) 03:26
なんか突然書き込み増えるから怖いね。

>>259
do{/*...*/}while(0);は覚えておきます。
俺知らなかったよ、内容あるじゃん(笑)>>261

>>246
コンパイラ依存だけれど、
#define HOGE(x) if(strcmp(string,#x)==0) hoge(x)
と定義して、
HOGE(START);
などとやれば、見た目はすっきりします。
しかし俺ならばstd::mapなどを使って書くだろうけど。

>>250
C++ではあまり普通ではないようですよ。
constで定義すると、コンパイラに正確に最適化される上に
型チェックも行えるので、最近はconstが主流です。
しかし、
#define XXX_xxx1 0x1
#define XXX_xxx1 0x2
#define XXX_xxx1 0x4
...
などとやる場合はdefineの方が素直です。
ここでconst、enumを使うのは邪道でしょうね。


278 名前: 投稿日: 2001/03/07(水) 03:30
>>263
dataセクションに実行付加が付く可能性が高いので、
最近では危険でしょうね。TurboCでは大丈夫だと思うけど。

>>276
多分普通だと思います。boolでなくintの場合は
a=1-a;とやるのがgoodでしょう。ぱっと思いつきにくいよね。

>>277
自己レス。
#define XXX_xxx1 0x1
#define XXX_xxx2 0x2
#define XXX_xxx3 0x4
ですね


279 名前: 投稿日: 2001/03/07(水) 03:47
ちょっとした質問があります。
スレと直接の関連が無いのでsageますが……

1:unionの効果的な使用法
昔は(PC98の)VRAMをint配列とunionしたりして
そこそこ意味があったけれど、最近は効果的な
使用法がいまいち思いつきません。例えば、
struct label{char tag[4];char dummy;char data[15];}
union{char raw[20];struct label x} abc;
などとやって、abc.rawに"SOME USAGE"を代入、とかかな?

2:protectedの継承の意味
C++での話です。動作はわかるんですが、どういう意味があるのか
どういう場面で使うのかさっぱりわかりません。
protectedを効率的に使ういい場面を知っている人は教えてください。



280 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 03:55
unionを使うところって、OOPならポリモーフィズムを使うべきところが
ほとんどだから、それで正しいんじゃないかな。


281 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 04:16
276が意味不明。も少し詳しい説明きぼん


282 名前: 投稿日: 2001/03/07(水) 04:22
>>280
なるほど、C++に移行した結果残ったCの遺物と。
最近ハードに密着しなくなったのも原因かもしれないですね。

>>281
予想ですが、bool f=false;/*...*/f=!f;
というコードの話だと思います。


283 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 06:58
>>277
0x1, 0x2, 0x4の定義だけは#defineでって、そんなもんかね?
const でやっちゃうけど。なんかマズイことあったっけ?
Delphiなんかだと、集合型があってスマートにかけるんだけどねえ。

>>276
むしろBoolで、 f = 1 - f; とされることのほうがトリッキーだよ。
ちなみに、Pascal(またか)だとBoolean型は f := not f; とするしか選択がない(藁



284 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 06:59
Boolでなくboolだ。これだからPascal野郎は…。


285 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 06:59
>>279
非公開メンバは普通 protected にする
private は身内にすら見せないから不便


286 名前: =283=284なんで。 投稿日: 2001/03/07(水) 06:59



287 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 07:07
>>285
おまえC++も質問の意図もまったくわかってねえよ。
逝ってよし


288 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 07:33
非公開メンバは普通 vrivateにする
private は身内にすら見せないから便利


289 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 08:38
>>288
typo?


290 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 09:34
yes


291 名前: 276 投稿日: 2001/03/07(水) 09:41
失礼タイプミス スマソん
282さんの通り
 bool f=false; /*...*/ f=!f;
でおます
トグル変数なんですな
さらにこれをかいた当時はCだったので
 int f=false; /*...*/ f=!f;
としてトリッキーと見られたみたい
ついついくせでboolとしてしまったある


292 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 09:51
>>285

それよか、お友達にはprivateな部分が見えちゃっていいのか?
って方が気になる > かみんぐあうとC++



293 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 11:13
>>292
そこらへん、Bjarneがどう考えていたのか興味あるね。
D&Eの邦訳って出てたっけ?
洋書は高いしなー。


294 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 11:24
>>248
ループの継続条件は、変な番兵でやるより、番兵なしで、
i < sizeof tbl / sizeof *tbl の方がいいと思うぞ。

あと、線形探索よりも、テーブルをはじめにqsortしておいて、
bsearchで二分探索の方が普通だと思うな。


295 名前: 285=288=アホ 投稿日: 2001/03/07(水) 11:48
privateメンバとpublicメンバの話をしているのはよくわかった。
で、private継承とpublic継承は知ってるか?
285で反応している>>279の質問は、protected継承の話なんだが。
292もアホに反応するなよ。


296 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 11:49
>>279
private/protectedな継承は外部に対してスーパークラスの
インターフェイスを隠したい時に使えますね。(んなこた解ってるって?)
他の言語なら継承を用いずにコンポジションで実現しなければならない
場面で利用出来そうです。
JavaのStackクラスなんかは失敗例で、コンポジションを使うべき、
或いはprotectedな継承が使えれば良かったケース。

# 用語の使い方からC++屋じゃないことは明らか(藁



297 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 11:54
C++でprivateメンバの実装が見えちゃうって事自体は、
Cとの互換性を保つために仕方がないと割りきったんじゃないかなぁ。
要は、スタックにオブジェクトを確保するためにデータメンバが必要で、
インラインで呼び出すために、privateメソッドのインターフェースも必要と。


298 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 11:56
>296
多分、>>279はprivate継承の意義はその通りだと知っているはず。
でも、protected継承の意義が不明ということだと思う。
この辺は、Effective C++に詳しいね。


299 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 11:57
>296
気が付かなかった。
Vectorのインタフェース丸見えですな。


300 名前: 297 投稿日: 2001/03/07(水) 12:47
>>292-293はfriendの事だって気付かなかった・・・俺ってバカだ。
うーむむ、俺も「friendにだけなら許す」という
アクセス属性が欲しいと思った事が何回かあるし。

別のキーワードを嫌った面もあるだろうけど、
特に、演算子のオーバーロードで多用される点からも、
「friendはメンバ関数の一種として扱え」って事かな?


301 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 12:51
javaのStackクラスはあくまでVectorクラスの拡張ですよ。


302 名前: 投稿日: 2001/03/07(水) 13:28
一般的でないために質問がわかりにくかったみたいですまないです。
こういう腐ったことを考えるのこそ、まさにオタの厨房ですな。

>>298
tnx。早速本屋で立ち読みします


303 名前: 296 投稿日: 2001/03/07(水) 13:40
>>298
protectedな継承なら、それをさらに継承したクラスからも外部には
非公開の親の親の機能を使えるじゃないですか。
通常のStackの外部インターフェイスとしてはinsertElementAt()
みたいなメソッドは不要なはずですが(だと思ってるけど)、Stackを
継承してStackの途中の要素に対してアクセスする何かを作る時、
privateな継承だとStackのpublic/protectedなインターフェイスしか
使えないっしょ。

だからといってprivate/protectedな継承がいいといっているわけじゃない。
コンポジションで代用出来るから敢えて必要な機能じゃないよね。



304 名前: 292 投稿日: 2001/03/07(水) 13:47
>>295

なんとなく反応しちまったよ。スマソ


305 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 13:49
トリッキーっつーか、C++になってないか? > スレ


306 名前: 296 投稿日: 2001/03/07(水) 13:52
ごめんよー


307 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 13:54
publicじゃない継承はコンポジションみたいなもんなんだからコンポジション
したときにその変数をprivate/protectedにするかの選択ができるように
private/protected継承ができるんじゃないの?

俺のトリッキーコード
既存のクラスライブラリがあって、そのライブラリのソースコードには触れられなくて
でもあるメンバ変数にアクセスしたかったとき
#define private public
#include <XXXXXXX.h>
とやったぞ


308 名前: 投稿日: 2001/03/07(水) 13:56
>>305
すまないです。C++スレで質問すべきでした。


309 名前: 296 投稿日: 2001/03/07(水) 14:02
>>307
>publicじゃない継承はコンポジションみたいなもんなんだからコンポジション
>したときにその変数をprivate/protectedにするかの選択ができるように
>private/protected継承ができるんじゃないの?
そのとおり

>#define private public
>#include <XXXXXXX.h>
有名だよね。
でもそのクラスをさらに拡張しようとする人は泣くかもね(藁
元の設計意図は大事に&元の設計はきちんと(藁藁

このへんで抜けます。



310 名前: 本題外れまくりの298 投稿日: 2001/03/07(水) 15:01
>302の1
あ、Effective C++に載っているのは
「public継承はis-aという意味である」
「private継承はhas-aの代替手段である」
「protected継承の意味は知らん」
って事だけです。
まあ、よほどの達人以外、買って損はしない本だと思うけど。


311 名前: 投稿日: 2001/03/07(水) 15:14
>>310
やっぱ書いてないよね?昔読んだときに書いてない気がしたんだ。
面白い本だというのは激しく同意。


312 名前: デフォルトの名無しさん 投稿日: 2001/03/07(水) 23:11
ここは原典にもどってみよ〜ナリよ〜
こゆのはどうよポン

time_t tt = time( NULL );
struct tm * ptm = localtime( &tt );
printf("今日は%.2s曜日ナリ〜","日月火水木金土"+ptm->tm_wday*2);


313 名前: デフォルトの名無しさん 投稿日: 2001/03/08(木) 00:08
わりとふつーっぽい>312


314 名前: デフォルトの名無しさん 投稿日: 2001/03/08(木) 00:15
ふつーナリか。。。(ショボン


315 名前: デフォルトの名無しさん 投稿日: 2001/03/08(木) 00:43
原典⇒原点
ということで、減点


316 名前: デフォルトの名無しさん 投稿日: 2001/03/08(木) 01:01
>>315
 イスラム原典
 ハンムラビ法典
 信長の野望 (原典版)



317 名前: デフォルトの名無しさん 投稿日: 2001/03/08(木) 01:12
>>312
.2s
っての初めてみました。
2文字までって事?
文字列引数の長さ調整ができたのか〜


318 名前: 投稿日: 2001/03/08(木) 13:22
>>312
一般的にするにはこう言うのがいいのかもね。
string sample="今日は";
time_t tt = time( NULL );
struct tm * ptm = localtime( &tt );
sample+=&("日\0月\0火\0水\0木\0金\0土"[ptm->tm_wday*3])+string("曜日です");
全然トリッキーじゃないけど、参考までに


319 名前: デフォルトの名無しさん 投稿日: 2001/03/08(木) 16:19
>>318
Perlだとこうなるな。
$str = "今日は";
$str .= ('日','月','火','水','木','金','土')[(localtime(time()))[6]];
$str .= "曜日です。";



320 名前: トリッキーの1 投稿日: 2001/03/08(木) 21:50
>>319
素晴らしい。perlの方でより美しく書けてしまうのが悲しい。
かくいう俺もperlよく使うけど……。

なんとかCで
sample+=(char**)({"日","月","火","水","木","金","土"})[ptm->tm_wday];
みたいに書く方法無いかな?(ちなみに↑は無理ですよ)


321 名前: デフォルトの名無しさん 投稿日: 2001/03/08(木) 22:24
出現順番ちがうけど、
sprintf( work, "今日は%2.2sです",&((short*)"日月火水木金土")[dayofweek])
short*はあんまり意味なし。+にすればもっと簡単。


322 名前: トリッキーの1 投稿日: 2001/03/08(木) 22:36
sprintfの様な関数を使わずには無理かな?
標準関数だから使っても問題なしなんだけれど、
やはりオーバーヘッドなどを考えてしまう厨房な俺。


323 名前: デフォルトの名無しさん 投稿日: 2001/03/08(木) 23:38
printfはそんなにオーバーヘッドかい?>322


324 名前: トリッキーの1 投稿日: 2001/03/08(木) 23:53
自分で作るとなるとかなりのオーバーヘッドになりそうで。
%sなどをサーチしてそこに文字列を代入する手間を考えると、
結構な労力が必要かと思われます。

暇を見て後でdisassembleしてみます。


325 名前: トリッキーの1 投稿日: 2001/03/09(金) 04:36
>>323
strcatを使って同様(>>318)のコードを書いて、
>>321のコードと簡易プロファイラ(QueryPerformance*)で比較した結果、
大体5:8という結果が出ました(両者最適化済)。
個人的な予想だと1:10位だったので、sprintfは全然overheadになってない感じです。
やっぱり実際profileを取ってみないと、本当のボトルネックはわかりませんね。


326 名前: デフォルトの名無しさん 投稿日: 2001/03/09(金) 12:38
下のコード、DVDの暗号を解除するコードなそうなんですけど、
これこそトリッキーなコードだと思いませんか?(笑

#!/usr/bin/perl -w
# 526-byte qrpff, Keith Winstein and Marc Horowitz <sipb-iap-dvd@mit.edu>
# MPEG 2 PS VOB file on stdin -> descrambled output on stdout
# arguments: title key bytes in least to most-significant order
$_='while(read+STDIN,$_,2048){$a=29;$c=142;if((@a=unx"C*",$_)[20]&48){$h=5;
$_=unxb24,join"",@b=map{xB8,unxb8,chr($_^$a[--$h+84])}@ARGV;s/...$/1$&/;$d=
unxV,xb25,$_;$b=73;$e=256|(ord$b[4])<<9|ord$b[3];$d=$d>>8^($f=($t=255)&($d
>>12^$d>>4^$d^$d/8))<<17,$e=$e>>8^($t&($g=($q=$e>>14&7^$e)^$q*8^$q<<6))<<9
,$_=(map{$_%16or$t^=$c^=($m=(11,10,116,100,11,122,20,100)[$_/16%8])&110;$t
^=(72,@z=(64,72,$a^=12*($_%16-2?0:$m&17)),$b^=$_%64?12:0,@z)[$_%8]}(16..271))
[$_]^(($h>>=8)+=$f+(~$g&$t))for@a[128..$#a]}print+x"C*",@a}';s/x/pack+/g;eval

[Hot Wired - 7行でDVD暗号を解読するプログラム]
http://www.hotwired.co.jp/news/news/technology/story/20010308302.html





327 名前: デフォルトの名無しさん 投稿日: 2001/03/09(金) 12:42
見事にevalってますなぁ。


328 名前: トリッキーの1 投稿日: 2001/03/09(金) 14:18
>>326
ナイスネタ。
N88BASICと同様、1行にたくさん書いてあるのが逆に美しく感じられます。
evalっていかにもインタプリタって感じで、色々怪しい事が出来そうですね。
恥ずかしながら今まで知りませんでした。

1行80文字未満で7行以下。これを越えるのはRubyしか無理かな。
気合いの入ったRuby使いさん、チャレンジしてみませんか?(笑)


329 名前: デフォルトの名無しさん 投稿日: 2001/03/09(金) 22:03
>>326
暗号を解除するプログラムが暗号ですね。


330 名前: デフォルトの名無しさん 投稿日: 2001/03/10(土) 19:03
ageとくよ


331 名前: デフォルトの名無しさん 投稿日: 2001/03/10(土) 21:06
RSAアルゴリズムを二行のPerlコードで表したのもらしい。
これって実用性あるのだろうか?

print pack"C*",split/\D+/,`echo "16iII*o\U@{$/=$z;[(pop,pop,unpack"H*",<>
)]}\EsMsKsN0[lN*1lK[d2%Sa2/d0<X+d*lMLa^*lN%0]dsXx++lMlN/dsM0<J]dsJxp"|dc`




332 名前: デフォルトの名無しさん 投稿日: 2001/03/10(土) 21:49
これevaってるのはpack+の文字数をケチるためだけ?



333 名前: デフォルトの名無しさん 投稿日: 2001/03/10(土) 23:31
>>321
sizeof(short) != 2 な処理系だと?


334 名前: デフォルトの名無しさん 投稿日: 2001/03/12(月) 00:51
>>315-316
なんだかスゲー笑った。

あげー


335 名前: デフォルトの名無しさん 投稿日: 2001/03/25(日) 13:33
>>2の意味がわかりません。。。


336 名前: デフォルトの名無しさん 投稿日: 2001/03/25(日) 19:17
オタッキーなコード・・・・・・
もぇっもぇっ、さくらたん、とか、アニメ落ち、とか
コメントに書いてあるのだろうか。



337 名前: デフォルトの名無しさん 投稿日: 2001/03/26(月) 13:10
>>336
そうだよん
あとデバッグメッセージかな
OutputDebugString("こりすたん。。。ハァハァ")


338 名前: 335 投稿日: 2001/03/27(火) 00:09
>>335 誰か教えて!


339 名前: プリプリ博士 投稿日: 2001/03/27(火) 00:30
>>335
>>2は、aとbを入れ替えるマクロ、らしいぞ!
ゴ〜


340 名前: デフォルトの名無しさん 投稿日: 2001/03/27(火) 02:59
というか、swapという単語を辞書で引けって感じ・・・(^^;

ちなみに、>>2のマクロはa==bの時はデータ異常になるという蟲持ち。


341 名前: 335 投稿日: 2001/03/27(火) 03:30
>>339 >>340 SWAPの意味はわかるけど、なんで>>2 でできるの?


342 名前: 340 投稿日: 2001/03/27(火) 03:35
>>342
自分のスキルアップのためにも、人に聞く前に自分で計算してみな?

と、ごまかしておこう
昔、手書きで計算してみて納得したけど、もう忘れたよ(^^;;;


343 名前: プリプリ博士 投稿日: 2001/03/27(火) 04:56
>>340
問題があるのは値が a==b のときではなく
swap(a,a)のように同じ変数を入れたとき、らしいぞ!
ゴ〜


344 名前: デフォルトの名無しさん 投稿日: 2001/03/27(火) 08:42
a==bだと0になっちまうだろ。


345 名前: SAGE 投稿日: 2001/03/27(火) 09:10
>>335
手計算してみれ。

(a,b) =
・(0,0) -> (0,0) -> (0,0) -> (0,0)
・(0,1) -> (1,1) -> (1,0) -> (1,0)
・(1,0) -> (1,0) -> (1,1) -> (0,1)
・(1,1) -> (0,1) -> (0,1) -> (1,1)


346 名前: デフォルトの名無しさん 投稿日: 2001/03/27(火) 11:42
344も0になるかどうかやってみれ


347 名前: デフォルトの名無しさん 投稿日: 2001/03/27(火) 17:29
>>343
xor eax, eax



348 名前: デフォルトの名無しさん 投稿日: 2001/03/28(水) 00:15
>>347
それは0になるが、それがどうした?


349 名前: 347 投稿日: 2001/03/28(水) 11:46
ふつうのコードでしょ。
a^=b^=a^=b
も理解できるはず。
a==bの場合は大丈夫。
&a==&bのときは両方0
>>343としたのは間違い。
スマン


350 名前: デフォルトの名無しさん 投稿日: 2001/03/28(水) 12:20
4 名前:デフォルトの名無しさん投稿日:2001/02/26(月) 22:11
そして3は浮動小数点演算に上記のマクロを使用して氏んだ



351 名前: 優しい名無しさん 投稿日: 2001/03/28(水) 15:45
^= ってなーに?


352 名前: SAGE 投稿日: 2001/03/28(水) 16:12
>>351
歯痛的lonely話


353 名前: デフォルトの名無しさん 投稿日: 2001/03/28(水) 19:24
そもそも生のSwapなんてするか?
使うのはソートの時くらいじゃないの?


354 名前: デフォルトの名無しさん 投稿日: 2001/03/28(水) 21:28
新しいネタきぼーん!!!


355 名前: 351 投稿日: 2001/03/28(水) 21:56
>>352 あぁ、あれかぁ。
じゃ「1」と「10」なら、「0001」と「1010」で、、、えーっと・・・
(0001,1010)→(1011,1010)→(1011,0001)→(1010,0001)
お!す、すげーーー。さんすく。

#^=を、"x乗"のことかと思って、何のことかさっぱりわからんかった。。。
#知らなかったのは、俺だけ?それとも、質問できずに困ってた人、いない?


356 名前: デフォルトの名無しさん 投稿日: 2001/03/29(木) 01:07
いないと思われ。

てゆーかー、
> (0001,1010)→(1011,1010)→(1011,0001)→(1010,0001)
の意味が不明。

1010 ^ 0001 = 1010
1011 ^ 0001 = 1010

とかいった表現にしてほしい。してほしい。。。。


357 名前: デフォルトの名無しさん 投稿日: 2001/03/29(木) 02:58
>347
>xor eax, eax
 なつかしいね、これ。
代入で0クリアするよりも、何クロックか速いんだよね。



358 名前: デフォルトの名無しさん 投稿日: 2001/03/29(木) 03:17
>>356 1010 ^ 0001 = 1010
↑お前が間違っとるやんけ。
>>355 は (a,b) の変移を1行で書いたのだろ。


359 名前: デフォルトは名無しさん 投稿日: 2001/03/29(木) 16:34
goto文をつかわずにネストの深いfor文から抜け出す方法


360 名前: デフォルトの名無しさん 投稿日: 2001/03/29(木) 16:50
↑return



361 名前: デフォルトの名無しさん 投稿日: 2001/03/29(木) 16:57
↑longjmp(藁



362 名前: デフォルトの名無しさん 投稿日: 2001/03/29(木) 17:05
↑終了フラグでネスト毎にブレーク(w


363 名前: 347 投稿日: 2001/03/29(木) 17:06
↑throw


364 名前: 347 投稿日: 2001/03/29(木) 17:07
↑throw


365 名前: 359 投稿日: 2001/03/29(木) 18:30
協議の結果、returnを採用することにいたしました。
上司にはそのように報告し関数を一つ追加申請します。
ご協力ありがとうございました。


366 名前: デフォルトの名無しさん 投稿日: 2001/03/29(木) 19:10
俺が感心したのは次の半透明演算。ビット演算って奥が深いね。

RGB各5bitの16bitピクセルデータc0とc1の半透明演算。
c = (c0 & c1) + (((c0 ^ c1) & 0x7bde) >> 1);


367 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 00:36
>>366
うーん。ちょっと方向が違うかも試練がラスターオペレーションコードも
奥が深いね。3項のヤツ。。。


368 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 01:58
>>211
古いネタなので再掲
>Z80アセンブラデ ジサツプログラムヲ ツクレ
> メモリクウカンハ 0-FFFFh スベテ RAM
> ソノルーチンヲ ヨブト RAMエリア スベテ 0クリア
> ルーチンハ リロケータブル デアルコト
> スグ コタエラレルヤツハ カクナ

誰も答えてないようなので・・・・・
LD BC,0
LD HL,0 ;なくてもよい
LD E,L
LD D,H
INC DE
LD (HL),0
LDIR



369 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 02:19
ここはプログラムっぽいのならなんでもいいのかな?
echo10回実行のシェルスクリプトってこう書くよね

#!/bin/sh
foo=1
while [ "$foo" -le 10 ]
do
echo hogehoge
foo=$(($foo+1))
done

これをスマートに出来るかな?
bashなんでrepeat命令は無しです


370 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 04:20
#!/bin/sh
ruby -e '10.times { print "hogehoge\n" }'


371 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 09:41
>>369
#!/bin/sh
echo hogehoge | head -10



372 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 09:41
>>369
#!/bin/sh
yes hogehoge | head -10



373 名前: 371 投稿日: 2001/03/30(金) 09:43
これは間違い。スマソ。


374 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 09:47
>368
HLの初期値がLD (HL),0やLDIRを指してると失敗するぞ
まあ普通はそんなとこには置かんが‥



375 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 10:09
>>369
#!/bin/sh
for i in 0 1 2 3 4 5 6 7 8 9; do echo hogehoge; done


376 名前: 368 投稿日: 2001/03/30(金) 12:46
>>374
そっか、じゃあ
 LD HL,LDIRの次
とすれば完璧!



377 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 14:41
>>369
コピペです。ちょっとすっきり

#!/bin/sh
for i in 'seq 10'; do echo hogehoge; done


378 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 18:18
可変個の引数を取るshスクリプトで、引数それぞれに処理を行うとき、

while [ $# -gt 0 ]
do
  処理 $1
   :
  shift
done

これって常識?


379 名前: デフォルトの名無しさん 投稿日: 2001/03/30(金) 23:24
こういうリスト操作を考えたんだけど・・・
すでに前例があるのか知ってる人いない?

typedef struct DLList_
{
struct DLList_ *prev, *next;
} DLList;

void Ope(DLList *a, DLList *b)
{
b->prev->next = a->next;
a->next->prev = b->prev;
b->prev = a;
a->next = b;
}

/* 注:以下の説明で {12345} の様に表記されているものは
double linked list を意味する。つまり、5->next は 1 となる。*/

#define Merge(a, b) Ope(a, b)
/* A の要素 a の後ろに b を追加する。
引数: A={12345}, a=3, b={678}
結果: A=={12367845} */

#define Divide(a, b) Ope(b, a)
/* A の要素 a から b までを削除する。
引数: A={12345}, a=2, b=4
結果: A=={15}, a=={234} */



380 名前: デフォルトの名無しさん 投稿日: 2001/03/31(土) 09:22
>>378
常識つーか、普通だと思うが。


381 名前: デフォルトの名無しさん 投稿日: 2001/03/31(土) 16:52
>>379
一つの関数で、リストへの追加と削除を済ましてしまうという
ところがミソにゃのか!?

ただ、あらかじめprev,nextメンバは自分自身を指すようでない
とダメっぽいので

typedef struct DLList_
{
struct DLList_ *prev, *next;
DLList_(){
prev = next = this ;
}
} DLList;

とすると、より(他人が見て)分かりやすいにょ。(C++になるけど)


382 名前: デフォルトの名無しさん 投稿日: 2001/03/31(土) 19:00