pointers on string in C - c

I have this program in C
#include<stdio.h>
int main()
{
printf("Hello New!\n");
char c = 'd';
char* s = "hello world";
char **t = &s;
*t[0] = c;
return 0;
}
The program compiles but doesn't run.
I have this output :
Hello New!
Bus error
I don't understand why

String constants are stored in readonly memory and you cannot modify them.
If you must, then use:
#include<stdio.h>
int main()
{
printf("Hello New!\n");
char c = 'd';
char s[] = "hello world";
char **t = &s[0];
*t[0] = c;
return 0;
}
This allocates a local variable (not a constant) that is conveniently initialized and may be modified to your heart's content.

You may not modify the string that 's' points to, in any way. It is in a part of memory that you are not allowed to change.

String constants are unmodifiable, despite having the type char* rather than const char* for historical reasons. Try using the string constant to initialize an array, rather than a pointer:
#include <stdio.h>
int
main(void)
{
char s[] = "hello new!";
puts(s);
s[0] = 'c';
puts(s);
return 0;
}

A bus error usually means that you're accessing a pointer with an invalid value - e.g. an address that is out of the address space.
I would guess that in this case, it is because you are trying to write to memory that is read-only. The string "hello world" is in a memory segment that you are not allowed to write to. Depending on the operating system, these memory segments are either protected or you can write arbitrary garbage to it. Seems like yours doesn't allow it. As you can see in the other answers, you can work around this by copying/initializing the string constant into an array.

Related

Bus error in my own strcat using pointer

I'm doing a pointer version of the strcat function, and this is my code:
void strcat(char *s, char *t);
int main(void) {
char *s = "Hello ";
char *t = "world\n";
strcat(s, t);
return 0;
}
void strcat(char *s, char *t) {
while (*s)
s++;
while ((*s++ = *t++))
;
}
This seems straightforward enough, but it gives bus error when running on my Mac OS 10.10.3. I can't see why...
In your code
char *s = "Hello ";
s points to a string literal which resides in read-only memory location. So, the problem is twofold
Trying to alter the content of the string literal invokes undefined behaviour.
(almost ignoring point 1) The destination pointer does not have enough memory to hold the concatinated final result. Memory overrun. Again undefined behaviour.
You should use an array (which resides in read-write memory) with sufficient length to hold the resulting (final) string instead (no memory overrun).
Suggestion: Don't use the same name for user-defined functions as that of the library functions. use some other name, e.g., my_strcat().
Pseudocode:
#define MAXVAL 512
char s[MAXVAL] = "Hello";
char *t = "world\n"; //are you sure you want the \n at the end?
and then
my_strcat(s, t);
you are adding the text of 't' after the last addres s is pointing to
char *s = "Hello ";
char *t = "world\n";
but writing after 's' is undefined behavior because the compiler might put that text in constant memory, in your case it crashes so it actually does.
you should reserve enough memory where s points to by either using malloc or declare it array style
char s[32] = "Hello ";

How do I avoid segmentation fault?

The code is self-explanatory, but it gives me segmentation fault, why? :\
#include <stdio.h>
int main(void)
{
char *c = "Hella";
*(c+4) = 'o';
printf("%s\n",c);
}
How to avoid it?
Don't modify a string literal!
char *c = "Hella";
Declares a pointer c to a string literal "Hella" stored in implementation defined read only memory.
You are not allowed to modify this literal. An attempt to do so results in Undefined Behavior.
You are lucky that your program crashes, an Undefined Behavior does not always result in a crash but may cause your program to behave weirdly in any possible way.
What you need here is an array:
char c[] = "Hella";
Good Read:
What is the difference between char a[] = ?string?; and char *p = ?string?;?
Put your string into an array allocated onto the stack:
char c[] = "Hella";
Because as said, string literals are usually read-only.
the way you create c it points to a string literal. You can not modify it's contents. If you want to be able to do that use:
char c[6] = "Hella";
c[4] = o;
Or use a dynamically allocated char array.
You are trying to overwrite a literal. Really your code should read:
const char *c = "Hella";
Which kinda explains what is going on.
To overwrite your own memory:
char c[] = "Hella";
is safer.
You can not modify strings that are defined in code. Use strdup if you want to modify them.
#include <stdio.h>
int main(void)
{
char *c = strdup("Hella");
*(c+4) = 'o';
printf("%s\n",c);
free(c);
}

