• 締切済み

voidについて

voidはデータの定義の無い型であり、代入演算子で代入する場合に、データとして参照するvoid型のメモリの領域は、代入先として参照するvoid以外の型のメモリの領域の型に変換されるという事でしょうか。

みんなの回答

回答No.4

void型は、関数の返値がないという意味のことでしか使いません。 ということで、ご質問の内容は、voidポインタ型(void*)のことだと思いますので、そのつもりで回答します。 まず、voidポインタ型の存在意義は、抽象化と私は思っています。 たとえば、memcpy()関数の場合、プロトタイプは、 void *memcpy(void *buf1, const void *buf2, size_t n); です。 もし、おこでvoidポインタ型が存在しないとします。 memcpy()関数は、引数の種類だけ定義しなくてはいけなくなることは分かっていただけますか? intcpy(), charcpy(), longcpy(),..... ってな具合に、構造体のコピーも考えれば無限に関数が必要になります。 これは明らかに不経済です。 そこで、型が決定していない、抽象化したvoidポインタ型が必要になります。 C#でのジェネリック型と似たようなものです。 次に、void*からのキャストですが、実行時には何もやっていません。 キャストが行われたとき、メモリ領域になにか手が加わるというわけではないので、 つまり、「メモリ領域が変換される」という表現は違います。 ポインタというのは、変数のアドレスだというのはご承知かと思います。 たとえば、配列を格納するために、malloc()で領域 "array" を確保したとしましょう。 そして先頭が、0x0100だとしましょう。 配列の先頭は0x0100だとわかります。では次の要素は? voidポインタのままでは、それは分かりません。だって、サイズも何も決めない抽象的な存在ですから。 では、intポインタにキャストしたとします。 2番目のアドレスは何になるでしょう? intのサイズが32bitだったとしたら、0x0104ですね。 ここでの+4バイトの足し算はコンパイラが決めています。 代入についても、同様の理由で型が決まってないとできませんね。 アドレス計算や代入の方法などを、コンパイラが決めるためにキャストしている。 これが、キャストをしないといけないという理由です。

回答No.3

んーと・・・。 たぶんmallocの戻り値がvoid *でこれを例えばint *にキャストして 使用することについての質問だと思うのですが。。。。 違ってたらゴメン。 mallocはvoid型のメモリー領域を確保するわけではありません。 引数に与えられたバイト数のメモリー領域を確保するだけでデータ型は規定されません。 戻り値がvoid *なのはvoid *が汎用ポインタと言って、どのポインタ型にもキャストできるからです。 確保された領域をどの型で利用するかは自由です。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

文章の意味が分かりません. 具体的な例は出せますか?

  • morchin
  • ベストアンサー率16% (212/1281)
回答No.1

void型の変数は存在できないと思いますが、仮に出来ても、他の型に代入するとコンパイル時エラーが発生すると思いますが…。例えば、void*型など。

