C言語の文法の質問をさせていただきます。

int hoge;
などと宣言しますが、このintというのは型指定子というものでしょうか。

int *piyo;
という宣言のintも型指定子でしょうか。
この場合、* はなんと呼ばれるのでしょうか。(アスタリスクという記号です、という回答は期待していません。(^_^;)) ポインタ宣言子、でいいのでしょうか。これは「演算子」ではないんですよね?

char c[10];
という宣言の[ ]やその中に入っている10はなんと呼ばれるのでしょうか。

いま、手元に「新ANSI C言語辞典」という本があるのですが、説明を読んでもよくわかりません。

このQ&Aに関連する最新のQ&A

A 回答 (4件)

私の場合、演算子と呼ぶのに抵抗があるので、



例えば、「ポインタを宣言する場合は int *piyo のように、宣言子 piyo を * で修飾する」という感じで、ポインタ修飾子と呼んでいますが、定かではありません。

[]の中は要素数だと思います。

この回答への補足

int *piyo;
という宣言の * についてですよね。

>私の場合、演算子と呼ぶのに抵抗があるので、

やっぱりそうですよね。

演算子って言ったら、演算子の優先順位表ってあるじゃないですか、
あれを気にしなきゃいけなくなるように思えてくるんです。

あれは関係ないんですよね?

補足日時:2002/02/28 19:31
    • good
    • 0
この回答へのお礼

ご回答有難うございます。


>ポインタ修飾子と呼んでいますが、定かではありません。

(定かではないかもしれませんが、)ポインタ修飾子って言うんですね。

お礼日時:2002/02/28 19:38

補足します。



>(定かではないかもしれませんが、)ポインタ修飾子って言うんですね。

宣言において、* が宣言子の1つであり、さらに細分化して、修飾子と呼ぶ事は一般的だと思います。
* をポインタ修飾子、[] を配列修飾子、() を関数修飾子と記述されているものを見た事はありますが、一般的かどうかという点で、自信はありません。

>演算子って言ったら、演算子の優先順位表ってあるじゃないですか、
>あれを気にしなきゃいけなくなるように思えてくるんです。

宣言にも優先順位はあります。例えば、

int *func();

この宣言には、int, *, func, () の4つの宣言子があって、* と func よりも func と () が優先されるから、これが関数の宣言であると解釈されるわけですよね?

int (*func)();

そして、この場合は、* と func が優先されるので、関数へのポインタと解釈されます。どちらの場合も、一般的な演算子の優先順位と同じなので、優先順位があった方が理解しやすいと思います。

この回答への補足

>宣言にも優先順位はあります。例えば、
ここ以下の話は、「宣言にも優先順位はあり、その優先順位は演算子の優先順位と同じなので、演算子の優先順位の表を当てはめて考えても支障はないです。」ということですね。

補足日時:2002/03/03 12:09
    • good
    • 0

# 初めに言ってしまうと、それは「気にすべきではない分野」の1つです(笑)



Cでの「宣言」は、「宣言指定子」のリストと「宣言子」のリストで構成されます。
int や char などは「宣言指定子」であり、その中の「型指定子」に分類されます。
また、hoge や *piyo、c[10] は「宣言子」になります。

で、* なんですけど、これはあくまで「ポインタ演算子」です。
宣言で使えば「宣言子としてのポインタ演算子」となるわけです。
別に、演算を行うから演算子、というわけではないようです。
同様に、配列の宣言に使う場合の [ ] や 10 も、* 特別な呼び方はないようです。
[ ] は配列演算子だし、10 は定数式です。

ただし「宣言」においては、これらは「宣言子」の下階層に位置するので、* を「ポインタ宣言子」と呼んだり、[ ] を「配列宣言子」と呼んだとしても、(通じれば)問題はないでしょう。

この回答への補足

># 初めに言ってしまうと、それは「気にすべきではない分野」の1つです(笑)

質問した本人がいうのもなんですが、それは言えていると思います。(笑い)

ご回答はなんべんも読ませていただきますが、私の頭ではよくわかりません。
やっぱり気にしないようにします。(笑)

