• ベストアンサー

C言語によるメモリ読み書き

大学の授業でC言語を勉強しています。 下記のようなサンプルを頂いたのですがいまいち理解できません。 このサンプルは正しいのでしょうか。 Q) cpy_ptr_32はポインタ宣言で、"MEMORY_BASE"の"0x08000000"を入力していますが、その後for文中に"i"が入力されています。 これはデータが『0x08000000』、アドレスが『i』と認識して良いのでしょうか? 上記の場合、"MEMORY_BASE"はアドレスなのに、なぜデータとして扱っているのかが理解できません。 経験が浅いため、サンプルが正しいかも判断がつきません。 宜しくお願いします。 ================================================================ #define MEMORY_BASE 0x08000000 //MEMORYのベースアドレス int main (){ unsigned int* cpy_ptr_32 ; unsigned int read_data_32 ; unsigned int i ; while(1) { // Memory TEST cpy_ptr_32 = MEMORY_BASE ; for(i = 0 ; i < 0x2000000 ; i++){ *cpy_ptr_32 = i ; read_data_32 = *cpy_ptr_32 ; if (read_data_32 != i) { printf ("No Good !!! 32 bit access !!! error_address = %x \n" , cpy_ptr_32); WriteRead(LED ,0,0x0); return(0); } cpy_ptr_32++ ; WriteRead(LED ,0,0x1); } ================================================================

質問者が選んだベストアンサー

  • ベストアンサー
  • yphkz4063
  • ベストアンサー率23% (34/144)
回答No.3

#define MEMORY_BASE 0x08000000 //MEMORYのベースアドレス int main (){ unsigned int* cpy_ptr_32 ; unsigned int read_data_32 ; unsigned int i ; while(1) { // Memory TEST cpy_ptr_32 = MEMORY_BASE ; //ポインタにアドレス設定。ポインタ=即値とすることはできます。 for(i = 0 ; i < 0x2000000 ; i++){ *cpy_ptr_32 = i ; //cpy_ptr_32が示すアドレスに00000000~01ffffffの値を書き込む read_data_32 = *cpy_ptr_32 ; //正しく書き込まれているか確認するため読み出し if (read_data_32 != i) //読み出した値と書き込んだ値の比較 { printf ("No Good !!! 32 bit access !!! error_address = %x \n" , cpy_ptr_32); WriteRead(LED ,0,0x0); return(0); //32bitアクセスできないアドレスを表示して終わる } cpy_ptr_32++ ; //ポインタインクリメント WriteRead(LED ,0,0x1); } 例えば、4で割り切れるアドレスにしか32bitアクセスできない処理系がありますが、それを確認するプログラムのようです。 cpy_ptr_32++は、これが1byte加算されるのか4byteなのかは処理系(コンパイラ)によります。 ・・・というのがわたしの解釈です。

golgo20
質問者

お礼

ありがとうございます。 各行に対しての説明、とても参考になります。

その他の回答 (2)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

> このサンプルは正しいのでしょうか。 なんとも言えません。 まず、コメントに // が使われていますが、C99でしょうか? また、main関数のreturn文が省略されているのも、C99だからでしょうか? 処理系を特定しないのであれば、C99でなければ、これらは間違いです。 > これはデータが『0x08000000』、アドレスが『i』と認識して良いのでしょうか? おそらく違います。 > cpy_ptr_32 = MEMORY_BASE ; 整数型をポインタ型に暗黙的に型変換しているわけですが、その場合の結果は処理系に依存します。

golgo20
質問者

お礼

すみません。 "C99"が分かりません・・・。 他にも何種類かあるのでしょうか。

  • venzou
  • ベストアンサー率71% (311/435)
回答No.1

