#include<stdio.h>
#include<malloc.h>
void my_strcpy(char *sour,char *dest){
if(sour == NULL || dest == NULL){
return;
}
while(*sour != '\0'){
*dest++ = *sour++;
}
*dest = '\0';
}
int main(){
char *d = NULL;
char *s = "Angus Declan R";
d = malloc(sizeof(char*));
my_strcpy(s,d);
printf("\n %s \n",d);
return 0;
}
This func works fine and prints the string. My doubt is as the pointer "dest" will be pointing to the '\0' how does it prints the whole string(as it didnt point to the initial address of the string).
It's true that dest will point to the end of the string. But you are not printing the string by using dest - you are printing the string by using d which is a different variable.
Remember that in C and C++ values are passed by value by default - so when you call the function my_strcpy the value of the variable d is copied into the variable dest which is local to the function my_strcpy only and any changes to that variable will not affect d.
Also note that you are not allocating enough space for your d variable:
d = malloc(sizeof(char*));
This will allocate enough space for a pointer to character which will usually mean enough space for 4 (or maybe 8) characters. You should allocate enough space for the string you intend to copy plus one character for the terminating null byte. What is the size of the string you are trying to copy? Hint: strlen should help.
The d pointer passed in is a copy of the pointer, so the position/movement of the pointer in your function is not reflected back to where it was called in main. While d and dest both point to the same block of memory (at least initially) and any changes to that block of memory will be reflected on both ends, the dest pointer is only a copy.
my_strcpy(s,d);
C passes arguments by value. The value of d is passed to my_strcpy, which means d object inside main is not modified in your my_strcpy function.
Related
Can someone explain to me why my call to malloc with a string size of 6 returns a sizeof of 4 bytes? In fact, any integer argument I give malloc I get a sizeof of 4. Next, I am trying to copy two strings. Why is my ouput of the copied string (NULL)?
Following is my code:
int main()
{
char * str = "string";
char * copy = malloc(sizeof(str) + 1);
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
printf("%s\n", copy);
}
sizeof(str) returns the size of a pointer of type char*. What you should do is to malloc the size of the string it self:
char * copy = malloc(strlen(str) + 1);
Also, these lines:
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
Can be rewritten easily in C like this:
while(*copy++ = *str++);
First you should understand that sizeof(xxx) where xxx is any left value expression (a variable) is always equivalent to do sizeof(type of xxx). Hence what is really doing your sizeof(str) is returning the size of a char *, that is the size of any other pointer. On a 32 bits architecture you'll get 4, on a 64 bits architecture it'll be 8, etc.
So, as others also explained you have to know the length of the string you want to allocate, and then add 1 to store the terminal \0, C implicitly use to put at the end of strings.
But to do what you want (copy a string and allocate necessary space) it will be more simple and more efficient to use strdup, that does exactly that : a malloc and a strcopy.
You should also not forget to free space you allocated yourself (using malloc, calloc, strdup or any other allocation function). In C it won't go away when allocated variable go out of scope. It will stay used until the end of the program. That's what you call a memory leak.
#include <string.h> /* for strdup, strlen */
#include <stdio.h> /* for printf */
int main()
{
char * str = "string";
char * copy = strdup(str);
printf("bytes at least allocated for copy: %d\n", strlen(copy)+1);
printf("%s\n", copy);
free(copy);
}
One last point : I changed message to bytes at least allocated because you don't really know the size allocated when calling malloc. It quite often allocates a slighly more space that what you asked for. One reason is that in many memory managers free blocks are linked together using some hidden data structure and any allocated block should be able to contain at least such structure, another is that allocated blocks are always aligned in such a way to be compatible with any type alignment.
Hope it will help you to understand C a little better.
You're getting the size of the str pointer (4 bytes), not what it's pointing to?
sizeof(str) returns the space necessary to store the pointer to the string, not the string itself. You can see the size of the string with strlen(str) for example.
Then you affect your copy pointer to an integer which has the value 0 (the character '\0'). It is the same as copy = NULL, which is what the printf() function shows you.
sizeof() returns the size of the actual type of the variable. So, when you define your type as char *, it returns the size of a pointer.
But if you made your variable an array, sizeof would return the size of the array itself, which would do what you want to do:
char *ptr = "moo to you";
char arr[] = "moo to you";
assert(sizeof(ptr) == 4); // assuming 32 bit
assert(sizeof(arr) == 11); // sizeof array includes terminating NUL
assert(strlen(arr) == 10); // strlen does not include terminating NUL
To tackle your second questions, by executing the statement copy++ you have changed the value of copy (that is, the address in memory that holds a char array) so that by the time you print it out, it is pointing at the end of the array rather than the beginning (the value returned by malloc()). You will need an extra variable to update the string and be able to access the beginning of the string:
Edit to repair malloc/sizeof issue - thanks CL.
char * str = "string";
/* char * copy = malloc(sizeof(str) + 1); Oops */
char * copy = malloc(strlen(str) + 1);
char * original_copy = copy;
printf("bytes allocated for copy: %d\n", sizeof(copy));
while(*str != '\0'){
*copy = *str;
str++;
copy++;
}
copy = '\0';
printf("%s\n", original_copy);
sizeof() returns you the size of the pointer and not the amount of allocated bytes. You don't need to count the allocated bytes, just check if the returned pointer is not NULL.
The line copy = '\0'; resets the pointer and makes it NULL.
You can use:
size_t malloc_usable_size (void *ptr);
instead of : sizeof
But it returns the real size of the allocated memory block! Not the size you passed to malloc!
I want to copy one string to another string using pointer and I am getting garbage value (some unknown character) from printf function. What is wrong with it?
output is "string for copy**". At the place of ** getting some unknown character.
#include <stdio.h>
#include <conio.h>
void main()
{
char *s="string for copy",*c,*temp;//temp is used to back the
//pointer on 1st position
clrscr();
while(*s!=NULL)
{
*c=*s
c++;
s++;
}
c='\0';
c=temp;//back pointer to first position
printf("String from c:);
puts(c);
getch();
}
You need to allocate memory for your char * variables.
Also you never assign a value to temp (or allocate space for it) but then later in your code you assign c = temp. This means wherever c is currently at in memory will get assigned whatever was in memory at the location of temp.
c is char * are not allocating memory to it. So referring to it - reading from it or writing to it - is undefined behavior.
Allocate appropriate memory for c by using malloc() or other function before you copy characters into it.
So problem is not actually when you try to print using puts() but also when you copy characters to it by *c = *s.
Other than malloc(), change you code as below
...
//allocate memory for c
temp = c;
while(*s!='\0')
{
*c=*s
c++;
s++;
}
*c='\0'; //use *c
c=temp;
...
I have this custom string copy function and I've noticed that the *dest argument changes upon dereferencing it and modifying its contents:
char *copyArray(char *dest, char *src)
{
char *a = dest;
while (*dest++ = *src++)
;
char *b = dest;
if ( (a-b) != 0)
printf("Dest pointer has changed\n");
return dest;
}
And if you consider the following code:
int main()
{
char name [] = "Hello, there!";
char *new = copyArray(name, "bye");
printf("New is '%s', name is '%s'\n", new, name);
return 0;
}
I get the following output:
Dest pointer has changed
New is 'o, there!', name is 'bye'
Why does this happen?
My intent was for *new to point to the same location name[] points to, but obviously as the address changed, it points to a different place.
I feel that what's happened is that once the copying ended, C moved the original contents of the destination string minus the number of characters changed (4 for "bye") to a new address and assigned that to *dest.
Is this what's really happening? And could somebody please explain to me why?
This is not really work related, I'm just trying to understand better how pointers behave.
Thank you very much for your replies!
The problem occurs here
while (*dest++ = *src++)
;
which in plain english means copy the thing pointed to by src into the thing pointed to by dest, and after that increment both src and dest (that is, advance both pointers to point to the next thing).
Use a copy of the pointer if you want to avoid changing it - eg the a variable you already created, and return that one.
The argument dest is being incremented (in the while condition) four times (as "bye" is 4 characters including the null which will be assigned on the final iteration of the while) inside the function copyArray() and its value is then returned so new points to name + 4.
To have new point to the beginning of name return a from copyArray().
So basically strcpy assigns the address of the 2nd argument to the 1st, but how does it do it with an array as the first argument? like in my program, i tried changing the address of the array but unfortunately it wont compile. So I had to resort to making a character pointer variable to assign the return value of capitalize. Is there something I'm misunderstanding?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char string[20];
char *Capitalize(char *str)
{
int i;
char *temp;
temp = malloc(sizeof(char)*(int)(strlen(str)+1));
for(i = 0;i < strlen(str);i++)
{
if(*(str+i) >= 'a' && *(str+i)<= 'z')
*(temp+i) = *(str+i) - 32;
else
*(temp+i) = *(str+i);
}
*(temp+i) = '\0';
return temp;
}
int main(void)
{
string word;
printf("Enter word to capitalize: ");
scanf("%19s",word);
word = Capitalize(word);
printf("%s",word);
return 0;
}
strcpy() makes a copy, just like the name implies. it's perfectly legal to copy a string in to an array.
When you make an initialization of an array such as:
char myarr[] = "hello";
You're actually copying the characters into the array.
You seem to be confusing arrays with pointers (see here for some reason you can't treat them the same)
In C, qualifying an array by name without an indexer, is equivalent to specifying a pointer to the memory address of the first element in the array, that is why you can pass as a parameter an array to functions like strcpy.
char * strcpy ( char * destination, const char * source );
strcpy will copy whatever series of characters are found, starting at memory address specified by source, to the memory address specified by destination, until a null character (0) is found (this null character is also copied to the destination buffer).
The address values specified in the parameters are not modified, they just specify from where in memory to copy and where to. It is important that destination is pointing to a memory buffer (can be a char array or a block of memory requested via malloc) with enough capacity for the copied string to fit, otherwise a buffer underrun will occur (you will write characters past the end of your buffer) and your program might crash or behave in a weird way.
Hope I have been clear and not confused you more with my explanation ;)
The thing you seem to be missing is that in c/c++ strings ARE arrays, in most practical respects declaring
char c[] = "hello";
and
char* c = "hello";
is the same thing, all strcpy does is copy the characters into the destination memory, whether that memory is allocated as an array (presumably on the stack) or pointer (presumably on the heap);it does not make a difference.
just brushing up on some C for a class and I've run across a little something that makes me scratch me head. For this code:
char * findString(const char * s){
/* Allocate space */
char * ret = malloc(strlen(s) + 1);
/* Copy characters */
char * n;
n = ret;
for ( ;*s != 0; s++)
if (isLetter(*s))
*n++ = *s;
*n = 0;
/* return pointer to beginning of string */
return ret;
}
(We're just assuming an isLetter that returns a 1/0).
The idea of the snippet is to take a string with a bunch of crap in it, and return a string that contains only the letters.
So, how does 'ret' work in this instance? I'm very confused by the returning of 'ret' when 'n = ret' is declared above the for loop and 'ret' never gets set to anything afterwards. Obviously I'm missing something here. Help!
-R. L.
both ret and n are pointers to the same block of memory. their 'values' are simply memory addresses -- when you change *n, you change *ret, even though n and ret retain their original values.
//make n point to the beginning of the block of memory pointed
//to by ret
n = ret;
//iterate through the string which was passed to
//the function
for ( ;*s != 0; s++)
//if the current character is a letter:
if (isLetter(*s))
//set the character pointed to by n to
//the current character in the string, and then
//make n point to the next one.
*n++ = *s;
note that the loop increments n, and then after the loop sets the last character to 0 (to null terminate the string). Now, n points to the end of the string -- but since ret was never changed it still points to the beginning of the memory that you malloced before the loop. When you return it, you're returning a pointer to the new string which is the string you passed to the function, minus all non-letters.
Note that after this function returns, it is the caller's responsibility to free() the memory allocated by the function, lest ye roam into memory leaks.
ret, while semantically being a string, is actually a pointer to the first character of the string. n is used as a pointer to the current position in that string. So ret stays pointing to the start of the string, while n moves along the string as it is filled in. the *n = 0 then adds the null terminator. Thus while ret doesn't get set to anything, the contents of the string it points to are set.
n and ret are pointers, which means they contain addresses. In this case they both contain the address of the same character buffer that's being allocated with malloc. In this sense, n and ret are interchangeable.
Not much to it, really, line 3 allocates an empty string, ret, that is long enough to hold the argument even if it is all letters. That string will eventually be returned. the function then iterates through the argument and if it is a letter, puts it into the return string, by way of an intermediate pointer, n, which keeps track of the current position in the returned string.
The ret is a pointer to the beginning of the string to be returned. You need to create another pointer, n, because this pointer will not always point to the beginning of the string to be returned, it will walk on it, changing its characters. And, to be able to return a string, you must return a pointer to the beginning of the string, and you need to know where it ends (that's why you need the 0 added to the end).
Hope I helped!