Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

カンマ「,」演算子。評価順 序は変更不能?

329 views
Skip to first unread message

Tadakazu Nagai

unread,
Jan 1, 2001, 4:47:56 AM1/1/01
to
カンマ演算子で、ふと疑問になったので、以下のようなプログラムを
ためしてみました。

--- ここから ---
#include <iostream.h>
#include <string>

int main()
{
std::string nnn;

(nnn += "111",( nnn += "222" ,( nnn += "333")));

cout << nnn;

return 0;
}
--- ここまで ---

コンパイラはg++とbcc32を使いましたが、どちらも結果は、

 "111222333"

となります。"333222111"となるかと思ったのですが、違いました。

カンマ演算子の評価順序は処理系依存(定義)と理解していますが、
カッコ「()」を使って評価順序を変更することも出来ないのでしょ
うか?

では、失礼します。

P.S.
上記のようなカンマ演算子の使い方は、TCP/IPの教科書のサンプル
などで見かけますが、これは「文1, 文2, 文3; 」の順序が重要
でないことを強調したいときにやるんですかねぇ?

--
フリープログラマー
永井 忠一
http://www.kt.rim.or.jp/~nagai/


Kusakabe Youichi

unread,
Jan 1, 2001, 5:04:51 AM1/1/01
to
In article <92pjjt$gef$1...@netnews.rim.or.jp>, "Tadakazu Nagai"

<na...@kt.rim.or.jp> wrote:
>  "111222333"
>
> となります。"333222111"となるかと思ったのですが、違いました。

括弧って、「結合の優先順序」を変化させるだけで、
「評価順序」は制御できないのでは?

> カンマ演算子の評価順序は処理系依存(定義)と理解していますが、
> カッコ「()」を使って評価順序を変更することも出来ないのでしょうか?

ヘ_ヘ ____________________________
ミ・・ ミ vo...@merope.pleiades.or.jp
( ° )~ 日下部陽一
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Shin-ichi TSURUTA

unread,
Jan 1, 2001, 5:22:45 AM1/1/01
to
Tadakazu Nagaiさん、こんにちは、鶴田(SYN)です。

"Tadakazu Nagai" <na...@kt.rim.or.jp> wrote:
> カンマ演算子で、ふと疑問になったので、以下のようなプログラムを
> ためしてみました。
>
> --- ここから ---
> #include <iostream.h>
> #include <string>
>
> int main()
> {
> std::string nnn;
>
> (nnn += "111",( nnn += "222" ,( nnn += "333")));
>
> cout << nnn;
>
> return 0;
> }
> --- ここまで ---
>
> コンパイラはg++とbcc32を使いましたが、どちらも結果は、
>
>  "111222333"
>
> となります。"333222111"となるかと思ったのですが、違いました。

そりゃそうです。

((nnn += "111"),((nnn += "222"),(nnn += "333")));

と同じだということは、理解できているでしょうか?

> カンマ演算子の評価順序は処理系依存(定義)と理解していますが、
> カッコ「()」を使って評価順序を変更することも出来ないのでしょ
> うか?

a * b + (c * d)

って書けばわかるでしょうか。
____________________________________________________________
Name : Shin-ichi TSURUTA 鶴田 真一 (as SYN)
E-mail : syn...@pop21.odn.ne.jp
URL : http://www1.odn.ne.jp/synsyr/

FUJIIHARA Keiichi

unread,
Jan 1, 2001, 5:40:47 AM1/1/01
to
藤原と申します。

This message is reply to Tadakazu Nagai - san
(Subject was : カンマ「,」演算子。評価順序は変更不能?)

Message-ID: <92pjjt$gef$1...@netnews.rim.or.jp>
in Mon, 1 Jan 2001 18:47:56 +0900 ...


> カンマ演算子の評価順序は処理系依存(定義)と理解していますが、
> カッコ「()」を使って評価順序を変更することも出来ないのでしょ
> うか?
>

 そもそもカンマ演算子の評価順序は、「左から右」で規定」(処理系依存では
なく)されていたと思いますが。
 && や || と並んで評価順序が決まっている演算子です。
 これは、主に式がひとつしか許されてないところに、実質的に複数の式を置く
ために使用されたりします。

for (i = 0, j = 0; a[i] != 0; i++, j += 2) など
また、

for (i = 0, j = hoge(i) ;; i = hoge2(i), j = hoge3(i));
なども、評価順序が確定しているのでできなくはないのですが。

---
_/ -- Last 13080 hours until 2002 World Cup final ---------------------
_/ FUJIHARA Keiichi
_/ E-Mail : na...@sep.email.ne.jp <or> na...@qua.net
_/ URL : http://www.asahi-net.or.jp/~ig5k-fjhr/
--------------------------------------------+----- Luna Phase 6.00 ---
PGP FingerPrint = 7CC3 4F95 8CC7 87D3 7178 C348 CD65 7F08 D68F 69F6


Tadakazu Nagai

unread,
Jan 1, 2001, 12:26:15 PM1/1/01
to
藤原さん、こんにちは。

>  そもそもカンマ演算子の評価順序は、「左から右」で規定」(処理系依存では
> なく)されていたと思いますが。
>  && や || と並んで評価順序が決まっている演算子です。
>  これは、主に式がひとつしか許されてないところに、実質的に複数の式を置く
> ために使用されたりします。

完全に勘違いしてました。ご指摘の通りです。以前読んだ、

 More Effective C++
 項目7:&&、||、,をオーバーロードしない

を記憶違いしていました。

関数呼び出し時の、実引数の評価順が不確定、というのと混同し
ていました。

ご指摘ありがとうございました。m(_o_)m

P.S.
以前、行列の内積を「,」で書けないかと考えて、上記理由で止め
た記憶があります。

Tadakazu Nagai

unread,
Jan 1, 2001, 12:26:18 PM1/1/01
to
日下部さん、こんにちは。

