• 締切済み

ポインタ演算がうまくできません

以下のソースを実行すると、直値でアドレスをしていするのは うまくアセンブラに展開され、意図するアドレスを取り出す ことが出来るのですが、変数でアドレス演算させると意図する アドレスが取得できません。  何か記述がおかしいのでしょうか? ご存知の方宜しくお願い致します。 char const test_tbl[] = { -3, -2, -1, 0, 1, 2, 3, 4, 5}; unsigned char *ptr; unsigned char work; #define STA_OFFSET (&test_tbl[3]) void main( void) { // 適切なポインタが取得できる ptr = (STA_OFFSET + 3); // ポインタが取得できない。 work = 3 ptr = (STA_OFFSET + work); }

みんなの回答

回答No.5

こういった質問は、 「~」という方法で確認したら、「~」という結果を意図したにもかかわらず、「~」という結果だったと、そこをはっきり書かないと、回答はかなり難しいと思います。 どういう「意図しない」結果だったかは、解決の大きなヒントになるわけですが。

全文を見る
すると、全ての回答が全文表示されます。
  • a-saitoh
  • ベストアンサー率30% (524/1722)
回答No.4

興味深いですね.私の環境では再現しませんでした. 使っているコンパイラは何でしょうか? ざっとみて怪しいのは,wkがunsignedcharであること. ポインタに unsigned charを加えるときの自動型変換で トラブルが起きているのかも知れません.wkをintに変えたら 直りませんか?

全文を見る
すると、全ての回答が全文表示されます。
  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.3

