-1

Why do they all point to the same place? It is an optimization?

#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;
}

Output.

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

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

I'm not being clear, it's because I do not speak English (Translated by Google translante)

sapitando
  • 59
  • 4
  • 4
    Because you are passing them the same thing each time? – Eugene Sh. Aug 29 '16 at 17:28
  • 2
    What exactly were you expecting? – Fred Larson Aug 29 '16 at 17:29
  • are different pointers with different functions , and always generates the same address, then I lose the value of previous ... – sapitando Aug 29 '16 at 17:34
  • 2
    There is only one string. Every function returns what was passed to it, which is that same string. You changed the *content* of the string between each call, but the string is still the same one, at the same location in memory. – Weather Vane Aug 29 '16 at 17:35
  • Of topic: When printing pointers, you must cast to `void*`. Like `printf("p1 == %p\n", (void*)p1);` else it is UB – Support Ukraine Aug 29 '16 at 17:39
  • 1
    You pass an array to the functions. The array decays to a pointer, and you return that pointer. There is no difference between any of the 4 functions, they are identical. You pass the same array, and you get the same thing back. – Weather Vane Aug 29 '16 at 17:39
  • I thought it had something to do with Data segment or .rodata. – sapitando Aug 29 '16 at 17:59
  • I know how to avoid this , such as: char *p1 = (char *)malloc(80 * sizeof(char)); strcpy(p1, func1(acStr)); What I do not understand is why always returns the same address .. – sapitando Aug 29 '16 at 18:15
  • @Weather Vane Detail: "Every function returns what was passed to it, which is that same string." may mis-lead novice OP. The functions do not receive nor return a string. The functions receive and return a _character pointer_. That pointer points to the beginning of the string. – chux - Reinstate Monica Aug 29 '16 at 18:19
  • @chux my next comment after clarified that. The function receives an *array* which decays to a pointer. – Weather Vane Aug 29 '16 at 18:26
  • @Weather Vane Certainly we know the array conversion mechanics, yet further detail that I state for OP's clarity. The function was called with an array, yet the function does not receive the array, the conversion happens before the function argument is assigned. The function only receives a pointer. 6.0001 vs. half-a-dozen of the other. – chux - Reinstate Monica Aug 29 '16 at 18:37
  • Learn Pascal and then move to C , happens these blunders . – sapitando Aug 29 '16 at 18:48
  • @chux "is given" vs "receives" ... semantics! – Weather Vane Aug 29 '16 at 19:02
  • @Weather Vane The C spec distinguishes these using the semantics "actual argument" and `"formal parameter". If the C spec did not distinguish these, neither would I. – chux - Reinstate Monica Aug 29 '16 at 19:16

2 Answers2

2

In your 4 functions you return the same pointer that was passed as an argument, thus it doesn't change. It's still pointing to the same acStr variable.

Adding const to the argument type doesn't create a copy; it just prevents you from changing its content.

Also str[] and *str are the same in this case.

pleluron
  • 733
  • 4
  • 12
  • if I had done it : p1 = func1("ABCDEFGHIJ"); Then generate a copy. – sapitando Aug 29 '16 at 18:36
  • The other way is passed by reference. – sapitando Aug 29 '16 at 18:39
  • In that case the pointer returned would be different (unless you still pass 4 things the same, and the compiler option to merge duplicate string literals was disabled). And nothing is copied. – Weather Vane Aug 29 '16 at 18:43
  • @Weather Vane In this case it enters the aspect of literal strings and .rodata ? – sapitando Aug 29 '16 at 19:04
  • @sapitando you suggested passing a string literal. I replied that if you pass what *appears to be* the same string literal to each function, then you *could* get a different pointer back from each - unless you enable a compiler option to merge duplicate string literals. – Weather Vane Aug 29 '16 at 19:11
  • @Weather Vane Sorry if I 'm not being concise ( Blame Google translator) , but I understood what you said , just to make sure I understood what I asked. This String Literal going to read only memory . – sapitando Aug 29 '16 at 19:18
2

All of your functions return the value of their argument; in all four cases, the functions are receiving the address of the first element of acStr.

You're not changing where acStr is being stored between each call; you're only changing what acStr contains.

I took your code and added some calls to dump a memory map of your variables. Here's how things look at the very beginning, before you call 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    ....

The array object acStr starts at address 0x7fff5bfde5b0; you've initialized it so that it contains all zeros. The pointer variable p1 starts at address 0x7fff5bfde5a8, p2 starts at address 0x7fff5bfde5a0, etc. Note that the compiler does not have to lay separate objects out in the same order that they were declared.

Each of p1, p2, p3, and p4 initially contain an indeterminate value; they don't point to any object in particular. Trying to dereference each one of them at this stage would lead to undefined behavior.

After the call to func1, your objects look like this:

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

The contents of acStr have been modified, but its address stays the same. Similarly, the contents of p1 have been modified; it now contains the address of acStr (x86 stores multi-byte values in little-endian order, so they read "backwards").

After the call to func2, we have

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

Again the contents of acStr have been modified, but its address remains the same. Now both p2 and p1 contain copies of that address.

The same thing happens with the calls to func3 and func4; they return the address of their input, which doesn't change between the calls. That address value is copied to each of p3 and p4.

John Bode
  • 119,563
  • 19
  • 122
  • 198