• ベストアンサー

非常に基本的なポインタの使い方

非常に基本的なところだと思いますが、ポインタの理解がうまくなく意図どおりのプログラムが書けません。 何らか引数を渡して(とりあえず文字列"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"; とした場合はうまくいくので、余計に混乱しております。 どなたか、正解例をご教授いただけませんでしょうか。

  • ooss
  • お礼率82% (14/17)

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

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

if(a == "hogehoge"){ のところは、ポインタa のアドレスと 文字列 "hogehoge" が格納されているアドレスが等しいかと言う検査を行っています。 このとき、文字列 "hogehoge" は メモリ内の特定の領域に保存されていますので、引数で渡されたアドレスとは違うところを指してしまいます。 よって、条件が成立しません。 文字列 "hogehoge" と等しいのかを判断する場合には、strcmp() などで比較を行い、返り値によって判断する必要があります。

ooss
質問者

お礼

ありがとうございます。 strcmp()ですね! 実は一度も使ったことがないので、この機会にしっかり勉強します。

その他の回答 (2)

回答No.3

> char* a = argv[0]; > の箇所を単純に > char* a = "hogehoge"; > とした場合はうまくいくので、余計に混乱しております。 では、こちらのほうが(たまたま)うまくいくわけについて。 C言語で "hogehoge" とかかれた部分は、 1)メモリ上のどこかに、hogehoge というデータが保持されて、 2)その先頭のアドレス というデータになります。 ですから、 char *a = "hogehoge"; は、メモリ上にある、"hogehoge" という文字列の、先頭アドレスを渡しているだけで、文字列そのものを渡しているわけではありません。 同様に、char *a = argv[0]; は、argv[0] という文字列をポイントしている、アドレスを渡しているだけで、引数に指定したデータを直接渡しているわけではありません。 (もっと言えば、argv[0] には、引数は入っていません。通常、実行したプログラムのファイル名がはいています、実行時の引数は、argv[1] から順に格納されます) さて、C言語のコンパイラと、オプションの組み合わせによっては、「同じ文字列定数は、同じアドレスに保存する」ものがあります。 この場合、 if (a == "hogehoge") の、"hogehoge" と、 char a = "hogehoge"; の "hogehoge" は、同じアドレスに配置されます。従って、その先頭アドレスも、同じです。 このため、 char *a = "hogehoge"; で渡した値と、 if (a == "hogehoge") で、比較した、アドレス値がたまたま同じになります。 ですから、この場合は、見かけ上うまくいくわけです。

ooss
質問者

お礼

ありがとうございます。 非常に理解が深まりました。 > (もっと言えば、argv[0] には、引数は入っていません。通常、実行したプログラムのファイル名がはいています、実行時の引数は、argv[1] から順に格納されます) すみません。こちらは記載ミスです。ご指摘のとおりargv[1]です。 まだ正解にたどりつけていない状態ですが、いろいろ試してみます。

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

文字列を == で比較しちゃダメ~.

ooss
質問者

お礼

ありがとうございます。 言われてみればそのような規則があった気がしています。 基本が成っていませんでした。。。

