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
开始,等等。请注意,编译器不必按照声明的相同顺序放置单独的对象。
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 以小端顺序存储多字节值,因此它们读取 "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
的内容,但其地址保持不变。现在 p2
和 p1
都包含该地址的副本。
调用 func3
和 func4
也会发生同样的事情;他们 return 他们输入的地址,在调用之间不会改变。该地址值被复制到每个 p3
和 p4
。
为什么都指向同一个地方?是优化吗?
#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
开始,等等。请注意,编译器不必按照声明的相同顺序放置单独的对象。
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 以小端顺序存储多字节值,因此它们读取 "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
的内容,但其地址保持不变。现在 p2
和 p1
都包含该地址的副本。
调用 func3
和 func4
也会发生同样的事情;他们 return 他们输入的地址,在调用之间不会改变。该地址值被复制到每个 p3
和 p4
。