Consider char *a[] = {"abc", "xyz", "def"};
Deep copy char *a[] to char **b.
Can someone say what is deep copy? And how much memory we need assign to b?
char *a[n];
Is an array of n pointers-to-char. Each element of the array is contiguous in memory. The size in memory required is
sizeof(char *) * n
I've used the sizeof() operator here... you could assume 4 bytes for a pointer but this might not be safe... this depends on your hardware.
char **b
Is slightly different. This is a pointer to a point-to-char. **b has not allocated the array of pointers. First allocate the array...
char **b = malloc( sizeof(char *) * n);
EDIT: Thank you to interjay for pointing out my mistake... example below now uses strdup() to allocate the memory for each b[i]
**b points to the start of an array of n pointers. For each pointer in that array you could so do b[0] = a[0] for shallow copies
This is a shallow copy because b[0] will point to the same memory that a[0] points to. Thus changing the contents b[0] will change the contents of a[0].
A deep copy would imply that you have two totally independent entities... so changing the contents b[0] would not result in a change to the contents of a[0]. This means that for each b[i] you need to allocate new memory and copy the string from a[i] into that new block.
To deep copy:
char *a[n];
// ...intialise array a....
char **b = malloc( sizeof(char *) * n); // allocate array of pointers
if( b )
{
int i = 0;
for(; i < n; ++i)
b[i] = (char *)strdup(a[i]); // allocate memory for new string and copy string
}
else
printf("You ran out of memory!\n");
As an asside...
You've used constant strings so you shouldn't technically modify them...
char *xxx = "String";
char yyy[] = "String";
You can safely modify the contents of yyy. Normally you can modify the contents of xxx without any problem, but note, because the string memory is allocated at compile time, you could find that the compiler has, for example, placed it in read only memory.
EDIT:
There seems to have been debate on whether to cast return from malloc (which I've been in the habit of doing, but it seems this was a bad habit!)... see Why do we need to cast what malloc returns?
Walking on the a array, for eah a[i] request space to alloc it by using one of *alloc() family functions and put the result in the respective b[i]. The b pointers itself shall be a pointer with enough space for hold the number of string in a as pointers. Compute with something like this:
int bsize = (sizeof(a)/sizeof(a[0])) * sizeof(char*);
char **b = malloc(bsize);
int i,len;
/* if(b == NULL) /* error: no memory */
for(i = 0,len = sizeof(a)/sizeof(a[0]); i < len; i++) {
char *tmp = malloc(strlen(a[i])+1);
if(tmp == NULL) /* error: no memory */
strcpy(tmp, a[i]);
b[i] = tmp;
}
Note that you need to or hold the size of b array in memory either put a NULL at end of array.
You can just do
b=a
This will assign base address of array of pointers *a[3] to b.
Now you can access strings using b
for example string 1 can be accessed by *(b+0) gives address of string 1
string 2 " " *(b+1) " " string 2
string 3 " " *(b+2) " " string 3
Since you are assigning array of pointers to pointer to a pointer you are already assigning memory to b Hence you do not need to use malloc.
Only when you are assigning some data to a pointer at run time and you have not assigned memory to pointer in your program then only use malloc.
Related
I am trying to allocate individual elements of two dimensional array in function call.
I am getting the pointer reference char ***a pointer in function parameter like this int substr(char *arr,char c,char ***a,int k)
But I am getting segFault at realloc line. I am not getting any help from -Wall -Wextra. In this example the function substr allocate for 1 index element of two passed two dimensional array
But I like to allocate memory in called function
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int substr(char *arr, char c, char ***a, int k)
{
*(a + k) = realloc(a, 5);
return 0;
}
int main()
{
char *arr = "this is a new string. check it out";
char **a;
a[0] = malloc(5);
//....some code
//...
int count = substr(arr, ' ', &a, 1);
return 0;
}
From the conversation in the comments, there's some confusion about a[0]. Let's simplify it by working with char *.
// Declare the variable a which stores a pointer to a char.
char *a;
// Same as *a = 'b'
a[0] = 'b';
a[0] tries to access the memory a points to, same as *a. But a was never initialized, it points at some random memory you don't have access to, or is out of bounds. Segfault.
a has to have memory allocated to it to store 'b'.
// `a` points at 5 bytes of memory
// This is the same as `char *a; a = malloc(5)`.
char *a = malloc(5);
// The first byte of malloc'd memory is set to 'b'.
a[0] = 'b';
Now let's do it with an array of strings.
char **a;
a[0] = "some string";
Same problem. a is uninitialized and points at some random memory. a[0] = "some string"; tries to dereference a and segfaults.
So we need to first allocate space to store the pointers to the strings.
// Allocate space for 5 pointers.
// This is the same as `char **a; `a = malloc(...);`
char **a = malloc(sizeof(char *) * 5);
// Dereference the first pointer and have it point to a string.
a[0] = "some string";
Now to your code. Same thing.
char **a = malloc(sizeof(char *) * 5);
// Derefrence the first pointer in a and have it point to 5 bytes of memory.
a[0] = malloc(5);
If you want to reallocate the memory in a[0] you reallocate a[0], not a.
// Reallocate the 5 bytes of a[0] and return a pointer to 10 bytes.
// Assign the new pointer to a[0].
a[0] = realloc(a[0], 10);
If you want to do this in a function, pass in a pointer to the memory work with that. The function doesn't know nor care about the array a. Just the string.
// Note there's no need to pass in an array index.
void substr(char **dest) {
// dest is pointer to the pointer in a[0].
// *dest is the pointer in a[0], the malloc(5).
// Grow its memory and reassign it back to a[0].
*dest = realloc(*dest, 10);
// Assign to a[0] to demonstrate it works.
strcpy(*dest, "012345678");
}
int main(void) {
char **a = malloc(sizeof(char *) * 5);
a[0] = malloc(5);
substr(&a[0]);
puts(a[0]);
}
We can simplify this.
First, since a is allocated in main it can use automatic memory. This is memory which is automatically deallocated when the function exits. Because main is the first function it will be the last to exit, so any automatic memory in main will last for the whole program.
We can't use automatic memory in substr because it will be deallocated when substr returns.
Second, there's no need to allocate memory to a[0] if you're going to immediately realloc it. If you give realloc a null pointer it will allocate new memory.
int main(void) {
char *a[5];
a[0] = NULL;
substr(&a[0]);
puts(a[0]);
}
Finally, we can initialize all the pointers of a to NULL using a little syntactic trick.
int main(void) {
// Same as char *a[5] = {NULL, NULL, NULL, NULL, NULL};
char *a[5] = {NULL};
substr(&a[0]);
puts(a[0]);
}
I need some explanation for some commands in this particular piece of code:
#inlcude <stdlib.h>
#define PTRS 5
char *p[PTRS];
size_t nbytes = 10;
int i;
/* Allocating memory */
for (i=0; i<PTRS; i++){
printf("malloc of %10lu bytes ", nbytes);
if ((p[i] = (char *)malloc(nbytes)) == NULL){
printf("failed\n");
} else {
printf("succeeded\n");
nbytes *= 100;
}
/* Free the memory allocated */
for (i=0; i<PTRS; i++){
if(p[i]){
free(p[i]);
p[i] = NULL;
}
}
First one is
char *p[PTRS];
Does this line declare a pointer to an array or does it declare an array of pointers to char?
p[i] = (char *)malloc(nbytes) I understand that as i increases, p[i] will contain a pointer to the allocated memory called by malloc if it's successfully processed, and p[i] will beNULL` if no such memory can be prepared.
Second one is
if (p[i]){
free(p[i]);
p[i] = NULL;
}
This only frees memory if p[i] has any value (in this case a pointer to the memory). What happens if we remove if(p[i]) and only use free(p[i] and p[i] = NULL? Can we free a NULL pointer?
char *p[PTRS];
is equivalent to
char *(p[PTRS]);
i.e. it's an array of pointers, not a pointer to an array. A pointer to an array would be e.g.
char (*p)[PTRS];
The clockwise/spiral rule could be helpful in deciphering declarations. As would using resource such as https://cdecl.org.
And you can pass a NULL pointer to free (it's a no-op) so the check isn't needed really.
Depending on the further use of p, the p[i] = NULL assignment might not be needed either.
I understand that as i increases, p[i] will contain a pointer to the
allocated memory called by malloc
So if you understand this when it means that p[i] being an element of an array has the type char * because at least in the program there is explicit casting to this type of themalloc call in the if statement
if ((p[i] = (char *)malloc(nbytes)) == NULL){
So this declaration
char *p[PTRS];
declares an array of PTRS elements with the tyoe char *. I advice to write such a declarations like
char * p[PTRS];
inserting a blank after the character '*'.
You may rewrite the declaration also the following way
char * ( p[PTRS] );
A pointer to an array of PTRS elements of the type char is declared the following way.
char ( *p )[PTRS];
Can we free a NULL pointer?
More precisely it would be said may we use the function free with a null-pointer because we are not freeing a null pointer itself that in the context of your example has the automatic storage duration.
The answer is yes we may. A call of the function with a null pointer will have neither affect and is safe.
Thus this loop
for (i=0; i<PTRS; i++){
if(p[i]){
free(p[i]);
p[i] = NULL;
}
}
may be rewritten like
for (i=0; i<PTRS; i++){
free(p[i]);
p[i] = NULL;
}
Is the same
char* s1[size];
To
char** s2 = malloc(size * sizeof(char*));
They have any difference?
Theoretically, *arr[] and **arr are different. For example :
char *arr[size]; //case 1
Here arr is a an array of size size whose elements are of the type char*
Whereas,
char **arr; //case2
Here arr is itself a pointer to the type char*
Note: In case 1 array arr degrades to a pointer to become the type char** but it's not possible the other way around i.e, pointer in case 2 cannot become an array.
char* s1[size];
Is an array of pointers of type char that is allocated on the stack.
char** s2 = malloc(size * sizeof(char*));
Is a pointer of type char ** that is allocated on the stack but points to a dynamic array of pointers of type char * allocated on the heap.
The two differ in terms of scope and the usual difference between arrays and pointers.
There are few differences:
s1 is not an lvalue, so it cannot be modified (e.g. using assignment or increment operators). Because of this it resembles type char** const s1 which also does not allow modifications (but in this case this is caused by const modifier).
operator & used on address of array will return address of array (i.e. address of 1st element). When & will be used on variable, it will return its address:
assert((void*)&s1 == (void*)s1);
assert((void*)&s2 != (void*)s2);
sizeof() used on array will return array size, while sizeof() used on pointer will return pointer size - usually it will be the same as sizeof(void*), but C standard does not require this (see comments below):
assert(sizeof(s1) == size * sizeof(char*));
assert(sizeof(s1) == size * sizeof(s1[0])); // this is the same
assert(sizeof(s2) == sizeof(void*)); // on some platforms this may fail
and of course obvious one - s1 is allocated on stack, s2 on heap. Because of this s1 will be destroyed automatically when execution leaves current scope, and s2 requires call to free to release memory.
Update: here is example code which checks above asserts:
#include <assert.h>
#include <stdlib.h>
int main()
{
const int size = 22;
char* s1[size];
char** s2 = (char**)malloc(size * sizeof(char*));
assert((void*)&s1 == (void*)s1);
assert((void*)&s2 != (void*)s2);
assert(sizeof(s1) == size * sizeof(char*));
assert(sizeof(s1) == size * sizeof(s1[0])); // this is the same
assert(sizeof(s2) == sizeof(void*)); // on some platforms this may fail
free(s2);
// Attempts to modify value
char** const s3 = s1;
++s2;
//++s1; // compilation error - lvalue required as increment operand
//++s3; // compilation error - increment of read-only variable ‘s3’
return 0;
}
s1 is an array, s2 is a pointer. s2 points to the first element of the malloced array.
The array s1 has automatic storage duration, while the array which s2 points to has dynamic storage duration.
Also, in C89 char* s1[size]; is valid only if size is a constant expression, because C89 doesn't support variable-length arrays.
Let's say I have an array of char containing a sentence, and I want to copy that sentence in a different array but filtering a certain character:
char a[] = "hello everybody";
char b[sizeof(a)];
char idontwantyou = 'e';
int it = 0;
for (int i=0; i<sizeof(a); ++i)
if (a[i]!=idontwantyou)
b[it++] = a[i];
I had to allocate the same amount of memory for b than the size of a because I don't know the size of the sentence without the undesired characters right?
Now, I have my b array with the sentence hllo vrybody'#·&¡` right? I mean, there is "trash" at the end of the array.
Is there any way I could "cut" the trash in the tail so the size of b is the same value than it?
I just copied b in a new array I defined as char c[sizeof(b)] but this doesn't seem like a good practise.
Maybe realloc in b would do what I want?
In-place elimination of unwanted character, and allocated array size reduction:
char *a = strdup("hello everybody");
char idontwantyou = 'e';
char *b = a;
char *c = a;
Eliminate unwanted character:
while(*b)
{
if(*b != idontwantyou)
{
*c=*b;
++c;
}
++b;
}
*c='\0';
Reduce the size of the allocated array:
b=realloc(a, strlen(a) + 1);
if(NULL == b)
/*Handle error... */;
a=b;
Test results:
printf("array = \"%s\"\n", a);
Output should be:
array = "hllo vrybody"
sizeof(b) would be equal to sizeof(a), because that is the actual size of b. To use realloc, you have to allocate b using malloc in the first place.
That would be done in a way similar to this:
char a[] = "hello everybody";
/* better use strlen here -- it will also work with char*, and not only with
statically allocated arrays */
char *b = malloc(strlen(a)+1);
/* your code here */
char *tmp = realloc(b, it);
if (!tmp) {
free(b);
/* some error here! */
} else {
b = tmp;
/* continue working with b */
}
There are some important bits in here:
You have to manually free b after you’re done, because it is allocated on the heap instead of the stack, and thus you have to release the memory on your own instead of it getting released automatically on the function exit.
The return value of realloc may be NULL. In that case, the old memory is still allocated and you have to do some kind of error handling (as sketched with the if).
If realloc succeeds, tmp points to the new memory area and b is invalid, which is why we override b with tmp.
Another way to do it is to run two passes over the string, one to count and one to copy.
You should evaluate the problem in terms of how much this operation matters in the
overall cost and cpu+memory profile of the program. Most likely, it hardly matters at all.
In which case, the simplest is probably the best.
I'm am trying to write a program that reads in a series of strings from a text file and stores these in an array of strings, dynamically allocating memory for each element. My plan was to store each string in an array using a pointer and then grow the array size as more were read in. I am having trouble to understand why my test code below is not working. Is this a workable idea?
char *aPtr;
aPtr =(char*)malloc(sizeof(char));
aPtr[0]="This is a test";
printf("%s",aPtr[0]);
In C a string is a char*. A dynamic array of type T is represented as a pointer to T, so for char* that would be char**, not simply a char* the way you declared it.
The compiler, no doubt, has issued some warnings about it. Pay attention to these warnings, very often they help you understand what to do.
Here is how you can start your testing:
char **aPtr;
int len = 1; // Start with 1 string
aPtr = malloc(sizeof(char*) * len); // Do not cast malloc in C
aPtr[0] = "This is a test";
printf("%s",aPtr[0]); // This should work now.
char *str; //single pointer
With this you can store one string.
To store array of strings you Need two dimensional character array
or else array of character pointers or else double pointer
char str[10][50]; //two dimensional character array
If you declare like this you need not allocate memory as this is static declaration
char *str[10]; //array of pointers
Here you need to allocate memory for each pointer
loop through array to allocate memory for each pointer
for(i=0;i<10;i++)
str[i]=malloc(SIZE);
char **str; //double pointer
Here you need to allocate memory for Number of pointers and then allocate memory for each pointer .
str=malloc( sizeof(char *)*10);
And then loop through array allocate memory for each pointer
for(i=0;i<10;i++)
str[i]=malloc(SIZE);
char * aPtr;
is as pointer to a character, to which you allocated memory to hold exactly 1 character.
Doing
aPrt[0] = "test";
you address the memory for this one characters and try to store the address of the literal "test" to it. This will fail as this address most likley is wider then a character.
A fix to your code would be to allocate memory for a pointer to a character.
char ** aPtr = malloc(sizeof(char *));
aPtr[0] = "test";
printf("%s", aPtr[0]);
Are more elegant and more over robust approach would be to allocate the same (as well as adding the mandatory error checking) by doing:
char ** aPtr = malloc(sizeof *aPtr);
if (NULL == aPtr)
{
perror("malloc() failed");
exit(EXIT_FAILURE);
}
...
You are doing it totally wrong. The correct version of your code should be like this:
int main ()
{
char *aPtr;
aPtr =(char*)malloc(20*sizeof(char));
aPtr ="This is a test";
printf("%s",aPtr);
}
You can use pointer array. if you want to store multiple string. Yes I know using for loop will be easy. But I am trying to explain in simple way even a beginner can understand.
int main ()
{
char *aPtr[10];
aPtr[0] =(char*)malloc(20*sizeof(char));
aPtr[0] ="This is a test";
aPtr[1] =(char*)malloc(20*sizeof(char));
aPtr[1] ="This is a test2";
printf("%s\n%s\n",aPtr[0],aPtr[1]);
}