2016-08-29 5 views
-1

なぜ彼らはすべて同じ場所を指していますか?それは最適化ですか?c - なぜ彼らはすべて同じ場所を指していますか?

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 
#include <time.h> 
#include <conio.h> 


const char* func1(const char str[]){ 
// printf("%p\n", str); 
    return str; 
} 

const char* func2(const char *str){ 
// printf("%p\n", str); 
    return str; 
} 

char* func3(char str[]){ 
// printf("%p\n", str); 
    return str; 
} 

char* func4(char *str){ 
// printf("%p\n", str); 
    return str; 
} 


int main(void) 
{ 
    char acStr[81] = {0}; 
    const char *p1, *p2; 
    char *p3, *p4; 
    uint32_t uiCount; 
    srand (time(NULL)); 

    for(uiCount = 0; uiCount < (sizeof(acStr) - 1); uiCount++){ 
     acStr[uiCount] = rand() % 26 + 65; 
    } 
    acStr[80] = 0; 
    p1 = func1(acStr); 
    printf("p1 == %p\n", p1); 
    printf("%s", p1); 

    for(uiCount = 0; uiCount < (sizeof(acStr) - 1); uiCount++){ 
     acStr[uiCount] = rand() % 26 + 65; 
    } 
    acStr[80] = 0; 
    p2 = func2(acStr); 
    printf("p2 == %p\n", p2); 
    printf("%s", p2); 

    for(uiCount = 0; uiCount < (sizeof(acStr) - 1); uiCount++){ 
     acStr[uiCount] = rand() % 26 + 65; 
    } 
    acStr[80] = 0; 
    p3 = func3(acStr); 
    printf("p3 == %p\n", p3); 
    printf("%s", p3); 

    for(uiCount = 0; uiCount < (sizeof(acStr) - 1); uiCount++){ 
     acStr[uiCount] = rand() % 26 + 65; 
    } 
    acStr[80] = 0; 
    p4 = func4(acStr); 
    printf("p4 == %p\n", p4); 
    printf("%s", p4); 


    printf("\n"); 


    printf("p1 == %p\n", p1); /* Same address */ 
    printf("%s", p1); 

    printf("p2 == %p\n", p2); /* Same address */ 
    printf("%s", p2); 

    printf("p3 == %p\n", p3); /* Same address */ 
    printf("%s", p3); 

    printf("p4 == %p\n", p4); /* Same address */ 
    printf("%s", p4); 


    getch(); 
    return 0; 
} 

出力。

 
p1 == 000000000022FDC0 
USOPBBREKRTCCAXRFVPJPEVPESVTAIQUXIPNMCAWHZGWWUSUUNCWNGFRCTHLJLANVSRQJCTCOOXQZIYX 
p2 == 000000000022FDC0 
SVITQWBDXTQSUJKXIUKIANTUELJCJPVDYEBCIDGDWITCTZJTDERRPINICWNSIIKMAVTFKIUHEEGNEKBD 
p3 == 000000000022FDC0 
IDTZXTQWPSRURMWBCAKXWKXJANLVHRDMDREGKBYKJZMDHYHSGRMYAAAGWWRWSAJMBYODZYBKMYPPMVXN 
p4 == 000000000022FDC0 
TFCBRYSYRNNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRRSGDZWIXOVKYBRYPQOEXRFUJ 

p1 == 000000000022FDC0 
TFCBRYSYRNNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRRSGDZWIXOVKYBRYPQOEXRFUJ 
p2 == 000000000022FDC0 
TFCBRYSYRNNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRRSGDZWIXOVKYBRYPQOEXRFUJ 
p3 == 000000000022FDC0 
TFCBRYSYRNNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRRSGDZWIXOVKYBRYPQOEXRFUJ 
p4 == 000000000022FDC0 
TFCBRYSYRNNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRRSGDZWIXOVKYBRYPQOEXRFUJ 

私はそれは、このように、私はあなたが引数として渡されたのと同じポインタを返すあなたの4つの機能では英語 (グーグルのtranslante訳)

+4

毎回同じものを渡すためですか? –

+2

あなたは正確に何を期待していましたか? –

+0

は、異なる機能を持つ異なるポインタであり、常に同じアドレスを生成します。次に、以前の値を失います。 – sapitando

答えて

2

を話さないので、それはだ、明確されていませんよ変更されません。それでも同じ変数acStrを指しています。

