アプリ版:「スタンプのみでお礼する」機能のリリースについて

同じ内容で先週に質問して締め切ってしまったんですが、理解出来ない点があるので再度質問させてください。

C言語の引用符「'」と二重引用符「"」の違いがよく分かりません。
という質問に対し、
「文字と文字列の違い」
という回答をいただいたんですが、strcat()の第2引数に1文字だけ指定する場合に二重引用符でなければならないのが何故なのか分かりません。
分かる方がおられたら教えていただけないでしょうか?

よろしくお願いいたします。

ちなみに以前の質問は
http://oshiete1.goo.ne.jp/qa4386678.html
です。

A 回答 (9件)

>> 第2引数は文字「列」定数でも良いのでは?


>何か認識にずれがあるような気がします
大変、失礼しました。
文字「列」定数と読み違えてましたorz
    • good
    • 2

確かにsizeof('a')が4でsizeof("a")は2になりますね。


私も'a'はchar型で"a"はchar*型だと思いこんでました
勉強になりました。
    • good
    • 0

型による違いです。



'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); /* 一文字しか連結できないよ… */
    • good
    • 1

> >仮に文字定数を渡してもコンパイルはできますが、


> >デタラメですのでまともに動作しません。
> 第2引数は文字定数でも良いのでは?

何か認識にずれがあるような気がします。

char s[10] = "abc";
strcat(s, 'd');

は、まともに動作しませんよね。
    • good
    • 0

>仮に文字定数を渡してもコンパイルはできますが、


>デタラメですのでまともに動作しません。
第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文字、終端などという概念がありません。」
#多少語弊はありますが、こんな感じで覚えとくといいと思います
    • good
    • 0

回答者の間でも若干の混乱が見られるようですので、少し補足します。


質問者さんには若干難しい点もあるかと思いますので、分からない部分は質問してください。

まず、一重引用符で囲まれた文字の並びは文字定数です。一重引用符で囲んだ場合でも、複数文字の並びを指定することができます。
このとき、最初の一重引用符の前に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);

と宣言されるはずです(定義ではありません)。
第二引数には文字列(の先頭要素へのポインタ)を渡さなければなりません。仮に文字定数を渡してもコンパイルはできますが、デタラメですのでまともに動作しません。
    • good
    • 0

Cに置いて文字列というのは文字の配列で表現します。


つまり、 TCHAR*型です。
文字というのはコンピュータにとっては単なる数値です。

例えば'A'==0x41です。

printf("%x\n", 'A');

とすると 41 が表示されますよね。
シングルクォートで囲まれたトークンは単に数値(TCHAR型)に変換
されます。
TCHAR*型を要求する引数に指定することはできません。
    • good
    • 0

" "で囲まれた文字列には最後に文字列の終わりを示す0があります。


'C'は1バイトですが"C"は実は2バイト分の領域を使っています。
strcatの引数は文字列と決まっているので文字列じゃないとだめです
    • good
    • 0

'C'は文字(char)ですね。


"C"は文字列で文字列とは文字の配列(char *)です。

一方strcatは
char *strcat(char *s1, const char *s2);
上記のように定義されていて第2引数にはcharのポインタを要求します。(定義は環境に依存するかも?)
なので連結する文字が1文字でも文字列を指定する必要があります。
    • good
    • 0

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