> > となります。"333222111"となるかと思ったのですが、違いました。
>
> 括弧って、「結合の優先順序」を変化させるだけで、
> 「評価順序」は制御できないのでは?
>
> > カンマ演算子の評価順序は処理系依存(定義)と理解していますが、
> > カッコ「()」を使って評価順序を変更することも出来ないのでしょうか?

ご指摘の通り、「評価」と、「結合」は別概念でした。混同しました。

 エキスパートCプログラミング
 「結合規則とは何か」

など、読み返してみました。

ちなみに、カンマ「,」は何項演算子なんでしょうね?

では、ありがとうございました。

FUJIIHARA Keiichi

unread,
Jan 1, 2001, 7:46:45 PM1/1/01
to
藤原です

This message is reply to Tadakazu Nagai - san

(Subject was : 「評価」と「結合」を混同)

Message-ID: <92qefr$scn$1...@netnews.rim.or.jp>
in Tue, 2 Jan 2001 02:26:18 +0900 ...

>
> ちなみに、カンマ「,」は何項演算子なんでしょうね?
>

 カンマ演算子そのものは2項演算子です。
 i = 1, j = 1, k = 1;
 という書き方だと、あまり、2項という気はしませんが、これは、2項演算子
の + が、
a = b + c + d;
 という形で使われるのと同じです。

 さて、+ や , は、「左から右」の結合方向の2項演算子です。
 このため、

a + b + c
 は、
(a + b ) + c
と解釈されます(それぞれの + は、確かに2項ですね)

 a, b, c;
 は、同じく、
(a, b), c
 と解釈されます。
 , は、評価順序が規定されていますから、最初に、(a, b) を評価して、b
が式の値となります。この後、c を評価するので、あたかも、a b c を順番
に評価しているように見えます。

 これとは逆に、= は、「右から左」の結合規則を持ちます。

a = b = 2;
 と書けば、「a と b を 2 にしている」ように見えますが、これは、
( = も2項演算子なので)
a = (b = 2)
 と解釈されます。

 まず、b = 2 が実行されて、その結果、式の値は 2 になります。
 その(式の値の) 2 を、さらに a に代入します。
 結果としては、a b とも 2 になります。

とまあ、こういう仕掛けです。

---
_/ -- Last 13066 hours until 2002 World Cup final ---------------------

--------------------------------------------+----- Luna Phase 6.55 ---

Isao Nakagawa

unread,
Jan 2, 2001, 12:09:28 AM1/2/01
to
in article <92pjjt$gef$1...@netnews.rim.or.jp>, Tadakazu Nagai wrote
>カンマ演算子の評価順序は処理系依存(定義)と理解していますが、

カンマ演算子の評価順序は前から、と規格で決められています。
関数の引数の区切りのカンマと間違えていませんか?

>カッコ「()」を使って評価順序を変更することも出来ないのでしょ

だから、A, (B , C) の評価は、A → (B, C) の順です。
(B, C) の評価は B → C の順です。

結局、括弧でくくってもこの式の評価は A → B → C の順で行われます。

>上記のようなカンマ演算子の使い方は、TCP/IPの教科書のサンプル
>などで見かけますが、これは「文1, 文2, 文3; 」の順序が重要
>でないことを強調したいときにやるんですかねぇ?

その教科書がなんだかわからないのでなんとも答えられないですけど、
カンマ演算子なんてそんなに使うことがあるのでしょうか?

--
Isao Nakagawa mailto:isa...@big.or.jp

Tadakazu Nagai

unread,
Jan 2, 2001, 3:32:25 AM1/2/01
to
こんにちは。

> 関数の引数の区切りのカンマと間違えていませんか?

ご指摘の通りでした。m(_o_)m

> >TCP/IPの教科書のサンプル
> >などで見かけますが、これは「文1, 文2, 文3; 」の順序が重要
> >でないことを強調したいときにやるんですかねぇ?
>
> その教科書がなんだかわからないのでなんとも答えられないですけど、

すみません。失念しました。

 UNIXネットワーク
 プログラミング
 第2版 Vol.1

にそのような例があったと思うのですが、見なおしているのですが、
見つけられません。

> カンマ演算子なんてそんなに使うことがあるのでしょうか?

私にも、実用的な使い方は思いつきませんが、無理に考えると、

int ret;
ret = Nnn(), Nnn(), Nnn();

のように、最後の一回の成否だけに関心がある場合とかはどうで
しょうか。

では、失礼します。

Dairyo Gokan

unread,
Jan 2, 2001, 5:01:26 AM1/2/01
to
Tadakazu Nagai wrote:
-----------------------------------------------------------------------

> 私にも、実用的な使い方は思いつきませんが、無理に考えると、
>
> int ret;
> ret = Nnn(), Nnn(), Nnn();
>
> のように、最後の一回の成否だけに関心がある場合とかはどうで
> しょうか。
-----------------------------------------------------------------------

可読性も考慮すれば、普通 ...

Nnn(), Nnn(), ret = Nnn();
または
Nnn(); Nnn(); ret = Nnn();

でしょう。 少なくとも上記コードには、「あえてカンマ演算子を使わ
なければならない理由」が見つかりませんよね。

 「言語仕様こそが正義」だと思って、通常使われないコード表記を
使うと、コンパイラの思わぬバグに遭遇する可能性が高いと思います。

 以前「Microsoft Quick C Ver 2.0(DOS版)」で多重forループ内
の ...

for(j=m,k=n;j<jMax;j++)
~~~~~~~
のようなコードすら正常に展開できず、ハマったことがあります。

+---------------------------------------------------------------------+
| From : Dairyo Gokan ( 後神 大陵 ) |
| Org. : Hitmark Computer Corporation ( ヒットマークコンピュータ ) |
| Adrs : 13256 Northup Way Suite 3, Bellevue WA 98005 |
| TEL:425-649-8808 FAX:425-649-9001 mailto:na...@can.bekkoame.ne.jp |
+---------------------------------------------------------------------+

