sizeofが多い

[戻る]
菱王 2005/07/29(金) 10:24:05
VC6でプログラム作ってて不思議なことありました。

#define NAME "nam"

int a = sizeof(NAME);

上記でなぜかaに4が入ります。
3文字なのになぜ4なのですか?

tetrapod 2005/07/29(金) 10:27:27
4文字だから。
なぜ4文字かわからないのであれば、C/C++ の入門書を読みましょう。

Blue 2005/07/29(金) 10:31:55
<string.h>をインクルードして

strlen( NAME ) と sizeof( NAME ) で得られる結果が違うことを
確認しましょう。そしてなぜ違うのかを理解してください。

REE 2005/07/29(金) 10:36:07
この場合は、文字数に関係なく4になる気がします。

答えは、"nam" は const char *型で、その処理系ではポインタのサイズが4だから

Blue 2005/07/29(金) 10:41:24
> この場合は、文字数に関係なく4になる気がします。
あれ。。。

> #define NAME "nam"
> int a = sizeof(NAME);
は
int a = sizeof( "nam" );
なんですよね?

> ポインタのサイズ
文字リテラルはどうなんでしたっけ?

ためしに、
int a = sizeof( "name" );
にしたら a が 5 になりました。(VC6)

処理系によって違うのかなぁ・・・

tetrapod 2005/07/29(金) 10:42:24
REE さん、違う。
sizeof("abcde") は6です。4にはなりません。なってはいけません。

επιστημη [E-Mail] 2005/07/29(金) 10:51:43
文字列リテラルは char* ぢゃなく char[] だろうから、
sizeof("なにか") は 「"なにか"を格納するのに必要な配列の大きさ」が返ってくんでねぇが?

n 2005/07/29(金) 10:51:59
VC6だと

const char* s="";
size_t c=sizeof(s);

で c==4に、

const char s[]="";
size_t c=sizeof(s);

で c==1に、

#define s ""
size_t c=sizeof(s);

で c==1になりました。


ということは "" の型は const char[] でしょうか。

επιστημη [E-Mail] 2005/07/29(金) 10:56:16
早速ぢっけん:

#include <iostream>

int main() {
  std::cout << typeid("name").name() << std::endl;
}

実行結果:
char const [5]

…だと、VC++7はゆってます。

菱王 2005/07/29(金) 11:21:01
[[解決]]
なんとなくわかった気がします

REE 2005/07/29(金) 13:37:58
すいません。
間違っていたようです。

>文字列リテラルは char* ぢゃなく char[] だろうから、
勉強になりました。

そういう型なら、以下の二通りが通るのも自然ですね。

char *p = "abc";
char s[] = "abc";

tetrapod 2005/07/29(金) 16:20:40
ROM読者のための蛇足など。

char *p="abc"; は
ポインタ変数 p と配列 "abc" があり、この場合、配列が先頭要素へのポインタに成り下が
る。
つまり p は文字列リテラルの先頭要素 'a' を指す。
本来 "abc" は const char [] なので char * に変換しようとすると const が落ちるが
文字列リテラルに限り、互換性のために「非推奨の機能」として認められている。

char s[]="abc"; は
配列 s と配列 "abc" があって、後者は前者の初期化子として用いられている。
この場合 "abc" はポインタに成り下がることなく初期化子として s の初期化に使われる。
つまり上記コードは char s[4]; memcpy(s, "abc", 4); とほぼ同義。

なので
p[0]='A'; は "abc" の 'a' を書き換えようとするのに対して
s[0]='A'; は s の最初の要素を書き換える。

文字列リテラルは const char [] なので、これを書き換えようとすると未定義動作、
つまり p[0]='A'; は誤ったプログラムであり、エラーが発生する。
 (VC++ ではコンパイルオプション -GF が必要)

これに対し char s[] は const ではない、ごくふつーの「変数」なので、
これを書き換えようとする s[0]='A'; は正しいプログラムである。
もし仮に s が自動変数なら再初期化が行われる時点で "abc" に戻る。

RAPT 2005/07/30(土) 01:26:51
追試。
επιστημηさんのコード、VC++6sp4,非MFC,C++では、
  char [5]
でした。

# typeid演算子って初めて知りました。

古いスレッドには追加発言できません。