strcpy function with pointers to character array - c

In the code below the result is stack overflow. Though null character is there with both the strings, so the strcpy loop should terminate as the source string has null character. Why stack overflow occurs??
#include <stdio.h>
#include<strings.h>
int main(void) {
char *str="Hello world";
char *str1="Good morning";
strcpy(str,str1);
printf("%s",str);
return 0;
}

The error isn't stack overflow, but modifying a string literal.
str is a pointer that points to a string literal "Hello world", and modifying a string literal is undefined behavior.
Change str to:
char str[100] = "Hello world";

Related

strcat function not working with pointers

int main(int argc , int *argv[]){
char str[7] = "Mobile";
char str2[11] = "Samsung4g";
char *str3 = 0;
str3 = ( char* )(malloc(30));
str3 = "Carrier";
strcat(str3, str);//Problem facing here, dunno why
Like what others have mentioned in the comments, the statement:
str3 = "Carrier";
overwrites the value of str3 with the address of the string literal "Carrier" causing the address returned by malloc() to be lost.
Using str3 then in strcat() as a first argument attempts to modify a string literal which results in undefined behaviour.
Use strcpy() or equivalent functions to copy strings in C.

Weird segmentation fault (difference between arrays and pointers ?)

i cant see why i'm getting segmentation fault from this code and somehow when i use arrays instead of pointers it works, i would be happy if anyone can make me understand this.
void main() {
char *str = "example string";
wrapChrInStr(str, 'a');
}
void wrapChrInStr(char *str, unsigned char chr) {
char *ptr = str;
char c;
while((c = *ptr)) {
if(c != chr) {
*str = c;
str++;
ptr++;
} else {
ptr++;
}
}
*str = '\0';
}
Thank you. I'm doing a lot of c programming and its really weird that i never faced that before.
Probably because you don't realize that there are different ways of storing a
C-String. You may have been lucky enough never to have encountered a segfault
because of this.
String literals
A string literal is declared with double quotation marks, e.g.
"hello world"
This string is usually stored in a read-only section. When using string
literals, it's best to declare the variables with a const like this:
const char *str = "hello world";
With this you know that str is pointing to read-only memory location and you cannot
manipulate the contents of the string. In fact, if you do this:
const char *str = "hello world";
str[0] = 'H';
// or the equivalent
*str = 'H'
the compiler will return an error like this:
a.c:5:5: error: assignment of read-only location ‘*str’
which I found very helpful, because you cannot accidentally manipulate the
contents pointed to by str.
Arrays
If you need to manipulate the contents of a string, then you need to store the
string in an array, e.g.
char str[] = "hello word";
In this case the compiler knows that the string literal has 10 characters and reserves 11 bytes (1 byte for '\0' - the terminating byte) for str and initializes the array with
the contents of the string literal.
Here you can do stuff like
str[0] = 'H'
but you cannot access beyond the 11th byte.
You can also declare an array with a fixed size. In this case the size must be
at least the same as the length+1 of the string literal.
char str[11] = "Hello world";
If you declare less space (char str[3] = "hello world"; for example),
your compiler will warn you with something like this
a.c:4:14: warning: initializer-string for array of chars is too long
but I'm not sure what happens if you execute the code anyway. I think this is a case of undefined behaviour
and that means: anything can happen.
Personally, I usually declare my string without a fixed size, unless there is
a reason for having a fixed size.

copy one string in to other using pointer produce Garbage values why?

if take array it will be fine but as i used *str1 and str2 it does not work
#include <stdio.h>
void copystr(char* ,char*);
int main()
{
char *str1="xxx";
char *str2= "yyy";
copystr(str1, str2);
printf("\n %s",str2);
}
void copystr(char *dest,char *src)
{
while(*src!='\0')
*dest++=*src++;
*dest='\0';
return;
}
char *str = "some string"
Here str is a pointer pointing to a constant memory, which can't be edited and leads to undefined behaviour.
But If you declare like
char str2[] = "some string"
Now str2 above is pointing to a memory which is not constant and can be changed. Thus will work.
More explanation here:
char *array and char array[]
Destination string str1 is a string literal. String literals are non modifiable. Any attempt to modify it will invoke undefined behavior.

String concatenation. C

All of the code below on C.
Both the code snippet below are compiled, but the difference is that the second program crashes at startup.
One:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char *str[80];;
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
Two:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char *str="";
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
The difference is that in the first case, said the size of the str string, while the second is not. How to make string concatenation without a direct indication of the size of the string str?
The difference is that in the first case, said the size of the str
string, while the second is not.
No. In the first program, the following statement
char *str[80];
defines str to be an array of 80 pointers to characters. What you need is a character array -
char str[80];
In the second program,
char *str="";
defines str to be a pointer to the string literal "", not an array. Arrays and pointers are different types.
Now, the second program crashes because
char *str="";
defines str to be a pointer to a string literal. The first argument of strcpy should be a pointer to a buffer which is large enough for the string to be copied which is pointed to by its second argument.
However, str points to the string literal "" which is allocated in read-only memory. By passing str to strcpy, it invoked undefined behaviour because strcpy tries to modify it which is illegal. Undefined behaviour means the behaviour is unpredictable and anything can happen from program crash to due to segfault (illegal memory access) or your hard drive getting formatted. You should always avoid code which invoked undefined behaviour.
How to make string concatenation without a direct indication of the
size of the string str?
The destination string must be large enough to store the source string else strcpy will overrun the buffer pointed to by its first argument and invoke undefined behaviour due to illegal memory access. Again, the destination string must have enough space for the source string to be appended to it else strcat will overrun the buffer and again cause undefined behaviour. You should ensure against this by specifying the correct size of the string str in this case.
Change to:
One:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
Two:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char str[80]="";
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char *str=NULL;
size_t strSize = strlen(foo)+strlen(bar)+strlen("TEXT ")+1;
str=malloc(strSize);
if(NULL==str)
{
fprintf(stderr, "malloc() failed.\n");
goto CLEANUP;
}
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
CLEANUP
if(str)
free(str);
}
size_t len1 = strlen(first);
size_t len2 = strlen(second);
char * s = malloc(len1 + len2 + 2);
memcpy(s, first, len1);
s[len1] = ' ';
memcpy(s + len1 + 1, second, len2 + 1); // includes terminating null
Did I do good?
In the second version you have set char *str=""; this is equivalent to allocating an empty string on the stack with 1 byte which contains null for end of string. Had you written char*str="0123456789", you would have allocated 11 bytes on the stack the first 10 of which would have been "0123456789" and the 11th byte would have been null. If you try to copy more than allocated bytes to the str, your program might crash. So either allocate dynamically enough memory, or statically.
Both programs are wrong, the first provokes undefined behavior exactly as the second one.
char *str[80]; is array of pointers which you pass to functions ( strcpy, strcat) as first argument, while the first argument for those functions should be char *. Possible solution for this issue to define str as char str[80];
The issue with the second program is that char *str=""; is a pointer to read only piece of memory, which can't be changed.In this case one of possible solutions can be :
char* str = malloc(80);
strcpy(str,"");
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
You'll have to allocate memory before copying. The first defines the size so as 80
char *str = new char[10]; could also be a method of allocation. malloc function could also be used to allocate memory.
Here are some references that might help you
http://www.cplusplus.com/reference/cstdlib/malloc/
http://www.cplusplus.com/reference/cstdlib/calloc/

character pointer

Why this code does not work?
int main(){
char *str ="abcde";
scanf("%s",str);
printf("%s",str);
}
but this works?
int main(){
char str[] ="abcde";
scanf("%s",str);
printf("%s",str);
}`
In the first code, you declare a pointer, which points to a string literal: "abcde".
This might be a constant, and you will not be able to change it.
The second code is declaring an array and filling it with ['a','b',c','d','e','\0'], and is not a constant - so you can change it.
Because char *str ="abcde"; is a pointer to string literal which is most likely stored in read-only memory.
char str[] ="abcde"; is an array initialized with "abcde".
You should also check out Difference between char* and char[]
When string value is directly assigned to a pointer, it’s stored in a
read only block(generally in data segment) that is shared among
functions
char *str = "GfG";
...
char str[] = "GfG"; /* Stored in stack segment like other auto
variables */ *(str+1) = 'n'; /* No problem: String is now GnG */
http://www.geeksforgeeks.org/archives/5328

Resources