0

ダブル ポインターの動作をテストしていたときに、よくわからない結果が得られました。

==> コー​​ド 1 :

int main (int argc , char **argv)
{

if(*argv+1 ==NULL)
{
    printf("NULL pointer \n");
    exit(0) ;
}
else
{ 
    printf("test double pointer[] : %s \n ",*argv+1);  

}

return(0);
}

====> 結果 1

root@root:/home/aa/test# ./geip 1255
test double pointer[] : /geip 
root@root:/home/aa/test#

===> コー​​ド 2 :

int main (int argc , char **argv)
{

if(*argv+9 ==NULL)
{
    printf("NULL pointer \n");
    exit(0) ;
}
else
{ 
    printf("test double pointer[] : %s \n ",*argv+9);
}
 return(0);
 }

==> 結果 2 :

root@root:/home/aa/test# ./geip 1255
test double pointer[] : 55 
root@root:/home/aa/test#

==> 結果 3 :

root@root:/home/aa/test# ./geip 
test double pointer[] : ELL=/bin/bash 
root@root:/home/aa/test#

printf は n 番目の単語 (1 と 9) から表示されるようですが、このポインターの動作をどのように説明できますか?

4

4 に答える 4

10

あなたはそれを間違って使用しています。

*argv+1(argv[0])+1は "./geip"と解釈されるargv[0]ため、"/geip" が得られます。

*argv+9と解釈されます(argv[0])+9が、argv[0]長さが 6 しかないため、結果は未定義です。

あなたの場合、 argv はおそらく次のように保存されます:

.  /  g  e  i  p \0  1  2  5  5 \0
0  1  2  3  4  5  6  7  8  9 10 11

+9「55」を取得する理由を説明します

しかし、それは決して役に立たないので、本当に忘れるべきです! これは未定義の動作であり、使用しないでください。

于 2013-07-12T14:26:21.627 に答える
1

char **argvへのポインタですchar *(より単純に文字列と呼ばれることもあります)。するときは、このポインターを逆参照します*argv。この逆参照の結果はa です。char *つまり、a のアドレスですchar。結果に加算を行うと、コードは新しいアドレスを計算しています。したがって、たとえば while*argvは文字列の最初の文字のアドレスになり、文字*argv+1列の 2 番目の文字のアドレスになります。

文字列の長さよりも長い数を追加すると、「安全」から抜け出します。C では、文字列の末尾を超えるポインター演算を実行できることを思い出してください。2 番目の例では、printf に先頭から 9 バイト先に進み*argv、そこから次の\0(または NULL) バイトまで文字を出力するように要求しています。プログラムのプロセス空間から任意のメモリを効果的に読み取っています。これにより、何が印刷されているかが説明されます。

于 2013-07-12T14:35:41.860 に答える
1

実際には複数の問題があります。

  1. どうか、root として動作しないでください。ただしないでください。
  2. あなたの構文 ( *argv + 9) は文字通り、「引数 argv を無視し、ポインタを 9 文字移動する」という意味です。したがって、(は引数のインデックスを示します) を使用するか、難しい方法で実行したい場合は、括弧を追加する必要があります: ../geip 125555argv[i]i = 1..N*(argv + i)
  3. コードをより適切にフォーマットしてみてください。stackoverflow の人だけでなく、あなたにとっても読みやすくなります。

たとえば、次を実行すると./geip a b c 123

  • argv[0]保持しているstringプログラム名 -./geip
  • argv[1]string最初の引数を保持しています-a
  • argv[2]string2番目の引数を保持しています-b
  • argv[3]string3番目の引数を保持しています-c
  • argv[4]string4番目の引数を保持しています-123
  • argv[5]argcがbwするのでNULLです5(コメントを参照)
  • argv[>5]これ以上引数がないため、良い考えではありません。したがってargc、引数がいくつあるかを確認することをお勧めします。
于 2013-07-12T14:35:54.920 に答える
0

ポインタ演算を行うだけです: **argv はポインタのリストへのポインタです *argv はリストの先頭です

//char **argv is given from outthere
char *p;
p = *argv; // the same as "p = *argv[0]"
for (int i = 0; i < 100) {
  printf("Next: %s\n", p+i);
}

それを実行して、リストの先頭から次の 100 バイトまでのメモリのダンプを確認してください。

于 2013-07-12T14:36:38.397 に答える