c - 为什么它们都指向同一个地方?

c - Why do they all point to the same place?

为什么都指向同一个地方?是优化吗?

#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

我不清楚,因为我不会说英语 (由 Google 翻译)

在您的 4 个函数中,您 return 作为参数传递的相同指针,因此它不会改变。它仍然指向同一个 acStr 变量。

const 添加到参数类型不会创建副本;它只是阻止您更改其内容。

此外 str[]*str 在这种情况下是相同的。

你所有的函数return它们参数的值;在所有四种情况下,函数都接收 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    ..@.

         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    ....

数组对象acStr起始于地址0x7fff5bfde5b0;你已经初始化它,所以它包含所有零。指针变量 p1 从地址 0x7fff5bfde5a8 开始,p2 从地址 0x7fff5bfde5a0 开始,等等。请注意,编译器不必按照声明的相同顺序放置单独的对象。

p1p2p3p4 中的每一个最初都包含一个 不确定的 值;他们没有特别指向任何对象。在此阶段尝试取消引用它们中的每一个将导致未定义的行为。

调用 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    ..@.

         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 的地址(x86 以小端顺序存储多字节值,因此它们读取 "backwards")。

调用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    ..@.

         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 也会发生同样的事情;他们 return 他们输入的地址,在调用之间不会改变。该地址值被复制到每个 p3p4