でもすみません、やっぱり以下の部分が気になります。
>で、* なんですけど、これはあくまで「ポインタ演算子」です。
>別に、演算を行うから演算子、というわけではないようです。

演算を行わないのに演算子なのかなあ、と思ってしまうのです。

補足日時:2002/02/28 19:14
    • good
    • 0

>int hoge;


>などと宣言しますが、このintというのは型指定子というものでしょうか。
はい

>int *piyo;
>という宣言のintも型指定子でしょうか。
そです。

>この場合、* はなんと呼ばれるのでしょうか。(アスタリスクという記号です、という回答は期 待していません。(^_^;)) ポインタ宣言子、でいいのでしょうか。これは「演算子」ではないん ですよね?
演算子ではないです。あまり*そのものを何て呼ぶかは聞いたことはないですね。int* でポインタ宣言、と言うのでポインタ宣言子でいいんじゃないでしょうか。

>char c[10];
>という宣言の[ ]やその中に入っている10はなんと呼ばれるのでしょうか。
要素数、でしょうかね。

参考URL:http://black.sakura.ne.jp/~third/c.html

この回答への補足

ご回答にはたいへん感謝いたします。

>あまり*そのものを何て呼ぶかは聞いたことはないですね。

* はなんなのか、なんて考える人はいないのかなあ(笑)

でもご回答を読んでひとつ思いました。
>>int *piyo;
>>という宣言のintも型指定子でしょうか。
>そです。
int* がポインタ宣言子であって、その中のintが型指定子というなら、intを除いた * の部分にも名前があるんじゃないかなあ、というふうに思いました。
 ないものはないんでしょうかねえ。

補足日時:2002/02/28 19:00
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Qvoid (*signal(int signum, void (*handler)(int)))(int);

の解釈を教えてください
最後の「(int)」については詳しくお願いします

Aベストアンサー

signalが

(1)1つ目の引数の型:int
(2)2つ目の引数の型:引数がintで戻り値がvoidである関数へのポインタ
(3)戻り値の型:引数がintで戻り値がvoidである関数へのポインタ(2と同じ)

を満たす関数である事を宣言しています。最後の(int)はsignalの戻り値の
関数ポインタがint型の引数を持つ事を示しています。

「引数がintで戻り値がvoidである関数へのポインタ」の型をHANDLERと表すと

HANDLER signal(int signum, HANDLER handler);

となります。

Qint main(int argc, char* argv[]) についての質問

こんにちは.つね日ごろ思っている質問させてください.
Cの参考書には,
(1)
void main(void)
{
}

(2)
int main(int argc, char* argv[])
{
return 0;
}
の2つのパターンが記載されていますが,
どういう違いがあるのでしょうか?

(1)の場合main関数は,型を持たず,引数も持たない.
※Turbo Cなどのコンパイラーでは,
return文がないと警告出ます.
(2)の場合は,int 型をかえし,引数はint型 変数と char型ポインタ配列(?)
を指定している.
といったくらいしか分かりません.

(2)に関してもう少し述べれば,
コマンドラインからファイルを指定し,実行することが
できると勉強した記憶があるのですが,
理解があいまいです.

特に(2)の場合のmain関数の意味と,その使い方について
アドバイスお願い致します.

Aベストアンサー

> (1)
> void main(void)
  ...
> (2)
> int main(int argc, char* argv[])
  ...
> の2つのパターンが記載されていますが,どういう違いがあるのでしょうか?

(1) は、間違いです。少なくとも ANSI-C の規格に合致していません。

main() は、特別な関数で、ANSI-C の規格では以下の三通りのうちのどれか
でなくてはいけない、と定められています。

int main(void)
int main(int argc, char *argv[]);
int main(int argc, char *argv[], char *envp[]);

因みに三番目の形式では、三つ目の引数には環境変数が入ります。
以下のようなコードで確認ができます。

int main(int argc, char *argv[], char *envp[])
{
  int i = 0;
  while (envp[i]) {
    printf("envp[%d] = '%s'\n", i, envp[i]);
    ++i;
  }
  return 0;
}


> ※Turbo Cなどのコンパイラーでは,return文がないと警告出ます

