0

I am wondering if one could change the string stored in a variable, without changing the address. And I am unable to write the code to do this, since when I write codes like

char* A = "abc";
char* B = "def";
A = B; <-- if I write down this code, then A will point to B and address changes. 

So does anyone know how to do this, changing the string stored in A to "def" ,without changing the initial address of A?

Moreover, I have tried to change only one word in variable A, again, without changing the address.

To do this, I have write the following failure code. BUT I don't know why it fails.

#include <stdio.h>
#include <string.h>

int main(void)
{
    char* s = "ABC";

    // print value and address of s.
    printf("Value of s is %s \n", s);
    printf("Address of s is %p \n", s);

    s[0] = 'v';

    printf("Value of s is %s \n", s);
    printf("Address of s is %p \n", s);
}

Using gdb, I figure out that s[0] = 'v' is invalid and lead to segmentation fault. Why is it the case? Can anyone tell me the reason behind this as well? Thanks.

1

2 Answers 2

2

This answer is based on a similar one of mine from some time ago.

By declaring a string in the manner you have, you have effectively created a const string that is stored in read only memory.

Short answer:


char A[] = "abc";  // 'A' points to a read-write string, which is 4 characters long { 'a', 'b', 'c', '\0' }
char* B;           // 'B' is a pointer that currently points to an unknown area since it isn't initialized
B = A;             // 'A' and 'B' now point to the same chunk of memory
char C[] = "abc";
snprintf(C, strlen(C)+1, "def"); // Modify the contents of the area 'C' points to, but don't change what 'C' actually points to.

Long answer:


Consider the example below:

char strGlobal[10] = "Global";

int main(void) {
  char* str = "Stack";
  char* st2 = "NewStack";
  str = str2;  // OK
  strcpy(str, str2); // Will crash
}

To be safe, you should actually allocate as a pointer to const data to make sure you don't attempt to modify the data.

const char* str = "Stack"; // Same effect as char* str, but the compiler
                           // now provides additional warnings against doing something dangerous

The first way of allocating memory is static allocation in read-only memory (ie: as with str and str2).

The second allocation is known as dynamic allocation, which allocates memory on the heap, not the stack. The string can be modified without hassle. At some point, you need to free this dynamically allocated memory via the free() command.

There is a third means of allocating a string, which is static allocation on the stack. This allows you to modify the contents of the array which is holding the string, and it is statically allocated.

char str[] = "Stack";

In summary:

Example:                       Allocation Type:     Read/Write:    Storage Location:
================================================================================
const char* str = "Stack";     Static               Read-only      Code segment
char* str = "Stack";           Static               Read-only      Code segment
char* str = malloc(...);       Dynamic              Read-write     Heap
char str[] = "Stack";          Static               Read-write     Stack
char strGlobal[10] = "Global"; Static               Read-write     Data Segment (R/W)
Sign up to request clarification or add additional context in comments.

7 Comments

It looks like you copied a significant portion of your other answer - which is a pretty good answer, by the way. You may want to link that answer, so that in case you or someone else makes improvements to it, both places would benefit.
Thanks. I learn a lot from you and the summary is really cool.
@dasblinkenlight Will do. Normally I just flag as a duplicate, but it gets ignored.
"Code segment" isn't really correct. On ELF targets, it will end up in a .rodata section, which is separate from the .text section. And, those should be in different loaded segments as .rodata should be r-- while .txt should be r-x, and .data should be rw-.
On a Linux machine: $ readelf -a random_elf_file might be the most enlightening. That and /proc/[some pid]/maps.
|
1

You can change a string only when its content resides in "writable" memory. When you do this

char* A = "abc";

the content of the string A, a string literal, resides in memory that cannot be written. However, if you change the declaration to this

char A[] = "abc";

your string would become writable, and you would be able to copy new content into it:

char A[] = "abc";
char* B = "def";
strcpy(A, B);

The address of the string would remain the same.

One caveat here is that you cannot copy a string into A if its content is longer than that of your original string. To work around this issue, declare A with a specific size, like this:

char A[100] = "abc";
char* B = "quick brown fox jumps over the lazy dog";
strcpy(A, B); // This would work fine

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.