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

C 为什么它们都指向同一个地方?,c,pointers,string-literals,C,Pointers,String Literals,为什么它们都指向同一个地方?这是一个优化 #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(co

为什么它们都指向同一个地方?这是一个优化

#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;
}
#包括
#包括
#包括
#包括
#包括
常量字符*func1(常量字符字符串[]){
//printf(“%p\n”,str);
返回str;
}
常量字符*func2(常量字符*str){
//printf(“%p\n”,str);
返回str;
}
char*func3(char str[]{
//printf(“%p\n”,str);
返回str;
}
char*func4(char*str){
//printf(“%p\n”,str);
返回str;
}
内部主(空)
{
char acStr[81]={0};
常量字符*p1,*p2;
字符*p3,*p4;
uint32\u t uiCount;
srand(时间(空));
对于(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);
对于(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);
对于(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);
对于(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);/*相同地址*/
printf(“%s”,p1);
printf(“p2==%p\n”,p2);/*相同地址*/
printf(“%s”,p2);
printf(“p3==%p\n”,p3);/*相同地址*/
printf(“%s”,p3);
printf(“p4==%p\n”,p4);/*相同地址*/
printf(“%s”,p4);
getch();
返回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 p1==0000000000 22FDC0 USOPBBREKRTCAXSRFVPJPEVPESVTAIQUXIPNMCAWZGWWWWWWWWWWGFRCTHLJLLANVSRQJCTCOXQZIYX p2==0000000000 22fdc0 SVITQWBDXTQSUJKXIUKIANTUELJCJPVDYEBCIDGWITCTZJTDERRPINICWNSIIKMAVTFKIUHEEGNEKBD p3==0000000000 22fdc0 IDTZXTQWPSRURMWBCAKXWKXJANLVRDMDREGKBYKJZMDHYHSGRMYAAAGWWRWSAJMBYDZYBKYPmVxN p4==0000000000 22fdc0 TFCBRYSYRNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRSGDZWIXOVKYPBRQOEXRFUJ p1==0000000000 22FDC0 TFCBRYSYRNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRSGDZWIXOVKYPBRQOEXRFUJ p2==0000000000 22fdc0 TFCBRYSYRNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRSGDZWIXOVKYPBRQOEXRFUJ p3==0000000000 22fdc0 TFCBRYSYRNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRSGDZWIXOVKYPBRQOEXRFUJ p4==0000000000 22fdc0 TFCBRYSYRNDUEEOQAPMAGOVQKYNIKNGOQJSBFKYTVRIGWHZMCLFNASRSGDZWIXOVKYPBRQOEXRFUJ 我不清楚,因为我不会说英语
(由Google translante翻译)

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

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


在这种情况下,
str[]
*str
也是相同的。

所有函数都返回其参数的值;在所有四种情况下,函数都接收
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,等等。请注意,编译器不必按照声明对象的相同顺序排列单独的对象

p1
p2
p3
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    ..@.

         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以小尾端顺序存储多字节值,因此它们读取“向后”)

调用
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
的内容,但其地址保持不变。现在
p2
p1
都包含该地址的副本


func3
func4
的调用也会发生同样的情况;它们返回输入的地址,在两次调用之间不会改变。该地址值被复制到
p3
p4
中的每一个

因为你每次都传递相同的东西?你到底期望什么?不同的指针具有不同的函数,并且总是生成相同的地址,那么我就失去了previous的值…只有一个字符串。每个函数都返回传递给它的内容,即相同的字符串。您在每次调用之间更改了字符串的内容,但字符串仍然是相同的,位于内存中的相同位置。您将数组传递给函数。数组衰减为指针,然后返回该指针。这4个功能中的任何一个都没有区别,它们是相同的。您传递相同的数组,然后返回相同的内容;然后生成一个副本。另一种方法是通过引用传递。在这种情况下,返回的指针将不同(除非您仍然传递4个相同的内容,并且编译器选项合并重复项)