VC6でプログラム作ってて不思議なことありました。
#define NAME nam
int a = sizeof(NAME);
上記でなぜかaに4が入ります。
3文字なのになぜ4なのですか?
4文字だから。
なぜ4文字かわからないのであれば、C/C++ の入門書を読みましょう。
<string.h>をインクルードして
strlen( NAME ) と sizeof( NAME ) で得られる結果が違うことを
確認しましょう。そしてなぜ違うのかを理解してください。
この場合は、文字数に関係なく4になる気がします。
答えは、nam は const char *型で、その処理系ではポインタのサイズが4だから
> この場合は、文字数に関係なく4になる気がします。
あれ。。。
> #define NAME nam
> int a = sizeof(NAME);
は
int a = sizeof( nam );
なんですよね?
> ポインタのサイズ
文字リテラルはどうなんでしたっけ?
ためしに、
int a = sizeof( name );
にしたら a が 5 になりました。(VC6)
処理系によって違うのかなぁ・・・
REE さん、違う。
sizeof(abcde) は6です。4にはなりません。なってはいけません。
文字列リテラルは char* ぢゃなく char[] だろうから、
sizeof(なにか) は 「なにかを格納するのに必要な配列の大きさ」が返ってくんでねぇが?
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[] でしょうか。
早速ぢっけん:
#include <iostream>
int main() {
std::cout << typeid(name).name() << std::endl;
}
実行結果:
char const [5]
…だと、VC++7はゆってます。
なんとなくわかった気がします
すいません。
間違っていたようです。
>文字列リテラルは char* ぢゃなく char[] だろうから、
勉強になりました。
そういう型なら、以下の二通りが通るのも自然ですね。
char *p = abc;
char s[] = abc;
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 に戻る。
追試。
επιστημηさんのコード、VC++6sp4,非MFC,C++では、
char [5]
でした。
# typeid演算子って初めて知りました。