Can I initialize string after declaration?

Can I initialize string after declaration?
char *s;
s = "test";
instead of
char *s = "test";
You can, but keep in mind that with that statements you are storing in s a pointer to a read-only string allocated elsewhere. Any attempt to modify it will result in undefined behavior (i.e., on some compilers it may work, but often will just crash). That's why usually you use a const char * for that thing.
Yes, you can.
#include <stdio.h>
int
main(void)
{
// `s' is a pointer to `const char' because `s' may point to a string which
// is in read-only memory.
char const *s;
s = "hello";
puts(s);
return 0;
}
NB: It doesn't work with arrays.
#include <stdio.h>
int
main(void)
{
char s[32];
s = "hello"; // Syntax error.
puts(s);
return 0;
}
It is correct for pointers (as mentioned above) because the string inside quotes is allocated from the compiler at compile time, so you can point to this memory address. The problems comes when you try change its contents or when you have a fixed size array that want to point there

changing one char in a c string

I am trying to understand why the following code is illegal:
int main ()
{
char *c = "hello";
c[3] = 'g'; // segmentation fault here
return 0;
}
What is the compiler doing when it encounters char *c = "hello";?
The way I understand it, its an automatic array of char, and c is a pointer to the first char. If so, c[3] is like *(c + 3) and I should be able to make the assignment.
Just trying to understand the way the compiler works.
String constants are immutable. You cannot change them, even if you assign them to a char * (so assign them to a const char * so you don't forget).
To go into some more detail, your code is roughly equivalent to:
int main() {
static const char ___internal_string[] = "hello";
char *c = (char *)___internal_string;
c[3] = 'g';
return 0;
}
This ___internal_string is often allocated to a read-only data segment - any attempt to change the data there results in a crash (strictly speaking, other results can happen as well - this is an example of 'undefined behavior'). Due to historical reasons, however, the compiler lets you assign to a char *, giving you the false impression that you can modify it.
Note that if you did this, it would work:
char c[] = "hello";
c[3] = 'g'; // ok
This is because we're initializing a non-const character array. Although the syntax looks similar, it is treated differently by the compiler.
there's a difference between these:
char c[] = "hello";
and
char *c = "hello";
In the first case the compiler allocates space on the stack for 6 bytes (i.e. 5 bytes for "hello" and one for the null-terminator.
In the second case the compiler generates a static const string called "hello" in a global area (aka a string literal, and allocates a pointer on the stack that is initialized to point to that const string.
You cannot modify a const string, and that's why you're getting a segfault.
You can't change the contents of a string literal. You need to make a copy.
#include <string.h>
int main ()
{
char *c = strdup("hello"); // Make a copy of "hello"
c[3] = 'g';
free(c);
return 0;
}

Is it possible to modify a string of char in C?

I have been struggling for a few hours with all sorts of C tutorials and books related to pointers but what I really want to know is if it's possible to change a char pointer once it's been created.
This is what I have tried:
char *a = "This is a string";
char *b = "new string";
a[2] = b[1]; // Causes a segment fault
*b[2] = b[1]; // This almost seems like it would work but the compiler throws an error.
So is there any way to change the values inside the strings rather than the pointer addresses?
When you write a "string" in your source code, it gets written directly into the executable because that value needs to be known at compile time (there are tools available to pull software apart and find all the plain text strings in them). When you write char *a = "This is a string", the location of "This is a string" is in the executable, and the location a points to, is in the executable. The data in the executable image is read-only.
What you need to do (as the other answers have pointed out) is create that memory in a location that is not read only--on the heap, or in the stack frame. If you declare a local array, then space is made on the stack for each element of that array, and the string literal (which is stored in the executable) is copied to that space in the stack.
char a[] = "This is a string";
you can also copy that data manually by allocating some memory on the heap, and then using strcpy() to copy a string literal into that space.
char *a = malloc(256);
strcpy(a, "This is a string");
Whenever you allocate space using malloc() remember to call free() when you are finished with it (read: memory leak).
Basically, you have to keep track of where your data is. Whenever you write a string in your source, that string is read only (otherwise you would be potentially changing the behavior of the executable--imagine if you wrote char *a = "hello"; and then changed a[0] to 'c'. Then somewhere else wrote printf("hello");. If you were allowed to change the first character of "hello", and your compiler only stored it once (it should), then printf("hello"); would output cello!)
No, you cannot modify it, as the string can be stored in read-only memory. If you want to modify it, you can use an array instead e.g.
char a[] = "This is a string";
Or alternately, you could allocate memory using malloc e.g.
char *a = malloc(100);
strcpy(a, "This is a string");
free(a); // deallocate memory once you've done
A lot of folks get confused about the difference between char* and char[] in conjunction with string literals in C. When you write:
char *foo = "hello world";
...you are actually pointing foo to a constant block of memory (in fact, what the compiler does with "hello world" in this instance is implementation-dependent.)
Using char[] instead tells the compiler that you want to create an array and fill it with the contents, "hello world". foo is the a pointer to the first index of the char array. They both are char pointers, but only char[] will point to a locally allocated and mutable block of memory.
The memory for a & b is not allocated by you. The compiler is free to choose a read-only memory location to store the characters. So if you try to change it may result in seg fault. So I suggest you to create a character array yourself. Something like: char a[10]; strcpy(a, "Hello");
It seems like your question has been answered but now you might wonder why char *a = "String" is stored in read-only memory. Well, it is actually left undefined by the c99 standard but most compilers choose to it this way for instances like:
printf("Hello, World\n");
c99 standard(pdf) [page 130, section 6.7.8]:
The declaration:
char s[] = "abc", t[3] = "abc";
defines "plain" char array objects s and t whose elements are initialized with character string literals.
This declaration is identical to char
s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type "pointer to char" and initializes it to point to an object with type "array of char" with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined.
You could also use strdup:
The strdup() function returns a pointer to a new string which is a duplicate of the string s.
Memory for the new string is obtained with malloc(3), and can be freed with free(3).
For you example:
char *a = strdup("stack overflow");
All are good answers explaining why you cannot modify string literals because they are placed in read-only memory. However, when push comes to shove, there is a way to do this. Check out this example:
#include <sys/mman.h>
#include <unistd.h>
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int take_me_back_to_DOS_times(const void *ptr, size_t len);
int main()
{
const *data = "Bender is always sober.";
printf("Before: %s\n", data);
if (take_me_back_to_DOS_times(data, sizeof(data)) != 0)
perror("Time machine appears to be broken!");
memcpy((char *)data + 17, "drunk!", 6);
printf("After: %s\n", data);
return 0;
}
int take_me_back_to_DOS_times(const void *ptr, size_t len)
{
int pagesize;
unsigned long long pg_off;
void *page;
pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize < 0)
return -1;
pg_off = (unsigned long long)ptr % (unsigned long long)pagesize;
page = ((char *)ptr - pg_off);
if (mprotect(page, len + pg_off, PROT_READ | PROT_WRITE | PROT_EXEC) == -1)
return -1;
return 0;
}
I have written this as part of my somewhat deeper thoughts on const-correctness, which you might find interesting (I hope :)).
Hope it helps. Good Luck!
You need to copy the string into another, not read-only memory buffer and modify it there. Use strncpy() for copying the string, strlen() for detecting string length, malloc() and free() for dynamically allocating a buffer for the new string.
For example (C++ like pseudocode):
int stringLength = strlen( sourceString );
char* newBuffer = malloc( stringLength + 1 );
// you should check if newBuffer is 0 here to test for memory allocaton failure - omitted
strncpy( newBuffer, sourceString, stringLength );
newBuffer[stringLength] = 0;
// you can now modify the contents of newBuffer freely
free( newBuffer );
newBuffer = 0;
char *a = "stack overflow";
char *b = "new string, it's real";
int d = strlen(a);
b = malloc(d * sizeof(char));
b = strcpy(b,a);
printf("%s %s\n", a, b);

Resources