同じものを表すときは、同じ型を使いましょう(特別な理由が無い限り) どうしても同じ型で宣言できないときは型キャストもしょうがないでしょう。 test_tblをconst unsigned charに、とptrをconst unsgned char *に変えたら動きましたよ。 確認:VC++6 typedef unsigned char BYTE; const BYTE test_tbl[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8'}; const BYTE *ptr; BYTE work; #define STA_OFFSET (&test_tbl[2]) int main(int argc, char *argv[]) {  ptr = STA_OFFSET + 1;  printf("%c\n",*ptr);  work = 2;  ptr = STA_OFFSET + work;  printf("%c\n",*ptr);  return 0; }

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

test_tbl を const char [] で定義してるんだから, ポインタの ptr は const char * じゃないと. 記述としておかしいのはそこだけ. それでもダメなら, アセンブラレベルでどうなっているかチェックするか, コンパイラのバグを疑うかですね.

tv_junky
質問者

補足

失礼しました。 >> ポインタの ptr は const char * じゃないと こちらも質問時の記載ミスです。 実際にはTypedefして使用しているのですが、 const char * と同様の宣言をしております。 使用しているコンパイラでは、記憶型指定子というものを つかって記述しています。

全文を見る
すると、全ての回答が全文表示されます。
  • Trick--o--
  • ベストアンサー率20% (413/2034)
回答No.1

・型が悪い? charは「文字型」です。整数を扱うなら「int」にしましょうか。 ・セミコロンが無い work=3 の行に;がありません。 ・const constの有無で弾かれます。STA_OFFSETを型キャストすれば通りましたが…… 確認環境:VC++6

tv_junky
質問者

補足

説明不足ですいません。 ・セミコロンが無いのは質問時に打ち直ししたためです。 実際はあります。書き間違いました。 ・型は1Byteデータのテーブルです。実際はunsigned charを 予定しています。 ・const は ROMに割り付けたいのでつけています。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ポインタ代入のoperator演算子のオーバロードの仕方

    下記、unsigned char*型を自前のクラスで作成した場合 どの様なoperator演算子が必要になりますでしょうか。 目的は、下記compにアクセスした回数をカウントさせたい為です。オーバロード関数の内部にカウンタを持たせたい。 unsigned char* と互換性を持たせるため、クラスはポインタとして定義して使用したいと思っています。 unsigned char comp[1000] ; int main( int, char** ){ unsigned char *v_ptr ; v_ptr = &comp[0] ; <- ここ *v_ptr = (unsigned char)100 ; <- ここ *v_ptr++ = *sw_ptr++ ; <- ここ return 0; } 下記のように使いたい unsigned char comp[1000] ; int main( int, char** ){ count * v_ptr ; v_ptr = &comp[0] ; <- ここ *v_ptr = (unsigned char)100 ; <- ここ *v_ptr++ = *sw_ptr++ ; <- ここ return 0; } class count{ public: unsigned char* operator*() { return ptr ; }  v_ptr& operator=()?? private: unsigned char* ptr ; } ; 色々調べてみましたが、自前クラスが右辺にある時のポインタ、アドレスオーバロードはありましたが、左辺のポインタ代入、値代入を見つける事が出来ませんでした。

  • ポインタの演算について

    ポインタの演算に関して質問させて下さい。 unsigned long型のポインタに+1すると実際のアドレスは+4になってしまいます。 ex) unsigned long *a: 0xb7de1000 a+1 : 0xb7de1004 よって、アドレス+1(上では0xb7de1001)に値をかきこみたいのですが、 *(a+1)=ffffffffとすると 0xb7de1004に値が書きこまれてしまいます。 32bitの値を書きこみたいので現在は char *a: *(unsigned long*)(a+1)=ffffffff としているのですが、キャストを使わずに同様のことを実現することは可能でしょうか? ご教授よろしくお願いします。

  • C言語のchar ポインタ

    char ポインタで分からないことがあるのですが・・↓ ------ { char array[7]; char *ptr; strcpy(array, "abcdef"); ptr = &(array[0]); printf(" array = %s\n ptr = %s\n", array, ptr); } ------ これを実行して, array = abcdef になるのは分かるのですが ptr = abcdef  になるのはどうしてでしょうか。 ポインタはアドレスを指し示すものですよね。だったら ptr = にはarray[0]のアドレス('a'のアドレス)が入るのでは 無いんでしょうか・・?

  • ポインタについて

    C言語のポインタについての質問です。 main関数内が int main(void){ int data[10],datum,index,result,*ptr; ptr=data; ~~以下略~~ となっています。 これの「ptr=data;」を配列要素を用いて書き直しなさいという問題があるのですが、問題の意図がよくわかりません。 私としては「ptr=&data[0];」と書き変えろという意味なのかと思ったのですが、問題の意図に適しているでしょうか? 私の考えが間違っていましたら、問題の意図について指摘して下さい。 宜しくお願いします。

  • delete演算子オーバーロードについて

    delete演算子オーバーロードする際、 デストラクタが呼び出される困っています。 例えば、 void* operator new(size_t size, const char* filename , int line , const char* funcname ); とnew演算子をグローバル定義します。 すると、意図通りnew演算子がCallされ、対応するコントラクタも 問題なくCallされます。 そして、上記new定義にペアとなるdelete演算子もグローバル定義します。 void operator delete(void* pMem, const char* filename , int line , const char* funcname ); 通常どおりdeleteで呼び出してしまうと、標準のdeleteがcallされてしまうため、 #define MYELETE(s) operator delete( (void*)(s) , __FILE__ , __LINE__ , __FUNCTION__ ) 上記のようなカスタムマクロを定義してCallしています。 オーバーロード定義されたアドレスがCallされるところまで、 意図通りなのですが、肝心のデストラクタがCallされません。 型が判明している場合、 単体でデストラクタを明示的に呼び出すことはできますが、 任意のポインタのデストラクタを明示的に呼び出す方法は ありますでしょうか?

  • C言語でのコンパイルエラー

    初心者です。 非常に基本的な質問かもしれませんが、 ご回答いただけたらうれしいです。 void test1(unsigned char* data) { } void test2(unsigned char** data) { } int main(void) { unsigned char data1[6]; unsigned char data2[6][6]; test1(data1); test2(data2); } としてtest1はうまくいくのに、 test2はコンパイルエラーになります。 どっちもポインタになると思うのですが…。 また、unsigned char data2[6][6]を 他の関数の引数とする場合は どうすればよろしいのでしょうか? 宜しくお願いいたします。

  • ポインタ配列の動的確保

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • CHAR型ポインタについて。

    CHAR型ポインタについて。 当方C言語初心者です。 ポインタと文字列の関係分からないことが出てきました。 参考にしている本があり、そのページに下記のソースで「const char *pc1」のポインタ変数を用意して、そこに直接文字列を代入しています。 本来、「char *pc1」はchar型のアドレスを格納するための変数のはずなのに、その変数に文字列を代入してることに疑問を感じました。 この記述の仕方は間違っていないのでしょうか?また、アドレスを格納するための変数「*pc1」に「abcdefg」の文字列はどのようにメモリ上で格納されているのでしょうか? 知ってどうなるの?みたいな質問かもしれませんが、ご教授いただけると幸いです。 #include <stdlib.h> #include <string.h> void func(void) { const char *pc1 = "abcdefg"; //←ココ char *pc2 = (char *)malloc( strlen(pc1) +1); if ( pc2 ) { strcpy( pc2, pc1 ); free( pc2 ); } }

  • 関数ポインタについて

    C言語によるUNIXシステムにプログラミング入門という本を読みながらC言語を勉強しています。 しかし、サンプルとして提示された下記の内容の意味がわかりません。 分からない箇所が「関数ポインタ」と呼ばれるものがついているということが分かった程度で、どういう意図で記述されているのかがわかりません。 分からないプログラムの処理内容は、ファイル内のデータを16進数で表示するというものです。 分からない箇所を記します。 #include <stdio.h> #define BUFF 17 /*buffer*/ #define ERR -1 /*system call error*/ void usage(void); /*put usage message*/ char *command_name /*command name*/ FILE *fpin; /*file pointer*/ main(int argc,char *argv[ ]){ char *rindex(const char*s,int c); /*末尾から文字列検索*/ void hexdump(void); ... ... } void hexdump(void){ ... ... } void usage(){ ... ... } 不明なのは、main関数の中の char *rindex(const char*s,int c); /*末尾から文字列検索*/ void hexdump(void); です。 Cについて、不明なところが多いので、利用する関数は使う前に宣言しなければいけない程度の理解ですが、そうだとしてもusageメソッドはmain関数の外であるのに、rindexとhexdumpは何故main関数の中で宣言されているのでしょうか。 上記の不明点とは別で、rindexの前にポインタが付いていると思うのですが、hexdumpやusageにはついていません。 知人からは、関数までのポインタを返すとのことでしたが、用途もいまいち理解できません。 全てではなくてもいいので、ヒントをいただけるとうれしいです。 よろしくお願いします。

  • ダブルポインタ?

    下記のような関数が存在し、 最終的には mainで宣言した変数 "a" にDataGetでコピーしたデータを mainで再び使用したいのですが、 下記の方法だとmainに何も帰ってきません。 (NULLのまま・・・) 下記の関数を使用しmainに上手くデータを 引き継ぐためにはどうすれば良いのでしょうか? void Mem(int nSize,void **ptr){ char *tmp; tmp = malloc(nSize); *ptr = tmp; } void DataGet(char *aa,char *a){ int nSize = 5; (void)Mem(nSize,(void **)&a); memcpy(a,aa,nSize); return; } void main(){ char aa[20]; char *a = 0x00; memset(aa,0x00,20); memcpy(aa,"test",4); (void)DataGet(aa,a); /* aデータをここから再び使いたい */ }