知ってる人には当たり前かもしれんけど、
知らない人にはちょっと嬉しいコード募集。
Iterator ite = aCollection.iterator();
while (ite.hasNext()) {
Object obj = ite.next();
・
・
}
より、
for (Iterator ite = aCollection.iterator(); ite.hasNext();) {
Object obj = ite.next();
・
・
}
のほうが、Iteratorのスコープが限定されて嬉しいよね、とかそういうヤツ。
public static void main(String[] args) throws Exception
if( ( fp = fopen( ..)) == NULL){
じゃなくて
if( fp = fopen( ..), fp == NULL){
とか。
for(;;){
try something.
if( ...) break ;
commit something.
}
6 :
仕様書無しさん:01/11/25 17:11
boolean f1();
int f2(); // 0:success
String f3(); // "OK":success
の時に、
boolean result = true;
result &= f1();
result &= f2() == 0;
result &= f3().equals("OK");
こんな感じ。
ifネストを深くしたりしなくていい
∧,,∧ / ̄
ミ,,゚Д゚彡< インデントがだるいので。
'ミ つ旦)~~ \_
⊂ミ",, ,,ミ つ
Object1 := TObject.Create; try
Object2 := TObject.Create; try
Object1.xxx;
finally Object2.Free end;
finally Object1.Free end;
8 :
仕様書無しさん:01/11/25 17:36
void hoge()throws Throwableは、
void hoge()でオーバーライドできる。
if(NULL==(fp=fopen("filename.ext","r"))) {
...
}
for (int i = 0, int n = aString.length(); i < n; i++) {
・
・
}
11 :
仕様書無しさん:01/11/25 18:43
12 :
仕様書無しさん:01/11/25 18:43
*(p++)++;
13 :
なっちはすばらしひ:01/11/25 18:45
*(*(*P++)++)++;
10 NEW
15 :
仕様書無しさん:01/11/25 19:36
俺の秘蔵のウル技を教えてやるよ。
AUTO
と入力すると、行番号が自動で振られるよ。
試してみな(´ー`)y−〜〜
16 :
仕様書無しさん:01/11/25 20:01
>>10 「ふつう」って、誰が使ってたのか、教えて欲しい。
>16
ふじつうのtypoと思われ。
18 :
仕様書無しさん:01/11/25 20:18
>>2 って別にイテレータのスコープ限定されてないと思うが。
(単にすっきりした書き方、というなら納得だが)
19 :
仕様書無しさん:01/11/25 20:19
Foo::~Foo( );
20 :
仕様無しさん:01/11/25 20:29
java。
s.equals( "SomeString" ) sがnullなら例外。
"SomeString".equals( s ) sがnullならfalse。
21 :
仕様書無しさん:01/11/25 20:30
class Foo {
private:
Foo( );
public:
Foo* Create( );
~Foo( );
};
22 :
仕様書無しさん:01/11/25 20:34
オイラあまり深いインデントや長いブロックが好きではないので
for(...){
if(条件){
// 長いコード
}
}
と書くより
for(...){
if(! 条件) continue;
// 長いコード
}
と書いている。他人のコード見てるとあまり普通じゃ
ないみたいだけど。
23 :
仕様書無しさん:01/11/25 20:36
Win32+C/C++
SendMessage( hctrl, BM_SETCHECK, flg?BST_CHECKED:BST_UNCHECKED, 0 );
24 :
仕様書無しさん:01/11/25 20:36
>>20 それ書いたら、こんな妙なコードを書くなって注意されたyo!
結局例外をトラップ&スルー(何もしない)するコードに全個所書き直し。
確かにパッと見はハァ?って感じだけど、そんなに変かな?
25 :
仕様書無しさん:01/11/25 20:38
>>22 使用する条件をある程度限定できるなら continue も美しいのでOKと思うYO
なぜ if(s != null && s.equals("SomeString")) では
ないのだ?
>>18 C++では意味がある。
(プログラミング言語C++第3版 Bjarne Stroustrup著
178ページ 6.3.3.1 for文のなかでの宣言 より)
> for-statementの初期設定部では、変数を宣言することもできる。初期設定部が宣言に
> なっている場合、そこで導入された変数(複数の場合もある)は、for-statementの末尾ま
> でのスコープを持つ。たとえば、次の通り。
試験には出ないかもしれないが覚えて欲しいんだよもん。
>>27 Java使ったことないからわかんないんだけど、if文の中の条件判断する順番って決まってるの?
30 :
仕様書無しさん:01/11/25 20:54
>>28 おかしいなぁ・・・VC++では、forを抜けた後もその変数参照できるよ。
>>29 C/C++ と同じで左から右へ、s != null が偽なら
論理積の右オペランド s.equals("SomeString") は
評価されない。
32 :
仕様書無しさん:01/11/25 20:58
>>10 >for (int i = 0, int n = aString.length(); i < n; i++) {
ふつうの文字列型のサイズを取得するメソッドは重くないから、
こんな書き方する必要ないよ。
どうしても効率気にするなら、イテレータ使うだろうし。
そういう書き方でも悪くないけど「ふつう」じゃないだろ。
>>32 >>10 じゃないけど、
> ふつうの文字列型のサイズを取得するメソッドは重くないから、
それは十分に承知してるけど、多重ループの最も内側なんかだと、
こんな風に効率重視で書きたくなる。
35 :
仕様書無しさん:01/11/25 21:09
どうしようもなくなった時の、コードの書き方。
コードの深層に以下の文を挿入する。
/* ごめんなさい。出来ませんでした m(_ _)m ヒラニヒラニ.... */
>>32 あ、そういう意味か、
>>10 のコードは。
String クラスは内部で文字列長を変数に持ってるからな、
メソッド呼び出しのオーバーヘッドくらいか。とはいえ
strlen() な元 C/C++ 使いならやりたい気持ちも分かる。
37 :
仕様書無しさん:01/11/25 22:36
呼び出しのオーバーヘッドも、
頻繁に使用するルーチンの場合はもったいないから、
漏れは長さはローカル変数に取るよ。
38 :
仕様書無しさん:01/11/25 22:40
> ふつうの文字列型のサイズを取得するメソッドは重くないから、
重くないといっても、ローカル変数に持つよりコストが軽いはずは無いよねぇ・・・。
漏れは、毎回文字列長を取得する人なんているのかと思ってむしろ驚いてる。
いまどきは、ループをどれだけコンパクトに書くかでコードの品質が決まるのに。
可読性を損なわずに速度を選ぶ
>>10のコードはその意味で優秀と思うが。どう?
39 :
仕様書無しさん:01/11/25 22:42
foo()
{
/** なんかのコード **/
:
:
{
int x;
/*** デバッグコード ***/
}
}
そこまで拘りたいなら配列でやるんじゃないの?
> いまどきは、ループをどれだけコンパクトに書くかでコードの品質が決まるのに。
( ´,_ゝ`)フーン
42 :
仕様書無しさん:01/11/25 22:51
>>39 の手は俺もよく使う。急いでいるときなんかには特に。
>>10 (a) for (int i = 0, int n = aString.length(); i < n; i++) {
(b) int n = aString.length()
for (int i = 0; i < n; i++) {
(c) for (int i = 0; i < aString.length(); i++) {
と書いた場合、(a)と(b)は同じ処理だけど、(c)は違う処理になるね。
これはやっぱコンパイラの最適化の範疇外かなあ?
>>43 String.length() に副作用があるかどうかってのは
普通のコンパイラにはわからないから、無理なんじゃないかなあ。
(a1) for (int i = 0, int n = aString.length(); i < n; i++) {
(a2) for (int n = aString.length(), int i = 0; i < n; i++) {
だったら (a2) の方が良かったりすることはないかなぁ?
>>43 クラスの内部と外部は独立して最適化されるから、(c)の最適化は無理だね。
俺は(c)使う奴とは一緒に仕事したくないな。
こんなくだらないところで速度落とされたらたまらん。
>>38 >漏れは、毎回文字列長を取得する人なんているのかと思ってむしろ驚いてる。
>いまどきは、ループをどれだけコンパクトに書くかでコードの品質が決まるのに。
この人、10年くらい進歩とまってるんじゃない?
やっぱ最適化は無理だよねえ・・・
効率も気になるけど、それよりも、意味の無い処理が入っていると著しく読みにくいという
のが最大の問題だと思うな。個人的には。
length()のメソッドがinline化されてればオーバーヘッドも生じないよね。
inline化されてるかどうかは知らんけど・・・
ってか、オーバーヘッドも気になるくらい速度が必要な個所なら
文字列クラスなんて使わないんじゃないの?
>>46 おいおい、お前こそ何言ってんの。
>>38の言ってる事、間違ってないよ。
あと、この程度の追加で「読みにくい」なんて人はVBでもやってなさい。
inline化されてても、毎回thisの参照が発生するよ。
ローカル変数より速い可能性はありえない。
>>48 同意。
漏れなら
>>43の(c)で書くな。
実行して速度が気になるなら、実測してから最適化する。
ミクロな部分は可読性にこだわり、マクロな部分で
効率を目指す方が経験上良いと思われ。
まぁ、そこまで速度が必要な個所ならローカル置くべきだろうね。
ってか、それなら文字列クラス使わずに配列使った方がいいだろ?
でも、速度をほとんど気にしないような個所だったら
ローカルに置かずに直接判定してしまうようなコーディングでも
問題ないだろ?
1 'SAVE "AAA.BAS"
まるで違う世界の人たちと話しているみたいだ。
漏れの職場じゃ、1行程度で速度を稼げるところは、速度優先だわ。
可読性を損なうほどの変更とみなさない。
if(){
:
}
より
if()
{
:
}
の方がif文をコメントするだけで条件を外せるのでデバッグ時に便利なんだが、
社長に訊いたら「ソースがびみょ〜に長くなるからキライ」だそうだ。
みんなはどっち?
>>55 印刷時に行数が少ないほうが便利なので、前者。
>>54 問題なのはホントに速度を稼いでるか、というところでは?
可読性優先で書いて実測するのが一番良いと思うけどな。
しまった・・・もしかして俺誤解されてる・・・?
>>49 (い) for (int i = 0, int n = aString.length(); i < n; i++) {
ここではaStringの中身を変更しない
}
(ろ) for (int i = 0; i < aString.length(); i++) {
ここではaStringの中身を変更しない
}
(は) for (int i = 0; i < aString.length(); i++) {
ここでaStringの中身を変更する可能性がある
}
上記の場合は、 (ろ) のパターンで書くやつは逝ってよし!
理由:
1 効率が悪い
2 読みにくい(for文の中でaStringの中身を変更するのかと思っちゃうジャン)
>>49=54
いや、(a)や(b)が悪いとは言ってないが
速度を要求されないようなところでは
別に(c)の書き方でもいいってことだろ?
ちょっと、頑なになりすぎてないか?
>問題なのはホントに速度を稼いでるか、というところでは?
>>55 K&Rは前者だね。
>>56 印刷するんだ。もう随分ソースを印刷してない気がする。
ローカル変数へのアクセスが、クラスのメンバ変数へのアクセスよりも効率が良いかどうかを
判断するとしたら、
C++のクラスの一般的な実装方法ってどうなってんだろう?
&&
クラスのメンバーにアクセスするのにかかる命令は、スタックにアクセスする場合と比べて
どっちが早いんだろう?
&&
実はプラットホームによって結構違うんじゃない?(上記全部チャラ?)
てなことになって、収束できないよお〜(
>問題なのはホントに速度を稼いでるか、というところでは?
可読性は損なうというほど損なっても無いしなぁ。
速度は、「実測値は知らんが確実に低コスト」が保証されているなら、
それを否定する理由はない。
大体、職場全体で避けえる無駄を徹底的に避けるということで合意しとるからなぁ。
ミクロなルーチンは、可能な限り速度を稼いで、バグを取ったら中は見ない。
むしろ、マクロなところのほうが、可読性重視だよ。
処理の流れを明瞭にするために。
どっちが最終的に速度を得られるかというと・・・・。
>>63 >マクロなところのほうが、可読性重視だよ。
マクロなレベルが違うのかな?
漏れが思ってるマクロなレベルは、
データ構造とかクラス設計のレベルでの話なんだが。
このレベルだと可読性とは別次元の話になるんだけど。
65 :
仕様書無しさん:01/11/25 23:48
(1)for( int i = 0; i < a.length(); i++ )
(1)for( int i = 0, int n = a.length(); i < n; i++ )
(2)みたいな書き方しても、稼げる速度なんて微々たるもんだろ、
「こんな書き方するやつと仕事したくない」って、こだわる程の
ことか?
と、思って、実際にどの程度早くなるか測定したらVC++6.0の
だと(1)のほうが早かったね。
まあ昔風の書き方だと、コンパイラの最適化に合わないことも
あるってことで。
>>65 間違えました。上2行は訂正です。
(1)for( int i = 0; i < a.length(); i++ )
(2)for( int i = 0, int n = a.length(); i < n; i++ )
今検証しているが、ローカル変数派に残念な結果になりそう。
HotStop とかの調整もあるのでもうちょっと待って。
待ってる間に。
漏れはローカル変数なるべく作らない派。
これでずっと可読性が上がると思う。
前にニセ確率のスレであったようなソースは絶対書かない。
69 :
仕様書無しさん:01/11/26 00:14
PowerPCプロセッサならFPUでの計算が整数値以上に異様に速いのと整数値
演算と並列に行われるのを利用して故意にFloatやDoubleの型の数値で演算を
使うことがある。
諸刃の剣だがApple Dveloper Jurnalに紹介されたPowerPC601発表時か
らの隠れたテクニック。画像の色変換やフィルターリングで使ったりする。
70 :
仕様書無しさん:01/11/26 00:32
>for (int i = 0, int n = aString.length(); i < n; i++) {
aString.length() にこだわらなければアリかと。
n = aString.indexOf(aStr)
とか、
n = ((List)aMap.get(aKey)).size
とか。
>>22 インデントの深さも処理によりけりかな。浅ければ良いというものじゃ
ないし。どっちかと言うと慣れと可読性の問題かな。
でも、こういう処理の書き方は感心しないっす。
{
Ptr foobuf1 = NULL;
Ptr foobuf2 = NULL;
foobuf1 = malloc(1024);
if (!foobuf1)
return;
foobuf2 = malloc(1024);
if (!foobuf2)
{
free( foobuf1 );
return;
}
・
・
・
free( foobuf2 );
free( foobuf1 );
}
少々インデントが深くなってもこういう書き方が綺麗で好きだな。
後処理とかの漏れも少ないし・・・
{
Ptr foobuf1 = NULL;
Ptr foobuf2 = NULL;
foobuf1 = malloc(1024);
if (foobuf1)
{
foobuf2 = malloc(1024);
if (foobuf2)
{
・
・
・
free( foobuf2 );
}
free( foobuf1 );
}
}
72 :
仕様書無しさん:01/11/26 01:16
>>69 プロセッサのクセはある程度考えながら書くなぁ。構造体のライメントとか
も無駄が無いように心掛けたりとか。
最適化のオプションと合わせてどういう風にスケジューリングされながら
処理されるのか、等を「想像」しながら。
ローカル変数の実測結果はまだなんだろうか?
>>65 すこし詳しく調べたら違った結果が出たので報告(VC6.0)
(1)for( int i = 0; i < a.length(); i++ ) hoge(a[i]);
(2)for( int i = 0, int n = a.length(); i < n; i++ ) hoge(a[i]);
aが関数内のローカル変数の場合、(1)が速い
aが引数(参照渡し)の場合、(1)が速い
aがメンバ変数の場合、(2)が速い
でした。
メンバ変数にアクセスすると、かなり遅くなるので、
スピードを気にして、(2)のスタイルにしてる人は
関数内のローカル変数の変数にコピーして(1)のスタイル
を使うというのが正解ですな。
(自分はそこまで、スピードが必要なことはほとんどないけど)
いろいろやってたら長くなってしまったので簡単な結果だけ:
for(int y=0; y<100000000; y++){
for(int i=0; i<str.length(); i++){
/* */
}
}
こういうループの前後で時間を計ってみた。str.length() は
62 にしたので、for() の条件文は 6,300,000,000 回呼び出
されることに注意。
i<str.length() を先にすると 37,974:45,896 ミリ秒で i<str.length()
の方が速い。n=str.length() を先にすると 46,947:37,715
ミリ秒で n=str.length() の方が速い。
結果としてコードの書き方 (順序や関数化、HotSpot の有無等)
によってすぐに結果が逆転するという傾向がつかめた。ただし
分母が 10 億のオーダーなので双方大差はない。
で、こんなことやってみればすぐ分かるはずなのにローカル
変数支持派はなんでそれを主張しているのかが分からん。
オイラは
>>57 に同意だけど、頭だけで結論出す人たちとの
仕事はご遠慮願いたいね。
>>74 おお、ありがと。
メンバが遅いとは以外だった。
アドレッシングの関係か。
実測結果を載せてもらえるとさらにありがたいが。
ちなみに /* */ を y=1<<8; にした時、hoge.method() にした時、
HotSpot の有無などによってぜんぜん結果が違ってました。それから
>>78 実行時には -verbose:gc オプション付けて GC が発生して
いないことも付け加えときます。
81 :
71ではないが....:01/11/26 01:40
>>76 「gotoを使う==既にロジックが破綻している」という認識も一部にあり。
「gotoを使う==バグの元」という認識も一部にあり。
gotoはカッコ悪いナリ。
と個人的に思う。
82 :
仕様書無しさん:01/11/26 01:40
結論は「小手先の最適化は HotSpot にかき消される」ということで
よろしいでしょうか?
>>78 できればバージョンや環境も教えてくれ。
>>81 try...finally が使えるならその方がいいんだけどね。
そうでない場合で、正常動作条件までの絞込みが複雑だと
goto を使った方がすっきりする場合はある。
もちろん、そんな複雑な条件が出ないように設計できればベスト。
>>78 ありがと。
実測結果はやっぱ説得力あるね。
ところで
>37,974:45,896 ミリ秒
これの読み方がいまいちよく判らないんだけど。
こんなんで良いかい?
OS: Windows 2000 Professional
CPU: Pentium III 850MHz
MEM: 256MB
D:\新しいフォルダ>java -version
java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24)
Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)
ちなみに -Xint で HotSpot はずすと i<str.length() が
俄然速くなった。
>>79 だいたい、2〜3%の差がありました。
現実のコードの場合、ループ内にいろいろ処理を書くので、
この差はもっと薄まると思います。
(空ループにすると、最適化でループそのものが削除されてしまうので
測定の時はダミー関数をひとつ食わせてます。)
・・・
Javaか・・・
JavaとC++のメソッド呼び出しを同列に比較しちゃいかんのとちゃうか?
>>85 あ、すまん。37,974:45,896 ミリ秒は
for(int i=0; i<str.length(); i++) : 37,974 ミリ秒
for(int i=0, n=str.length(); i<n; i++) : 45,896 ミリ秒
という意味。左側が条件内 length() 呼出版で、右側が初期化時
length() 呼出版ということ。時間かかってたのは HotSpot の
ため結果が安定しないのをどう表現しようか考えていたため (w
だれかVC++でも計測してくれないかなあ。
アセンブラコードの出力付きで。
試すパターンが多くて面倒だと思うけどさ。
93 :
仕様書無しさん:01/11/26 01:56
>>91 シラフになってから計測しておくよ。
つーか、自分で計測しれ!
Java で最適化したければ C や C++ の定番を持ち込むよりも
JIT コンパイラの傾向をつかんだほうがはるかにハイリターン
ということですか?
ところで HotSpot って JIT コンパイラですよね?
>>93 >>74 は「メンバ変数」の意味がわからないのと、アセンブラコードがないので・・・
>>94 了解っす。気が向いたら自分でも計ります。
timeGetTimeだとmillisecondsまでしか計れないけど、
QueryPerformanceFrequencyとか使えばいいのかなぁ?
98 :
仕様書無しさん:01/11/26 02:10
timeGetTime()は1ms単位では正確ではないし、
そのレベルでも回数こなせば問題ないかと。
>>96 メンバ変数ってのは、メンバ関数から、メンバ変数にアクセスって
ことです。
class Test {
public:
std::string a;
sokutei();
};
Test::Ssokutei()
{
for(...a.length()...)
}
ローカル変数派とか変な呼び名はやめて欲しいなぁ。
そういう変なこだわりじゃなくて、
自分の責任範疇で最適な動作を追及しているだけでしょ。
労力や可読性の兼ね合いを損なうほどのことでもないし、
>>49みたいなPGが迫害されるようじゃいかんとは思うんだけどねぇ。
たった1行がそんなに可読性を損なうというなら、やめときゃいいとは思うけど、
それほどのもんでもなかろう。
こういうループで速度を稼ぐこと億劫がる傾向の人って、
他のところでも同じようなことをして速度を損なうんじゃないかなぁ。
仮にこのループが、最も速度を稼ぐのに効率的なところだとして、
それでなおかつ、i < aString.length( ) を使う人、手を挙げてごらん?
こういうところで論じるのは、どうでもいい場所に関することじゃなく、
ソフトウェア品質に影響する部分として論じ合うべきでしょう?
>>101 もう何をいってるのやら。
訳がわかりません。
103 :
仕様書無しさん:01/11/26 02:17
>こういうところで論じるのは、どうでもいい場所に関することじゃなく、
>ソフトウェア品質に影響する部分として論じ合うべきでしょう?
この点は同意。
全体には影響しないだろうって意見は、何のための意見なんだろうと思うね。
こういう場合「ループそれ自体」の話をすべきだろう。
104 :
仕様書無しさん:01/11/26 02:21
>>101 だから速度を要求する場合なら、それ相応のコーディングはするが
速度を要求しない(どちらの方法を選択しても体感速度が変わらないような)
個所なら i < aString.length() でも構わないとおれは思ってる。
そもそも、速度を要求するような文字列処理で文字列クラスを使おうなどとは思わん。
106 :
仕様書無しさん:01/11/26 02:22
なに?文字列クラスに限定する話なのコレ(w
>>106 >速度を要求する場合なら、それ相応のコーディングはするが
>>78 >>82 >>95 Java 使って本気でパフォーマンスに注意しながらソフト作っている
人にとっては至極まっとうな結論なのだが...。逆にローカル変数
使って最適化した気になってる連中がかなり痛いよ。無視したろうか
と思ったけど、めんどくさがらずに実証した
>>78 は偉い。
109 :
仕様書無しさん:01/11/26 02:30
>>108 ローカル変数だけで最適化した気になってた奴などいたか?
俺は、意味の方が気になるなー。
毎回aString.length()というメソッドを実行する必要がないのに実行するのが嫌。
言語も速度も気にしてない。
111 :
仕様書無しさん:01/11/26 02:31
for(int i = 0, int n = s.length(); i < n; i++ )
最初は、「こう書くのがふつう」みたいな大雑把で勘違いした
話だったのに、論破されたら、急にゴネだしたね。
>>10
112 :
仕様書無しさん:01/11/26 02:32
一体何人書き込んでるんだ(w
>>109 下の「全部読む」クリックして「効率」で検索かけてみろよ。
>>107 >>速度を要求する場合なら、それ相応のコーディングはするが
>こういうところで論じるのは、どうでもいい場所に関することじゃなく、
>ソフトウェア品質に影響する部分として論じ合うべきでしょう?
どうでもいい部分のコーディングに関して議論する意味は無いと思うが。
>>100 CとかC++で速度が気になるならアセンブラ出力させてみたりするよね?
しかしJavaでアセンブラレベルまで落として速度のチューニングはしないのではないかと?
>>107 あなたが速度を要求されたときのコードを教えて欲しいなり(w
118 :
仕様書無しさん:01/11/26 02:43
ループのたびに、length()呼ぶのに抵抗あるって人は、
イレテータの時はどうしてんの?
終端を調べるのに、普通は毎回メソッドを呼び出してるけど、
そんなんも、ローカル変数にコピーするの?
119 :
仕様書無しさん:01/11/26 02:44
イテレータはイテレータのまま使うしかないに決まってるじゃん。
120 :
仕様書無しさん:01/11/26 02:46
はいは〜い。
皆さん明日は仕事ですよぉ〜 (w
122 :
仕様書無しさん:01/11/26 02:50
ところどころ論点ずれているけど、
今のここの話は要するに
効率を追いかけるか、
可読性を追いかけるかっていう話だよね?
(ちがったらスマソ)
>>120 そうか?length()を呼ぶのに抵抗あるって言ってるのも、
おなじくらい痛いように思うぞ。
>>123 いや、おれはlength( )使う人なんだけど、
>>118の質問って、意味的には
「可読性を著しく損ない、安全性も怪しい方法をとるのか?」
って問いだよな。
そこまで極端なこと言ってる奴は居なかったように思うから「痛い」って書いたのよ。
>>122 技術者のオナニーテクニックの議論です(ワラ
length() を毎回呼び出すのに抵抗がある人は、
length() が strlen() みたいに内部に全文字を
走査するループを持っていると思っているからでは?
実際は、String 内のプライベートメンバ変数を
参照しているだけだと思われるので、
関数呼び出しのコストだけのはず。
いや、彼らは呼び出しコストを気にしてるみたいだよ
>>126
>>126 そして話が振り出しに戻る。
お〜い誰か実測の準備してくれ〜 (w
>>121 俺は今日も仕事でしたが何か? (泣
>>122 いや違う。
>>10 に対する反応だ。
>>10の書き方は
・ ふつうなのか?
・ 効率がいいのか?
・ 読みやすいのか?
とかだろう。
普通に最適化をかけたら、C/C++ならローカル変数のほうが若干速いコードを
吐く道理だよね。
そのとき改めて
わずかな速度が大切か、わずかな可読性が大切かって話になるだけで、
実測値を出して結論が出るという考え方は甘いような。
スレのタイトルから外れまくってるじゃないか藁
>>117 単純にループ内で何度も呼ぶ必要がないメソッドor関数は
ループの外に出すだけ。
または
ループ回数が少なくなる方法を探すか
133 :
仕様書無しさん:01/11/26 03:03
>>132 結局やることおんなじだよな。
局面選ぶか、いつもやるかって違いだけだ。
for (int i = 0, int n = aString.length(); i < n; i++) {}
これって文法的におかしくない?
カンマ演算子のオペランドが宣言文になってるけど。
そもそもどの言語?
C++限定の話:
ループ内で、文字列にconstメンバ関数しか使ってなかったら、
length() 呼び出しは一回に最適化されそうなもんだし、
まっとうなライブラリ実装者だったら、length関数は
インライン関数にしていて、呼び出しコストゼロに
すべきだけどね。
Java でも、そういうの期待したいところだけど、
length は final メソッドになってないから、
inline 展開はまずされないと思われる。
(Stringを継承するクラスのため)
うぅむ。length()コスト気にしない派だったのに、俺(w
136 :
仕様書無しさん:01/11/26 03:07
javaでしょ。
137 :
仕様書無しさん:01/11/26 03:08
やるならいつもやるほうが読みやすいような・・・・
139 :
仕様書無しさん:01/11/26 03:11
>>135 それでもthis間接参照があると、ローカル変数よりは・・・・
>>135 いや、String は final クラスだ。
public final class String implements java.io.Serializable, Comparable
議論がループしてます(w
142 :
仕様書無しさん:01/11/26 03:15
Javaの文字列ってイテレータ使えないの?
イテレータを使えば、イデオム的で効率もいいでしょ。
と、一瞬思ったけど、Javaはイテレータでも遅いのかな?
>>141 すみません。多分、後から割り込んできた、ワタシのせいです。
>>135 あり、final でしたか。1.3 の JavaDoc を見て確認した
つもりだったんですが。ちょっと古かったかも。
>>139 確かに、誠にその通り。
しかし、そこまで要求するなら、そもそも、
String 使うなぁと思わなくも(藁
>>143 Stringを使って楽をしながらも、少しでも効率を良くしたいという、
わがままなプログラマ達の議論です。(w
ここの皆さんは、VMがどんな最適化するかもワカラナイ環境で、
コーディング時に重箱のすみ突っつくような最適化(になって
いるのかどうかもわからないのに)になんでこだわるの?
普通の仕事は、「コーディングの時は可読性一本槍」で、
「実行してプロファイルとってどうしてもやばいとこだけ
チューニング、を速度が仕様を満たすまで繰り返し」じゃ
ないの?作業効率考えたら。
しかも、最近の多くのプログラムはコードの実行部分以外に
オーダの違うボトルネックがいっぱいあったりするので、
全然気にしないでいい場合も多いし。
暇つぶしの話題というなら、それはありだろうけど。
147 :
仕様書無しさん:01/11/26 03:28
要求というよりは・・・・
書いてる側がどこに美学を持つか、だろうね。
Stringが必須の前提では、
自分の責任で処理できるところをできるだけ速くするか、
あるいは見易さを追求するか、
っていう普通のPGの誰もが考える問題がたまたまここで展開したように思う。
ちなみに、俺はString使わないでいいところは使わないけど。
速度が求められるケースが多いから。
148 :
仕様書無しさん:01/11/26 03:30
javaの最適化を理解したら、javaなりの最適化をするに決まっておる。
>>146 まあ、たまーにこういう議論から新しい視点や面白い発想も開けることがあるので、
無碍に扱うこたぁないよ。(たまーにだけどな)
ワタシは下手に手動最適化しても、可読性さげて、
バグの温床になって、結局人に迷惑かけるだけだから、
見やすさ優先派です。
とはいえ、単に速度が優先されるような境遇になって
いないだけなので、別に自分のやり方が常に正しい
などとは全くもって思ってないです。
# だいたいボトルネックになるのは、
# アルゴリズムが悪かったり、
# SQLが悪かったり、仕組みが悪かったり(笑)
どうでもいいけどこのスレ、夜中なのに伸びが早すぎ(w
>>150 連休明けで生活リズム壊れて寝れない人と
連休なのに会社で残業中の人が盛り上がってるのかと・・・(w
おれも146に賛成!
153 :
仕様書無しさん:01/11/26 03:51
>>149 僕も基本的に可読性重視。
読み易いプログラムは無駄が少なく速いと思ってるし・・・
3Dのレンダリング処理のループみたいにマジで「速度命」のロジックを
組むときは基本的なセオリーの他に69や72みたいにプロセッサの特性
(含:キャッシンングやスケジューリング)やコンパイラが吐くコードの
癖を考慮して書く。
ローカル変数だからどうだ.....みたいな事はコンパイラが吐くアセンブル
コードを見て決める。
154 :
仕様書無しさん:01/11/26 04:01
通常は、可読性重視でよい。
ちゃんとしたアルゴリズム考えてれば多くの場合問題ないはずだ。
できの悪い元コンパイラ屋などは、高級言語でも常にアセンブラに
近いコードを書こうとする。また、それを人に押し付ける。
こういう人間は、はやく引退するべき。
155 :
仕様書無しさん:01/11/26 04:05
じゃ、
プログラマ板の結論としては
for(int i = 0; i < str.length(); i++ )
で、書けと。
for(int i = 0, int n = str.length; i < n; i++ )
はドキュソ。
でよろしいですね。
>>154 って、いうか、そういう人は、もう寝ちゃった可能性大(藁
157 :
仕様書無しさん:01/11/26 04:08
159 :
仕様書無しさん:01/11/26 04:10
可読性を損なわない範囲の最適化。
これが一番美しいと思う。
160 :
仕様書無しさん:01/11/26 04:19
>>155 どっちでも好きにしろ、但し
1.他人に(あるいは「コーディングルールが決まってる
プロジェクトで」)押し付けんな。
2.プログラムの中では統一しろ。
ってところじゃない?
161 :
仕様書無しさん:01/11/26 04:28
常に柔軟な考えをもつべし。
コーディングとはこうだと決め付けて頑固一徹にならないこと。
ローカル変数増やしてまでこんな書き方するかね?
俺がこれを見たら、途中でlength()が変わるなどの特殊な
ことやってると思うね。
でもたとえば、以下のような
printf("%c-%d: ", "BINGO"[(cell[n] - 1) / 15], cell[n]);
ごくふつうのコードが、「可読性が」云々文句いわれたら、
どう書き直します? (15は実際にはマクロになってるとして)
164 :
仕様書無しさん:01/11/26 11:07
>>163 読みやすいかどうかって客観的な基準がないから、
難しいところだけど、文字列に配列演算子(だっけ?)を
使うのって、知らない人も多いかもしれない。
おれの場合こうするかな?
char szBingo[] = "BINGO";
int no = (cell[n] - 1) / 15; // この計算の意味を書く
printf("%c-%d: ", szBingo[no], cell[n]);
この方がコメントつけやすい。
可読性をあげるなら (cell[n] - 1) / 15 は
何の計算かってことを書かないといけないと思うが・・・
コメントのつけやすさ」という観点で「no」という
変数を導入したのはわかりますが、
szBingoという変数はなぜ導入しました?
(即値をそのまま書いた方が解りやすいと思いませんか?)
> 何の計算かってことを書かないといけないと思うが・・・
まあ、それはコメントを1行入れればすみますね。
"BINGO" という文字定数がコード中にあちこちに散在するなら
定数宣言しておくのが普通だわな。
> (即値をそのまま書いた方が解りやすいと思いませんか?)
いいえ、思いませんね。
> 読みやすいかどうかって客観的な基準がないから、難しい
「読みやすさはひとによって違う」っていうのを認めてしまうと、
読みやすくかくための理由としての
(1)未来の自分が見て勘違いしないため
(2)他のひとが見たときのため
のうち(2)と矛盾してしまい、「大義名分」が減ってしまうので:)
「ひとによらず客観的で絶対的なみやすさ」っていうものも
ある程度はあるっていうことにしないと ;)
> あちこちに散在するなら定数宣言しておく
あ、この場合は1箇所だという仮定での話です。
#define MAX 1000
みたいなのって、たとえ1箇所でも名前つけちゃいますよね。
>>163 >>「可読性が」云々文句いわれたら
そいつの頭を書き直す、かな。
細かいことだけど・・・
(cell[n] - 1) / 15って cell[n] / 15 - 1 じゃないか?
そろそろ、スレの本題に帰ることをキボンヌ
for (int i = 0, int n = 10; i < n; i++) {};
やっぱりおかしいと思うんだけど。bcc32でエラーが出ます。
VC++6.0では怪しい警告。int i = 0, n =10;ならいいみたいだけど。
でも間違ってたら恥ずかしいけど。。。
>>174 for(int i=0,n=10;i<n;i++){};
はVC++では普通に使う書き方だけど、可読性を考えたら
int i,n=0;
for(i=0;i<n;i++){};
だなぁ。俺にとっての“美しいソース”とは
「初心者でもスラスラ読める」というのが必須条件だから。
177 :
仕様書無しさん:01/11/26 15:44
ひとつの美学として、
コンパイラにより多くの最適化の機会を与える書き方ってのもあるよね。
まあ、ここで主流らしき人らはそんなのどうでもいいらしいけど。(w
私もforの場合は事前にintで宣言しますねー。
見やすいから
179 :
仕様書無しさん:01/11/26 15:51
C++のコードだと
for(int i = 0;...
って書き方が、しょっちゅう出てくるんで、目になじんでしまってますが。
180 :
仕様書無しさん:01/11/26 15:54
Cの書式についてはK&R第2版準拠.
理由:とりあえずみんな読んでるから.
181 :
仕様書無しさん:01/11/26 15:57
>>180 うわ、俺それ読んでねーよ。(10年もPGやってるのに)
DQNか俺(w
> (cell[n] - 1) / 15って cell[n] / 15 - 1 じゃないか?
いいえ、前者で合ってますよ。
> C++のコードだと` for (int i = 0;...って書き方が、
> しょっちゅう出てくるんで、目になじんでしまってますが。
別にC++やJavaじゃなくてもCでも標準ですよ。
ウソこけぇぇぇぇぇぇぇぇぇ!!!!!
Cではできないだろ・・・
C99だとOKとかいう話になるの?
C99 なら出来るよ。
C99対応の処理系って今何がある?
mainの戻り値の型を書かない奴がC99処理系を想定してるわけないじゃん・・・。
189 :
仕様書無しさん:01/11/26 17:44
int n;
(1)if( MIN <= n && n <= MAX )
(2)if( (unsigned)(n-MIN) <= MAX-MIN )
n が MINとMAXの間か調べるコード。
(1)を(2)のように書き換えると速くなった。
大昔、コンパイラがバカでCPUも遅かった時代に
使ったテクニック。
注:n,MIN,MAXのとりうる値に気をつけないとバグる
190 :
仕様書無しさん:01/11/26 18:52
void asmfunc1( int param1, int param2 );
#ifdef _DEBUG
#define asmfunc1(p1,p2) ASSERT(0<p1),ASSERTE(100<p2),asmfunc1(p1,p2)
#endif
アセンブラなど、内部で引数チェックが難しい関数の、デバッグ時の引数チェック。
ヘッダを入れる場所を間違えると大変。
でも、便利。
191 :
仕様書無しさん:01/11/26 18:59
C99って標準なのか?
192 :
仕様書無しさん:01/11/26 19:04
C99を実務で使える環境なんて俺の仕事がらみでは見たことねぇが。
どこに居るんだC99って・・・・。
193 :
仕様書無しさん:01/11/26 19:07
今マ板で話題の例の本ってC99準拠だったりする?
> C99って標準なのか?
最新の標準規格ですね。
また始まった...
しかし PC での de-facto standard (でもないか?) であるところの Visual C++ では
for (int i=0; ... ) {
}
for (int i=0; ... ) { ← ここで二重定義
}
なんで、for 内で定義し辛かったりする。
…“マクロで逃げなさい”っつってる奴もいるけどね。
197 :
仕様書無しさん:01/11/26 20:01
C99って、たしかgccの最近のバージョンでオプション付けてやると使える筈。
あのー
>>if( ( fp = fopen( ..)) == NULL){/*なんか処理*/}
よくこういうコード書かれるかたが多いですけど、
fp = fopen(....);
if (NULL == fp){/*なんか処理*/}
とかのほうがいいのではと、いつも思うのですが、
他の方はどうなんでしょう?
僕はこの方がfp = fopen()のところでデバッガで止めて、
fpにNULLを代入することで、きちんとエラーが処理できるか
見れるのでバグが少ないと思うのですが。
もしかして一行派の人は、きちんとテストしてないの?
>>198 漏れも2行にわける。
でも、1行で書いてもファイルの有り/無し環境でテストすれば
テストしたことになるんではないかと思うけど。
200 :
仕様書無しさん:01/11/26 21:09
>if (NULL == fp)
この書き方だと、なんで「if(fp == NULL)」にしない?
ゴルァって怒られることない?
>>200 その話をするとまた不毛な宗教戦争になるよ。
202 :
仕様書無しさん:01/11/26 22:06
>>78 のコードを効率意識して書くなら、
int n = str.length();
for(int y=0; y<100000000; y++){
for(int i=0; i<n; i++){
/* */
}
}
ってやるな。
# もちろんループ内で str が変化しないことが前提だけど。
ようするに「ループの外に出せるものはできるだけ出す」ってこと。
可読性も効率も悪くないっしょ。
203 :
名無しさん:01/11/26 22:10
vbはだめですか?
>>198 スコープなどで差し支えなければ、
FILE *fp=fopen(...);
if( fp == NULL ){
/* なんか、処理 */
}
と書きます、ワタシ。
さもなければ、
if( (fp=fopen(...)) == NULL ){
/* なんか、処理 */
}
って、書いたりする。
要は可読性より、短く書きたいだけなんかい!>俺
> >>if( ( fp = fopen( ..)) == NULL){/*なんか処理*/}
> よくこういうコード書かれるかたが多いですけど、
> fp = fopen(....);
> if (NULL == fp){/*なんか処理*/}
> とかのほうがいいのではと、いつも思うのですが、
そういう変なことを言うひとのために380ペイジに解説してあります。
> int n = str.length();
> for(int y=0; y<100000000; y++){
> for(int i=0; i<n; i++){
このオオボケな書き方って、その昔三田某が、
「これのほうが正しい」と雑誌の記事に書いてて大笑いされた
やつですね。
もしかしてそれを読んで影響を受けてる?
(まさか本人だったりして...^^;)
>>206-207 アンタが来るとスレがつまんなくなるんだよ。
とっととどっかに消えろよ。
そもそも
> if ((fp = fopen(...)) == NULL) {
が、「コードを短くするため」のものだと思っているあたりで
ダメダメですね。
日下部さん、俺も同じ見解だけど、どこがどういう風にダメか書けよ。
そういう書き方をする人は、その人なりの知見や論理でそうなったんだから。
あなたの書き方は他人の無知をあげつらってるようにしか見えなんだいよ。
>>204 いや、だから 202 は 78 のコードの別の問題点を
指摘しただけでしょ?
まあ、204 のコードは最悪だと思うけど。
212 :
仕様書無しさん:01/11/27 07:21
>>208,
>>210 さん、
Kusakabe Youichi氏の書き込みは無視しないとスレが荒れますよ。
みんなでKusakabe Youichi氏の署名の記事は見なかったことにして、
淡々と話を進めるとスレは荒れない。
>>202 もしかして外側に回数の多いループを持ってこない方が良いという意味か?
もうちょっと話の流れつかんでから発言したほうがよかったね。
for(int i = 0; i < str.length(); i ++) の効率云々を話してたんだから。
>>94 >>74 だと細かい計測条件が不明だから、なんとも言えん気がする。手元の処理系で計測して
みたので、結果をつけときます。
表の見方は次のとおり。実際のソースコードを後につけておくので、細かいことはそちらを参照。
(1) byval, byref というのは std::string を「値」で渡しているか、「参照」で渡しているかの違い。
(2) a.length() は毎回 std::string::length() を呼び、len は std::string::length() をローカル変数
に格納して利用。
(3) 最後の数値は実行に要した時間で、単位は秒。
// ------------------------------------------------------------------
// Visual C++ 6.0, STLport 4.5, 最適化 /O1
// ------------------------------------------------------------------
byval a.length() 1.7
byval len 1.8
byref a.length() 1.6
byref len 1.7
// ------------------------------------------------------------------
// Borland C++ Compiler 5.5.1, 付属の Rogue Wave STL, 最適化 -O1
// ------------------------------------------------------------------
byval a.length() 4.8
byval len 4.4
byref a.length() 1.9
byref len 1.8
// ------------------------------------------------------------------
// Cygwin gcc 2.95.3-5, 付属の SGI STL, 最適化 -O2
// ------------------------------------------------------------------
byval a.length() 3.4
byval len 2.9
byref a.length() 2.5
byref len 3.4
>>214 続き
使ったソースコード
#include <string>
#define MAXCOUNT 10000000
#ifdef BYREF
# define PARAMTYPE const std::string&
#else
# define PARAMTYPE std::string
#endif
volatile void foo(char) {}
void
check(PARAMTYPE a)
{
for (int count = 0; count < MAXCOUNT; ++count) {
#ifdef LENGTH_ALWAYS
for (size_t i = 0; i < a.length(); ++i)
foo(a[i]);
#else
size_t len = a.length();
for (size_t i = 0; i < len; ++i)
foo(a[i]);
#endif
}
}
int
main(void)
{
check("foooooooooooooooooooooooooo");
return 0;
}
>>215 続き
1000 万回のループでこれだから、length() を毎回呼ぶのか、それとも変数に格納しておくかで
有意な差はないでしょう。
あと length() は const メンバ関数で、実装によってはさらにインライン関数だから、最適化する
と関数呼び出しのオーバーヘッドはなくなります。実際に VC6, STLport 4.5 でアセンブリコード
を出力させてみたところ、length() はインライン展開されメンバ変数へのアクセスに書き換えられ
ていました。
mov eax, DWORD PTR [esi]
pop ecx
mov ecx, DWORD PTR [esi+4]
inc edi
sub ecx, eax
cmp edi, ecx
edi がループカウンタ i で、[esi], [esi+4] がそれぞれ文字列の先頭と最後のポインタを格納し
ているメンバ変数 (_M_start, _M_finish) ですね。
あと Borland C++ Compiler で byval が異常に遅いですが、これは length() メソッドよりも、
コピー時の処理が時間を食っているのだと思います。
> 日下部さん、俺も同じ見解だけど
とか書いといて、
> こがどういう風にダメか書けよ
といいつつ自分は書いてないあたりがまぬけですね。
(1) for(int i = 0, int n = s.length(); i < n; i++ )
(2) for(int i = 0, i < s.length(); i++ )
もしs.length() の文字列がグローバルな変数なら
マルチスレッドな環境では致命的な違いが生じると思われ。
別のスレッドがループ中に文字列を書き換える可能性があるので。
最適化しないのはコンパイラが正しいことをしている。
> そういう書き方をする人は、その人なりの知見や論理でそうなったんだから
だからこそオオボケなのでは?
>>218 それは、変数の修飾とか、状況によって違うでしょ。
マルチスレッドの整合性のとりかたは、ユーザに任せるのが
一般的。
> 効率云々を話してたんだから。
こういうボケナスにはカーニハンの鉄則集8-10を壁に貼っといて
ほしいです:)
「効率について云々していいのは実際に測定したデータを示す人のみ」
> マルチスレッドの整合性のとりかたは、ユーザに任せるのが
一般的
というか、他のスレッドがその文字列を書き換えるような状況では、
そもそもその初期状態の長さをもとに処理するのが正しいロジックか
どうかという疑問が生じますね。
>>218 C++ では、Java と違って規格にスレッドが入っていないから、そのあたりの意味付けはライブラリ実
装者の裁量ですね。
ところで (1) の書き方でも、そもそも別スレッドが文字列を書き換えた瞬間に n の値は「文字列 s の
長さ」とは全く無関係な何かになってしまうが、その n に何か意味があるの? グローバルな文字列
を for ループ中で操作/参照する場合には、結局
- for ループに入る前にロック
- for ループから出たらアンロック
ってコードを自分で書くしかないと思うが。
(あと Kusakabe に関しては、技術的な話には対応しても構わないが、それ以外の煽りは放置で頼む。
また荒れるから)
何度もでてるけど、C++で
for(int i=0, int n=0; i<n; ++i)
はコンパイル通らないはず。
VCは知らんけどbccでもgccでも通らないし
プログラミング言語C++第3版の付録の文法を見てもこれは間違ってる。
for(int i=0, n=0; i<n; ++i)
なら通る。
length のハナシは、そろそろやめにしないか?
不毛だ。
ではスレッドにふさわしい?話に。
0,1が交互に入れ替わる書き方
1 if ( a==0 ) a = 1; else a = 0;
2 a = (a==0);
3 a = a ^ 1;
4 a ^= 1;
m の立っているビット数をカウントする方法。
初めて知った時はえらく感激した。
inline int count(UINT64 m)
{
m = (m & 0x5555555555555555) + ((m >> 1) & 0x5555555555555555);
m = (m & 0x3333333333333333) + ((m >> 2) & 0x3333333333333333);
m = (m + (m >> 4)) & 0x0f0f0f0f0f0f0f0f;
m += m >> 8;
m += m >> 16;
m += m >> 32;
return (int)(m & 0x00000000000000ff);
}
5 a = !a;
6 a = 1 - a;
7 a -= 1;
8 a = "10"[a];
>>231 7 は a *= -1 の間違いか? これだと 1, -1 の繰り返しになるけど。
8 は '1', '0' と 1, 0 の区別がついてないでしょ。ダメ。
>>231 7はダウト。8はすごいな。
こんなコード書いてる奴がいたら殴るけど。
>>232 そっか。だまされたぞ。
8' a = "10"[a] - '0';
こうか?。文字コードの順番忘れた。
9 a = cos(a*π/2);
>>234 敢えて書くなら
a = "\000\001"[a]
じゃないのか。8 進数表記。
使いみちは限定されるが、
#define swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
>>237 それも、副作用がある式を a, b に書いたらダメだわ、a == b だとダメだわで、書いてるやつが
いたら殴るコードですな。(しかも、最近のコンパイラだとむしろ遅いし)
4バイトを1ワードで扱いたい時。ただし処理系によって
順番が変わる?事があるかも。
union ONE_WORD {
struct {
char d;
char c;
char b;
char a;
};
int abcd;
};
> 副作用がある式を a, b に書いたらダメだわ
そうですね。それだけでかなり使いみちが限定されます。
> しかも、最近のコンパイラだとむしろ遅いし
いえ、ふるいコンパイラーでも、もともと「かえって遅い」例ですよ。これ。
> 処理系によって順番が変わる
その心配の前にメンバーのあいだの「隙間」があくかも
しれない心配のほうが先ですね。
常識的にはbitをマスクしたりシフトしたりするマクロを
使うでしょう。(エンディアンの心配はそのあと)
>>241 charを4つ並べて隙間ができる処理系があるか?
ところで (a==0) が1になるという保証はあるんでしたっけ?
とりあえずおまえら volatileとstrength-reduceの意味調べてから出直してこい
>>242 さすがに商用レベルの処理系では、見たことないなぁ。
規格の上では、そもそも union を使ったときに struct と int abcd が「同一のメモリアドレス」に配置
されるかどうかも処理系依存だし、sizeof(int) == 4 も処理系依存。ただし、こういうコードが必要にな
るのはふつーはハードウェアよりの部分だから、そもそもコードに移植性が要るのかって問題がある。
ま #ifdef で切るなり、ドキュメントに明記してあれば問題ないよね。
>>244 もしかして std::string の話をしてる?
にせものばっかりだな。
>>239 struct sockaddr_in とか。
249 :
仕様書無しさん:01/11/27 12:52
>>241 ビットフィールドはどうよ。
int サイズの境界をまたがなくても
勝手に間が空く事ってあるのかな??
故意に空ける事は出来るけど。
>>243 その条件式が真なら。
251 :
仕様書無しさん:01/11/27 13:05
>>249 unionをビットフィールドで、代用するってこと?
どうやるの?
>>250 いい加減なことを書かないように。ANSI C の規格書に明確に 1 or 0 だと書いてある。
254 :
仕様書無しさん:01/11/27 13:24
コンパイラが特定の規格書に準拠しているのを保証できないのに
規格書を盾にするのは虚しい・・・
>>253 一般的な話をするなら、せめて ANSI C に限定しなければ何も言えん。
ANSI C++ のように規格が制定されて日が浅いため、準拠している処理系が少ないならともかく、
C89 は十分に浸透しているから、準拠していない例外部分を探したほうが早い。で、今時 == の
結果が 0 でも 1 でもない処理系って何があるの?
258 :
仕様書無しさん:01/11/27 13:45
規格に無知&無頓着を装う煽りが来ると、
途端に過敏に反応する人が居るのが笑える。
>>258 装うことに何の意味があるんだ?
C++ だけど、
template <typename T> Traits {};
と空っぽの struct を定義しておいて、あとで specialization するのは、わりと使う。
>>260 煽る意味があるのではないかと。程度の低い趣味ではあるが。
このスレって有用な部分もあるけど、
宗教戦争の火種を常に抱えてておもろいな。
真(1)、偽(0)を数値として取り扱うのは
ソースコードとしてあまり美しくないと個人的には思うから
(a == 0 ? 1 : 0)とか書いても悪くは無いと思う。
でも
真(1)、偽(0)を数値として取り扱うのはやめろとまでは
言うつもりは無いよ。
>>262 boolean の扱いも宗教戦争の火種だね。
数値として取り扱うのが美しくないなら
a, !a
だけ使って、比較は一切なしというのが原理主義者的立場と思われ。
ある日C++に移行することを想定して、
それを数値化する意味では262の書き方はありのような。
(a==1)は true / false になるから。
== true とかって書く人、いる?
true は true だと分かっていても、かけない人は多いと思う。
割と心理的な作用で、boolean を 1/0 にあてることはしないな。
それと同じ意味合いで ANSI C に (a==0) の結果が 1 or 0 だとあっても、
それを数値にあてるのは心理的に気持ち悪い。
>>264 CのコードはCのまま、C++に取り込めばいいだろ。
C++に書き換える必要はない。
>>251 char 4 つの構造体を
ビットフィールドに変えるってこと。
> charを4つ並べて隙間ができる処理系があるか?
> さすがに商用レベルの処理系では、見たことないなぁ。
いくらでもありますよ。経験値足りない?
> volatileとstrength-reduceの意味調べてから出直して
前者はCではある程度実装依存ですね。
> == true とかって書く人、いる?
Cではたとえば、
if (flag == true) ...
とかだったら省略しちゃってif (flag) にしちゃうけど、
if (a == true && b == false)
とかの場合は省略しないで書いちゃいますね > == true
# あ、C++のときもそうしてるかも
271 :
仕様書無しさん:01/11/27 17:35
>>267 int a;
a = (a==0);
このコードをC++に取り込んだら速攻でエラーだ。
話の筋では、この点への懸念を
>>264は話してると思うよ。
> え、ANSI 限定の話だったの?
これは自分が間違えたののごまかし方としてはかなりみっともないですね。
> コンパイラが特定の規格書に準拠しているのを保証できないのに
> 規格書を盾にするのは虚しい・・・
コンパイラーのふるまいの「保証」とか言ったら、
i += 3;
だってエラーにせずに通すっていう保証はどこにもないですよね。
(標準規格の前提での話題でなければ)
(しかも実在する!)
>>271 どこが?
C++ だと a == 0 の結果は
型 bool
値 true or false
で、bool と int は暗黙の変換が認められている。それで、変換後の値も
true -> 1
false -> 0
だけど。
スレが腐り始めてます。
ここの板で腐っていないスレは見たことありませんが
>272ってホンモノ?ぺたぺた
>>202 のプログラムのどこが悪いのかわからん。。。
>>277 別に悪くはないが、良くもない。実行時の効率を問題にしてるなら str.length() を一時変数に
置いても、ループ内で毎回 str.length() を計算しても(まともな STL の実装を使ってる限りは)
速度は大差ないし。
悪いのはコードよりも、実際にプロファイルも取らずに「この方が速いはず」と小手先の最適化
に走る姿勢と思われ。
>>278 ありがと!
「ループの外に出せるものはできるだけ出す」ってのが間違いなのかと思った。。。
280 :
仕様書無しさん:01/11/27 23:02
push 0
ret
良スレに育ちそうだったのにな。
残念だね。って俺1じゃないけどね。
#define TRUE (0==0)
#define FALSE (0==1)
「何をするコードか」は書いてないので、いろいろ解釈はありえると
は思うんだけど、
でもこのひと、
>>172 仕様書無しさん wrote:
> 細かいことだけど・・・
> (cell[n] - 1) / 15って cell[n] / 15 - 1 じゃないか?
どういうふうに考えてこういうふうに勘違いしたんだろう
(たとえばまたくちがう処理を想像してたとか)
興味ある。
284 :
仕様書無しさん:01/11/28 04:02
誰でも知ってると思うけど
__LINE__
__FILE__
__DATE__
これにASSERTEぐらいはつかいましょう
また、
#if DEBUG
#define HOGE() hogehoge()
#else
#define HOGE()
#end
なんてこともやりますね
>>284 Fortran には、そういうのないの?ジサク?
> いくらでもありますよ。経験値足りない?
処理系の例は?
> i += 3;
> (しかも実在する!)
これも。
そんな環境では動かないことを知ってるだけでも参考になるので。
>>285 そいうのを知る前にFortranからCに移ったのでわかりません
288 :
仕様書無しさん:01/11/28 12:55
true との比較は、bool 型をサポートしてない場合
安全性に欠ける。
false は 0 でしか代用できないが、
true は 0 以外の何でも代用できるからだ。
とはいえ、一貫していれば普通は問題にならない。
(変な人間が社内にいる場合は問題になるが。)
問題は Windows プログラミングにおける TRUE だ。
MSDN は戻り値が BOOL の関数の戻り値は、
必ず「0 か 0 以外の値か」という形で書かれている。
TRUE を返すという保証はしてくれていないわけで、
TRUE と比較するのは安心できない。
さすがはマイク○ソフト。
もう1つは is 系の関数。
戻り値の型が int 型である通り、
実際 1 以外の値が返ってくるのがほとんどである。
これを bool 型の変数に代入する際は、
bool b = (isalpha(c) == 1); ではなく、
bool b = (isalpha(c) != 0); のようにする必要がある。
typedef int bool; な環境(VC++4.2 とか)で、
bool b = isalpha(c); なんてした日にゃ目も当てられんわけだ。
もっとも、bool 変数に int 値を代入するなという話もあるわけだけども、
そういう環境ではコンパイルが通っちゃうのでタチが悪い。
というわけで、true とはあんまり比較したくない、
というか、折角 boolean 値なんだから、比較は使いたくないなぁ。
と、そこまで言うと趣味の領域に入るのでやめ。
言いたかったことは、場合によっては気を遣う必要があるってこと。
TRUE なんか使わんよ。
コードでも、
#define FALSE (0)
if (FALSE != 被判定値)
{ /* TRUE のときのコード */
}
てなもんだ。
判定式で左に定数を書くのは、漏れの趣味。
>>283 スマソ、完全な勘違い
ちと、ぼけてたわ
291 :
仕様書無しさん:01/11/28 14:18
おまえらの糞コードの書き方知っても全然うれしくないですよ。
292 :
仕様書無しさん:01/11/28 14:28
目で見て true という文字が合った方が分かりやすいというなら、
template <typename TYPE>
inline bool istrue (TYPE b){ return (b ? true : false); }
template <typename TYPE>
inline bool isfalse(TYPE b){ return (b ? false : true); }
という関数テンプレートを使うというのはどうかな。
bool への代入には
template <typename TYPE>
inline bool tobool (TYPE b){ return (b ? true : false); }
を通すとか。
>>288 仕様書無しさん wrote:
> もう1つは is 系の関数。
> 戻り値の型が int 型である通り、
> 実際 1 以外の値が返ってくるのがほとんどである。
> これを bool 型の変数に代入する際は、
> bool b = (isalpha(c) == 1); ではなく、
> bool b = (isalpha(c) != 0); のようにする必要がある。
isの場合はさすがに if (isalpha(c))とかif (!isalpha(c))って
書きますね。名前的に。
> 言いたかったことは、場合によっては気を遣う必要があるってこと。
というか、MSの「0か0以外」を返す関数をtrue/falseとかと混同するといけない
だけでは?
それは単に bool にキャストすれば良いんでは?
>>289 仕様書無しさん wrote:
> if (FALSE != 被判定値)
> 判定式で左に定数を書くのは、漏れの趣味
一時期(15年ぐらい前?)三田某が、それをどこかで覚えてきて、
うれしそうにそれをかたってましたね:) (まるで自分で発明したかのように)
実際にはもっと前に一時期一部で流行って、そのまま廃れた書き方ですよね。
廃れるには廃れるだけの理由があったのに:)
別に流行でコード書いてるわけじゃないからいいんじゃない?
わざわざ通ぶらないでいいよ。>>Kusakabe
>>297 仕様書無しさん wrote:
> わざわざ通ぶらないでいいよ。>>Kusakabe
こうかいてあるとまるで通ぶっているようですね:)
通ぶってるんじゃなくて、通のつもりなの?
>>299 仕様書無しさん wrote:
> 通ぶってるんじゃなくて、通のつもりなの?
というか、そんなに卑屈にならなくてもいいのでは?
ごくふつうのやり方を自分が知らなかったからといって:)
>ごくふつうのやり方を自分が知らなかったからといって:)
知ってましたよ。
>ごくふつうのやり方を自分が知らなかったからといって:)
自分がそう思っているから自分以外もそうだと思うのは重症ですね。
日下部さんの偽者釣られてるヤツ、ドキュソ
>日下部さんの偽者釣られてるヤツ、ドキュソ
正しい日本語でどうぞ
「日下部さんの偽者に釣られてるヤツ、ドキュソ 」だ。
文句あっか!ゴルァ
意外とまともなスレだったのに。残念。
実のあるスレ狙ってやって来て台無しにしてる。
そういうことにしたい。
>>294 int とかから bool へのキャストは
警告の出る環境があるので。
VC++6.0 では警告レベル 3 。
実害はないけど鬱陶しい。
あと、typedef int bool; の環境では
true/false に変換されない。
309 :
仕様書無しさん:01/11/28 20:42
実測の話題が出てたので、ちょっとネタフリ。
VC+MFCだと以下の方法で実測してるんだけど、
ある処理の集合を実測するのに、他に良い方法ある?
DWORD dwTime = GetTickCount() ;
// なにかの処理
TRACE("//// Execute Time = %d ////\n\n", GetTickCount() - dwTime) ;
312 :
仕様書無しさん:01/11/28 21:25
313 :
仕様書無しさん:01/11/28 23:50
VBで実測するにはどんな方法がありますか?
(厨房な質問でスマソ)
>>313 上にも書いてあるが timeGetTime() 使えば良いだけだが。もしかして VB から Win32 API 呼び出す方法が
わからない?
315 :
仕様書無しさん:01/11/29 00:19
おれは、ふつうこう書く。
for(int i=0 ; i<strlen( s ) ; ++i ) {
//s[i]を使った処理
}
>>309: 仕様書無しさん wrote:
> 実測の話題が出てたので、ちょっとネタフリ。
じゃあ私は寝たふり。
ヘ_ヘ ____________________________
ミ・・ ミ
[email protected] ( ° )〜 日下部陽一
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>315 ネタは sage てな。それから void には反応しないようにね。
>315
sはstd::stringで、strlenも多重定義されていると見た。
>>288 0 か非 0 を bool に代入するなら
bool a = !!zero_or_nonzero();
普通は素直に
bool a = zero_or_nonzero() != 0;
だけどね。
ネタっぽいので sage
321 :
仕様書無しさん:01/12/25 08:12
あげま〜す
ヤシが降臨して沈んでしまった数々の良スレが次々に上がってくるなぁ。
しみじみ平和を実感する。
>>321 おつかれ!
323 :
仕様書無しさん:02/01/13 06:49
ポリゴンの辺の表示などループする物に。
int foo[] = { 0, 1, 2, 3, };
int n = sizeof(foo) / sizeof(foo[0]);
for(int i = 0, j = n-1; i < n; j = i++)
printf("%d - %d\n", foo[j], foo[i]);
sizeof(foo) / sizeof(foo[0]) はマクロにしておくと便利。
>>324VC6SP5のincludeディレクトリでgrepしてみた。
AVIRIFF.H(19): #define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0]))
EDK.H(294): #define ARRAY_CNT( array) (sizeof( array) / sizeof(array[0]))
KS.H(30): #define SIZEOF_ARRAY(ar) (sizeof(ar)/sizeof((ar)[0]))
MAPIDBG.H(48): #define dimensionof(a) (sizeof(a)/sizeof(*(a)))
SNMP.H(565): #define DEFINE_SIZEOF(Array) (sizeof(Array)/sizeof((Array)[0]))
あちこちでてんでに定義してやがる(;´д`)
>>323 早速球のポリゴンを作るルーチンで採用。
ちょっと嬉しかった。ありがとう。
327 :
仕様書無しさん:02/02/04 00:54
亞毛
328 :
仕様書無しさん:02/02/04 04:11
∧ ∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
(,,゚Д゚) < age.
./ | \_____________
(___/
/
コンマ演算子は優先順位がもっとも低くオペランドも左から右へ評価される性質を持つ。
式としての値は一番最後に評価されたものとなる。
if文の中でインクリメントとストリーム出力の両方をしたい場合
if(i < 1){
printf("%s Stream Out\n",argv[1]);
i++
}
とすれば良いが
if(i < 1)
printf("%s Stream Out\n",(i++,argv[1]));
ともできる。
でもわかりづらい。
その為オナニーソース専用としてなら有効である。
330 :
仕様書無しさん:02/02/05 20:23
良スレage
/*
やれと言われたからやるけど、ここの修正は責任持ちません。
出張は行けません。
*/
332 :
仕様書無しさん:02/02/05 21:15
オナニーソースといえば、
1[argv] っつーのはどーよ。
VC++とgccはコンパイルできたようだけど。
333 :
仕様書無しさん:02/02/05 21:17
334 :
仕様書無しさん:02/02/05 21:53
REM いくらコメント書いても多分忘れます。
REM ムリです。覚えてられません。
REM だいたい変数を至るところでいじられちゃあ……
REM あと平林はフラグ立てすぎです。
/*
$author HOGE
$comment 文句は仕様決めた奴に言え。俺のせいじゃない。
*/
336 :
仕様書無しさん:02/02/05 21:56
>>323 >for(int i = 0, j = n-1; i < n; j = i++)
スゲー感動。使わせて頂きます!!
337 :
仕様書無しさん:02/02/05 22:07
//なんでもいいです、もう。早く帰れれば……
>>332 a[i] <=> *(a + i)
x + y <=> y + x
ゆえに
a[i] <=> i[a]
だからそれはANSI準拠をうたうコンパイラではコンパイルできるべきかと。
#define TRACEVALUE(x) fprintf(stderr,"%s:%d",#x,x)
どの型でもいけるようになんないかな?
>339
%d のあたりが激しく型に依存しそうな気配。
あ、C++つかえば、ポリモルフィズムでなんとかなるのかな?
coutとか使って...
見つからなかった時の処理。
関数化したりとかもあるけど取り敢えず。
・まあ、普通
for(i = 0; i < n; i++)
{
if(arr[i] == x)
break;
}
if(i == n)
printf("見つからない\n");
・ifを減らす
for(i = 0; i < n; i++)
{
if(arr[i] == x)
goto found;
}
printf("見つからない\n");
found:
・でも結局番人がいいかと思ったり
arr[n] = x;
for(i = 0; arr[i] != x; i++)
;
if(i == n)
printf("見つからない\n");
>>342 値を伴う途中脱出と合流は関数に切り出すと見やすくなる。
bool find_x( T x, const T * arr, size_t n, size_t& found_pos )
{
for (size_t i = 0; i < n ; ++i )
{
if (arr[i] == x)
{
found_pos = i;
return true;
}
}
return false;
}
とした上で
size_t found_pos;
if ( find_x(x, arr, n, found_pos) )
{
printf( "見つかった → %d\n", found_pos );
} else {
printf( "見つからない\n" );
}
344 :
仕様書無しさん:02/04/06 05:36
ほげ
345 :
仕様書無しさん:02/04/06 06:01
下に行くに従い、意図が分かり難いコードになってると感じる漏れは厨房。
>324
それはDQNが使うとハマる罠。
下流の関数に配列の先頭ポインタを渡して、その引数に対してこれを使うとあぼーん。
実際居るから困るんだけど。
>>345 そりゃ関数の切り分けかたがマズイのでは?
下に行くほど単機能になるので、わかりやすくなると思うが。