Shinji KONO

unread,
Jan 2, 2001, 5:44:51 AM1/2/01
to
河野 真治@琉球大情報工学です。

In article <3A51A6F6...@can.bekkoame.ne.jp> ,
Dairyo Gokan <na...@can.bekkoame.ne.jp> writes

> 「言語仕様こそが正義」だと思って、通常使われないコード表記を
>使うと、コンパイラの思わぬバグに遭遇する可能性が高いと思います。

確かに...

> for(j=m,k=n;j<jMax;j++)
>のようなコードすら正常に展開できず、ハマったことがあります。

ほとんど、そこにしか使わない構文なのに...

僕は、

if (i>0) j=a,j=b;

みたいなコードを見たことがあります。

comma は、もう obsolete と言う感じがするので、僕も使わないように
してます。

どっちかっていえば、Perl 風の
open(..) or die(...)
とか
i++ if (i>0);
みたいのが欲しい気がする。あと、
last LABEL;
next LABEL;
かな...

---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)

Yuki Shiino

unread,
Jan 2, 2001, 6:52:50 AM1/2/01
to
 椎野です。与太話です。

永井さんの記事<92pjjt$gef$1...@netnews.rim.or.jp>から


> P.S.
> 上記のようなカンマ演算子の使い方は、TCP/IPの教科書のサンプル
> などで見かけますが、これは「文1, 文2, 文3; 」の順序が重要
> でないことを強調したいときにやるんですかねぇ?

 カンマ演算子の評価順序が規定されているのは既に藤原さんの
指摘する通りですが、式と文の区別が出来ていない様に見えます。
正確には「式1, 式2, 式3; 」ですよね。
 式と文は別物です。
 式と文を混同する人が少なからず居るので気になりました。

--
椎野 裕樹 <yu...@cds.ne.jp>

Shin-ichi TSURUTA

unread,
Jan 2, 2001, 11:55:42 PM1/2/01
to
Dairyo Gokanさん、こんにちは、鶴田(SYN)です。

Dairyo Gokan <na...@can.bekkoame.ne.jp> wrote:
> Tadakazu Nagai wrote:
> -----------------------------------------------------------------------
> > 私にも、実用的な使い方は思いつきませんが、無理に考えると、
> >
> > int ret;
> > ret = Nnn(), Nnn(), Nnn();
> >
> > のように、最後の一回の成否だけに関心がある場合とかはどうで
> > しょうか。
> -----------------------------------------------------------------------
>
> 可読性も考慮すれば、普通 ...
>
> Nnn(), Nnn(), ret = Nnn();
> または
> Nnn(); Nnn(); ret = Nnn();
>
> でしょう。 少なくとも上記コードには、「あえてカンマ演算子を使わ
> なければならない理由」が見つかりませんよね。

恐らく質問の意図はこんなコードのことではないでしょうか。

while ((low ^ low+range)<TOP || range<BOT && ((range= -low & BOT-1),1))
OutByte(low>>24), range<<=8, low<<=8;

Tadakazu Nagai

unread,
Jan 3, 2001, 3:35:51 AM1/3/01
to
まだ結合規則と評価順序を理解しきれていないので、同じ内容を
続けます。

今度の例は「+」 演算子ですが、これの結合規則は右から左(←)
ですが、評価の順序はどうなるのでしょうか?

#今まで、「+」 演算子の結合規則は左から右(→)と勘違いし
#ていました。あらためて勉強になりました。

vvvv 例1 vvvv
int main()
{
string nnn;

(nnn += "111") + (nnn += "222") + (nnn += "333");

cout << nnn;
//Edit1->Text = nnn.c_str();
}

### g++(gcc version 2.7.2.3)の実行結果 ####
222111333

### Borland C++ 5.5 for Win32 の実行結果 ####
333222111
^^^^ 例1 ^^^^

ためしたところ、処理系によって異なります。

カンマ演算子についての評価順序は先に教えていただきましたが、他の
演算子についての評価順序というのは何を見れば書かれているのでしょ
うか?手持ちの教科書では、優先順位と結合規則については書かれてい
るものが多いですが、評価順序については書かれていないようです。

上記の動作を見ると、「+」 演算子の式の評価順序は処理系依存に思え
ますが、本当はどうなのでしょうか?

また、g++ ですが、以下のように

vvvv 例2 vvvv
int main()
{
string nnn;

(nnn += "111") + ((nnn += "222") + ((nnn += "333")));

cout << nnn;
//Edit1->Text = nnn.c_str();
}

### g++(gcc version 2.7.2.3)の実行結果 ####
333222111
^^^^ 例2 ^^^^

と、カッコにより、式の評価順序が変わります。逆に、BCC32の方は、
評価順序はカッコに影響されないようです。

いまだに基本的な部分を混乱していますが、

 ・結合順序と式の評価順序は別である
 ・カッコは評価順序に影響を与えない

などに、確信が持てません。

では、お時間のあるときにでも、コメント頂ければと思います。m(_o_)m

Tadakazu Nagai

unread,
Jan 3, 2001, 3:42:26 AM1/3/01
to
永井です。

途中で気づいたのですが、訂正をサボりました。

ご指摘の通りですね。

"Yuki Shiino" <yu...@cds.ne.jp> wrote in message
news:92sff2$i8b$1...@news.cds.ne.jp...

Tadakazu Nagai

unread,
Jan 3, 2001, 3:47:09 AM1/3/01
to
永井です。訂正です。

> 私にも、実用的な使い方は思いつきませんが、無理に考えると、
>
> int ret;
> ret = Nnn(), Nnn(), Nnn();
>
> のように、最後の一回の成否だけに関心がある場合とかはどうで
> しょうか。

