• ベストアンサー

ポインターについて

http://oshiete1.goo.ne.jp/kotaeru.php3?q=2352832 で、質問させて頂いた者です。 ポインターの使い方について 理解できないところがありましたので 新しく質問をさせて頂きました。 ----------- ↓構造体の型を宣言しています typedef struct douken_ { char tiku[11]; char ken[9]; } douken; int main(void){ FILE *fp; ↓変数を宣言 douken dou [100]; ・ ・ ・ while (fgets(buff,sizeof buff,fp) != NULL){ ファイルから読み込んだデータを構造体に格納 memcpy(&dou[i].tiku ,buff,10); memcpy(&dou[i].ken ,buff+10,10); 【ここが問題】 現データと全データを比較する if (strcmp(dou[i].tiku , dou[i-1].tiku)){ ----------- if文で現データと全データを比較する時に、 実数だと正常に動くのですが ポインターで指定すると 警告が出てしまいます。 if (strcmp(&dou[i].tiku , &dou[i-1].tiku)){ とすると >警告 W8075 kadai3-2.c 33: 問題のあるポインタの変換(関数 main ) という警告が出てしまうのです。 どうしてポインターで指定すると 警告が出るのかが分からないのです。 (memcpyではファイルから読み込んだデータを 構造体に格納するときはポインターで指定しているのに…) ご教授して頂けたら幸いです。

  • niiza
  • お礼率43% (211/486)

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

  • ベストアンサー
回答No.2

この件、ちょっと面倒な点があります。 まず、 memcpy() の最初の引数の型は、void * です。 言い換えると、「ポインタなら、何でもOK」 strcmp() の最初の引数の型は、const char * です。 つまり、「char のポインタのみOK」です(const も重要ですが、説明上無視します) さて、dou[i].tiku の型は、char の(ポインタではなく)配列です。 以上のことをふまえた上で……。 strcmp(dou[i].tiku, ... ) これは、strcmp に、char の配列を渡しています。 ところで、関数の引数となった配列は、ポインタに変換されるので、この時点で、char のポインタに変換されます。 従って、strcmp は受け入れてくれます。 strcmp(&dou[i].tiku, ....) これは、strcmpに、char の配列のアドレスを渡しています。 上記のように、「配列」は「ポインタ」に変換されますが「配列のアドレス(配列へのポインタ)」は、そのままの型を持ちます。 つまり、char * に対して、配列のアドレスを渡そうとするので、警告が出ます。 一方、memcpy() の方は、void * であり、どのような型のポインタも(文法上)受け入れてくれるので、警告は出ません。 あと、 &dou[i].tiku という表記ですが、配列名に & をつけると、配列の先頭を示しポインタを返すので、これ自体はOKです。 (dou[i].tiku の場合は、配列名を char へのポインタに変換してくれるので、アドレスとしては、同じものになります。型は異なりますが)

niiza
質問者

お礼

関数に渡したときにポインタに変換されているんですね。 大変に参考になりました。

その他の回答 (1)

  • m_mik
  • ベストアンサー率26% (31/117)
回答No.1

今までのご質問内容も見直してきたのですが… まず、strcmp()は int strcmp(const char *s1, const char *s2); と定義されていますので、引数は2つで、charのポインタを渡すことになります。 strcmp(&dou[i].tiku , &dou[i-1].tiku) では、第一引数、第二引数ともにcharのポインタのアドレスを渡そうとしています。 (dou[i].tiku が charのポインタですよね) Cのほうが暗黙のうちにポインタのポインタ→ポインタへの変換を行おうとしますので「問題がある変換」となってしまいます。 実数と仰られていますが、渡しているのはポインタだったのです。 (実数を指定するとしたら、dou[i].tiku[0] という指定になり、&dou[i].tiku[0] ならば「正しい指定」となります) 同時に気になったのですが、 memcpy(&dou[i].tiku ,buff,10); memcpy(&dou[i].ken ,buff+10,10); の部分は正しいのでしょうか? dou[i] の前の & は不要だと思います。 理由は上記で述べています。 以上、いかがでしょうか?

