回答:
表現:
(expression1, expression2)
最初にexpression1が評価され、次にexpression2が評価され、式全体のexpression2の値が返されます。
i
も、5、4、3、2、1の値はありません。これは単に0です。式に副作用がない限り、これは実質的に役に立ちません。
i = b, c;
(i = b), c
代入=
はカンマ演算子よりも優先されるため、と同等です,
。カンマ演算子は、すべての中で最も優先順位が低くなっています。
expression1, expression2;
最初にexpression1
、おそらくその副作用(関数の呼び出しなど)expression2
について評価され、次にシーケンスポイントがあり、次に評価されて値が返されます…
私はwhile
ループで最も使用されるのを見てきました:
string s;
while(read_string(s), s.len() > 5)
{
//do something
}
操作を行ってから、副作用に基づいてテストを行います。もう1つの方法は、次のようにすることです。
string s;
read_string(s);
while(s.len() > 5)
{
//do something
read_string(s);
}
while (read_string(s) && s.len() > 5)
。明らかにread_string
、戻り値がない(または意味のある値がない)場合は機能しません。(編集:申し訳ありませんが、この投稿の古さに気づきませんでした。)
while (1)
とbreak;
、本体内のステートメント。コードのブレークアウト部分をwhileテストに強制的に入れたり、do-whileテストに押し下げたりしようとすると、多くの場合エネルギーが無駄になり、コードの理解が難しくなります。
while(1)
とbreak
、
コンマ演算子は、左のオペランドを評価し、結果を破棄し、右側のオペランドを評価し、それが結果になります。慣用的に使用される変数の初期化時にリンクに記載されているように使用されるfor
ループを、それが次の例を与えます。
void rev(char *s, size_t len)
{
char *first;
for ( first = s, s += len - 1; s >= first; --s)
/*^^^^^^^^^^^^^^^^^^^^^^^*/
putchar(*s);
}
それ以外の場合は、コンマ演算子の多くの優れた使用法はありませんが、読み取りや保守が難しいコードを乱用することは簡単です。
ドラフトC99標準以下のような文法は以下のとおりです。
expression:
assignment-expression
expression , assignment-expression
そしてパラグラフ2は言う:
コンマ演算子の左のオペランドは、void式として評価されます。評価後にシーケンスポイントがあります。次に、右側のオペランドが評価されます。結果にはタイプと値があります。 97)コンマ演算子の結果を変更しようとしたり、次のシーケンスポイントの後にアクセスしたりした場合の動作は未定義です。
脚注97は言う:
コンマ演算子は左辺値を生成しません。
つまり、コンマ演算子の結果に割り当てることはできません。
コンマ演算子の優先順位が最も低いため、使用()
すると大きな違いが生じる場合があることに注意してください。次に例を示します。
#include <stdio.h>
int main()
{
int x, y ;
x = 1, 2 ;
y = (3,4) ;
printf( "%d %d\n", x, y ) ;
}
次の出力が表示されます。
1 4
コンマ演算子は、その両側の2つの式を1つに結合し、左から右の順序で両方を評価します。右側の値は、式全体の値として返されます。
(expr1, expr2)
のよう{ expr1; expr2; }
ですがexpr2
、関数呼び出しまたは代入で結果を使用できます。
for
ループでは、次のように複数の変数を初期化または維持することがよくあります。
for (low = 0, high = MAXSIZE; low < high; low = newlow, high = newhigh)
{
/* do something with low and high and put new values
in newlow and newhigh */
}
これとは別に、私はそれを「怒って」、他の1つのケースでのみ使用しました。これは、常にマクロで一緒に実行される2つの操作をラップする場合です。ネットワーク上で送信するために、さまざまなバイナリ値をバイトバッファーにコピーするコードと、取得した場所で維持されるポインターがありました。
unsigned char outbuff[BUFFSIZE];
unsigned char *ptr = outbuff;
*ptr++ = first_byte_value;
*ptr++ = second_byte_value;
send_buff(outbuff, (int)(ptr - outbuff));
値がshort
sまたはint
s の場合、これを行いました:
*((short *)ptr)++ = short_value;
*((int *)ptr)++ = int_value;
後で(short *)ptr
L値ではなくなり、インクリメントできないため、これは本当に有効なCではないことを後で読みましたが、当時のコンパイラは気にしていませんでした。これを修正するには、式を2つに分割します。
*(short *)ptr = short_value;
ptr += sizeof(short);
ただし、このアプローチは、すべての開発者が両方のステートメントを常に入力することを忘れないようにしていました。出力ポインタ、値、値の型を渡すことができる関数が必要でした。これはCであり、テンプレートを使用するC ++ではないため、関数が任意の型をとることができなかったため、マクロを使用しました。
#define ASSIGN_INCR(p, val, type) ((*((type) *)(p) = (val)), (p) += sizeof(type))
コンマ演算子を使用することで、これを式またはステートメントとして希望どおりに使用できました。
if (need_to_output_short)
ASSIGN_INCR(ptr, short_value, short);
latest_pos = ASSIGN_INCR(ptr, int_value, int);
send_buff(outbuff, (int)(ASSIGN_INCR(ptr, last_value, int) - outbuff));
これらの例はどれも良いスタイルだとは思わない!確かに、ループでカンマ演算子を使用することに対してもアドバイスするSteve McConnellのコードコンプリートを覚えているようですfor
。読みやすさと保守性のために、ループは1つの変数だけで制御され、for
行自体の式にはループ制御コードのみが含まれている必要があります。初期化やループメンテナンスの他の余分なビットはありません。
式の1つ(おそらくinit式またはループ式)で複数のことを実行するファンキーなループを作成するときに、私がそれが役立つと私が見た唯一の場所は、次のようなものです。
bool arraysAreMirrored(int a1[], int a2[], size_t size)
{
size_t i1, i2;
for(i1 = 0, i2 = size - 1; i1 < size; i1++, i2--)
{
if(a1[i1] != a2[i2])
{
return false;
}
}
return true;
}
構文エラーがある場合や、厳密なC以外のものが混在している場合はご容赦ください。、演算子が適切な形式であるとは主張していませんが、それを使用できます。上記の場合、おそらくwhile
代わりにループを使用するので、initとループの複数の式がより明確になります。(そして、宣言してから初期化するのではなく、インラインでi1とi2を初期化します...何とか何とか何とか。)
これは、@ Rajeshと@JeffMercadoからの質問に対処するために、これを復活させています。これは、検索エンジンの上位ヒットの1つであるため、非常に重要だと思います。
たとえば、次のコードスニペットを考えてみましょう
int i = (5,4,3,2,1);
int j;
j = 5,4,3,2,1;
printf("%d %d\n", i , j);
印刷されます
1 5
i
ほとんどの回答で説明したようなケースが処理されます。すべての式は左から右の順序で評価されますが、最後の式のみがに割り当てられi
ます。(
式)is
1` の結果。
j
以降場合は、異なる優先順位の規則に従う,
最小演算子の優先順位を有しています。これらの規則により、コンパイラーは割り当て式、定数、定数...を認識します。式は再び左から右の順に評価し、その副作用は、目に見えるとどまるので、されj
ている5
の結果としてj = 5
。
興味深いことに、int j = 5,4,3,2,1;
言語仕様では許可されていません。初期化子が期待し代入式を直接ので、,
オペレータが許可されていません。
お役に立てれば。