これでは、カンマ演算子より代入演算子の方が優先順位が高いので、
最初の一回だけの成否を着目していますね。正しくは、

ret = ( Nnn(), Nnn(), Nnn() );

でないと、説明の通りではありませんでした。失礼しました。

では、失礼します。


Tadakazu Nagai

unread,
Jan 3, 2001, 4:03:12 AM1/3/01
to
こんにちは。永井です。

> 可読性も考慮すれば、普通 ...
>
> Nnn(), Nnn(), ret = Nnn();
> または
> Nnn(); Nnn(); ret = Nnn();
>
> でしょう。 少なくとも上記コードには、「あえてカンマ演算子を使わ
> なければならない理由」が見つかりませんよね。

ですよね。

個人的には他の言語文化の影響ではないかと疑っていますが...

私は書けませんが、Lispとか?

#たとえば、Pascal屋さんは、C 言語でも前方参照をあまり使わずに書く
#というようなイメージを個人的には持っていたりします。

>  「言語仕様こそが正義」だと思って、通常使われないコード表記を
> 使うと、コンパイラの思わぬバグに遭遇する可能性が高いと思います。

このご意見は全く同意します。私も、進んで“言語の暗がり”に踏み込
もうとは思いません。f^^;

ただ、どこに暗がりがあるのかを勉強しておくことは大切だと思うので
すが、このスレッドはそんな程度の意味しかないのですが、申し訳ない
デス。m(_o_)m

>  以前「Microsoft Quick C Ver 2.0(DOS版)」で多重forループ内
> の ...
>
> for(j=m,k=n;j<jMax;j++)
> ~~~~~~~
> のようなコードすら正常に展開できず、ハマったことがあります。

f^^;;;

しかし、何らかのプログラミング言語の処理系を作るというのは大変な
んだろうなぁ、と思うこの頃です。

最近知人から「yaccによるc コンパイラプログラミング 近藤 嘉雪」を
借りて読んでいるのですが、難しい...

では、コメントありがとうございました。m(_o_)m

Tadakazu Nagai

unread,
Jan 3, 2001, 4:07:17 AM1/3/01
to
河野さん、こんにちは。永井です。

> どっちかっていえば、Perl 風の
> open(..) or die(...)
> とか

論理演算子が制御構造に使えるというのは斬新でした。

これは、ねらって設計したのでしょうかね?

私は苦手ですが、英語チックというのが良いですね。

では、

FUJIIHARA Keiichi

unread,
Jan 3, 2001, 5:10:11 AM1/3/01
to
藤原です。

This message is reply to Tadakazu Nagai - san

(Subject was : カッコは評価の順序を制御するか?)

Message-ID: <92uo4l$ag7$1...@netnews.rim.or.jp>
in Wed, 3 Jan 2001 17:35:51 +0900 ...


>  ・結合順序と式の評価順序は別である
>  ・カッコは評価順序に影響を与えない

 C言語において評価順序が規定されている演算子は、
&& || ,
 の3つだけです。(あと3項演算子の ? : も)
 評価順序は、処理系によっても、最適化の状態によっても変わってきます。
このため、評価順序に依存した式は、書いてはいけないことになっています。

 例えば、

(a + b) + (c + d)

 のような式は、

 1)a と b の足し算の結果に
 2)c と d の足し算の結果を足す
 という意味ですが、この場合例えば、

 1) d を計算する
 2) a を計算する
 3) c を計算する
 4) 1)と3)を足して、その結果をどこかにおいておく
 5) b を計算する
 6) 2)と5)を足して、その結果をどこかにおいておく
 7) 4)と6)を足して、式の結果が決定する
 という順序で(評価順序は d → a → c → b)計算される
かもしれません。この場合でも、先に挙げた式の意味は正しく反映されている
ことになります。

 あと、2項演算子 + の結合は、「左から右」です。
 単項の + は、「右から左」ですけど。
 単項の + って、ほとんど使われない気がしますが、単項の - と同じカテゴリ
です。

i = -j; とかの。

---
_/ -- Last 13033 hours until 2002 World Cup final ---------------------

--------------------------------------------+----- Luna Phase 7.85 ---

Tadakazu Nagai

unread,
Jan 3, 2001, 9:29:20 AM1/3/01
to
こんにちは。永井です。

ご丁寧なご回答をありがとうございます。大変良く理解できました。

> >  ・結合順序と式の評価順序は別である
> >  ・カッコは評価順序に影響を与えない
>
>  C言語において評価順序が規定されている演算子は、
> && || ,
>  の3つだけです。(あと3項演算子の ? : も)
>  評価順序は、処理系によっても、最適化の状態によっても変わってきます。
> このため、評価順序に依存した式は、書いてはいけないことになっています。
>
>  例えば、
>
> (a + b) + (c + d)
>
>  のような式は、
>
>  1)a と b の足し算の結果に
>  2)c と d の足し算の結果を足す
>  という意味ですが、この場合例えば、
>
>  1) d を計算する
>  2) a を計算する
>  3) c を計算する
>  4) 1)と3)を足して、その結果をどこかにおいておく
>  5) b を計算する
>  6) 2)と5)を足して、その結果をどこかにおいておく
>  7) 4)と6)を足して、式の結果が決定する
>  という順序で(評価順序は d → a → c → b)計算される
> かもしれません。この場合でも、先に挙げた式の意味は正しく反映されている
> ことになります。

手持ちの「プログラミング言語C 第2版」を読みなおしましたが、

 「優先度と評価順序」

という節にも、ちゃんと説明されていました。

#これまで、私は深く追求したことがなかったようです。

勉強不足で大変お恥ずかしい。

#調べてから書けば良かったのですが、どうも、先入観に
#まどわされました。m(_o_)m

