環境 WIN98 VC++6.0 MFC にて
いつもお世話になります。
先日質問したばかり(QNo.682705)なのですが、やはり納得できないことがあるのでお願いします。
分かっている人からみれば、おかしな疑問と思われるかも知れませんが、私にとっては素朴に疑問が生じてしまいます。
***************************
以下2つのコードのうち、<A>は文法的にOKで<B>がNGな理由が知りたいです。
<A>
CString* str ;
str = (CString*)m_array.GetAt(i) ; //OK
<B>
CString* str ;
str = (CString*)("999") ; //NG
<A>は、m_arrayの要素にCString*を入れていて、初めて成り立つ式です。
と教わりましたが、むしろ私にはCString*以外が入っているため、CString*のキャストしていると思える。
CString*が入っているのなら、キャストする必要は無いのではないでしょうか?
ネット上で見つけたコードなため、実際の値やm_arrayの宣言がどうなっているかは確認出来ません。
そして、<A>がおかしなコードでは無いという大前提にたつと、<A>は別の表現をすると
<A>
str = (CString*)(CString*以外のポインタ) ;
となります。
そうすると<B>のコードも、"999"は999の文字列が入っているアドレスを指すポインタであるという考えが正しいとすると、
<B>
str = (CString*)(999をさすポインタ) ;
となり、おかしなコードではないと思えるのですが、考え方のどこがおかしいのでしょうか?
**************************
以下のことを教わった上であえて聞いています。
str = (CString*)("999"); は、リテラル文字列をつっこもうとしています。
リテラル文字列とCStringはまったく別物です。
No.2ベストアンサー
- 回答日時:
ポインタからポインタへのキャストは
(継承が関係しない限り)
コンパイラに型情報を通知するだけで
実質何も実行されません。
なのでキャストが有効かどうかは
プログラマにかかっています。
<A>の場合
MSDNには
CPtrArray クラスは、void ポインタの配列をサポートします。
とあります。つまり、<A>のm_arrayの要素は
CStringへの実体を指すvoid型へのポインタです。
なので、このキャストは本来CStringであるものを
CStringにキャストして保存しています。
<B>の場合
char*からCString*へ変換しています。
つまり、charがあるところにCStringがあるように
認識しろとコンパイラに命令しています。
コンパイラは渋々CStringにみなしますが
実行してもうまく動作するはずがありません
(char*からCStringへのキャストは
CStringのコンストラクタが働くのですが)
回答ありがとうございます。
キャストについて100%誤解していました。
>har*からCString*へ変換しています。
>つまり、charがあるところにCStringがあるように
^^^^^^^^^^^^^^^^
>認識しろとコンパイラに命令しています。
今までずっとどうしてこんな手品のようなことが出来るのか不思議でした。が、私が勝手にそう思い込んでいただけでこんなことは出来ないのですね。
今回の一連の疑問のなぞがようやく解けた気がします。
(まだ、言い切る自身がない)
No.4
- 回答日時:
#1 の「お礼」と,#3 の uyama33 さんのアドバイスに関してです。
> 一方、"999"は999の文字列が入っているアドレスを指すポインタであると思っていたのですが、
> これがそもそも大きな勘違いなのでしょうか?
このこと自体は正しいです。(だからといって,CString* にキャストしても良いという意味ではないです)
# 厳密には,"999" の型はポインタではなくて配列ですが。
"999" と書いただけで,コンパイラが「どこか」にメモリを確保して,
999 という文字列(実体は char 型の配列,\0 で終端)を置きます。
この文字列の寿命はプログラムの開始から終了までです。
回答ありがとうございます。
>このこと自体は正しいです。
あぁ良かった。これが正しくないとまた新たな悩みが生じるとこでした。
>("999" と書いただけで,コンパイラが「どこか」にメモリを確保して,
これもメモリ確保することが正しいのですね。
あぁ良かった。
補足ありがとうございます。
No.3
- 回答日時:
一方、"999"は999の文字列が入っているアドレスを指すポインタであると思っていた
の部分ですが、
どの段階で、 999の文字列が入っているメモリーが確保されてそのアドレスが決定されるのか
について誤解されていると思います。
ソースコードの中に
"999"
とあるだけではだめで、
char bbb[4] = "789";
とすると、このコードが実行された段階で、
メモリー上に確保され、
bbb はその先頭の7を指します。
ただし、
この、bbbを CString* に変換しようとすると
問題が起きます。
CString は、クラスですので
それへのポインターは、メモリー上に確保された
オブジェクトの先頭を指します。
果たして、このオブジェクトの先頭は
char の配列からなっているのでしょうか?
オブジェクトの中で文字列が、どの場所に
(先頭から何バイト目に保存されているか)
どのようなかたちで保存されているかはわかりません。
(ユニコードなのか、シフトジスなのか、1文字が8ビットなのか16ビットなのか)
ですから、
bbb を CString* に変換することは無謀です。
CString str ;
str = CString("999");
とすれば、自動的な型変換によって、
オブジェクト内の適当な位置に、
適当なデータ型で保存されます。
No.1
- 回答日時:
(A)のm_array.GetAt(i)は、もともとCString*を返すのかもしれません。
つまりこのとき、キャストは本来不要です。なぜ不要なキャストをするのかといえば、ソースコードの可読性のためです。
他人のソースでは「実際の値やm_arrayの宣言がどうなっているかは確認出来ません」ということが、あります。その場合でも、CString*が返されることが伝わります。
回答ありがとうございます。
調べたところm_array.GetAt(i)はvoid *を返していたのでキャストが必要だということが分かりました。
一方、"999"は999の文字列が入っているアドレスを指すポインタであると思っていたのですが、これがそもそも大きな勘違いなのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- C言語・C++・C# str[j++]の意味 2 2022/08/30 16:20
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- その他(プログラミング・Web制作) pythonにおける単方向リストの実装について 4 2022/07/13 12:34
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- Visual Basic(VBA) エラー処理 3 2022/04/11 14:58
- Excel(エクセル) PHPプログラムをエクセルに張り付けると検索ボックスがでてくる! 3 2022/05/08 07:10
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
セグメントエラー
-
fopne で失敗する原因
-
c言語で任意のファイルから読み...
-
C言語でのconstを返す関数
-
【なぜポインタを使うのか】
-
main(int argc,char **argv[])...
-
nullポインタを逆参照とは?
-
構造体を値で渡す良い点はあり...
-
【C言語】戻り値が構造体の関数
-
関数ポインタの高速化のメリット
-
自作strcat
-
アプリを32bitから64bit移行
-
popenした子プロセスのプロセス...
-
C言語によるメモリ読み書き
-
JavaとC++はどう似てる?
-
ハンドル、アドレス、ポインタ...
-
c言語のポインタについて初心者...
-
キャストについて str = (CStr...
-
リトルエンディアンというもの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
fopne で失敗する原因
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
戻り値で構造体を返すことは可...
-
LPSTR型の初期化について
-
Cで作成したDLL関数をVBから呼...
-
ExcelVBAでのkernel32(64bit)
-
アプリを32bitから64bit移行
-
構造体とfscanf
-
c言語で任意のファイルから読み...
-
デバイスハンドルとは?
-
main(int argc,char **argv[])...
-
基本アルゴリズムの『返す』の...
-
コンストラクタでnewを失敗した...
-
C言語の関数と配列に関する質問
-
参照型で受け取った引数をポイ...
-
ハンドル、アドレス、ポインタ...
-
DLL<->VB間での受け渡し(文字...
おすすめ情報