個人的に読んでいたC言語に関する文章に使われていた表現のうち,今のところ個人的に謎のものをまとめます。ここではJIS規格に沿ったC言語をC言語と呼びます。
謎の表現1.「printf文」,「scanf文」
多くの場合,printf関数やscanf関数の関数呼出し式にセミコロン(;)を付けて式文にしたものだと解釈しています。
「printf文」,「scanf文」という表現を許した場合,「puts文」,「putchar文」,「getchar文」,「strcat文」といった表現も許すのでしょうか?
謎の表現2.「参照渡し」
この表現は,ポインタを渡すことができると解釈しています。
「参照渡し」はC言語の引数渡し機構を紹介するときの便宜的な表現でつかわれることがあるように思われますが,C言語は値渡し(call by value)を採用しています。なお,C++では参照渡し(call by reference)を用いることができます。
[1]において「参照」は以下の意味で使われています。
- [1,p.4] 「オブジェクトを参照する場合,オブジェクトは,特定の型をもっていると解釈してもよい (6.3.2.1 参照)。」
謎の表現3.「変数はオブジェクトを参照するためのもの」
「識別子はオブジェクトを参照するもの」と解釈しています。
「メモリ上のオブジェクト,すなわち変数や配列要素」という表現が[2,5.1 Pointers and Addresses]にありますので,ある条件の下で「オブジェクト=変数」となるはずです。
The & operator only applies to objects in memory: variables and array elements. It cannot be applied to expressions, constants, or register variables.
[1]では「参照」は以下の文脈で使われています。
- 「オブジェクトを生存期間の外部で参照したときの動作は未定義とする。」
謎の表現4.「箱」
「箱」は比喩的な表現です。「箱」=「オブジェクト」と解釈しています。
謎の表現5.「struct x {...} は型の定義」
型の宣言であることはわかるのですが、型の定義なのかは分かりません。オブジェクトの定義でないことは分かります。また int x; は変数xの宣言であり定義でもあることも分かります。typedef .... が型定義なのも分かります。
ポインタに関する謎の表現
謎の表現P1.「ポインタとはアドレスである。」
ポインタという術語は,少なくとも以下の3通りの意味で正しく使われています。多くの場合,おそらく1を意図しているのではないかと解釈しています。その場合でも,アドレスを値としてもつだけでは不十分で,型などのオブジェクトの属性も必要でしょう(例えば,p++の評価をするためには型情報が必要)。
- 変数(オブジェクト)のアドレスを格納する変数(オブジェクト) [2,5 Pointers and Arrays]。
A pointer is a variable that contains the address of a variable.
- 被参照型Tから派生されるポインタ型 [1,p.27]。
被参照型Tから派生されるポインタ型は,"Tへのポインタ"と呼ぶ。
- 以下のような*の構文単位 [1,p.85]。
int *p;
なお,「アドレスxは型"〜型へのポインタ"をもつ」や「アドレス定数cは"〜を指すポインタ"である」は理解できました。
謎の表現P2.「ポインタはある記憶域を指し示す」
register宣言された変数が割り付けられた記憶域(storage)を指すことはできないので,この記憶域はメモリの間違えではないかと解釈しています。「指し示す」は「指す」と解釈しています。
なお,[2,4.7 Register Variables]によると,レジスタが実際にはメモリに置かれていたとしても,レジスタ変数のアドレスを取ってくることはできないようです。
it is not possible to take the address of a register variable (a topic covered in Chapter 5), regardless of whether the variable is actually placed in a register.
例: 不適切な参照外し
#include <stdio.h>
int main(void)
{
register char c = '!';
char *p = &c; /* &c は不適切な参照外し */
printf("c = '%c'\n", c);
printf("p = '%p'\n", p);
}
% cc invalid_pointer.c
cc invalid_pointer.c
invalid_pointer.c:6:15: error: address of register variable requested
char *p = &c;
^~
1 error generated.
謎の表現P3.「ポインタが指す先の値」
「ポインタが指すオブジェクトの値」と解釈しています。
謎の表現P4.「int型のポインタ変数」
「int型オブジェクトへのポインタ型の変数」と解釈しています。
謎の表現P5.「ポインタと配列は同じもの」
これは単なる勘違いだと思います。
謎の表現P6.「2つ以上の値を返す関数」
値はひとつしか返せません。
なお,[1,p.52]にある方法で呼び出し側の複数のオブジェクトの値を呼び出された側で変更することができます。
関数は,その仮引数の値を変更してもよいが,これらの変更が実引数の値に影響を与えることはで きない。一方,オブジェクトへのポインタを渡すことは可能であり,関数はそれによって指される オブジェクトの値を変更してもよい。
謎の表現P7.「配列名はポインタ」
これは勘違いと思います。配列名は識別子(名前)です。ポインタは変数,型,もしくは構文要素*です。識別子はこれらのいずれでもないので配列名はポインタではありません。
文字列に関する謎の表現
文字列str1を逆順にした文字列をstr2。例えば,"abc"がstr1に格納されていたら,"cba"をstr2に格納する。
C言語における文字列はナル文字まで含まれる。[1,p.124]に以下のようにある。
最初のナル文字で終わり,かつそれを含む連続した文字の並びを文字列(string)という。
「文字列str1が格納する最初の0に先行する文字列の値を逆順にした値の列,およびその直後に0を値とする文字の並びをもつような文字列str2」と解釈する。
表記揺れ
個人的には[1]の表記を用いることにする。コロンの左に書くことにする。
[1]の表記 | 別表記 | 個人的に使用を控えたい表記 |
---|---|---|
返却値 | 戻り値,返り値 | |
ナル文字 | ヌル文字 | |
制御式 | 条件式 | |
仮引数 | パラメータ | |
実引数 | アーギュメント | |
オペランド | 被演算子 |
続く,かも。
#参考文献
[1] JIS X 3010:2003 プログラム言語C
[2] Kernighan, B. W. and D. M. Ritchie (1988). The C Programming Lnaguage.