>  あと、2項演算子 + の結合は、「左から右」です。
>  単項の + は、「右から左」ですけど。
>  単項の + って、ほとんど使われない気がしますが、単項の - と同じカテゴリ
> です。
>
> i = -j; とかの。

ご指摘の通り、勘違いです。

重ねて、ご教授、ありがとうありがとうございました。m(_o_)m

では、失礼します。

Masamichi Motoyoshi

unread,
Jan 3, 2001, 12:05:05 PM1/3/01
to
本吉です。

Isao Nakagawaさんの<92rnq6$12h1$1...@news01.sakura.ne.jp>から
>
>カンマ演算子なんてそんなに使うことがあるのでしょうか?

一般的かどうかはわかりませんが、
私の場合、while や for の条件式中で
代入と複数の条件での比較を行う際、
または、副作用のあるマクロ(特に isXXXX系のマクロ)を
利用する際に
好んでカンマ演算子を使っています。

char* skip_blanks(char* p)
{
char ch;
while ((ch = *p++), isspace(ch)) ;
return p-1;
}

ま、上の例の場合はカンマ演算子使わずに、

for (ch = *p++; isspace(ch); ch = *p++)

とか、

{
for (; isspace(*p); p++) ;
return p;
}

とかの方が一般的かもしれませんが。

Takao Ono

unread,
Jan 3, 2001, 11:10:26 PM1/3/01
to
小野@名古屋大学 です.

二項演算子の + の評価順序が未定義なのはさておき....

<92uo4l$ag7$1...@netnews.rim.or.jp>の記事において
na...@kt.rim.or.jpさんは書きました。
nagai> (nnn += "111") + (nnn += "222") + (nnn += "333");
これは += がオブジェクトの値の変更を伴うため未定義動作のはず. 2つの
シーケンスポイントの間ではオブジェクトは 1回しか値を変更してはいけ
ません.
# おおざっぱには, シーケンスポイントというのは「それまでの副作用を
# すべて精算するところ」と考えていいと思います.

で, 「a && b」, 「a || b」, 「a, b」, 「a ? b : c」のいずれにおいて
も式 a を評価したあとにシーケンスポイントがあるので式 b (や c) では
式 a における副作用をすべて解決したあとの値が使われるわけです.
--
名古屋大学 工学部 電子工学科 平田研究室
小野 孝男

Takao Ono

unread,
Jan 4, 2001, 9:28:14 PM1/4/01
to
小野@名古屋大学 です.

とっても勘違いしてました m(_._)m

以下 C++ の話 (C には const char * を右辺に受け取る += 演算子が存在
しないため) ですが....

<930t3i$jt8$1...@henry.hirata.nuee.nagoya-u.ac.jp>の記事において
私は書きました。
takao> <92uo4l$ag7$1...@netnews.rim.or.jp>の記事において
takao> na...@kt.rim.or.jpさんは書きました。
takao> nagai> (nnn += "111") + (nnn += "222") + (nnn += "333");
takao> これは += がオブジェクトの値の変更を伴うため未定義動作のはず. 2つの
takao> シーケンスポイントの間ではオブジェクトは 1回しか値を変更してはいけ
takao> ません.
num は string でしたね m(_._)m

組込み型なら上の説明の通りですが, string は組込み型ではないのでこの
説明はあてはまりません. この場合 num += "なにか" は (多分)
string::operator +=(const char *)
を呼出すことになるんですが, この場合この関数の呼出しの前後にシーケ
ンスポイントがあります. したがって, 「連続するシーケンスポイントの
間ではオブジェクトをたかだか 1回しか変更してはいけない」という制限
は関係ありません.

が, いずれにしても 3つの += のどれを最初に解決するか決っていないの
で, 考えられる 6通りの結果のうちどれになってもよいということになり
ます.

Tadakazu Nagai

unread,
Jan 5, 2001, 10:14:11 AM1/5/01
to
永井です。ご丁寧なご説明をありがとうございました。

これも知らない話でした。勉強になりました。

また、「fj.comp.lang.c++」かとも迷ったのですが、ま
ぎらわしかったようでご迷惑をかけました。

#しかし、C についてなら、だいぶ正しい知識を自分は
#持っているかと思っていましたが、まだまだ知らない
#ことがあるものですね。私はわかっていなかったのに、
#正しくコンパイルしてくれていたコンパイラに感謝で
#すね。

では、ありがとうございました。m(_o_)m

--
フリープログラマー
永井 忠一
http://www.kt.rim.or.jp/~nagai/


"Takao Ono" <ta...@hirata.nuee.nagoya-u.ac.jp> wrote in message
news:933bfu$oje$1...@henry.hirata.nuee.nagoya-u.ac.jp...

Norikatsu Shigemura

unread,
Jan 6, 2001, 2:29:35 PM1/6/01
to
重村法克です。

<12011.9...@rananim.ie.u-ryukyu.ac.jp>の記事において
河野 真治さんは書きました。

>どっちかっていえば、Perl 風の
> open(..) or die(...)
>とか