Turbo C は、規格に厳格なのでしょう。返り値が void なのはおかしいので、
int だとみなすよ、という警告も出てるはず。で、int が帰り値だとみなし
ているので return が無いと、返り値が不定になるよ、と警告を出している
のでしょう。

> (1)
> void main(void)
  ...
> (2)
> int main(int argc, char* argv[])
  ...
> の2つのパターンが記載されていますが,どういう違いがあるのでしょうか?

(1) は、間違いです。少なくとも ANSI-C の規格に合致していません。

main() は、特別な関数で、ANSI-C の規格では以下の三通りのうちのどれか
でなくてはいけない、と定められています。

int main(void)
int main(int argc, char *argv[]);
int main(int argc, char *argv[], char *envp[]);

因みに三番目の形式では、三...続きを読む

Qchar *name1[4] とchar name2[][4] の違いについて

C言語のことで質問があります。

char *name1[4]は
char *name1[4] = {"abcdefghi","jkl","l","mn"};
と宣言でき,ポインタを4つ確保した形となりました。

char name2[][4]は
char name2[][4] = {"abc","def","ghi","jkl","mno","pqr","stu","vwx"};
と4文字以内の文字列を初期化した数だけ確保した形となりました。

この結果からchar *name1[4]の意味は,char name2[][4]ではなくchar name2[4][]に近いと思いました。
しかし,char name2[4][]ではポインタを4つ確保した事にはならないみたいでコンパイルが通りません。
*name1[4]では4つのポインタを確保できるのに~と思ってしまいます。

ポインタと配列は別物と考えるべきなのでしょうか?
訳の分からない質問かもしれませんが,
何卒ご指導いただくようよろしくお願いします。

Aベストアンサー

ポインタと配列の違いというのは、変数と定数の違いのようなものです。

話を簡単にするために、一次元配列から考えましょう。

char *p1; と定義した時のp1は、いうまでもなくポインタで、
これは変数です。p1は任意の文字列を指すことができます。
char a1[4]; と配列の形で定義した場合のa1については、
a1[0]やa1[1]等を、通常のchar型の変数と全く同じように扱うことが
できます。しかし、a1自体は、例えば a1 = p1; のように値を代入する
ことができません。(逆の p1 = a1; は可能。)つまり、この場合のa1は、
変数ではなく、定数のようなものなのです。

複合的なケースについて見てみましょう。
char **q1; ポインタへのポインタ
 q1,*q1,**q1,q1[0],*q1[0],q1[0][0] のいずれも変数として
 扱うことができます。(値を代入することが文法的に許されます。
 ただし、実行時にはアクセス違反になる場合もあります。)
char q2[4][4]; 二次元配列
 q2,q2[0]は変数として扱うことができません。q2[0][0]のように
 して、初めて変数として扱えるようになります。
char *q3[4]; ポインタの配列
 q3は変数として扱うことができませんが、q3[0],*q3[0],q3[0][0]
 はいずれも変数として扱うことができます。
 なお、この定義は char *(q3[4]); とした場合と全く同じ意味です。
char (*q4)[4]; 配列へのポインタ
 q4,(*q4)[0],q4[0][0]はいずれも変数として扱うことができます。
 しかし、*q4,q4[0]は変数として扱うことができません。

char *name1[4]; と char name2[4][]; は確かに似ています。しかし
違うところもあります。それは、name1[0] が変数として扱えるのに
対し、name2[0] には値を代入できないという点です。(データの
具体的な構造については、inthefloiさんが書いておられる通りです。
> char name2[4][]ではポインタを4つ確保した事にはならないみたい
というのも、全くその通りで、配列の定義では、ポインタ変数の領域
を確保する余地はないのです。

ポインタと配列の違いというのは、変数と定数の違いのようなものです。

話を簡単にするために、一次元配列から考えましょう。

char *p1; と定義した時のp1は、いうまでもなくポインタで、
これは変数です。p1は任意の文字列を指すことができます。
char a1[4]; と配列の形で定義した場合のa1については、
a1[0]やa1[1]等を、通常のchar型の変数と全く同じように扱うことが
できます。しかし、a1自体は、例えば a1 = p1; のように値を代入する
ことができません。(逆の p1 = a1; は可能。)つまり...続きを読む

Qint select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)について

