Thread: A few questions about string literals and inputting strings

  1. #1
    Registered User
    Join Date
    Nov 2010
    Posts
    12

    A few questions about string literals and inputting strings

    I'm trying to gain a better intuition on how string literals work in C.

    Code:
    char * c = "hello";
    
    c = "goodbye";
    After the code segment above completes, what happens to the space in memory where the bytes making up the string "hello" are located? Does that space remain untouchable for the life of the program even though it's no longer accessible, or is it "freed up" the second I assign c = "goodbye"?


    Also, what would the following code do?
    Code:
    "howdy";
    Would it create space for "howdy" and then free it back up right after the statement completes? Are these string literals put into memory at compile time or run time? If it's compile time, does that mean it lives for the life of the program?


    Similarly, when you write the statement "char c[30];" are those 30 bytes set aside at compile time or run time? What if the "char c[30];" was declared within a function. What happens when the function completes (and c no longer exists?)? Are the 30 bytes ever "freed up", or are they just sitting there, unable to be used for the rest of the program?



    Finally, the following code produces a seg-fault when I run it and enter a single-character string for input, and I'm trying to understand why.
    Code:
    char * c = "hello";
    
    scanf( "%s", c );
    My current understanding of the above code segment is this: a pointer to a character is declared and given the name c. The base address of the string "hello" is then assigned to c. When I run this, I enter the string "a" as my input, which scanf writes to the location specified by c, which is the base address of "hello". So why does this give me a seg-fault? Shouldn't I be able to input any string that is the same size or smaller than the string "hello"? What am I not thinking about correctly?

    Also, in the above example (which was only constructed for learning purposes) for a real program I would replace the "char * c = "hello";" with "char c[100];". Is this the way it's usually done if you're just inputting a string?

    I'm very confused. However many questions you feel like answering, I'm grateful.
    Last edited by itsthemac; 03-27-2011 at 09:57 PM.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    String literals are never freed. As a matter of fact, it would be wrong to try to do so:
    Code:
    c = "hello";
    free( c ); /* wrong */
    A variable declared in a function, unless specified as static is destroyed when that function ends. Now, there's a difference here:
    Code:
    void foo( void )
    {
        char *c = "world";
    }
    When you call foo, the variable c is created. When foo ends, the variable c is destroyed. What it points at however, isn't destroyed or freed. It wouldn't even be freed if you had allocated it dynamically inside that function.

    The pointer itself is destroyed when the function ends. What it points at is not.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Most of your questions are compiler/environment-specific. How memory is handled behind the scenes is largely implementation-specific. Some things are optimized right out of existence by the compiler.
    If you understand what you're doing, you're not learning anything.

  4. #4
    Registered User
    Join Date
    May 2010
    Location
    Naypyidaw
    Posts
    1,314
    String literal like "hello" are not modifiable. Their life time is same as static variable. They'll live as long as program is running.

    "char c[30];" was declared within a function. What happens when the function completes (and c no longer exists?)? Are the 30 bytes ever "freed up", or are they just sitting there, unable to be used for the rest of the program?
    ,
    Local variables are allocated on stack. and once function returns they die. Note the same for local scope variable.
    That's why returning local variable address is wrong.
    eg.
    Code:
    char *foo(void) {
       char c[100];
       ...
       return c;          // wrong!
    
    }
    
    char *p;
     {
       char c[100];
       p = c;
     }                 // p is no longer pointing to valid memory.
    Also, in the above example (which was only constructed for learning purposes) for a real program I would replace the "char * c = "hello";" with "char c[100];". Is this the way it's usually done if you're just inputting a string?
    Pointer and array are different things. char c[100] means you have memory to hold 100 char.
    char *c means you just have a pointer which is un-initialized. You need to initialize it to point to some memory.
    Last edited by Bayint Naung; 03-27-2011 at 10:29 PM.

  5. #5
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Indeed, these questions are somewhat compiler and platform dependant.

    syntax - C++ strings: [] vs. * - Stack Overflow is a good page to explain briefly the difference between char c[] = "hi" and char* c = "hi".

    Quote Originally Posted by itsthemac View Post

    Also, what would the following code do?
    Code:
    "howdy";
    Would it create space for "howdy" and then free it back up right after the statement completes? Are these string literals put into memory at compile time or run time? If it's compile time, does that mean it lives for the life of the program?
    Whether or not it exists in the executable file at all is compiler dependent. I'd expect most decent optimising compiler/linkers to remove it.

    I don't think it could ever incur any run-time overhead.

    For char* c = "hello there" --

    The compiler will put "hello world" as data into the executable file (where and how depends on the platform). Then in a simple world, when you start executing the program, it will load all of the global variables and string literals before getting to main().

    Similarly, when you write the statement "char c[30];" are those 30 bytes set aside at compile time or run time? What if the "char c[30];" was declared within a function. What happens when the function completes (and c no longer exists?)? Are the 30 bytes ever "freed up", or are they just sitting there, unable to be used for the rest of the program?
    char c[30] is a proper variable that'll probably be allocated on the stack if it's a local variable. As far as i know the memory will be freed at the end of the function.

    Finally, the following code produces a seg-fault when I run it and enter a single-character string for input, and I'm trying to understand why.
    Code:
    char * c = "hello";
    
    scanf( "%s", c );
    My current understanding of the above code segment is this: a pointer to a character is declared and given the name c. The base address of the string "hello" is then assigned to c. When I run this, I enter the string "a" as my input, which scanf writes to the location specified by c, which is the base address of "hello". So why does this give me a seg-fault? Shouldn't I be able to input any string that is the same size or smaller than the string "hello"? What am I not thinking about correctly?
    Your understanding is correct -- the scanf will try to write to the memory where "hello world" is held. But string literals specified in this manner are const, and cannot be modified.
    This would fail with a segfault too:

    Code:
     
    char *c = "hello world";
    c[1] = 'a';
    I believe this is part of the C standard. Certainly some compilers/linkers rely on the non-modifiable-ness of string literals and merge identical strings to save space (I doubt x86 compilers do this, since executable size is rarely a concern).

    Also, in the above example (which was only constructed for learning purposes) for a real program I would replace the "char * c = "hello";" with "char c[100];". Is this the way it's usually done if you're just inputting a string?
    char *c = "hello"; is fine and good for strings you don't want to modify.

    You can use
    char c[] = "hello"; to do the same-ish thing and get a modifiable string on the stack (has additional run time overhead of copying the literal onto the stack). You could use scanf on a string defined in this manor.

    I'd favour char c[100] or similar -- allocating an appropriate length string for any input that may be read to it. Otherwise you could easily get careless and not have a long enough array for some input. Or of course you can dynamically allocate memory with malloc:

    char *c = (char*)malloc(100);
    Last edited by smokeyangel; 03-27-2011 at 10:46 PM.

  6. #6
    Registered User
    Join Date
    Nov 2010
    Posts
    12
    Thank you everyone for the help!

Popular pages Recent additions subscribe to a feed