niiza
質問者

お礼

関数に渡したときにポインタに変換されているんですね。 大変に参考になりました。

関連するQ&A

  • if文で…

    いつもお世話になっております。 ------------------------ typedef struct douken_ { char tiku[11]; char ken[9]; } douken; int main(void){ FILE *fp; douken dou [100]; char buff [18 /* douken */ + 2 /* CrLf(\n\r) */ + 1 /* \0 */]; int i; i = 0; fp = fopen("ex3.fil","rb"); if ( fp == 0 ){ printf("can't open\n"); exit(1); } memset (dou , '\0' , sizeof dou); memset (buff, '\0' , sizeof buff); 問題はここから----------------- while (fgets(buff,sizeof buff,fp) != NULL){ memcpy(&dou[i].tiku ,buff,10); memcpy(&dou[i].ken ,buff+10,10); if (&dou[i].tiku == &dou[i-1].tiku){ printf("%s %s",&dou[i-1].tiku,&dou[i].tiku,&dou[i].ken);} else{ printf("-----------------------"); } ------------------------ 上記のプログラムでは ファイルから読み込んだデータを 構造体に格納して if文で現データと全データを 比較するという処理をしています。(つもり) 構造体に格納するところまでは 出来たのですが if文のところが上手く行きません。 例えば 現データ(tiku)関東地区 前データ(tiku)関東地区 と、同じ場合は 関東地区 東京 と、表示したいのに ----------- と、elseの処理をしてしまいます。 対処方法をご存じでしたら、 ご教授して頂けたら幸いです。

  • ファイルから読み込んだデータを構造体に格納できますか?

    1レコード19バイトのファイルを 読み込む処理を行っています。 地区名10バイト 県名8バイト 改行1バイト このデータをdouken(構造体)に格納したいのですが >while (fgets(dou,19,fp) != NULL){ で、エラーになってしまいます。 どのようにしたら ファイルから読み込んだデータを 構造体に格納できますか? #include<stdio.h> #include <stdlib.h> struct douken { char tiku[10]; char ken[8]; } main(void){ FILE *fp; struct douken dou[100]; int i; fp = fopen("ex3.fil","rb"); if ( fp == 0 ){ printf("can't open\n"); exit(1); } while (fgets(dou,19,fp) != NULL){ ・ ・ ・

  • strcmpで警告が…

    http://oshiete1.goo.ne.jp/kotaeru.php3?q=2352461 で、質問させて頂いた者です。 ご回答の通りに「strcmp」を使って、 if (strcmp(&dou[i].tiku , &dou[i-1].tiku)){ printf("-----------------------\n"); } と、してみたところ 上手く動くようになりました。 ただ、 >警告 W8065 kadai3-2.c 32: プロトタイプ宣言のない関数 'strcmp' の呼び出し(関数 main ) という警告が出てしまいます。 対処方法をご存じでしたら、 ご教授して頂けたら幸いです。

  • Vectorでヒープエラーが出る

    下記のプログラムで、2回目のループを抜けたところでヒープエラーが 出てしまいます。 2回目のループ時にv[0]とv[1]の中のbuffが同じポインタを指してしまうことが原因のようですが、なぜ同じポインタを指してしまうのかがわかりません。 どうしたらこの問題が解決するのでしょうか? 以上、よろしくお願いします。 #include "CBuff.h" main(){ vector<CBuff> v; char *tmpstr; for (int i = 0; i < 3; i++){ if (i == 0){ tmpstr = new char[5]; memcpy(tmpstr, "aaaa", 5); }else if(i == 1){ tmpstr = new char[6]; memcpy(tmpstr, "bbbbb", 6); }else { tmpstr = new char[7]; memcpy(tmpstr, "cccccc", 7); } CBuff cb; cb.setBuff(tmpstr, strlen(tmpstr) + 1); v.push_back(cb); delete [] tmpstr; } } 【CBuff.h】 #pragma once class CBuff{ char *buff; public: CBuff(); ~CBuff(); void setBuff(char*, size_t); }; CBuff::CBuff(){ buff = NULL; } CBuff::~CBuff(){ if (buff != NULL){ delete [] buff; buff = NULL; } } void CBuff::setBuff(char *input, size_t size){ buff = new char[size]; memcpy(buff, input, size); }

  • ポインタ

    #include "stdafx.h" #include <ctype.h> #include <string.h> #include <stdlib.h> typedef struct { char number[6]; char class_type[20]; char name[8]; char subject[5]; } my; my data[100]; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char bufG[1111]; int i; if((fp=fopen("test.txt","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf,1000,fp) !=NULL){ str=buf; while(*str != '\0'){ if(*str != ','){ for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; // printf("%s", bufG); switch(field){ case 0: strcpy(data[line].number, bufG); break; case 1: strcpy(data[line].class_type, bufG); break; case 2: strcpy(data[line].name, bufG); break; case 3: strcpy(data[line].subject, bufG); break; } field++; } else{ str++; } } line++; field = 0; } printf("%s", data[2].subject); fclose(fp); return 0; } このプログラムをベースにしてメモリの無駄を省けるような プログラムに修正したいのですが、 ポインタほんとできなくて困ってます。 教えていただいてメモリを取る位置とかは大体わかりました。 まず構造体のメモリをとります。しかしこのままでは固定長になってるので 構造体を少しいじくりますよね。 構造体の中身なのですが typedef struct{ int number; char *class_type; char *name; char *subject; } my; my *data; にして data = malloc(100); このような形でとります。 文字列の型ですがchar *class_typeのようにポインタで宣言しないと bufGを代入して値を入れるときに型が合いませんので 配列にしないのであればポインタ型宣言でいいと思います。 しかしポインタで宣言してstrcpy(・・)の所を data[line].class_type = bufG にするとエラーはでませんが*strの値が変わる度に data[line].class_typeの値が変動するのでdata[line].class_typeが 国語 とかになったりします。 なんかもうさっぱりわからないんですが どうすればいいのでしょうか? 変換したソースがほしいです。

  • ポインタ…(゜Д゜≡゜Д゜)?

    え~C言語初心者です。 ポインタ、文字列等の比較を教えて下さいm(._.)m ペコッ 下記ソースでおかしいところがあれば指摘お願いします。 (1)数値の比較  int i = 10;  if(i == 10){処理} (2)文字の比較  char c = 'c';  if(c == 'c'){処理} (3)文字列の比較  char *c = "abc";  if(c == "abc") {処理}   ↑これだとポインタと文字列の比較になるんですよね?  if(0 == strcmp("abc",c)){処理}   ↑この書き方で問題ないのでしょうか?  if(0 == strcmp("abc",*c)){処理}                ~~  だとダメなのでしょうか? ※int型のポインタを使う場合  int *i = 0;  if(0 == *i){処理}   になるのでしょうか?

  • memcpyについて

    構造体に整数のデータを格納する方法を 教えて下さい。 「ex」ファイルのデータ 41 4352 42 2341 43 5411 --------- これらのデータを kihokyu[1].tosi=41 kihokyu[1].kan=4352 kihokyu[2].tosi=42 kihokyu[2].kan=2341 という感じで格納したいのです。 プログラム 構造体のテンプレートを宣言 typedef struct nentbl_ { int tosi; int kan; } nentbl; int main(void){ char buff[16]; FILE *fp; int age , kyoku , i, y; 構造体を宣言 nentbl kihokyu[50]; ファイルを開く fp = fopen("ex.fil","rb"); ・ ・ ・ while(fgets(buff,sizeof buff,fp) != NULL){     整数に変換 y = atoi(buff); ここでエラー memcpy(&kihokyu[i].tosi,y,4); パラメータ '__src' は const void * 型として定義されているので int は渡せない(関数 main ) たぶんmemcpy関数の使い方が間違えていると思うのですが… ご教授して頂けたら幸いです。

  • ポインタと配列

    次のソースで、結果表示でポインタを使いたいのですが、うまくいきません。1件しか表示されないのです。 ポインタの扱いがおかしいのだと思いますが、どうしたらよいでしょうか? #include <stdio.h> #include <string.h> int search(char key[256],FILE *fp,char *result[256][256]); main(void) { FILE *fp; int rep,n,i; char x[256],key[256],*result[256][256]; printf("検索キーワードを入力してください。\n" "キーワード>"); gets(key); if((fp=fopen("personal.txt","r"))==NULL) { printf("ファイルをオープンできません\n"); exit(1); } printf("=====検索結果=====\n"); n=search(key,fp,result); for(i=0;i<n;i++) { printf("%s\n",result[i]); } printf("検索結果:%d件です。\n",n); fclose(fp); } int search(char key[256],FILE *fp,char *result[256][256]) { int n=0; char *p,word[256],*name; while((p=fgets(word,256,fp))!=NULL) { if(strstr(word,key)!=NULL) { name=strtok(p," "); strcpy(result[n],name); n++; } } return n; } 実行すると、下の警告がでます。 illegal pointer combination(param)

  • 単語の出現頻度を調べるプログラム

     ファイルからデータを読み込んで、単語の出現頻度を調べるプログラムを作ろうと考えて、下記のようなプログラムを書いてみました。 #include <stdio.h> #include <string.h> main() { struct data {char word[128]; int freq;} word_data[128]; char words[128]; char term[128]; int i=0; int nw=0; int j; char buff[128]; FILE *fp_in=fopen("data.txt","r"); while(fgets(fp_in,128,buff)!=EOF){ char buff[128]; int k; for(k=0;k<=128;k++){ printf("%s",buff); if(('A'<=buff[k] && buff[k]<='Z')||('a'<=buff[k] && buff[k]<='z')) term[i++]=buff[k]; else if(i>0) term[i]='\0';} for(j=0;j<nw;j++){ if(strcmp(term,word_data[j].word)==0) break; if(j==nw) {strcpy(word_data[j].word,term); word_data[j].freq=1; nw++;} else if(j!=nw) {word_data[j].freq++; i=0;} }} for(j=0;j<nw;j++) printf("%s %d",word_data[j].word,word_date[j].freq); return 0;} コンパイルは通ったのですが、実行しても画面に何も表示されません。原因は何処にあるのでしょうか?分かる方がいましたら、ご回答宜しくお願いします。

  • ポインタに ~0を入れること

    見かけたCのプログラムで、 ポインタに~0を代入するものを見ました。 そのプログラムをそのまま載せるのはわかりにくいので、 代わりに以下のプログラムを作って実行しました。 #include <stdio.h> int main(void) { char *pa[3]; int i; pa[0]=0; pa[1]=~0; pa[2]="Hello"; printf("sizeof(char*)=%d\n", sizeof(char*)); for(i=0; i<=2; i++) { if(pa[i]==NULL) printf("pa[%d] はNULLです。\n", i); if(pa[i]==(char*)0xFFFFFFFF) printf("pa[%d]は全ビット1です。\n", i); if(pa[i]==~0) printf("pa[%d]は~0です。\n", i); } return 0; } 結果 sizeof(char*)=4 pa[0] はNULLです。 pa[1]は全ビット1です。 pa[1]は~0です。 このプログラムはコンパイル時にエラーも警告も出ず、 動作も意図したとおりです。 pa[1]に入っている ~0 は、int型の定数なのでしょうか。 それならば、 pa[1]=~0; という代入や if(pa[i]==~0) という比較は 左辺はchar*型で右辺はconst int型であって型が異なりますが、 問題ないのでしょうか。 ~0は0の否定なので、全ビットは1なのでしょうけど、 int型(の定数)だと思います。 ~0というのは何か特別な値なのでしょうか。 ポインタに~0を入れるというのは、意味があるのでしょうか。 (例えば、「ポインタに0を入れるということは、ヌルポインタであって、ポインタとして無効なんですよ」のようなこと。)

専門家に質問してみよう