ポインタのアドレスについて
- char型の配列を直接Fooにキャストして利用したいが、Foo構造体のdataにint型の配列として利用することはできるか
- foo->data=new int**[2]としてしまうとbytData[8]が破壊されてしまうため、別の方法を模索している
- foo->data = (int**)&bytData[8]の部分がうまくいかないので、そもそもこの方法は無理だと考えている
- ベストアンサー
ポインタのアドレスについて
こんばんわ。 以下のようなchar型の配列を直接Fooにキャストして利用したいのですが、 Foo構造体のdataにはint型の配列として利用したいのですが可能でしょうか? char型の配列を直接Fooにキャストした後にdataの部分を操作すれば 可能かと思っていたのですがうまくいきません。 foo->data=new int*[2]; としてしまうとbytData[8]が破壊されてしまいます。 このような方法は無理でしょうか? struct Foo { int tenmp ; int count ; int** data ; } ; char bytData[ 4 + 4 + 8 ] = { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, } ; int _tmain(int argc, _TCHAR* argv[]) { Foo* foo ; foo = reinterpret_cast< Foo* >( bytData ) ; foo->data = (int**)&bytData[ 8 ] ; // ここがダメ。 printf( "%d\n", *foo->data[ 0 ] ) ; // 3 printf( "%d\n", *foo->data[ 1 ] ) ; // 4 return 0 ; }
- TeijigoTeatime
- お礼率93% (268/286)
- C・C++・C#
- 回答数4
- ありがとう数20
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
ポインタと配列の違いを、もういちどちゃんと勉強しなおした方がいいと思います。 foo = reinterpret_cast< Foo* >( bytData ) ; の後では アドレスbyData : foo->tenmpの領域 : 値=0x00000001 アドレスbyData+4 : foo->countの領域 : 値=0x00000002 アドレスbyData+8 : foo->dataの領域 : 値=0x0000000400000003 となっています。 dataは int**ですから、 data[0] は 「dataの値が示すアドレスにある、 int *の値」 です。 アドレス 0x0000000400000003 : foo->data[0]の領域: 仮に 0x1000000000000000 とする *foo->data[ 0 ] とすれば、「上記のアドレスが示すアドレスにある、intの値」となります。 アドレス 0x1000000000000000 : *foo->data[ 0 ]の領域: 仮に 0x000000010 とする → printf( "%d\n", *foo->data[ 0 ] ) ;// 0x000000010 = 16 foo->data=new int*[2]; では、 foo->dataの領域に、 new int*[2]の結果が代入されます。 new int*[2] で 0x2000000000000000 が確保されたとすると アドレスbyData+8 : foo->dataの領域 : 値=0x2000000000000000 よって > bytData[8]が破壊されてしまいます というのは当り前の現象です。 struct Foo { int tenmp ; int count ; int data[2] ; } ; と配列で宣言すると、dataとして int2個分の領域がFooの中に確保されます。 アドレスbyData : foo->tenmpの領域 : 値=0x00000001 アドレスbyData+4 : foo->countの領域 : 値=0x00000002 アドレスbyData+8 : foo->data[0]の領域 : 値=00000003 アドレスbyData+12 : foo->data[1]の領域 : 値=0x00000004 となる *** 可能性はあります *** ですが ○sizeof(int)がいくつになるか? ○メンバがこの順番に並んでいるか? ○メンバが隙間無く並んでいるか? ○3,0,0,0 は 3なのか、0x03000000 なのか、それ以外なのか といったことが、コンパイラ,CPU,OS,設定等によって違ってくることがあります。 精通している人が理解した上で、十分に注意して使う(でも使いたくない)裏技です。 // 特に、C++ではこれでは問題になることがあります
その他の回答 (3)
- Tacosan
- ベストアンサー率23% (3656/15482)
いやいや, int が 4バイトかつ 4バイトアラインと仮定すれば foo->data=new int*[2]; で「bytData[8]が破壊される」のは明らかでしょ? むしろ何をどう考えたら「破壊されない」と思えるのかが知りたいよ. 端的にいえば int x = 1; x = 2; とやったときに「x が 1 のままでないのはおかしい」って思うか, ってことなんだけど.... ちなみに「メンバがこの順番に並んでいるか?」だけは (その場合) 規格で保証されているはずです>#3. 今の規格 (C++11 and/or C++14) を持っていないの「はず」としておくけど, C++98 でそうなってるしここを変える必然性はないと思うので今でも大丈夫じゃないかな. ほぼ「メンバが隙間無く並んでいるか?」も大丈夫だとは思うけどこっちが成り立つ必然性はない.
お礼
早々のご返答ありがとうございます。 とても参考になり、改めて勉強不足を実感しました。 また環境を書いていませんでした。 お手数をおかけして申し訳ありません。
- redfox63
- ベストアンサー率71% (1325/1856)
やるとすれば Fooの定義を struct Foo { int tenmp; int count; int* data[1]; }; といった具合に定義してやる方法だと思います Foo* foo; foo = einterpret_cast< Foo* >( bytData ); // これは不要 // foo->data = (int**)&bytData[ 8 ] ;// ここがダメ。 printf( "%d\n", *foo->data[ 0 ] ) ;// 3 printf( "%d\n", *foo->data[ 1 ] ) ;// 4 WinAPIで使う BITMAPINFOのような使い方です …
お礼
早々のご返答ありがとうございます。 ビットマップを読み込んだことがありましたのでなるほどと思いました。
関連するQ&A
- 関数に配列を渡した場合にサイズが
C言語初心者です。 以下のように関数に配列を渡した場合、サイズが変わってしまうのは何故でしょうか。 #include "stdafx.h" void fanc(char [3]); int _tmain(int argc, _TCHAR* argv[]) { char a[] = {'a','b','c'}; printf("%d\n",sizeof(a)); // aのサイズ 3 fanc(a); return 0; } void fanc(char b[]){ printf("%d\n",sizeof(b)); // bのサイズ 4 }
- ベストアンサー
- C・C++・C#
- _TCHAR*での引数の読み込み
VC++2010での、通常の #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { return 0; } のウィザードを使って、arvg[1]やargv[2]に引数を与えて、本体内で通常のCで使う printf("%s\n", argv[1]); や fopen(argv[1], "r"); を使いたいのですが、引数の型が_TCHAR*になっているため文字がそのまま使えません。 int main(int argc, char *argv[]) で使えば問題なく使えるのですが、デフォルトのウィザードを使った時の使い方を知っておきたいのです。 御経験のある方、御教示お願い致します。
- ベストアンサー
- C・C++・C#
- ポインタのポインタ
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char **argv){ int i; if(argc != 2) { fprintf(stderr, "Usage: %s vector\n\tEx: %s 11110000\n", argv[0], argv[0]); return 1; } for(i=0;i<8;i++){ if(**argv == '0'){ printf("%d\n",i); } else{ printf("A%d\n",i); } argv++; } return 0; } コンパイルして./a.exe 10010011などと入力しても A0 A1 Segmentation Faultとなります。 どうすれば、 A1 0 ・・・省略 for文で回した8回分、出力が可能になるのか教えてください。 初歩的な質問ですいません。
- ベストアンサー
- C・C++・C#
- C言語のprintfで桁数をそろえる
次ので桁数をそろえると書いてあったけどやってみたらできなかった。 コンパイラはMS visual c++バージョンはおそらく7.1.3019 #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { int a; scanf("%d",&a); printf("a=%3d\n",a); return 0; }
- ベストアンサー
- C・C++・C#
- 実行ファイルのメモリ上のアドレスについて
実行ファイルのメモリ上のアドレスを以下の様に 書いて確かめましたがこのやりかたであっていますか? (=exeファイルがメモリ上に読み込まれているアドレス) また、実際にアドレスが表示されるのですが、このアドレスをみて 実際のメモリ本体のどこにロードされているかを理解する 必要はあるでしょうか? カーネルのプログラミングをしているときは必要? int _tmain(int argc, _TCHAR* argv[]) { printf("%p\n",_tmain); return 0; }
- ベストアンサー
- C・C++・C#
- 文字配列から数値への変換
MicrosoftのVisual-Studio 2005を使っています。 C/C++については、ほぼ素人で、困っています。 下記のような簡単なソースで、 456 012 678 を表示するようにしたいのですが、できなくて困っています。 最初の 123 789 345 は下記のソースで表記できたのですが、どうすればよいの でしょう? 数値をわざと文字列で読み込んで、これを 数値に変換しているのでややこしいのかもしれませんが、 できればこれでやりたいので、申し訳ありませんが、教えていただ けないのでしょうか。よろしくお願いします。 #include "stdafx.h" #include "stdlib.h" char str[3][200] = { "123 456", "789 012", "345 678" }; int _tmain(int argc, _TCHAR* argv[]) { int a[10]; for (argc = 0; argc < 3; argc++){ a[argc] = atof(str[argc]); printf("%d\n", a[argc]); }; return 0; }
- 締切済み
- C・C++・C#
- C言語のフローチャート
昨日に引き続き失礼します。下記のプログラムを作成したのですがフローチャートは、どのように書けばいいのでしょうか? #include "stdafx.h" #include <stdio.h> int _tmain(int argc, _TCHAR* argv[]) { char ss[10] = "abcdefg"; char *ssp; ssp =ss; while (1){ if (*ssp ==0) break; printf("文字 *ssp=%c\n",*ssp); ++ssp;} int ary[10] = {1,2,3,4,5,6,7,8,9,10}; int *pt; pt = ary; while (1) { if (*pt == 10) break; printf("値 *pt=%d\n",*pt); ++pt;} return 0; }
- 締切済み
- C・C++・C#
- ポインタについての質問など
(1) プログラム引数を取る時の記述ですが…. (int argc, char *argv[]) (int argc, char **argv) 本によって記述がまちまちなんです. これらはどう違うのでしょうか? 特に後者の解釈の仕方がいまいち分からないので教えてください. 配列になってないように見えるのですが…. (2) 後者の記述(int argc, char **argv)で書かれたプログラムで ./program.exe okwave と引数を取ったとき,okwaveのoからeまでをfor文やwhile文でたどって何らかの処理をしたいのですが,どうすればいいのでしょうか? (3) ポインタには関係ありませんが,Windowsでncursesは使えないのでしょうか?
- ベストアンサー
- C・C++・C#
- 非常に基本的なポインタの使い方
非常に基本的なところだと思いますが、ポインタの理解がうまくなく意図どおりのプログラムが書けません。 何らか引数を渡して(とりあえず文字列"hogehoge"を渡す)、そのポインタaをtest関数に渡して、ちゃんと"hogehoge"が渡っていれば「pass」と出力する 意図なんですが、どうもうまくいっていないようです。 ----------------------------- int test(char* a) { if(a == "hogehoge"){ printf("pass\n"); }else{ printf("ng\n"); } return 0; } int main(int argc, char* argv[]) { char* a = argv[0]; // "hogehoge"を渡しているとします。 test(a); return 0; } ----------------------------- 何がおかしいのか理解ができず、困っています。 ちなみに char* a = argv[0]; の箇所を単純に char* a = "hogehoge"; とした場合はうまくいくので、余計に混乱しております。 どなたか、正解例をご教授いただけませんでしょうか。
- ベストアンサー
- C・C++・C#
お礼
早々のご返答ありがとうございます。 とても参考になます。改めて勉強不足を実感しました。 また環境を書いていませんでした。大変失礼しました。