冗談で open(..) || error_exit(filename); みたいなのを書いたこと
あります。気持ち悪くてそれ以後使っていませんが(^^;。

> i++ if (i>0);
>みたいのが欲しい気がする。あと、
> last LABEL;
> next LABEL;
>かな...

確かに。あと unless 。if(!(...)) の時の括弧が深すぎて…。


<92upvg$k8u$1...@netnews.rim.or.jp>の記事において
na...@kt.rim.or.jpさんは書きました。

>> どっちかっていえば、Perl 風の
>> open(..) or die(...)
>> とか

>論理演算子が制御構造に使えるというのは斬新でした。
>これは、ねらって設計したのでしょうかね?
>私は苦手ですが、英語チックというのが良いですね。

まさに『開け, さもなくば死ね』:-)では? (^^;

# それよりも die を導入したセンスの方が…(^^;

Tadakazu Nagai

unread,
Jan 8, 2001, 12:14:23 AM1/8/01
to
永井です。

> 冗談で open(..) || error_exit(filename); みたいなのを書いたこと
> あります。気持ち悪くてそれ以後使っていませんが(^^;。

CもC++も、ブール式の短絡評価(short circuit evaluation) を採用
しているそうなので、書けそうですね。

> >> どっちかっていえば、Perl 風の
> >> open(..) or die(...)
> >> とか
>
> >論理演算子が制御構造に使えるというのは斬新でした。
> >これは、ねらって設計したのでしょうかね?
> >私は苦手ですが、英語チックというのが良いですね。
>
> まさに『開け, さもなくば死ね』:-)では? (^^;

私が読んだPerlの教科書では、

 Don't move, or die!
 「動くと撃つぞ!」

の例で説明していました。

#Perlは自然言語なんですね;-)

では、失礼します。

Shiroh Sado

unread,
Jan 8, 2001, 8:12:41 AM1/8/01
to

佐渡です。

永井さん、こんにちは。

スレッド「制御構造としてのOR演算子」での
na...@kt.rim.or.jp氏の発言 <93bi7j$dr5$1...@netnews.rim.or.jp> より引用


>> 永井です。
>>
>> > 冗談で open(..) || error_exit(filename); みたいなのを書いたこと
>> > あります。気持ち悪くてそれ以後使っていませんが(^^;。
>>
>> CもC++も、ブール式の短絡評価(short circuit evaluation) を採用
>> しているそうなので、書けそうですね。

この話題を読んだ後、使い捨て系のプログラムを書く必要が
あったので、つい影響を受けて、次のようなのを書きました
(記事末尾)。
枯れ木も山のにぎわいでも無いですが、汚いプログラムも話
のツマミぐらいにはなるかもしれませんので、どうぞ。

>> #Perlは自然言語なんですね;-)

どうもCだと自然言語のように読めるようには書くのは面倒そ
うです。結局、普通に書いてある方が読みやすい、って思っ
てしまいました。

また、使うたびに警告「value computed is not used」が出
ます。

# どうも、林晴比古さんの著書「Cプリプロセッサパワー」の
# 再来という印象しか無いです。ずいぶん昔の本ですが。
## 字が間違っていたら申し訳ありません。

/*
hoge.c :

argv[2]からshortの列を読み込み、各々を
atof(argv[1])倍してargv[3]に書き出す。
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

/*
エラー終了用
*/
int dead( int val, char *message, ... ) {
va_list ap;

va_start( ap, message );
vfprintf( stderr, message, ap );
va_end( ap );
exit( val );

return 0;
}

/* file sizeを調べる関数(返り値はbyte単位) */
long filesize( FILE *fp ) {
long x;

/* ファイルサイズ取得 */
fseek( fp, 0L, SEEK_END );
x = ftell( fp );
rewind( fp );

return x;
}

#define or || /* PERLの真似 */

int main( int argc, char *argv[] ) {
int i; /* ループ変数 */
int n; /* 要素数 */
double rate; /* 倍率 */
int x;
short *a; /* バッファ */
char *filename; /* ファイル名 */
char *filename_out; /* ファイル名(出力) */
FILE *fp;

/* 引数の数を検査 */
argc==4 or dead( 0, "%s :\n%s 倍率 入力ファイル名 出力ファイル名\n",
argv[0], argv[0] );

/* 倍率を読み込み */
sscanf( argv[1], "%lf", &rate)==1
or dead( 1, "倍率「%s」が数値に変換できない\n", argv[1] );

/* ファイル名を設定 */
filename = argv[2];
filename_out = argv[3];

/* 入力ファイルをopen */
( fp = fopen( filename, "rb" ) )!=NULL
or dead( 1, "ファイル%sがオープン(rb)できない。\n", filename );

/* mallocによるメモリ確保 */
( a = malloc( (n=filesize(fp)/2)*2 ) )!=NULL
or dead( 1, "%d byteのmallocに失敗\n", n );

/* 読み込み */
(x=fread( a, sizeof(short), n, fp )) == n
or dead( 1, "読み込みが不完全( %d/%d )\n", x, n );

/* ファイルを閉じる */
fclose(fp)==0
or dead( 1, "入力ファイルのfcloseに失敗\n" );

/* 変換 */
for( i=0 ; i<n ; i++ ) {
a[i] *= rate;
}

/* 書き出し用オープン */
( fp = fopen( filename_out, "wb" ) )!=NULL
or dead( 1, "ファイル%sがオープン(wb)できない。\n", filename );

/* 書き出し */
(x=fwrite( a, sizeof(short), n, fp )) == n
or dead( 1, "書き出しが不完全( %d/%d )\n", x, n );

/* ファイルを閉じる */
fclose(fp)==0
or dead( 1, "出力ファイルのfcloseに失敗\n" );

/* バッファを開放 */
free( a );

return 0;
}

s/die/dead/ は、たんにユーモアと思ってください。

---
佐渡詩郎 (さど しろう) / e-mail : sa...@smlab.tutkie.tut.ac.jp

Shiozaki Takuya

unread,
Jan 9, 2001, 12:14:45 AM1/9/01
to

塩崎です。


<93cec9$1h9$1...@news.tut.ac.jp>の記事において
sa...@smlab.tutkie.tut.ac.jpさんは書きました。

>> どうもCだと自然言語のように読めるようには書くのは面倒そ
>> うです。結局、普通に書いてある方が読みやすい、って思っ
>> てしまいました。

そもそも、UNIX の syscall は perl とエラーの真偽が反転してるので、
普通に書くと

open(...) and die

「開いて、そして死ね」になっちゃいますな :-)


では。
--
Takuya SHIOZAKI / ASTEC Products, Inc.

Shiroh Sado

unread,
Jan 9, 2001, 2:09:27 AM1/9/01
to

佐渡です。

塩崎さんこんにちは。

スレッド「Re: 制御構造としての OR演算子」での
tshi...@astec.co.jp氏の発言 <93e6o5$9qk$1...@tokyonet-entrance.astec.co.jp> より引用


>> そもそも、UNIX の syscall は perl とエラーの真偽が反転してるので、
>> 普通に書くと
>>
>> open(...) and die
>>
>> 「開いて、そして死ね」になっちゃいますな :-)

:-)

