C Language
一般的なCプログラミングのイディオムと開発者の実践
サーチ…
リテラルと変数の比較
ある値とある変数とを比較しているとします
if ( i == 2) //Bad-way
{
doSomething;
}
==
=
と間違っているとします。それから、それを理解するあなたの甘い時間がかかります。
if( 2 == i) //Good-way
{
doSomething;
}
次に、等号が誤って残っていると、コンパイラは「リテラルへの割り当てを試みました」と文句を言います。これは2つの変数を比較するときは保護されませんが、少しずつ役立ちます。
詳細はこちらをご覧ください。
関数のパラメータリストを空白にしないでください - voidを使用してください
呼び出されたときに引数を必要とせず、関数プロトタイプと関数定義でパラメータリストを定義する方法のジレンマに直面している関数を作成しているとします。
プロトタイプと定義の両方に対してパラメータリストを空にする選択肢があります。これにより、必要な関数呼び出しステートメントのように見えます。
あなたは、キーワードvoidの使用法のうちの1つ(そのうちのほんの少数しかありません)のどこかを読んで、呼び出し中に引数を受け入れない関数のパラメータリストを定義することです。したがって、これも選択肢です。
だから、正しい選択ですか?
ANSWER:キーワードvoidを使用する
一般的な助言:言語が特定の目的のために使用する特定の機能を提供している場合は、コード内でその機能を使用する方がよいでしょう。たとえば、 #define
マクロの代わりにenum
を使用します(これは別の例です)。
C11セクション6.7.6.3「関数宣言子」第10項には、
リスト内の唯一の項目としての型の名前のないパラメーターの特殊なケースは、関数にパラメーターがないことを指定します。
その同じセクションのパラグラフ14は唯一の違いを示しています:
...その関数の定義の一部である関数宣言子の空のリストは、その関数にパラメータがないことを示します。その関数の定義の一部ではない関数宣言子内の空のリストは、パラメーターの数またはタイプに関する情報が提供されないことを指定します。
上記のものについてK&R(pgs- 72-73)によって提供された簡単な説明:
さらに、関数宣言に引数が含まれていない場合
double atof();
それはまた、atof
の議論については何も仮定されないことを意味するとatof
。すべてのパラメータチェックがオフになります。この空の引数リストの特別な意味は、古いCプログラムを新しいコンパイラでコンパイルできるようにすることです。しかし、新しいプログラムでそれを使うのは悪い考えです。関数が引数を取る場合は、それらを宣言します。引数がない場合はvoid
使用しvoid
。
これはあなたの関数プロトタイプがどのように見えるかです:
int foo(void);
そして、これは関数の定義方法です:
int foo(void)
{
...
<statements>
...
return 1;
}
上記のint foo()
型の宣言(つまり、キーワードvoidを使わずにint foo()
を使う利点の1つは、 foo(42)
ような誤った文を使って関数を呼び出すとコンパイラがエラーを検出できることです。この種の関数呼び出し文では、パラメータリストを空白のままにしてもエラーは発生しません。エラーは静かに通過し、検出されず、コードは実行されます。
これはまた、 main()
関数を次のように定義する必要があることを意味します:
int main(void)
{
...
<statements>
...
return 0;
}
空のパラメータリストで定義された関数が引数を取らなくても、関数のプロトタイプは提供されないので、引き続き引数を指定して関数を呼び出すと、コンパイラは不平を言わないことに注意してください。例えば:
#include <stdio.h>
static void parameterless()
{
printf("%s called\n", __func__);
}
int main(void)
{
parameterless(3, "arguments", "provided");
return 0;
}
そのコードがproto79.c
ファイルに保存されていれば、GCCを使ってUnix上でコンパイルすることができます(デモンストレーションに使用されるmacOS Sierra 10.12.5のバージョン7.1.0):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -pedantic proto79.c -o proto79
$
より厳しいオプションを指定してコンパイルすると、エラーが発生します。
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -pedantic proto79.c -o proto79
proto79.c:3:13: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
static void parameterless()
^~~~~~~~~~~~~
proto79.c: In function ‘parameterless’:
proto79.c:3:13: error: old-style function definition [-Werror=old-style-definition]
cc1: all warnings being treated as errors
$
関数に正式なプロトタイプstatic void parameterless(void)
すると、コンパイルでエラーが発生します。
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition -pedantic proto79.c -o proto79
proto79.c: In function ‘main’:
proto79.c:10:5: error: too many arguments to function ‘parameterless’
parameterless(3, "arguments", "provided");
^~~~~~~~~~~~~
proto79.c:3:13: note: declared here
static void parameterless(void)
^~~~~~~~~~~~~
$
道徳的 - 常にプロトタイプがあることを確認し、ルールに従わないときにコンパイラがあなたに指示するようにしてください。