Thread: Pass by Reference with a pointer to char

  1. #1
    Registered User
    Join Date
    Oct 2008
    Posts
    11

    Pass by Reference with a pointer to char

    I'm relatively new to C and I was pretty sure I had a decent understanding of pointers and how they are used. However, I was just playing around with the concept of Pass by Reference and came across a bit of a delima. Hopefully someone can help explain this to me....

    I have 2 small programs to test my knowledge of pass by reference and I wanted them both to have the same results however they do not:

    Program 1
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    int main(){
    
     char* hostname= (char*)calloc(10, sizeof(hostname));
     hostname = "unchanged";
     printf("Address of hostname = %d\n", &hostname);
     someFunction(&hostname);
     printf("Hostname: %s\n", hostname);
     return 0;
    
    }
    
    
    someFunction(char** s){
    
       printf("s = %d\n", s);
       printf("Address of s = %d\n", &s);
       printf("*(&s) = %d\n", *(&s));
       *s = "changed";
    }
    Program 2

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    int main(){
     char* hostname = (char*)calloc(10, sizeof(hostname));
     hostname = "unchanged";
     printf("Address of hostname = %d\n", &hostname);
     someFunction(&hostname);
     printf("Hostname: %s\n", hostname);
     return 0;
    }
    
    
    someFunction(char* s){
    
       printf("s = %d\n", s);
       printf("Address of s = %d\n", &s);
       printf("*(&s) = %d\n", *(&s));
       *(&s) = "changed";
    
    }
    The results of Program 1 gives me what I expected which was hostname being changed to "change":

    Address of hostname = -1073845548
    s = -1073845548
    Address of s = -1073845584
    *(&s) = -1073845548
    Hostname: changed

    The results of Program 2 do not give me what I expected. Can someone please tell my why hostname does not get "changed" in this example?

    Address of hostname = -1074574892
    s = -1074574892
    Address of s = -1074574928
    *(&s) = -1074574892
    Hostname: unchanged

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    * and & "eat" each other, so *(&s) is the same as s (in fact, the standard says that a compiler is free to pretend you typed s, and doesn't have to fetch the pointer+dereference if it doesn't want to), so this is the same as typing "s = "changed";" and as you know changes made to the parameter (in this case s) are not seen in the calling function.

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Code:
    char* hostname= (char*)calloc(10, sizeof(hostname)); // allocates
    hostname = "unchanged"; // memory leak
    *(&s) is no different from simply s, or for that matter *(&(*(&(*(&s))))

    Don't use this to print an address:

    >> printf("s = &#37;d\n", s);

    Instead:

    printf("s = %x\n", s);

    The second version of 'someFunction' expects a char*, but you pass it a char**.

    My advice to you would be to spend a bit more time with your C programming text on pointers...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Registered User
    Join Date
    Oct 2008
    Posts
    11
    Hmm ok I understand that part I think...I had initially tried to do it like this but got a compile error:

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    int main(){
     char* hostname = (char*)calloc(10, sizeof(hostname));
     hostname = "unchanged";
     printf("Address of hostname = %d\n", &hostname);
     someFunction(&hostname);
     printf("Hostname: %s\n", hostname);
     return 0;
    }
    
    
    someFunction(char* s){
    
       printf("s = %d\n", s);
       printf("Address of s = %d\n", &s);
       printf("*(&s) = %d\n", *(&s));
       *s = "changed";
    
    }
    passbyref.c: In function `someFunction':
    passbyref.c:19: warning: assignment makes integer from pointer without a cast

    Any idea why this doesn't work?

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by JoshNCSU22 View Post
    Hmm ok I understand that part I think...I had initially tried to do it like this but got a compile error:

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    int main(){
     char* hostname = (char*)calloc(10, sizeof(hostname));
     hostname = "unchanged";
     printf("Address of hostname = %d\n", &hostname);
     someFunction(&hostname);
     printf("Hostname: %s\n", hostname);
     return 0;
    }
    
    someFunction(char* s){
    
       printf("s = %d\n", s);
       printf("Address of s = %d\n", &s);
       printf("*(&s) = %d\n", *(&s));
       *s = "changed";
    
    }
    passbyref.c: In function `someFunction':
    passbyref.c:19: warning: assignment makes integer from pointer without a cast

    Any idea why this doesn't work?
    Because it tries to assign a pointer ("changed" is a pointer-to-const-char) to an integral type (*s is just a char).

  6. #6
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Code:
    *s = "changed";
    s is a char * so *s is a char. "changed" in that context is a pointer to an array of characters. So you are trying to assign a pointer to a char (which is an integer).

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    There are two options here: Either pass in a pointer to the pointer to char, so that you can change the pointer to char to a different address - which if your original pointer is malloc'd, you'd leak it if you change the pointer.

    The second option is that you keep the pointer pointing to the same address, but update the content of that address. In this case, you will need to fix the code in main so that you use strcpy(hostname, "unchanged") instead of just pointing to the location of the constant "unchanged", since the latter should not be changed.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If you assign string literals, the type should be const char*, not char*.
    And realize that string literals are pointers! So you allocate memory and assign its address to a pointer, then you later assign a new address to the pointer, overwriting the old address. Memory leak!
    You cannot assign strings in C, you can only assign string literals. What does this mean? You can assign the address of a string (string literal) to a pointer, but you cannot copy a string you assignment:

    Code:
    char arr[50];
    arr = "My string"; // Error, cannot copy string
    const char* p;
    p = "My string"; // OK, assigns the address where "My string" resides to p.
    char* p2;
    p2 = "My string"; // Bad, string literals should be const.
    p2 = malloc(50);
    p2 = "My string"; // Bad, memory leak.
    To copy a string, use strcpy.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Mmm, depends. If you're just working with string literals (and the op is) then a simple assignment is all that's necessary.

    const char * s = "foo";
    const char ** t = s;
    *t = "bar";

    like that.

  10. #10
    Registered User
    Join Date
    Oct 2008
    Posts
    11
    Sebastiani,

    Just so I understand why ' hostname = "unchanged" ' is memory leak...

    Is that because hostname is a pointer to char and "unchanged" is also a pointer to char, then I allocate memory for hostname and then set it equal to another pointer? Sorry if that's way off I would just like to understand the issue better.

  11. #11
    Registered User
    Join Date
    Oct 2008
    Posts
    11
    Whoops just saw the latest posts from Elysia...let me take all that in

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by citizen View Post
    Mmm, depends. If you're just working with string literals (and the op is) then a simple assignment is all that's necessary.

    const char * s = "foo";
    const char ** t = s;
    *t = "bar";

    like that.
    Yeah, it is. They should be const, though, as noted, so you don't make mistakes of assigning or copying into them.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #13
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    >> Just so I understand why ' hostname = "unchanged" ' is memory leak...
    Well, yes. It is your responsibility to free what you allocate. So if you allocate a pointer and later assign it a different address, the memory you allocated is inaccessible. It's called a memory leak because that is wasting your resources and you won't get that data back.

    >> Yeah, it is. They should be const, though, as noted, so you don't make mistakes of assigning or copying into them.
    const data are const so that you don't edit the data. Copying and assigning wholesale is fine.

  14. #14
    Registered User
    Join Date
    Oct 2008
    Posts
    11
    Thanks for clarifying on the memory leak part. I understand now why it's leak; I didn't realize before that string literal actually was a pointer and allocated it's own memory like that. So if I declare something as const char *s = "string"; I don't really need to allocate any memory for it right? That gets take care of automatically?

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by citizen View Post
    >> Yeah, it is. They should be const, though, as noted, so you don't make mistakes of assigning or copying into them.
    const data are const so that you don't edit the data. Copying and assigning wholesale is fine.
    Yeah, so you don't modify it by mistake. The compiler will allow copying and assigning pointers (and string literals) still.

    Quote Originally Posted by JoshNCSU22 View Post
    Thanks for clarifying on the memory leak part. I understand now why it's leak; I didn't realize before that string literal actually was a pointer and allocated it's own memory like that. So if I declare something as const char *s = "string"; I don't really need to allocate any memory for it right? That gets take care of automatically?
    You only seem to misunderstand one thing: string literals do not allocate data.
    The reside in a read-only section and its address is stored in the pointer it's assigned to, so it should be const char*, since modifying (or trying to) the data will create a seg fault.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-13-2011, 08:28 AM
  2. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  3. Speed test result
    By audinue in forum C Programming
    Replies: 4
    Last Post: 07-07-2008, 05:18 AM
  4. Code review
    By Elysia in forum C++ Programming
    Replies: 71
    Last Post: 05-13-2008, 09:42 PM
  5. Problem with OpenGL tutorial
    By 2Biaz in forum Windows Programming
    Replies: 18
    Last Post: 09-16-2004, 11:02 AM