見当違いな質問かもしれませんがお願いします。

複数のソケットを監視する際にselectを使う場合のことですが、
selectの動作と戻り値について疑問があります。

http://www.linux.or.jp/JM/html/LDP_man-pages/man2/select.2.html
ここを参照すると、selectの戻り値は
「更新された 3 つのディスクリプタ集合に含まれているディスクリプタの数 (つまり、 readfds, writefds, exceptfds 中の 1 になっているビットの総数) を返す。」
とあります。
私の中でselectは登録してあるFDのうち、一つでも動きがあれば即座にselectを抜けるもの、という認識です。
この認識だとreadfds,writefdsが引数として与えられているとしても、
どちらかのfd_setのうち、一つでも動きがあればselect文は
抜けてしまうことになります。とすると、戻り値として
「readfds, writefds, exceptfds 中の 1 になっているビットの総数」
は常に1ということになってしまいます。しかし、総数というからには
複数同時に1になることもあるはずです。

私の認識が間違っているとは思うのですが、どう間違っているのかわかりません。
select文の動きについて詳しく教えていただけないでしょうか。
または良いページがあれば教えてください。

見当違いな質問かもしれませんがお願いします。

複数のソケットを監視する際にselectを使う場合のことですが、
selectの動作と戻り値について疑問があります。

http://www.linux.or.jp/JM/html/LDP_man-pages/man2/select.2.html
ここを参照すると、selectの戻り値は
「更新された 3 つのディスクリプタ集合に含まれているディスクリプタの数 (つまり、 readfds, writefds, exceptfds 中の 1 になっているビットの総数) を返す。」
とあります。
私の中でselectは登録してあるFDのうち、一つでも動きが...続きを読む

Aベストアンサー

>私の中でselectは登録してあるFDのうち、一つでも動きがあれば即座にselectを抜けるもの、という認識です。
この認識はあっています。
しかし、selectを呼び出す以前にOKになっているFDがあれば、それらは全てビットがONになります。

話しを簡単にする為に、受信のみのソケットを3つ作成したとします。
これらの3つのソケットに向けて相手が電文を送ったとします。
その状態でまだ、こちらはselectを呼び出さずにいます。しばらくしてから、selectを呼び出すと、selectは即座にリターンし、3つのビットが一度にONになっているはずです。
一方、相手が、一切電文を送ってない状態で、selectを呼び出した場合は、何れかのビットがONになればリターンするので、そのときは、貴方が想像しているように
ビットの総数は1になる可能性が高いです。
従って、相手が電文を送る前にselectを呼び出すか、送った後にselectを呼び出すかは、その時のタイミングにより異なります。従って、ビット数の総和が常に1であるとは、考えない方が無難です。(1つのソケットしか使用しない場合は別ですが・・・)

>私の中でselectは登録してあるFDのうち、一つでも動きがあれば即座にselectを抜けるもの、という認識です。
この認識はあっています。
しかし、selectを呼び出す以前にOKになっているFDがあれば、それらは全てビットがONになります。

話しを簡単にする為に、受信のみのソケットを3つ作成したとします。
これらの3つのソケットに向けて相手が電文を送ったとします。
その状態でまだ、こちらはselectを呼び出さずにいます。しばらくしてから、selectを呼び出すと、selectは即座にリターンし、3つのビ...続きを読む

Qint *a = new int; エラー

下記をコンパイルすると、'int' 型は 'int *' 型に変換できない(関数 main() )
とエラーが出てしまいました。 何がおかしいのでしょうか ?
初歩的な間違いをしていると思いますが、アドバイスお願いします。

#include<iostream>
#include<stdlib>
#include<ctime>
using namespace std;

void main(void)
{
int *a = new int;
a=rand();
cout<<a<<endl;
delete a;

}

Aベストアンサー

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;

int main(void)
{
srand ( time(NULL));
int *a = new int;
*a=rand();
cout<<*a<<endl;
delete a;
return 0;
}

/*
多分こうだと思う。
想像以上に乱数の精度が悪いような気がする。
*/


人気Q&Aランキング

おすすめ情報