constを引数型に追加してもコピーは作成されません。あなたのコンテンツを変更できないようにするだけです。

また、str[]*strも同じです。

+0

でした。p1 = func1( "ABCDEFGHIJ");次に、コピーを生成します。 – sapitando

+0

他の方法は参考として渡されます。 – sapitando

+0

その場合、返されるポインタは異なります(4つのものを引き続き渡し、重複する文字列リテラルをマージするコンパイラオプションが無効になっていない限り)。そして何もコピーされません。 –

2

すべての関数は引数の値を返します。すべての4つの場合において、機能はacStrの最初の要素のアドレスを受信して​​います。

ここでは、acStrが各呼び出しの間に保存されています。あなただけが変更されているacStrが含まれています。

私はあなたのコードを取り、変数のメモリマップをダンプするためのいくつかの呼び出しを追加しました。あなたがfunc1を呼び出す前に、ここでは、物事は非常に最初に見てみましょう:

 Item  Address 00 01 02 03 
     ----  ------- -- -- -- -- 
     acStr 0x7fff5bfde5b0 00 00 00 00 .... 
      0x7fff5bfde5b4 00 00 00 00 .... 
      0x7fff5bfde5b8 00 00 00 00 .... 
      0x7fff5bfde5bc 00 00 00 00 .... 
      0x7fff5bfde5c0 00 00 00 00 .... 
      0x7fff5bfde5c4 00 00 00 00 .... 
      0x7fff5bfde5c8 00 00 00 00 .... 
      0x7fff5bfde5cc 00 00 00 00 .... 
      0x7fff5bfde5d0 00 00 00 00 .... 
      0x7fff5bfde5d4 00 00 00 00 .... 
      0x7fff5bfde5d8 00 00 00 00 .... 
      0x7fff5bfde5dc 00 00 00 00 .... 
      0x7fff5bfde5e0 00 00 00 00 .... 
      0x7fff5bfde5e4 00 00 00 00 .... 
      0x7fff5bfde5e8 00 00 00 00 .... 
      0x7fff5bfde5ec 00 00 00 00 .... 
      0x7fff5bfde5f0 00 00 00 00 .... 
      0x7fff5bfde5f4 00 00 00 00 .... 
      0x7fff5bfde5f8 00 00 00 00 .... 
      0x7fff5bfde5fc 00 00 00 00 .... 
      0x7fff5bfde600 00 10 40 00 .[email protected] 

     p1 0x7fff5bfde5a8 00 80 0f 5c ...\ 
      0x7fff5bfde5ac c1 2a 00 00 .*.. 

     p2 0x7fff5bfde5a0 80 e6 fd 5b ...[ 
      0x7fff5bfde5a4 ff 7f 00 00 .... 

     p3 0x7fff5bfde598 48 83 0f 5c H..\ 
      0x7fff5bfde59c c1 2a 00 00 .*.. 

     p4 0x7fff5bfde590 00 00 00 00 .... 
      0x7fff5bfde594 01 00 00 00 .... 

配列オブジェクトアドレス0x7fff5bfde5b0acStr開始し、すべてのゼロが含まれるように初期化しました。ポインタ変数p1はアドレス0x7fff5bfde5a8で開始し、p2はアドレ​​ス0x7fff5bfde5a0などから開始します。コンパイラは、宣言されたのと同じ順序で別々のオブジェクトを配置する必要はありません。

p1のそれぞれ、p2p3、及びp4は最初不定値を含みます。彼らは特にどのオブジェクトにも指さない。この段階でそれぞれを逆参照しようとすると、未定義の動作につながります。 func1への呼び出しの後

は、あなたのオブジェクトは、次のようになります。

 Item  Address 00 01 02 03 
     ----  ------- -- -- -- -- 
     acStr 0x7fff5bfde5b0 4f 48 5a 5a OHZZ 
      0x7fff5bfde5b4 57 53 46 4b WSFK 
      0x7fff5bfde5b8 59 49 52 52 YIRR 
      0x7fff5bfde5bc 49 51 48 4e IQHN 
      0x7fff5bfde5c0 50 43 54 56 PCTV 
      0x7fff5bfde5c4 50 53 4d 5a PSMZ 
      0x7fff5bfde5c8 52 53 46 49 RSFI 
      0x7fff5bfde5cc 4b 50 50 59 KPPY 
      0x7fff5bfde5d0 5a 51 58 56 ZQXV 
      0x7fff5bfde5d4 4a 44 49 4a JDIJ 
      0x7fff5bfde5d8 4e 5a 41 56 NZAV 
      0x7fff5bfde5dc 50 48 49 47 PHIG 
      0x7fff5bfde5e0 4c 45 42 42 LEBB 
      0x7fff5bfde5e4 59 50 43 50 YPCP 
      0x7fff5bfde5e8 48 4a 58 52 HJXR 
      0x7fff5bfde5ec 41 4f 53 5a AOSZ 
      0x7fff5bfde5f0 46 50 58 51 FPXQ 
      0x7fff5bfde5f4 55 46 5a 4a UFZJ 
      0x7fff5bfde5f8 45 42 47 56 EBGV 
      0x7fff5bfde5fc 4b 52 42 57 KRBW 
      0x7fff5bfde600 00 10 40 00 [email protected] 

     p1 0x7fff5bfde5a8 b0 e5 fd 5b ...[ 
      0x7fff5bfde5ac ff 7f 00 00 .... 

     p2 0x7fff5bfde5a0 80 e6 fd 5b ...[ 
      0x7fff5bfde5a4 ff 7f 00 00 .... 

     p3 0x7fff5bfde598 48 83 0f 5c H..\ 
      0x7fff5bfde59c c1 2a 00 00 .*.. 

     p4 0x7fff5bfde590 00 00 00 00 .... 
      0x7fff5bfde594 01 00 00 00 .... 

内容acStrは変更されているが、そのアドレスは同じままです。同様に、p1の内容が変更されました。 acStrのアドレスが含まれています(マルチバイト値はリトルエンディアンの順に格納されるため、「後方に」読み込まれます)。

func2を呼び出した後、我々は再び

 Item  Address 00 01 02 03 
     ----  ------- -- -- -- -- 
     acStr 0x7fff5bfde5b0 56 45 5a 54 VEZT 
      0x7fff5bfde5b4 56 42 4a 44 VBJD 
      0x7fff5bfde5b8 4b 49 57 4b KIWK 
      0x7fff5bfde5bc 5a 51 4d 45 ZQME 
      0x7fff5bfde5c0 49 4a 57 43 IJWC 
      0x7fff5bfde5c4 4f 58 4d 55 OXMU 
      0x7fff5bfde5c8 59 53 50 49 YSPI 
      0x7fff5bfde5cc 4a 53 47 47 JSGG 
      0x7fff5bfde5d0 57 46 41 52 WFAR 
      0x7fff5bfde5d4 47 4a 57 53 GJWS 
      0x7fff5bfde5d8 54 56 46 53 TVFS 
      0x7fff5bfde5dc 4e 52 59 56 NRYV 
      0x7fff5bfde5e0 41 55 59 51 AUYQ 
      0x7fff5bfde5e4 52 4d 4b 52 RMKR 
      0x7fff5bfde5e8 47 42 43 53 GBCS 
      0x7fff5bfde5ec 56 49 41 54 VIAT 
      0x7fff5bfde5f0 51 41 4d 59 QAMY 
      0x7fff5bfde5f4 4c 4c 52 46 LLRF 
      0x7fff5bfde5f8 49 57 58 56 IWXV 
      0x7fff5bfde5fc 50 57 52 50 PWRP 
      0x7fff5bfde600 00 10 40 00 [email protected] 

     p1 0x7fff5bfde5a8 b0 e5 fd 5b ...[ 
      0x7fff5bfde5ac ff 7f 00 00 .... 

     p2 0x7fff5bfde5a0 b0 e5 fd 5b ...[ 
      0x7fff5bfde5a4 ff 7f 00 00 .... 

     p3 0x7fff5bfde598 48 83 0f 5c H..\ 
      0x7fff5bfde59c c1 2a 00 00 .*.. 

     p4 0x7fff5bfde590 00 00 00 00 .... 
      0x7fff5bfde594 01 00 00 00 .... 

acStrのが変更されている内容持っていますが、そのアドレスは同じまま。現在はp2p1の両方にそのアドレスのコピーが含まれています。

func3func4を呼び出しても同じことが起こります。呼び出しの間で変化しない入力のアドレスを返します。そのアドレス値はp3p4のそれぞれにコピーされます。

+0

これは詳細な説明です... – sapitando

関連する問題