2016-08-29 1 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 

Я не быть ясно, что это потому, что я не говорю на английском (Перевод Google translante)

+4

Потому что вы передаете им одно и то же каждый раз? –

+2

Что именно вы ожидали? –

+0

- разные указатели с различными функциями и всегда генерируют один и тот же адрес, затем я теряю значение предыдущего ... – sapitando

ответ

2

В ваших 4 функции вы возвращаете тот же указатель, который был передан в качестве аргумента, таким образом, его не меняется. Он все еще указывает на ту же переменную acStr.

Добавление const к типу аргумента не создает копию; это просто мешает вам изменять его содержимое.

Также str[] и *str в этом случае одинаковы.

+0

если бы я это сделал: p1 = func1 («ABCDEFGHIJ»); Затем создайте копию. – sapitando

+0

Другой способ передается по ссылке. – sapitando

+0

В этом случае возвращаемый указатель будет другим (если вы все равно не передадите 4 вещи одинаково, а параметр компилятора для объединения повторяющихся строковых литералов был отключен). И ничего не копируется. –

2

Все ваши функции возвращают значение их аргумента; во всех четырех случаях функции получают адрес первого элемента 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 .... 

массива объект 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 [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 (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 [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 были изменены, но его адрес остается прежним. Теперь оба p2 и p1 содержат копии этого адреса.

То же самое происходит с звонками func3 и func4; они возвращают адрес своего входа, который не изменяется между вызовами. Это значение адреса копируется на каждый из p3 и p4.

+0

Это подробное объяснение ... – sapitando

Смежные вопросы