関連するQ&A

  • void*型の配列について

    void* a[2]; void* b = a; void* c[2] = (void *[2])b; error C2440: '型キャスト' : 'void *' から 'void *[2]' に変換できません。 配列型への変換はありませんが、参照またはポインタから配列への変換があります。 void*型にした a を再度void*型の配列に戻すにはどのように記述すればよいでしょうか? 環境はXP(SP3)のVS2008 MFC です。 宜しくお願いいたします。

  • voidは型? それとも修飾子? もし型なら基本…

    ・voidは「型」なのでしょうか? それとも「修飾子」? ■もし型なら ・「基本型(プリミティブ型)」? ・「参照型(オブジェクト型)」? ・あるいはそれ以外?

    • ベストアンサー
    • Java
  • rubyにおける変数と代入のメモリの様子について

    Rubyの変数と代入演算は、メモリについてどのような扱いになっているのでしょうか。2点ほど疑問電があります。 1点目:代入演算は変数にアドレスを渡しているのか RubyLifeのRuby入門のサンプルをみて学習していたところ疑問がわきました。 http://www.rubylife.jp/ini/var/index4.html を参照しながら示します。 str1 = "Tokyo" str2 = str1 str1 << ",Japan" とやるとstr1もstr2も"Tokyo,Japan"となることから、rubyでの代入演算はアドレスを代入してると考えました。 2点目:新しくオブジェクトを代入すると別メモリ領域において、そのアドレスを代入しているのか str1 = "Tokyo" str2 = str1 str1 = "Osaka" とやると、str1は"Osaka"、str2は"Tokyo"となります。 前述の参照渡と考えるとstr2も"Osaka"となっているはずですが違いました。 ここで解説に(引用はじめ) なお2つの変数が同じオブジェクトを指し示した後で、どちらかのオブジェクトに新しいオブジェクトを 代入した場合は、代入された変数が指し示すオブジェクトだけが変更されるだけです。(引用おわり) とあります。 このことをふまえると、新しいオブジェクトを変数に代入するというのは、別のメモリ領域をつくってデータを置いてから、そのアドレスを変数に代入している、と考えました。 これら2つの考えと実際の仕組みは一致しているのでしょうか、と言うのが質問です。 質問点をまとめると、Rubyにおいて変数に対して ・代入演算はアドレスを代入しているのか(Cでいうポインタの扱いなのか) ・新しいオブジェクトを代入するときには、新メモリ領域を作ってデータを入れてそのアドレスを代入しているのか という点です。 ついこの間はじめたばかりの初心者ですが、どうかご教授よろしくお願いいたします。

    • ベストアンサー
    • Ruby
  • void*の型キャストについて質問です

    VisualStudio 2008 を使ってOpenCVを勉強中なのですが、 … IplImage *dst; … cvRelease(&dst); をすると、 error C2664: 'cvRelease' : 1 番目の引数を 'IplImage **__w64 ' から 'void **' に変換できません。(新しい機能 ; ヘルプを参照) と出ます。 確か、void*はどの型からでも明示型キャストは必要なかったと思うのですが、これはVisual Studio 2008 の仕様ですか?

  • Voidポインタで受け取った変数の型を調べる方法

    あるライブラリの関数を利用しようとしたのですが、その関数の引数にVoidポインタがあり、どういう型のデータを格納したのかわかりません。このポインタのアドレスに格納されたデータの型を調べる関数なり方法なりというのはあるのでしょうか。 Voidポインタというのは型を問わずに受け取れるというのは利点ですが、受け取ったものがあらかじめなんだかわからない場合はどうするのでしょうか。よろしくお願いします。

  • ()の役割について

    以下は、()の定義として正しいですか? 定義1:優先順位について、()内にある演算子の方が高くなる。 例えば、 「n=(10+10)/10;」は、本来は除法のほうが優先順位が高いから10/10という計算式から行うが、()により先に10+10が計算され、それから、20/10が計算され、nは2となる。 結合の規則については、()を用いるとその結合の規則の逆になる。 例えば、 n=80/10/1/(20/5);は、()が無ければ左から計算されるが、()があるから、「(20/5)」から計算され、あとは結合の規則通り左から計算されるから、nは2になる。 定義2:「キャスト演算子」としての役割がある。具体的には、大きいデータ型から小さいそれへの型変換を可能にし、「データが失われる可能性をプログラマが承知している旨」を明示する「明示的な型変換」の役割がある。

    • ベストアンサー
    • Java
  • voidポインタをハンドルへ

    voidポインタをハンドルへ 今、Form1でlogBoxというTextBoxを作成し、Form1.h以外ののソースからでも、エラーが出た場合そこにLogが吐き出されるようにしようとしています。 //clrres.h void *LOGBOX; void OutText(TextBox^ b,String^ s); extern inline void OUTPUTLOG(String ^s); //clrres.cpp #include "stdafx.h" #include"clrres.h" void OutText(TextBox^ b,String^ s){   b->AppendText(s+L"\r\n");   b->SelectionStart = b->Text->Length;   b->ScrollToCaret(); } inline void OUTPUTLOG(String ^s){   OutText((TextBox^)LOGBOX,s); } //Form1.hのForm1コンストラクタ内 System::IntPtr ptr=logBox->Handle; LOGBOX=ptr.ToPointer(); とすれば、簡単に、Logを書き出せるようになるかと考えたのですが、 error C2440: '型キャスト' : 'void *' から'System::Windows::Forms::TextBox ^' に変換できません。 と出てきます。 どの様にすれば、出来るようになるでしょうか? 宜しくお願いします。

  • C言語の副作用に関する未定義

    C言語で副作用を持つ演算を含む場合は、その副作用が実行されるタイミングが未定義となっているようですが、 以下のコード int a[10]; int i; while (i < 10) a[i++] = i; では、 a[i++] = i; の代入演算子(=)の結合規則が右から左であるため、aのインデックスとしてiが参照されるよりも早くiの値を代入しているため、未定義にならないと思うのですが、実際はどうなのでしょうか? (a[i] = i++; の場合は完全に未定義になる。) 実際にこのようなコードを書くことは無いと思いますが、気になったもので。 もしご存知の方がおいででしたら教えていただけないでしょうか。 よろしくお願いします。

  • structでvoid*型を利用して中身を動的に変化させる

    構造体の中にvoid*型のポインタを作り、そこの中身を替えることでデータを変えたいと思っています。 例 struct DATA{ void* p; } struct PROF_1{ char* name; int age; } struct PROF_2{ char* name; int age; int level; } void main(){ struct DATA data; struct PROF_1 p1={"HATOYAMA", 60}; struct PROF_2 p2={"OBAMA", 60, 1}; data.p = p1; printf("Name[%s] Age[%d]\n", (PROF_1)(data.p)->name, (PROF_1)(data.p)->age); data.p = p2; printf"Name[%s] Age[%d] Lv[%d]\n", (PROF_2)(data.p)->name, (PROF_2)(data.p)->age, (PROF_2)(data.p)->level); } このような感じで構造体の中にあるvoid*型のポインタの参照する場所を変えるだけで構造体の中身を変化させることが出来ないでしょうか?

  • 参照なバリアント

    VB熟達者というよりは、VBマニアな方々に質問です。 Sub Hoge(A) A = 6 End Sub Sub Main() Dim N As Long Hoge N Debug.Print N End Sub このコードを実行して "6" が出力されるのは明白です。 Hogeはバリアントの参照を取るにも関わらず、LongのNを渡してそのNに6を入れてくれました。 これは、VBが引数を渡す時点で変数A用のメモリ領域をかってに確保し、Nという変数の参照型を作ったということの証拠になります。 実際、DLLでAPIを用意して、バリアント構造体のVarTypeを調べたところ、未知の16387という数値が現れました。 これは、MSDNライブラリを見たところ、VT_LONG Or VT_BYREFのようです。 このように、VBでも参照型は存在していますが、隠蔽されています。 そこで、参照型をもっと自由に使いたいと思い、参照型を作るAPIを作ってみました。 しかし、=演算子で代入しようとしたところ、参照が解除されて通常のバリアント型に戻ってしまいます。 ただし、もともとある変数の参照であるバリアント変数を別の変数の参照に変えたもののときは、参照先に代入してくれました。 どうやらVBはケチなようで、VBが内部で引数として作った参照変数以外は、参照している先に代入はしてくれないようです。 この障害を乗り越える方法を思いついた方、ぜひ教えてください。