同じ内容で先週に質問して締め切ってしまったんですが、理解出来ない点があるので再度質問させてください。
C言語の引用符「'」と二重引用符「"」の違いがよく分かりません。
という質問に対し、
「文字と文字列の違い」
という回答をいただいたんですが、strcat()の第2引数に1文字だけ指定する場合に二重引用符でなければならないのが何故なのか分かりません。
分かる方がおられたら教えていただけないでしょうか?
よろしくお願いいたします。
ちなみに以前の質問は
http://oshiete1.goo.ne.jp/qa4386678.html
です。
A 回答 (9件)
- 最新から表示
- 回答順に表示
No.1
- 回答日時:
'C'は文字(char)ですね。
"C"は文字列で文字列とは文字の配列(char *)です。
一方strcatは
char *strcat(char *s1, const char *s2);
上記のように定義されていて第2引数にはcharのポインタを要求します。(定義は環境に依存するかも?)
なので連結する文字が1文字でも文字列を指定する必要があります。
No.2
- 回答日時:
" "で囲まれた文字列には最後に文字列の終わりを示す0があります。
'C'は1バイトですが"C"は実は2バイト分の領域を使っています。
strcatの引数は文字列と決まっているので文字列じゃないとだめです
No.3
- 回答日時:
Cに置いて文字列というのは文字の配列で表現します。
つまり、 TCHAR*型です。
文字というのはコンピュータにとっては単なる数値です。
例えば'A'==0x41です。
printf("%x\n", 'A');
とすると 41 が表示されますよね。
シングルクォートで囲まれたトークンは単に数値(TCHAR型)に変換
されます。
TCHAR*型を要求する引数に指定することはできません。
No.4
- 回答日時:
回答者の間でも若干の混乱が見られるようですので、少し補足します。
質問者さんには若干難しい点もあるかと思いますので、分からない部分は質問してください。
まず、一重引用符で囲まれた文字の並びは文字定数です。一重引用符で囲んだ場合でも、複数文字の並びを指定することができます。
このとき、最初の一重引用符の前にLが付けばワイド文字定数になります(L'A'など)。
(ワイド文字定数ではない)単純文字定数の場合、一重引用符の中に1バイトで表現できる文字を記述した場合は、その文字に対応した値を持つint型の整数定数になります(どんな値になるかは処理系定義)。2文字以上、または1文字でも1バイトで表現できない文字を指定した場合の値は処理系定義です。
単純文字定数はint型ですので、sizeof(int) == sizeof(char)となる処理系を除き、1バイトではありません。
ワイド文字定数の場合、一重引用符の中に実行拡張文字集合で表現可能な1文字を記述した場合は、その文字対応した値を持つwchar_t型の整数定数になります(どんな値になるかは処理系定義)。2文字以上、または実行拡張文字集合で表現できない文字を記述した場合の値は処理系定義です。
二重引用符で囲まれた文字の並びは文字列リテラルです。二重引用符の中には0個以上の文字の並びを記述することができます。最初の二重引用符の前にLが付けばワイド文字列リテラルになります。
(ワイドでない)単純文字列リテラルの型はcharの配列型であり、ワイド文字列リテラルの型はwchar_tの配列型です。決して、char*やwchar_t*ではありません。
文字列リテラルの末尾には原則としてナル文字が挿入されます。例えば、"
char s[] = "C";
であれば、
char s[2] = { 'C', '\0' };
と等価になります。ただし、
char s[1] = "C";
とした場合は、
char s[1] = { 'C' };
と等価になり、末尾にナル文字が挿入されません。
各文字に対応した値は処理系定義です。__STDC_ISO_10646__マクロが定義されている場合のワイド文字を除き、処理系を特定し、かつ移植性を諦めるのでない限り、ASCIIやUnicode等特定の文字コードであることを期待することはできません。
なお、TCHAR型というのは標準規格には存在しません。
Cの現行規格におけるstrcatは、<string.h>で
char *strcat(char * restrict s1, const char * restrict s2);
と宣言されるはずです(定義ではありません)。
第二引数には文字列(の先頭要素へのポインタ)を渡さなければなりません。仮に文字定数を渡してもコンパイルはできますが、デタラメですのでまともに動作しません。
No.5
- 回答日時:
>仮に文字定数を渡してもコンパイルはできますが、
>デタラメですのでまともに動作しません。
第2引数は文字定数でも良いのでは?
>strcat()の第2引数に1文字だけ指定する場合に
>二重引用符でなければならないのが何故なのか分かりません
なぜなのかというと、'\0'で終る、文字列で無いからです。
C言語では文字列とは最初のナル文字(\0)で終わり、
かつそれを含む連続した文字の並びの事を言います。
文字は「連続した文字の並び」でも、「\0を含みそれで終る」もの
でも有りません。
(ワイド文字にもナルワイド文字が存在しますが、
ようは同じような仕組みがワイド版という物にあると思って下さい。)
strcatの関数仕様として以下の様になっています。(一部抜粋)
char *strcat(char * restrict s1, const char * restrict s2);
strcat関数はs2が指す「文字列(終端ナル文字を含む)」のコピーを
s1が指す文字列の最後に付加する。
s2の先頭の文字がs1の指す文字列の最後のナル文字を書き換える。
つまり、引数に求められているのが終端ナル文字を含む文字列なので
文字である値を渡すことはできません。
「文字列は1文字でも終端にナル文字を含み連続した文字の並びとなります」
「文字は1文字、終端などという概念がありません。」
#多少語弊はありますが、こんな感じで覚えとくといいと思います
No.6
- 回答日時:
> >仮に文字定数を渡してもコンパイルはできますが、
> >デタラメですのでまともに動作しません。
> 第2引数は文字定数でも良いのでは?
何か認識にずれがあるような気がします。
char s[10] = "abc";
strcat(s, 'd');
は、まともに動作しませんよね。
No.7
- 回答日時:
型による違いです。
'a'は「char」型、"a"は「char *」型です。
また、"abc"は正しい記述ですが、'abc'はC言語の規格では許されない記述です。
ご存知かもしれませんが、関数strcatは、引数で指定された2つの文字列を連結する関数で、第2引数が1文字の文字列の場合だけでなく、2文字以上の文字列も連結できるように汎用的に関数が宣言・定義されています。
C言語の規格の具体的なプロトタイプ宣言は以下のとおりです。
char * strcat(const char * str1, char *str2); /* 汎用的 */
そのため、第2引数には「char *」型である二重引用符は指定できませすが、一重引用符は指定できません。
仮に関数strcatの第2引数の型が「char」型で宣言されていたら、一文字の文字列しか連結できない関数になってしまいます。
char * strcat(const char * str1, char str2); /* 一文字しか連結できないよ… */
No.8
- 回答日時:
確かにsizeof('a')が4でsizeof("a")は2になりますね。
私も'a'はchar型で"a"はchar*型だと思いこんでました
勉強になりました。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 英語 英語で質問です。文末で引用符が重複した時、二重に記載するのでしょうか? 2 2022/06/23 10:38
- 新幹線 乗り継ぎ割引【在来線➡新幹線➡在来線➡新幹線】 4 2023/01/20 21:03
- 日本語 「〜たり〜たり」の使い方 2 2022/06/08 21:30
- 日本語 「〜たり〜たり」の使い方 1 2022/06/05 16:25
- 新幹線 GWに東京〜新青森駅 (行き 帰り) 東北新幹線で行きます 往復割引は (行き 帰り) 両方の切符を 3 2023/03/11 21:14
- 新幹線 東京から姫路の往復割引、復路は、大阪まで在来線利用の時 6 2022/04/17 12:06
- 電車・路線・地下鉄 JR東日本が普通回数券を廃止。これ以外で事前に切符を買っておくことはできる? 9 2022/04/26 17:55
- 日本語 公用文における句点の打ち方について 2 2022/05/07 16:47
- 電車・路線・地下鉄 Suicaについて(定期券タイプは除く) 7 2022/10/17 13:17
- 新幹線 新幹線切符の改札の通し方について 3 2022/04/20 21:22
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
_tcscpy_s(wcscpy_s)の第二引数...
-
TCL言語で文字列検索方法を教え...
-
プログラムによく出てくるst...
-
ASPで別サイトの内容を Stream ...
-
括弧が含まれる文字列の括弧の...
-
fgetsで配列に数字を入れる。
-
VBA-DLLの引数受け渡しについて
-
ソースコードの間違い (C言語)
-
曜日を格納する配列の大きさ
-
C#でstringをポインタとして渡す
-
C++で入力した文字列から数字を...
-
VC++6.0 MFC ダイアログバーを...
-
ExcelVBAで質問です。離れた二...
-
c言語
-
C言語 配列の長さの上限
-
パイソンの
-
mallocについて
-
Excelですべての組合せ(重複組...
-
関数から配列を返すには?
-
文字列内の数字削除
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C++で入力した文字列から数字を...
-
nullと""、\\0とEOFの違いにつ...
-
プログラムによく出てくるst...
-
%dなどの違い
-
WSH(VBS)でJSONの文字列を読み...
-
TCL言語で文字列検索方法を教え...
-
C#でstringをポインタとして渡す
-
16進数を2文字ずつ配列に格納し...
-
_tcscpy_s(wcscpy_s)の第二引数...
-
C++で文字列の右端から特定の文...
-
シリアル通信で0x00を送信した...
-
VBA-DLLの引数受け渡しについて
-
数字の入った配列をファイルへ...
-
c#で他のアプリの文字入力フォ...
-
構造体→文字列→構造体 をする方法
-
Shift_JIS(16進)を文字に変換す...
-
バイナリファイル中の日本語文...
-
C言語の課題で困っています;
-
[C++]WCHARの1文字目しか表示で...
-
VB6.0でのバイナリデータの扱い...
おすすめ情報