This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Closed 8 years ago.
I have a very simple c question regarding memcopy that I have been able to fix but not understand why. The following code crashes with an "access violation" at runtuime:
char *src = "HELLO WORLD!";
char * dest = "hello world!";
memcpy(dest, src, strlen(src)+1);
dest would appear to be big enough and as I understand it memcpy should just blindly copy the bytes so I don't understand the problem.
Changing dest to an array e.g char dest[13]; fixes things, so is it a requirement that dest must be uninitialized memory and creating an array does this for you whereas the pointer declaration does not?
Cheers
When you do:
char *dest = "hello world!";
"hello world!" is kept in the read-only parts of the memory and pointer named dest is pointed to it, making any writing operation on this memory illegal. So if you try to use it as a destination in your memcpy; it's an access violation.
You should use:
char dest[] = "hello world!";
A string literal, "...", when used to initialise a char pointer, has type const char *, i.e. it's read-only.
dest should therefore have type const char *, at which point your code won't compile.
If you turn all your compiler warnings on then you'll get a warning for the "char * dest = ..." line.
char dest [] = "hello world!" and char* dest = "hello world!" is not the same thing. char dest[]="hello world!" is an array with 13 elements (the string is null-terminated). char* dest ="hello world!" is a pointer to an constant, null terminated string (also 13 characters).
Related
This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 2 years ago.
This program illustrates my question:
#include "stdio.h"
#include "string.h"
void first_try() // segmentation fault
{
size_t numc = 1;
char *dest = "i "; // this is bad? i need to declare character array first? why?
char *src = "lone wolf c program\n";
memcpy(dest, src, numc);
printf("%s", dest);
}
void second_try() // works
{
size_t numc = 1;
char dest[24] = "i get overwritten";
char *src = "lone wolf c program\n";
memcpy(dest, src, 20);
printf("%s", dest);
}
int main(void)
{
//first_try(); // run-time error
second_try();
}
Why does the first_try() method cause a segmentation fault error?
Context
// feel free to ignore this context
I'm still a c programming newb. I went to https://www.devdocs.io and looked at the api for memcpy().
My instinct was to immediately write first_try(). I don't understand the difference between the dest variables in each function. Don't they both contain valid address values?
I read in a "strings as pointers" blog that "the character array containing the string must already exist". Apparently, writing just char *dest = "string"; compiles but is less useful than writing char buf[] = "string"; with a follow-up ptr that can be passed around: char *dest = &buf;. I'd like to understand the 'why' in all of this.
In C all literal strings (like your "i ") is really a non-modifiable array containing the characters in the string, plus the null-terminator.
Attempting to modify a literal string leads to undefined behavior.
When you use a pointer for dest
char *dest = "i ";
you make the pointer point to the first element of the three-element array for the string "i ".
When you use it as a destination for memcpy you attempt to modify the contents of this non-modifiable array, leading to undefined behavior and your crash.
This is why you should generally always use const when defining such pointers:
const char *dest = "i ";
When you use an array for the destination, it's allocated in a writable part of the memory for your program and you can modify it as you please.
But please make sure the destination array is large enough to hold the full source string, including the null-terminator. Otherwise your memcpy call will write out of bounds of the allocated memory, and you will again have undefined behavior.
This question already has answers here:
Why does writing to a string literal in this C program segfault?
(6 answers)
What's wrong with my strcpy? [closed]
(4 answers)
Closed 9 years ago.
Yesterday I had a little trouble with a homemade "strcpy" function. It works now though but I'm a little confused!
char* a = "Hello, World!"; //Works
char b[] = "Hello, World!"; //Works also
strcpy(a, "Hello!"); //Segmentation fault
strcpy(b, "Haha!!"); //Works..
Where is the difference? Why does the char pointer cause a "Segmentation fault"?
Why does this even work? :
char* a = "Haha"; //works
a = "LOL"; //works..
char* a = "Hello, World!";
gives you a pointer to a string literal. A string literal may exist in read only memory so its contents cannot be changed.
char* a = "Haha"; //works
a = "LOL"; //works..
changes the pointer a to point to a different string literal. It doesn't attempt to modify the contents of either string literal so is safe/correct.
char b[] = "Hello, World!"
declares an array on the stack and initialises it with the contents of a string literal. Stack memory is writeable so its perfectly safe to change the contents of this memory.
In your first example since you are trying to write to a read only memory pointed by a,you will get the segmentation fault.If you want to use pointers then allocate the memory on heap,use and delete it after its use.
Where as b is an array of chars initialized with "Hello, World!".
In the second example you are making the pointer to point to different string literal which should be fine.
This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Closed 9 years ago.
In my GCC 32-bit compiler, the following code gives the output
char *str1="United";
printf("%s",str1);
output:
United
then should I consider char *str1="United"; the same as char str1[]="United"?
The two are not the same: char *str1="United" gives you a pointer to a literal string, which must not be modified (else it's undefined behavior). The type of a literal string should really be const but it's non-const for historical reasons. On the other hand, char str1[]="United" gives you a modifiable local string.
char* str = "United"; is read-only. You wouldn't be able to reach inside the string and change parts of it:
*str = 'A';
Will most likely give you a segmentation fault.
On the other hand char str1[] = "United"; is an array and so it can be modified as long as you don't exceed the space allocated for it (arrays cannot be resized). For example this is perfectly legal:
char str[] = "United";
str[0] = 'A';
printf("%s\n", str);
This will print Anited.
See the comp.lang.c.faq, question 1.32. It basically boils down to the fact that declaring the string in array form (char str[] = "foo") is identical to char str[] = {'f','o','o'}, which is identical to char str[] = {102, 111, 111}; that is, it is a normal array on the stack. But when you use a string literal in any other context it becomes "an unnamed, static array of characters, [which] may be stored in read-only memory, and which therefore cannot necessarily be modified." (And trying to modify it results in undefined behavior wherever it happens to be stored, so don't).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between char a[] = “string”; and char *p = “string”;
char *str = "Hello";
printf("%c",++*str);
This gives segmentation fault on linux with gcc.
The moment the first statement is changes to as
char str[10] = "Hello";
It works. What may be the reason?
It is undefined behaviour to attempt to modify a string literal.
The compiler is free to place it in read-only memory (as it probably does in your case). Attempting to modify read-only memory is what's probably triggering the segfault.
This statement char *str = "Hello"; stores the string "Hello" in RO-section and assigns the address of the area of RO-section(in which "Hello"is stored) to str. The data stored in RO-section cannot be modified thus you are getting a segfault.
char str[10] = "Hello";
is also wrong. You should instead write
char str[10];
strncpy(str,"Hello",sizeof(str));
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
Difference between char *str="STRING" and char str[] = "STRING"?
Need some help with C programming
while this snip gets segmentation fault
int main(void) {
char* str ="abcde";
str[strlen(str)-1] ='\0';
printf("%s",str);
return 0;
}
If I put
char str [] ="abcde"; instead of the pointer that works perfectly, do you have an idea why so?
When you write char *str = "abcde"; you make a char pointer to a string literal, which you are not allowed to modify.
When you write char str[] = "abcde"; you make a char array and copy a string literal into it. This is just a normal char array so you are free to modify it.
It is undefined behaviour to modify a string literal. This is a deliberate design decision that allows string literals to be placed in special read only sections of the output program. In practice many compliers and platforms do this (marking it read only means you need only one copy of the strings in memory, even if there is more than one instance of the program running). This leads to the behaviour you observed on your platform.
char *str = "abcde";
str is a pointer to char that points to a string literal. String literals are stored in read only memory. You can't modify them.
char str[] = "abcde";
The string literal "abcde" is copied into the array str. So you can modify it.
char * is pointer to char (string literal) and char [] is an array of char. You can't modify string literal but you can modify char array.