Help me in solving 2 questions on pointers:
1)Please tell me why do I get 'segmentation fault' when I run following snippet
main()
{
char *str1 = "united";
char *str2 ="front";
char *str3;
str3 = strcat(str1,str2);
printf("\n%s",str3);
}
2)Why don't I get output in following code:
main()
{
char str[10] = {0,0,0,0,0,0,0,0,0,0};
char *s;
int i;
s = str;
for(i=0 ; i<=9;i++)
{
if(*s)
printf("%c",*s);
s++;
}
}
Thank u.
You should review how strcat works. It will attempt to rewrite the memory at the end of your str1 pointer, and then return the destination pointer back to you. The compiler only allocated enough memory in str1 to hold "united\0" (7 chars), which you are trying to fill with "unitedfront\0" (12 chars). str1 is pointing to only 7 allocated characters, so there's no room for the concatenation to take place.
*s will dereference s, effectively giving you the first character in the array. That's 0, which will evaluate to false.
1) compiles to something like:
const char _str1[7] = "united";
const char _str2[6] ="front";
char *str1 = _str1;
char *str2 = _str2;
strcat(str1,str2);
str3 = str1;
str1 points to a buffer which is exactly 7 bytes long and is filled with 6 characters. The strcat put another 5 bytes into that buffer. 7 bytes cannot hold 11 characters.
The C there is no magic! If you do not explicitly allocate space for something, no one else does it either.....
2) isn't going to print anything. It steps through an array, every element of which is 0. It then tests if the current item (*s) is not 0 (if(*s)) , and if so, prints that item as a character. However, since the item always is 0, it always fails to test.
for question 2, think about what the following line does:
if(*s)
Related
I'm writing my own strcpy due to the fact that the default one in string.h only accept a const char * as a source string to copy from.
I'm trying this very basic prototype (yes, the return isn't meaningful, I'm just trying things):
int copyStrings(char * dest, char * source){
int i=0;
while(source[i]!='\0'){
dest[i]=source[i];
i++;
}
dest[i]='\0';
return 0;
}
and it gives me SIGSEGV, Segmentation Fault error in gdb, at the line dest[i]=source[i], right at the first character. I'm pretty sure dest[i] isn't a string literal, so I should be able to modify it.
What am I doing wrong?
EDIT: here's the calling
int main(){
char * str = (char*)malloc((int)sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int));
str = "hello";
str2 = "hey jude";
copyStrings(str2, str);
free(str);
free(str2);
return 0;
}
This is assigning a string literal to str2 - the very thing that you claim you aren't doing. This is actually the cause of your segfault.
str2 = "hey jude";
It also is causing a memory leak as prior to this, you malloc'd some memory and assigned it to str2 as well. But not enough memory to hold the string. Typically an int is 4 bytes and you need 9 bytes to store that string.
What you want to do is this, which allocates as many bytes as there are in the string, plus an extra one to store the \0 terminating character at the end.
str2 = malloc(strlen("hey jude")+1);
strcpy(str2,"hey jude");
or on some systems you can use POSIX function strdup() which effectively does the job of the above in one handy function call.
str2 = strdup("hey jude");
Let's go at it line by line and see where it goes wrong:
int main(){
char * str = (char*)malloc((int)sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int));
str = "hello";
str2 = "hey jude";
copyStrings(str2, str);
free(str);
free(str2);
return 0;
}
int main(){ - this is an improper definition of main. Should be int main(int argc, char **argv)
char * str = (char*)malloc((int)sizeof(double)); - defines str, then allocates (probably) 8 bytes of memory and assigns its address to str. malloc takes a size_t argument, so the cast (int)sizeof(double) is incorrect. Also, in C the return value of malloc should never be cast. So this line should be char * str = malloc(sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int)); - all the same problems as the preceding line. Should be char *str2 = malloc(sizeof(int));
str = "hello"; - causes a memory leak, because the memory you JUST ALLOCATED two lines earlier is now irretrievably lost. You've got two options here - either don't allocate the memory when defining str or free it first. Let's do the latter:
free(str);
str = "hello";
str2 = "hey jude"; - same problem, similar solution:
free(str2);
str2 = "hey jude";
copyStrings(str2, str); - here you're telling your routine to copy the constant string "hello" over the top of the constant string "hey jude". This will work fine on some systems, but will blow up on other systems. The question is in the treatment of the constant string "hey jude". If it's stored in modifiable memory the code will work just fine. If it's stored in memory which is marked as being unmodifiable, however, it will blow up. It seems that the latter is the case on your system. To fix this you probably want to go back to the previous line and change it to
str2 = malloc(20);
That's more memory than you'll need, but it will work just fine.
free(str); - you're attempting to free the constant string "hello", which is not dynamically allocated memory. This needed to be done prior to the assignment str = "hello";.
free(str2; - same problem as above. This needed to be done prior to the assignment str2 = "hey jude";.
} - correct
Best of luck.
Let's say I have a char *str and I want to assign it characters one by time using using pointers and incrementing ?
I've done :
char *str;
char c = 'a';
*str++ = c;
But it doesn't work.
How can I do that ?
str is just a pointer. It doesn't point anywhere valid (especially not to some memory you could write to). A simple possibility would be to have it point to an array:
char buf[1024] = {0}; // room for 1024 chars (or 1023 + a 0 byte for a string)
char *str = buf;
char c = 'a';
*str++ = c;
char *str is a pointer to a char (or an array of chars), however, you never assigned it. As has been mentioned earlier a char * basically says "go there" but there is no there there, you never gave it a value. You first need to use malloc to create space to put things in. Here's an example
char *str = malloc(sizeof(char)*10) //allocate space for 10 chars
char c = 'a';
str[0] = c;
no error check was made to malloc which you should do in your own program. You can also do it as such
char str[10];
char c = 'a';
str[0] = c;
however with this method you will be restricted to 10 chars and you cannot change that amount, with the previous method you can use realloc to get more or less space in your array.
But it doesn't work.
char* str;
... is not initialized to anything, therefore dereferencing it is to undefined behaviour. If it where initialized, then in expression *str++ = c; str++ is a post-increment operator, which returns a copy of the pointer whilst incrementing the original. The effect is that the copy points to the previous, and therefore what is pointed to by the previous pointer is assigned c.
To which part that doesn't work are you referring?
EDIT:
As mentioned in one of the comments, a copy is not really returned but the value is increment in place after having been evaluated.
As a variable with automatic storage duration the pointer str has indeterminate value. If even it had the static storage duration its value would be NULL. So you may not use such a pointer to store data.
What you mean can look for example the following way
#include <stdio.h>
int main( void )
{
char s[11];
char *p = s;
while (p != s + sizeof( s ) / sizeof( *s ) - 1 ) *p++ = 'a';
*p = '\0';
puts(s);
return 0;
}
The program output is
aaaaaaaaaa
Here in the program the pointer p of the type char * is initialized by the address of the first character of the array s.
Thus this statement used in the loop
*p++ = 'a';
fills sequentially the array with the character 'a'.
The next example is more interesting
#include <stdio.h>
char * copy_string(char *dsn, const char *src)
{
for (char *p = dsn; (*p++ = *src++) != '\0'; )
{
// empty body
}
return dsn;
}
int main( void )
{
char *src = "Hi QBl";
char dsn[7];
puts(copy_string(dsn, src));
return 0;
}
The program output is
Hi QBl
Here is a demonstration of a function that copies one character array containing a string into another character array using pointers.
I'm new to c, and confused by string ending char '\0', should I allocate it?
for example, I want to store a string with a max length of 6;
If I use array, should I use char str[6] or char str[7]?
char as[3] = "abc";
printf("%s\n", as);
//seems no problem
If I use char pointer, should I use char *str = malloc(6) or char *str = malloc(7)?
For an array that is pre-initialized, you don't need to write a number in the brackets. You can just write
char str[] = "this is my string";
And the compiler will automatically calculate the number of bytes needed.
But for malloc, you must add 1. Ex:
char *strdup(const char *str)
{
char *ret = malloc(strlen(str) + 1);
strcpy(ret, str);
return ret;
}
You should be using string length + 1. In your case you must use 7 while declaring the char array.
The example you provided would have worked because of the undefined behaviour shown by printf().
In addition to stackptr's answer:
If you are planning to overwrite your array:
char str[30] = "abc";
...
strcpy(str, "Hello world"); /* This will overwrite the content of "str" */
... the length of the array must be the maximum length of the string plus 1.
In the example above you may write strings of up to 29 characters length to the array.
Note that the following definition:
char str[] = "abc";
... implicitly creates an array of 4 characters length so you are limit to 3 characters.
In the case down below.
Does changing the string 'out' change the string 'str' respectively? In other words, do they have the same pointer?
Thank you in advance.
int main() {
char str[]={'g','o','o','d','/0'};
char special[]={'o','/0'};
char* out=str;
return 0;
}
It depends. If you write:
out = "hello!";
you do not change the string str, but simply make out point to another memory location.
But if you write into out like in this:
sprintf(out, "abcd");
then you do change str. But beware of overflow!
For starters I think you mean the terminating zero '\0' instead of the multibyte character literal '/0'.
To escape such an error it is better to initialize character arrays with string literals (if you are going to store a string in an array). For example
char str[] = { "good" };
or just like
char str[] = "good";
As for the question then after this assignment
char* out=str;
the pointer out points to the first character of the array str. Thus using this pointer and the pointer arithmetic you can change the array. For example
char str[] = "good";
char *out = str;
out[0] = 'G';
*( out + 3 ) = 'D';
puts( str );
Moreover an array passed as an argument to a function is implicitly converted to pointer to its first character. So you can use interchangeably either an array itself as an argument or a pointer that initialized by the array designator. For example
#include <stdio.h>
#include <string.h>
//...
char str[] = "good";
char *out = str;
size_t n1 = strlen( str );
size_t n2 = strlen( out );
printf( "n1 == n2 is %s\n", n1 == n2 ? "true" : "false" );
The output of this code snippet is true.
However there is one important difference. The size of the array is the number of bytes allocated to all its elements while the size of the pointer usually either equal to 4 or 8 based on used system and does not depend on the number of elements in the array. That is
sizeof( str ) is equal to 5
sizeof( out ) is equal to 4 or 8
Take into account that according to the C Standard the function main without parameters shall be declared like
int main( void )
I think there's a typo in your code, you have written '/0' but it's not a null character but '\0' is.
As far as out & str are concerned, str[] is a char array, whereas out is a pointer to it. If you make out point to some other char array there'll be no effect on str. But you can use out pointer to change the values inside the str[], like this,
int main( void )
{
char str[]={'g','o','o','d','\0'}; // There was a typo, you wrote '/0', I guess you meant '\0'
//char special[]={'o','\0'};
char* out=str;
for(int i=0; out[i] != '\0'; i++)
{
out[i] = 'a';
// This will write 'a' to the str[]
}
printf("out: %s\n", out);
printf("str: %s", str);
return 0;
}
No. out is a different variable that holds the same address str is at, i.e. it points to the same location. Note that changing *str will change *out.
In C, assignment takes the value of the right end and stores it in the left end, it does not makes the right "become" left
I have an array of characters declared as:
char *array[size];
When I perform a
printf("%s", array);
it gives me some garbage characters, why it is so?
http://www.cplusplus.com/reference/clibrary/cstdio/printf/
This url indicates printf takes in the format of: `int printf ( const char * format, ... );
#include <stdio.h>
#include <string.h>
#define size 20
#define buff 100
char line[buff];
int main ()
{
char *array[100];
char *sep = " \t\n";
fgets(line, buff, stdin);
int i;
array[0] = strtok(line, sep);
for (i = 1; i < size; i++) {
array[i] = strtok(NULL, sep);
if (array[i] == NULL)
break;
}
return 0;
}
You declare an array of characters like so:
char foo[size];
You seem to have it mixed up with char *, which is a pointer to a character. You could say
char *bar = foo;
which would make bar point to the contents of foo. (Or, actually, to the first character of foo.)
To then print the contents of the array, you can do one of the following:
// either print directly from foo:
printf("%s", foo);
// or print through bar:
printf("%s", bar);
Note, however, that C performs no initialization of the contents of variables, so unless you specifically set the contents to something, you'll get garbage. In addition, if that garbage doesn't happen to contain a \0; that is, a char with value 0, it will keep on outputting past the end of the array.
Your array is not initialized, and also you have an array of pointers, instead of an array of char's. It should be char* array = (char*)malloc(sizeof(char)*size);, if you want an array of char's. Now you have a pointer to the first element of the array.
Why are we making such a simple thing sound so difficult?
char array[SIZE];
... /* initialize array */
puts(array); /* prints the string/char array and a new line */
/* OR */
printf("%s", array); /* prints the string as is, without a new line */
The char in array after the end of what you want to be your string (ie. if you want your string to read "Hello" that would be the next char after the 'o') must be the terminating NUL character '\0'. If you use a C function to read input that would automatically be appended to the end of your buffer. You would only need to worry about doing it manually if you were individually writing characters to your buffer or something for some reason.
EDIT: As with pmg's comment, the '\0' goes wherever you want the string to end, so if you wanted to shorten your string you could just move it up closer to the front, or to have an empty string you just have array[0] = '\0';. Doing so can also be used to tokenise smaller strings inside a single buffer, just as strtok does. ie. "Part1\0Part2\0Part3\0". But I think this is getting away from the scope of the question.
ie. you wanted to store the first 3 chars of the alphabet as a string (don't know why anyone would do it this way but it's just an example):
char array[4];
array[0] = 'a';
array[1] = 'b';
array[2] = 'c';
array[3] = '\0';
printf("%s\n", array);
If you have something like char array[] = "Hello"; the '\0' is automatically added for you.
char *array[size];
array is not a char * with that, it's more like a char ** (pointer to an array of chars, with is similar to pointer to pointer to char).
If all you need is a C string, either:
char array[size];
and make sure you 0-terminate it properly, or
char *array;
and make sure you properly allocate and free storage for it (and 0-terminate it too).