ところで、openの返り値を変数に保存しておかなくて良いのか、
という疑問が。;-1

Shinji KONO

unread,
Jan 9, 2001, 2:22:36 AM1/9/01
to
河野 真治@琉球大情報工学です。

In article <93edf7$dq2$1...@news.tut.ac.jp> ,
sa...@smlab.tutkie.tut.ac.jp (Shiroh Sado) writes
>>> open(...) and die
>ところで、openの返り値を変数に保存しておかなくて良いのか、
>という疑問が。;-1

errno に入っているので大丈夫です。Perl だったら $! ですね。

Yoshio Kiya

unread,
Jan 9, 2001, 4:15:14 AM1/9/01
to
 後神さん、こんにちは、木屋です。

 今更ですが…m(_ _)m

Dairyo Gokan wrote in <3A51A6F6...@can.bekkoame.ne.jp>


> for(j=m,k=n;j<jMax;j++)
> ‾‾‾‾‾‾‾
> のようなコードすら正常に展開できず、ハマったことがあります。

 これたしか、最適化オプションをONにしたときに起こる現象だ
ったと思います。

 当時私もはまってMSに問い合わせたところ、ループ中に使用さ
れる変数が3つ以上になるとおかしくなると返事をいただきました。

=== Nihon Application Co.,LTD. 木屋 善夫 ki...@nac.co.jp ===

Tadakazu Nagai

unread,
Jan 9, 2001, 4:54:17 AM1/9/01
to
永井です。

> >>> open(...) and die
>
> >ところで、openの返り値を変数に保存しておかなくて良いのか、
> >という疑問が。;-1
>
> errno に入っているので大丈夫です。Perl だったら $! ですね。

ファイルディスクリプタのことじゃないのかな?

KATAYAMA Yoshio

unread,
Jan 9, 2001, 6:13:10 AM1/9/01
to
In article <93edf7$dq2$1...@news.tut.ac.jp>,
sa...@smlab.tutkie.tut.ac.jp (Shiroh Sado) writes:

>スレッド「Re: 制御構造としての OR演算子」での
>tshi...@astec.co.jp氏の発言 <93e6o5$9qk$1...@tokyonet-entrance.astec.co.jp> より引用

>>> そもそも、UNIX の syscall は perl とエラーの真偽が反転してるので、
>>> 普通に書くと
>>>
>>> open(...) and die
>>>
>>> 「開いて、そして死ね」になっちゃいますな :-)

open() の成否の判定は 0 かどうかではなく、-1(或は 負)かどうか
で行なわなければなりませんから、この式ではダメですね。

ウケ狙いで分かってやってるのか、勘違いなのかは分かりませんが、

>:-)

佐渡さんまでもが引っかかってしまうとは。:-O

>ところで、openの返り値を変数に保存しておかなくて良いのか、
>という疑問が。;-1

(fd = open(...)) >= 0 or die ぢゃぁ、カッコ悪過ぎですね。:-(
--
片山@PFU

Shiozaki Takuya

unread,
Jan 9, 2001, 6:31:27 AM1/9/01
to

塩崎です。


<KATE.01J...@sims211.trad.pfu.co.jp>の記事において
ka...@pfu.co.jpさんは書きました。

>> open() の成否の判定は 0 かどうかではなく、-1(或は 負)かどうか
>> で行なわなければなりませんから、この式ではダメですね。
>> ウケ狙いで分かってやってるのか、勘違いなのかは分かりませんが、

おお、これは失礼。うっかりしてました :-)

Hiroshi Toyoshima

unread,
Jan 10, 2001, 1:02:23 AM1/10/01
to
Norikatsu Shigemuraさんは、「Re: カンマ「, 」演算子。評価順序は変更不能?」でこう書きました。
---------- <937rmv$3aq$1...@alice.lb.u-tokai.ac.jp> ----------

> 重村法克です。
>
> <12011.9...@rananim.ie.u-ryukyu.ac.jp>の記事において
> 河野 真治さんは書きました。
>
> >どっちかっていえば、Perl 風の
> > open(..) or die(...)
> >とか
>
> 冗談で open(..) || error_exit(filename); みたいなのを書いたこと
> あります。気持ち悪くてそれ以後使っていませんが(^^;。
 気持ち悪いかどうかは別として、
 MFCユーザは否が応でもみんな使ってます。ほら、

-- afx.h ---

#ifdef _DEBUG
// (省略)
#define TRACE ::AfxTrace
// (省略)
#else // _DEBUG
// (省略)
#define TRACE 1 ? (void)0 : ::AfxTrace
// (省略)

-------------

TRACE("でばっぐ : val = %d" , val);

な具合に。

> >> どっちかっていえば、Perl 風の
> >> open(..) or die(...)
> >> とか
> >論理演算子が制御構造に使えるというのは斬新でした。
> >これは、ねらって設計したのでしょうかね?
> >私は苦手ですが、英語チックというのが良いですね。
>
> まさに『開け, さもなくば死ね』:-)では? (^^;
>
> # それよりも die を導入したセンスの方が…(^^;

 そういう、言語もあって え~んじゃないか~♪ ってな具合で。

--
Hiroshi Toyoshima mailto:hir...@lib.bekkoame.ne.jp

KATAYAMA Yoshio

unread,
Jan 10, 2001, 3:00:43 AM1/10/01
to
In article <93gtsm$95n$1...@nn-tk102.ocn.ad.jp>,
Hiroshi Toyoshima <hir...@lib.bekkoame.ne.jp> writes:

> 気持ち悪いかどうかは別として、
> MFCユーザは否が応でもみんな使ってます。ほら、

>#define TRACE 1 ? (void)0 : ::AfxTrace

なんだかな~っていうマクロ定義ですね。

> TRACE("でばっぐ : val = %d" , val);

debug != TRACE("でばっぐ : val = %d" , val);

とかしたいのかな?>MFC
--
片山@PFU

Shiroh Sado

unread,
Jan 10, 2001, 4:34:10 AM1/10/01
to

佐渡です。

片山さん、ご指摘有り難うございます。

スレッド「Re: 制御構造としての OR演算子」での

ka...@pfu.co.jp氏の発言 <KATE.01J...@sims211.trad.pfu.co.jp> より引用


>> ウケ狙いで分かってやってるのか、勘違いなのかは分かりませんが、
>>
>> >:-)
>>
>> 佐渡さんまでもが引っかかってしまうとは。:-O