処理系が分からないので、何とも言えませんが、 文法的には間違っていないと思います。 >unsigned int* cpy_ptr_32 ; cpy_ptr_32は unsigned int へのポインタです。 つまり、cpy_ptr_32 にはアドレスが入り、 ポインタが指す先 *cpy_ptr_32 には unsigned int が入ります。 >cpy_ptr_32 = MEMORY_BASE ; これはアドレスの代入です。 >*cpy_ptr_32 = i ; これは、unsigned int の代入です。 * が付いてますよね、これが重要です。 ポインタが指している先に i を代入しています。 この代入で cpy_ptr_32 自体の内容は変化しません。 >これはデータが『0x08000000』、アドレスが『i』と認識して良いのでしょうか? 逆ですね、アドレスが『0x08000000』で、そのアドレスに入っているデータが『i』 1回目の代入が終わった段階のメモリマップのイメージは下記 アドレス  データ   変数名 ????????  08000000  cpy_ptr_32 ????????  00000000  i 08000000  00000000    ← *cpy_ptr_32 ポインタの先 6回目の代入の後は下記のような感じ アドレス  データ   変数名 ????????  08000014  cpy_ptr_32 ????????  00000005  i 08000000  00000000 08000004  00000001 08000008  00000002 0800000C  00000003 08000010  00000004 08000014  00000005     ← *cpy_ptr_32 ポインタの先 これでイメージは伝わるかな?(^^;

golgo20
質問者

お礼

イメージ図まで添えてありがとうございます。 参考にさせて頂きます。

関連するQ&A

  • C言語でファイル読み書きを早くしたい。

    いつも利用させてもらって助かっています。 あるプログラムを作成しているのですが、ファイル入力の部分がネックとなってしまって、全体が使いものにならない状況に陥っています。 たくさんのデータをfread1回で読み込むことにより、読み込み速度はずいぶんと改善されましたが、まだ圧倒的に遅い状況です。システムコールを使いましたが、ほとんど改善されませんでした。 読み込み/書き込みの速度を改善する方法として,SSDメモリを使ったりする方法があると思いますが,プログラムの観点から改善できるところはないでしょうか? 下に、ファイル読み込みの部分だけ記述したコードを添付させて頂いたので、改善できる点があれば、御指摘頂けると助かります。 なお、前提として, (1)データはスタック領域だと不足するので、ヒープ領域に確保 (2)データファイルは改行無しの一連のデータ とします。 ちなみに、環境は OS   : CentOS5.3 memory   : 6GB コンパイラ : gcc です。 よろしくお願いします。 //----------------------------------------------------- //通常バージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; FILE *fp; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } fp = fopen("filein.dat", "rb"); fread( data, sizeof( unsigned char), (int)SIZE, fp ); fclose(fp); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; } //----------------------------------------------------- //readシステムコールを使ったバージョン #include <stdio.h> #include <stdlib.h> #define SIZE (512*1024*1024) //500MB int main(void) { unsigned long int i; unsigned char *data; data = (unsigned char *)malloc(SIZE); if(data == NULL) { printf("メモリが確保できません\n"); exit(EXIT_FAILURE); } int fd; fd = open( "filein.dat" ); read( fd, data, sizeof(unsigned char)*SIZE); close(fd); /* //表示 for( i=0; i<SIZE; i++ ){ printf("%2x", data[i]); } puts(""); */ FILE *fp; fp = fopen("fileout.dat", "w"); fwrite( data, sizeof( unsigned char), (int)SIZE, fp); fclose(fp); free(data); return 0; }

  • C言語に直して下さい

    VisualC++で円周率を求めるプログラムなのだそうですが、 自分はC言語しか使ったことがないため、よく分かりません。 Cでコンパイルできるように直していただけないでしょうか。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 21 #define K 100000 void add(unsigned long a[],unsigned long b[]) { int c = 0, tmp; for (int i = N - 1; i > -1; i--) { tmp = a[i] + b[i] + c; a[i] = tmp % K; c = tmp / K; } } void sub(unsigned long a[],unsigned long b[]) { int c = 0, x = 0; for (int i = N - 1; i > -1 ; i--) { x = c; if (a[i] < b[i] + x ) c = 1; else c = 0; a[i] = c * K + a[i] - b[i] - x; } } void div(unsigned long a[], unsigned long x) { int c=0, tmp; if (x >= K) { printf("Div Error\n"); getchar(); exit(1); return; } for (int i = 0; i < N ; i++) { tmp = (a[i] + c * K) / x; c = (a[i] + c * K) % x; a[i] = tmp; } } void clear(unsigned long a[]) { memset(a,0x00,sizeof(a)*N); } void set(unsigned long a[], unsigned long b[]) { memcpy(a,b,sizeof(a)*N); } void set(unsigned long a[], unsigned long b) { if (b<K) { clear(a); a[0]=b; } } int _tmain(int argc, _TCHAR* argv[]) { unsigned long pai[N], fn[N], gn[N], tmp1[N], tmp2[N]; int i; unsigned long n; clear(pai); clear(fn); clear(gn); clear(tmp1); clear(tmp2); set(fn, 16*5); set(gn, 4*239); for(n=0;n<40000;n++) { div(fn, 25); div(gn, 239); div(gn, 239); set(tmp1, fn); div(tmp1, 2*n+1); set(tmp2, gn); div(tmp2, 2*n+1); if (n%2==0) { add(pai, tmp1); sub(pai, tmp2); }else{ add(pai, tmp2); sub(pai, tmp1); } } for (i=0;i<N;i++) { printf("%5lu ", pai[i]); } getchar(); return 0; }

  • 配列について(C言語)

    配列の要素において一番目の要素以外を0にするプログラムを以下のように作成したのですが(while文を*b != 0という条件で作りたい)、while文内のところが間違っているためだと思われるのですが、うまく実行されません(実行しても何も表示されない)。どのようにしたらいいのでしょうか。または、何かが抜けている、ほかの部分が間違っている等もあるためにうまく実行されないということなのでしょうか。 #include <stdio.h> int main(void) { int a[5] = {5, 78, 2, 9, 0}; int i, *b; b = &a[0]; while (*b != 0){ if(*!=a[0]) *ptr=0; else *ptr=a[0]; } for (i = 0; i < 5; i++){ printf("ptr値 =%d ptrアドレス =%p \n", *ptr, ptr); } printf("\n"); return (0); }

  • C言語のコードについて

    C言語の問題なのですか、作成したのですが内容がわからないです。 コードをわかりやすく解説していただけると嬉しいです。 #include <stdio.h> void printBinary(unsigned char num) { int i ; /*①上位ビットから順に表示する*/ for(i = 7 ; i >= 0; i--) { /*②シフトとマスクを使用しています。*/ printf("%d", (num>>i) &0x01 ); } printf("\n"); } int main(void) { unsigned char num1 = 0xD2;/*11010010*/ unsigned char num2 = 0x5E;/*01011110*/ printf("0xD2 : "); printBinary(num1); printf("0x5E : "); printBinary(num2); return 0; }

  • C言語 教えて下さい!!!

    教えてください!! data01.txt というテストの得点が書き込んであるテキストファイルから得点を読み込んで、得点順に並べ替えて表示させるプログラミングなんですがコンパイルは成功します。 しかし、実行してみると全く違う結果になってしまいます。 どこが間違っているのか指摘してください。 #include <stdio.h> /* 構造体の宣言 */ struct data { int score; int rank; }d; /* 関数 */ void rank(struct data *x, int n) { int i, j; for ( i=0; i<n; i++) x[i].rank = 1; for ( i=0; i<n; i++) for ( j=0; j<n; j++) if(x[i].score < x[j].score) x[i].rank++; } /* main文 */ int main(void) { int a; struct data x[50]; /* ファイルから得点を読み込む */ FILE *fp; fp = fopen("data01.txt", "r"); for ( a=0; a<50; a++) x[a] = atoi(getc(fp); fclose(fp); /* 順位付け */ a = 50; rank(x,a); printf("Rank Score\n"); for ( a=0; a<50; a++) printf("%d %d\n", x[a].rank, x[a].score); return 0; } ちなみに data.txt は 左側の列は番号 右側の列が得点 1 50 2 62 3 73 4 42 5 99 6 10 7 68 8 54 9 87 10 98 11 54 12 30 13 15 14 60 15 78 16 98 17 65 18 75 19 32 20 99 21 80 22 64 23 52 24 31 25 99 26 10 27 20 28 5 29 65 30 53 31 54 32 35 33 45 34 23 35 26 36 97 37 88 38 99 39 56 40 42 41 32 42 56 43 56 44 54 45 0 46 54 47 80 48 99 49 54 50 56

  • C言語 探索に関して

    C言語探索プログラムについて質問です。 #include <stdio.h> #define MAXSIZE 100 void swapData(int *x, int *y){ int tmp; tmp = *x; *x = *y; *y = tmp; } void simpleSort(int data[], int first, int last) { int i, j; for(i = first; i < last; i++){ for(j = i+1; j <= last; j++){ if(data[i] > data[j]) { swapData(&data[i], &data[j]); } } } } int ArrayBinarySearch(int data[], int n, int x) { int left = 0, right = n - 1, center; while(left <= right){ center = (left + right)/2; if(data[center]=x){ return center; }else if(x > data[center]){ left = center + 1; }else if(x < data[center]){ right = center - 1; } } return -1; } int main(int argc, char *argv[]) { int data[MAXSIZE]; int i, x; FILE *fp; scanf("%d", &x); fp = fopen(argv[1], "r"); for(i = 0; i < MAXSIZE; i++) { if (fscanf(fp,"%d", &data[i]) == EOF) break; } simpleSort(data, 0, i-1); printf("%d", ArrayBinarySearch(data, i, x )); return 0; } 数値が書かれたファイルを読み込んでソートした後に二分探索を行うプログラムをつくったのですが、うまく動きません。 どこがおかしいか教えてください。 お願いいたします。 ちなみに関数ArrayBinarySearchは目的の値が見つかれば配列中でのインデックスを、見つからない場合は-1を返す関数にしているつもりです。

  • 型によらないCSVファイルの読み込みC言語プログラ

    あらかじめ型のわかっているN行*M列のエクセルデータをCSV形式にし、 読み込むプログラムを作成しました。 そのプログラムを下に示します #include <stdio.h> #include <stdlib.h> #include <string.h> /* 確保するデータ保存領域の大きさ(N行×M列) */ #define N 23 #define M 6 /* データの区切り文字 */ #define SEP_DATA ',' int csv_read(char filename[], double csv[N][M]) { /* ファイルオープン */ FILE *fp; if( (fp = fopen(filename, "r")) == NULL ) { printf(" file open error!!\n"); return -1; } /* 1行毎に読み出し */ char line[256], *ptr; int i, j, k; i=0; while (fgets(line, 256, fp) != NULL) { printf("*%s", line); ptr = line; j=0; do{ /* line[j]から次のタブ文字までを数値に変換 */ csv[i][j] = atof(ptr); /* 次のタブ文字の位置を探す */ ptr = strchr(ptr, SEP_DATA); /* タブ文字の次の文字を示す */ if (ptr!=NULL) { ptr++; } j++; }while(ptr!=NULL && j<M); i++; } /* ファイルクローズ */ fclose(fp); return 0; } int main(int argv, char *argc[]) { char filename[256]; if( argv > 1){ strcpy(filename, argc[1]); } else { printf("Please Input Filename:"); scanf("%s", filename); } /* データ保存用の領域を確保 */ double (*csvdata)[M]; csvdata = (double(*)[M])malloc(sizeof(double[M]) * N); //malloc(sizeof(*csvdata) * N); if ( csvdata == NULL ){ return -1; } int i,j; /* 配列の初期化 */ for( i=0; i<N; i++) { for( j=0; j<M; j++) { csvdata[i][j] = 0.0; } } /* CSVデータの読み込み */ if( csv_read(filename, csvdata) < 0 ) { return -1; } /* 配列の出力 */ for( i=0; i<N; i++) { printf("%lf", csvdata[i][0]); for( j=1; j<M; j++) { printf("\t%lf", csvdata[i][j]); } printf("\n"); } free(csvdata); csvdata = NULL; return 0; } これをNとMがどんな値であれ読み込めるようにするにはどうすれいいでしょうか

  • C言語におけるファイル読み込みor書き込みの高速化がうまくいかない

    新年早々、初歩的な質問で申し訳ありません。 C言語でファイルからの数値データの読み込み/書き込みを高速化したいと思っています。例えば、ファイルの数値データ 「0123456789abcdef...」 を、配列で取り込んで 「30313233343536373839616263646566...」 のようにprinf等で表示させたいと思っています。 とりあえず、読み込みの場合のみ示します。 現在,下のサンプルプログラムで示すようにgetcで一個ずつ取りこんでいますが、これだとデータの数がばかでかくなると大変な時間がかかってしまいます。これは一回一回ファイルにアクセスしているためだと考えられると思うのですが,これをファイルアクセス回数を減らし(つまり、ループ回数を減らし)一気に読み込みたいのですが,どうもうまくいきません。 この場合、ネットで調べたものの、どのようなI/O関数を使えばよいかわからず、freadとかを使うとバグってうまく読み込めません。 I/Oの取扱いが苦手なので原因なのですが、わかりやすく教えて頂けると助かります。 初歩的な質問で恐縮ですが、よろしくお願いします。 書き込みの方も教えて頂けると幸いです。 --------------------------------------------- #include <stdio.h> #define SIZE (65536*10) int main(int argc, char** argv){ unsigned long long int i; int j; unsigned char data[SIZE][16]; FILE *fp; fp = fopen("filein.dat", "rb"); //現在の読み込み処理 unsigned char tmp; for(i=0; i<SIZE; i++){ for(j=0; j<16; j++){ data[i][j] = getc(fp); } } /* //表示 for(i=0; i<SIZE; i++){ for(j=0; j<16; j++){ printf("%2x", data[i][j]); } puts(""); } */ return 0; } ------------------------------------------------- //filein.dat 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef...

  • 【C言語】 コンパイルエラーが解決できません

    参考書でC言語学習中の初心者です。 参考書記載のサンプルコードをコンパイルするとエラーになります。 誤字脱字は何度も確認しています。google等でも調べましたがわかりませんでした。。。 どなたか、どこが間違っているのかご教示いただけませんでしょうか。 また、何か的外れな記載があればご指摘いただけますでしょうか。 【環境】 OS: Mac OS X 10.9.3 コンパイラ:Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn) 【サンプルコード】  ------------------------------------------------- #include<stdio.h> int main(void){ int data; data = 10; printf("変数dataの値 = %d\n", data); printf("変数dataのアドレス = %08X", &data); return 0; } ------------------------------------------------- 【エラー】 破線内 ------------------------------------------------- sample12-1.c:9:45: warning: format specifies type 'unsigned int' but the argument has type 'int *' [-Wformat] printf("変数dataのアドレス = %08X", &data);                     ~~~~ ^~~~~ 1 warning generated. ------------------------------------------------- 宜しくお願い申し上げます。

  • C言語

    3. 整数配列data の,data[left]からdata[right-1]の最小値がある添字番号を返す関数 int min_ind_ary(const int data[ ], int left, int right) で最小値が複数あるときは,一番小さい添字を返すようにするにはどうしたらよいのかわかりません? 途中経過↓ #include <stdio.h> int min_ind_ary(const int data[10],int left,int right) { int i,min = 0; for( i = 1; i < left; i++){ if(data[min] < data[i]) min = i; } return min; } void print_ary(const int data[10], int size){ int i; for(i = 0; i < 10; i++){ printf("%2d", data[i]); } } void sort_ary (int data[10], int size) { int i; for(i = 0; i < size - 1; i ++ ) { int min, work; min = min_ind_ary(data, i, size); work = data[min]; data[min] = data[i]; data[i] = work; } return; } int main(void) { int data[10] = {1, 6, 4, 8, 2, 3, 5, 9, 7, 4}; print_ary(data, 10); sort_ary(data, 10); print_ary(data, 10); return 0; }

専門家に質問してみよう