関連するQ&A

  • ポインタについて

    こんにちは。「独習C」で独学している者です。その中の練習問題をやっていました。課題はコマンドラインから引数を受け取り各文字に1を加え暗号化して表示するというものでした。 自分で考え一応ちゃんと動くものが書けました。その後もっとシンプルにならないかと少しずつ余分な所を削っていき以下のようになりました。 #include <stdio.h> int main(int argc,char *argv[]) { char ch; if(argc != 2){ printf("引数が正しくありません"); exit(1); } else while(*argv[1] != '\0'){ printf("%c",*(argv[1]++) + 1); } return 0; } できた、できたと喜んでいたのですがソースをよく見ていると*(argc[1]++)の所を見てあれっと思いました。これでは文字列の二番目の要素からしか表示できないのではないのかと思ったのです。しかし動かすとちゃんと動くのです。ちゃんと1番目の要素も表示されるのです。自分としては++を消して次の行にargv[1]++を付け加えればいいと思ったのですがどうでしょうか?(←これでもちゃんと動きました)私のポインタに対する考え方が間違っているのでしょうか?よろしくお願いします。

  • ポインタのポインタ

    #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回分、出力が可能になるのか教えてください。 初歩的な質問ですいません。

  • ポインタについての質問など

    (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は使えないのでしょうか?

  • コマンドライン引数 *argv[]はなぜポインタ?

    C言語初心者です。 コマンドライン引数、 int main(int argc, char *argv[]) というのを最近勉強しましたが、引数2番目がポインタになっている理由について、 どなたか教えて下さい。 そういう仕様なんだから、それに従いましょう、ということでしょうか? int main(int argc, char argv[]) では、ダメなのでしょうか? このポインタでの引数渡しについて、 なんらかの納得のいく考え方をご存知の方がいらしたら、教えて下さい。 宜しくお願い致します。

  • _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[]) で使えば問題なく使えるのですが、デフォルトのウィザードを使った時の使い方を知っておきたいのです。 御経験のある方、御教示お願い致します。

  • ポインタの基本的な問題

    ポインタの勉強をしています。変数にポインタが付いている場合の動作は大体理解したつもりですが以下のように関数にポインタが付いているとどう扱えばいいのかわかりません。とりあえず、まずはtsukinonamae関数にinteger 1を渡して「1月」と表示させることから始めようとしていますが、それすらコンパイルエラーになります。引数nに1を渡すところはいいですよね?その後、nam[1]に入っているjanという文字列をchar型で返す?と思うのでメイン部で宣言したcharに渡そうとしているのですが。。 何が問題なのでしょうか。 char *tsukinonamae(int n); int main(){ int n = 1; char s[30]; s = tsukinonamae(n); printf("%s\n", s); } char *tsukinonamae(int n){ static char *nam[] = { "none", "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"}; return (n<1 || n>12) ? nam[0] : nam[n]; }

  • 「コマンドライン引数チェック」て何

    #include <stdio.h> int main(int argc, char *argv[]) { FILE *fp; char gyou[1024]; int gyousuu = 0; if ( argc < 2 ){ printf("file mei ga nai\n"); return -1; } fp = fopen(argv[1], "r"); if ( fp == NULL ){ printf("fopen dekinai\n"); return -2; } while(fgets(gyou, sizeof(gyou), fp) != NULL){ gyousuu++; } fclose(fp); printf("gyousuu=%d\n", gyousuu); return 0; }    以上のプログラムはご覧のとおり、「ファイルの行数を計算」のプログラムです。 さて以上の  if ( argc < 2 ){ printf("file mei ga nai\n"); return -1; } は「コマンドライン引数チェック」を行っています。・・・  if ( argc < 2 ){の「argcは2以上である必要がある」と参考書に書いてあります。   以上ですが意味が日光手前ですが、プログラムの行数をカウントするうえで、  「コマンドライン引数チェック」とはどんな作業を行っているとこなのでしょうか!?  よろしくお願いします。  

  • main(int argc,char **argv[])の意味を教えて下さい

     今晩は、Cの初心者です宜しくお願いします。  main関数の引数で、int main(int argc,char **argv[])とint main(int argc,char *argv[])と書かれている場合がありますが、 「**argv」と「*argv」の意味の違いはどのようなもので、どのように使い分けるのでしょうか。 また、必ずポインタ型でとるという決まりでしょうか。 宜しくお願いします。

  • 二行目の*の意味を教えてください。

    #include <stdio.h> int main(int argc, char *argv[]) { int i; for ( i = 0; i < argc; i++ ){ printf("argv[%d]=%s\n", i, argv[i]); } return argc; }  以上プログラムで、二行目の*の意味を教えてくさい。  6行目のargvには*が付いていません!?  よろしくお願いします。

  • ポインタについて

    今初めてポインタというものを勉強しております。 よろしくお願いします。 ◎1---------------------------------- #include<stdio.h> int main(void) { int mydt=1234; int *pt; pt=&mydt; printf("*pt=%d\n",*pt); printf("&mydt=%p\n",&mydt); return 0; } --------------------------------------- ◎1のようにmydtのアドレスをポインタptに代入すれば、このプログラムは正常に動きました。 ◎2----------------------------------- #include<stdio.h> int main(void) { int mydt=1234; int *pt=&mydt; printf("*pt=%d\n",*pt); printf("&mydt=%p\n",&mydt); return 0; } ---------------------------------------- ◎2で「int *pt=&mydt;」があまりどういう意味かはわかりませんが、これも正常に動きました。 ◎3------------------------------------ #include<stdio.h> int main(void) { int mydt=1234; int *pt; *pt=&mydt printf("*pt=%d\n",*pt); printf("&mydt=%p\n",&mydt); return 0; } -------------------------------------- ◎3のように◎2と違って「*pt=&mydt」の代入を後から行うと、「'=' : 'int *__w64 ' から 'int' に変換できません。」といったようなエラーが起きてしまいます。 ◎1と◎2の違い、後何故◎3はダメなのかがわかりません。 教えていただけると嬉しいです。 後補足として、配列とポインタについてですが、 ◎4------------------------------ char ss[10]="ABCDE"; char *ssp=ss; --------------------------------- ◎5---------------------------- char ss[10]="ABCDE"; char *ssp; ssp=ss; -------------------------------- ◎4と◎5も同じような事だとは思いますが違いを教えていただけると嬉しいです。 よろしくお願いします。

専門家に質問してみよう