お恥ずかしい。

>> >ところで、openの返り値を変数に保存しておかなくて良いのか、
>> >という疑問が。;-1
>>
>> (fd = open(...)) >= 0 or die ぢゃぁ、カッコ悪過ぎですね。:-(

そうですね。
Cで真似すると、とても格好悪くなるという特徴もある
んですよね。( <93cec9$1h9$1...@news.tut.ac.jp> )

Tadakazu Nagai

unread,
Jan 11, 2001, 7:52:00 AM1/11/01
to
永井です。

> > カンマ演算子なんてそんなに使うことがあるのでしょうか?
>
> 私にも、実用的な使い方は思いつきませんが、無理に考えると、

一つ、おもいついたので投稿してみます。

--- ここから ---
include <stream.h>

void foo(bool *ret)
{
static int icnt=0;

(icnt++ < 10) ? *ret = true : *ret = false;
}

int main()
{
bool ret=false;

while( foo(&ret), ret ){ // <<<== ここ
cout << "true\n";
}

cout << "false\n";
}
--- ここまで ---

私は、あまり、このようには書きませんが。

では、失礼します。

KATAYAMA Yoshio

unread,
Jan 11, 2001, 8:56:57 AM1/11/01
to
本題とは関係ありませんが、、、

In article <93ka4t$d$1...@netnews.rim.or.jp>,
"Tadakazu Nagai" <na...@kt.rim.or.jp> writes:

> (icnt++ < 10) ? *ret = true : *ret = false;

C と C++ では、conditional-expression の構文が違うんですよね。

この式は、

*ret = (icnt++ < 10) ? true : false;

とか

*ret = (icnt++ < 10);

と書く方がすっきりして分かり易いと思います。(特に *ret が複雑な
式の時)
--
片山@PFU

Kazuo Fox Dohzono

unread,
Jan 11, 2001, 12:29:48 PM1/11/01
to
茶々ですけど,

In article <93gtsm$95n$1...@nn-tk102.ocn.ad.jp>
Hiroshi Toyoshima <hir...@lib.bekkoame.ne.jp> writes:

> -- afx.h ---
>
> #ifdef _DEBUG
> // (省略)
> #define TRACE ::AfxTrace
> // (省略)
> #else // _DEBUG
> // (省略)
> #define TRACE 1 ? (void)0 : ::AfxTrace
> // (省略)
>
> -------------

TRACE ("val = %d", ++val);

ってやっちゃうとハマりそうですね.

--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp

[12],(6,9),0,0,2
(4/1449/3742)

Hiroshi Toyoshima

unread,
Jan 11, 2001, 10:40:58 PM1/11/01
to
Kazuo Fox Dohzonoさんは、「Re: カンマ「, 」演算子。評価順序は変更不能?」でこう書きました。
---------- <93ku35$1a8l$1...@news2.rim.or.jp> ----------
> 茶々ですけど,

 一応レス (^-^;

> In article <93gtsm$95n$1...@nn-tk102.ocn.ad.jp>
> Hiroshi Toyoshima <hir...@lib.bekkoame.ne.jp> writes:
>
> > -- afx.h ---
> >
> > #ifdef _DEBUG
> > // (省略)
> > #define TRACE ::AfxTrace
> > // (省略)
> > #else // _DEBUG
> > // (省略)
> > #define TRACE 1 ? (void)0 : ::AfxTrace
> > // (省略)
> >
> > -------------
>
> TRACE ("val = %d", ++val);
>
> ってやっちゃうとハマりそうですね.

 それだと、trace 出てくる結果は、forge ですね。

 最近流行の「ねつ造」

Kazuo Fox Dohzono

unread,
Jan 11, 2001, 11:16:20 PM1/11/01
to
In article <93lube$mvk$1...@nn-tk105.ocn.ad.jp>
Hiroshi Toyoshima <hir...@lib.bekkoame.ne.jp> writes:

> > TRACE ("val = %d", ++val);
> >
> > ってやっちゃうとハマりそうですね.
>
>  それだと、trace 出てくる結果は、forge ですね。

TRACE で出てくる結果は正しいつもりで書きました. 他には

while (0 < *p)
TRACE ("v = %d", *p++);

とか. ま, assert () も同じなんですけどね.

Tadakazu Nagai

unread,
Jan 12, 2001, 9:15:52 AM1/12/01
to
永井です。

> 本題とは関係ありませんが、、、

いえいえ。

> > (icnt++ < 10) ? *ret = true : *ret = false;
>
> C と C++ では、conditional-expression の構文が違うんですよね。
>
> この式は、
>
> *ret = (icnt++ < 10) ? true : false;
>
> とか
>
> *ret = (icnt++ < 10);
>
> と書く方がすっきりして分かり易いと思います。(特に *ret が複雑な
> 式の時)

ふむふむ。参考になりました。m(_o_)m

0 new messages