sizeofが多い – プログラミング – Home

通知
すべてクリア

[解決済] sizeofが多い


菱王
 菱王
(@菱王)
ゲスト
結合: 19年前
投稿: 2
Topic starter  

VC6でプログラム作ってて不思議なことありました。

#define NAME nam

int a = sizeof(NAME);

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


引用未解決
トピックタグ
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

4文字だから。
なぜ4文字かわからないのであれば、C/C++ の入門書を読みましょう。


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

<string.h>をインクルードして

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


返信引用
REE
 REE
(@REE)
ゲスト
結合: 23年前
投稿: 240
 

この場合は、文字数に関係なく4になる気がします。

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


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

> この場合は、文字数に関係なく4になる気がします。
あれ。。。

> #define NAME nam
> int a = sizeof(NAME);

int a = sizeof( nam );
なんですよね?

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

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

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


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

REE さん、違う。
sizeof(abcde) は6です。4にはなりません。なってはいけません。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

文字列リテラルは char* ぢゃなく char[] だろうから、
sizeof(なにか) は 「なにかを格納するのに必要な配列の大きさ」が返ってくんでねぇが?


返信引用
n
 n
(@n)
ゲスト
結合: 21年前
投稿: 90
 

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[] でしょうか。


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 21年前
投稿: 600
 

早速ぢっけん:

#include <iostream>

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

実行結果:
char const [5]

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


返信引用
菱王
 菱王
(@菱王)
ゲスト
結合: 19年前
投稿: 2
Topic starter  

なんとなくわかった気がします


返信引用
REE
 REE
(@REE)
ゲスト
結合: 23年前
投稿: 240
 

すいません。
間違っていたようです。

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

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

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


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

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
 RAPT
(@RAPT)
ゲスト
結合: 22年前
投稿: 310
 

追試。
επιστημηさんのコード、VC++6sp4,非MFC,C++では、
  char [5]
でした。

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


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました