i just started with programming and i don't know what does this mean ..
I tried everything i could..
I know its dynamic memory allocation but don't know what all these (stars) means.
Could someone explain me, what every type is?
This is the code:
char **text = (char **) malloc(n * sizeof(char*));
text[i] = (char *) malloc(MAX_LENG);
The code allocates (dynamic) memory for holding n strings. Each of these strings with max length MAX_LENG - 1.
I assume the complete original code to be:
char **text = (char **) malloc(n * sizeof(char*));
for (int i = 0; i < n; ++i)
text[i] = (char *) malloc(MAX_LENG);
or without the unnecessary casts:
char **text = malloc(n * sizeof(char*));
for (int i = 0; i < n; ++i)
text[i] = malloc(MAX_LENG);
So the first line, i.e.
char **text = malloc(n * sizeof(char*));
will give you a pointer to a memory area holding n pointers-to-char
The loop, i.e.
for (int i = 0; i < n; ++i)
text[i] = malloc(MAX_LENG);
then makes each of these n pointers point to a memory area with MAX_LENG chars.
It looks like:
So after this you have memory for n strings and can use them like:
strcpy(text[0], "HELLO"); // First string is "Hello"
strcpy(text[1], "WORLD"); // Second string is "World"
After this it looks like:
You can access the individual charaters like this
char c = text[1][4]; // c now holds the character 'D' from the string "WORLD"
A simple explanation can look the following way. Let's assume that you have an array of pointers to string literals. For example
char * s[] = { "Hello ", "World!" };
The array designator used in expression with rare exception is converted to pointer to its first element. So the array designator s in most cases is converted to pointer of the type char **. That is it is a pointer to an object of the type char *.
For example
char **p = s;
Dereferencing the pointer you will get the first element of the array that in turn has the type char *. For example
#include <stdio.h>
int main( void )
{
enum { N = 2 };
char * s[N] = { "Hello ", "World!" };
for ( char **p = s; p != s + N; ++p )
{
printf( "%s", *p );
}
putchar( '\n' );
return 0;
}
The program output is
Hello World!
Now let's assume that you want to allocate the array s dynamically. The array has N element of the type char *.
So you need to write the expression
malloc( N * sizeof( char * ) )
The function call return pointer to the start of the allocated extent of memory where there will be the first element of the type char *. That is the function returns a pointer of the type void * to potentially the first element of the dynamically allocated array.
So you need to write
char **p = malloc( N * sizeof( char * ) );
or
char **p = ( char ** )malloc( N * sizeof( char * ) );
It is similar to the declaration shown above
char **p = s;
Other answers explained what it does but I want to focus on one small detail.
char **text = malloc(n * sizeof(char*));
Using the types instead of objects in sizeof is considered as a not good practice. Why? If you change the type of the object you need to change all possible appearances of the old type. If you use the object in the sizeof - every sizeof will be calculated correctly without any changes in the code.
char **text = malloc(n * sizeof(*text));
Related
For the malloc statement below, I am failing to initialize a variable-sized object
int textsize = BUF_SIZE;
char *lines[textsize] = malloc(sizeof(char *) * textsize);
The objective is to have an array of pointers where each will store the pointers to STDIN lines entered by the user.
textsize is the number of lines that is supported as input by the user.
Error:
error: variable-sized object may not be initialized
char *lines[textsize] = malloc(sizeof(char *) * textsize);
This is because you have allocated the lines with textsize as a size:- static, and then you are trying to allocate dynamically using malloc..
Try double pointer
char **lines = malloc(...)
As #A.Shenoy mentioned, you should use a double pointer. The reason for that is when you do char *lines[textsize], you're creating a pointer to a char array, but malloc returns a char pointer. So the solution is to do char **lines which creates a pointer to a char pointer. You still need to allocate space for the pointers, this is how you can initialize the array;
#define ARRAY_SIZE 5 // array of 5 strings
char **lines = (char**) malloc(sizeof(char*) * ARRAY_SIZE);
int i;
for (i = 0; i < ARRAY_SIZE; i++) {
lines[i] = (char*) malloc(sizeof(char) * textsize);
}
// The array is now allocated, and you can fill it with strcpy
// Example for filling:
char text[] = "Hello World!";
strcpy(lines[0], text);
I'm not great with pointers. I know enough to get an array of pointers to char to work, as in the first example below. But I don't want to pass an entire array of pointers, because it takes up too much room on the stack. What I would like to do is pass a single pointer to the memory allocated for the array of pointers. I have no idea how to do this.
This program works:
#include "pch.h"
#include "$StdHdr.h"
#include "TmpTstPtr1.h"
#define SRC_LIN_SIZ 150
int main(int ArgCnt, char * ArgVal[])
{
char InpFilPth[MAX_PATH + 1];
FILE * InpFilPtr;
char ** SrcArr;
unsigned Sub1;
unsigned SrcArrCnt = 0;
strncpy_s(InpFilPth, "TmpTstPtr1.cpp", strlen("TmpTstPtr1.cpp"));
fopen_s(&InpFilPtr, InpFilPth, "r");
SrcArr = (char **)malloc(999999 * sizeof(char *));
LodSrcArr(InpFilPtr, SrcArr, &SrcArrCnt);
for (Sub1 = 0; Sub1 < SrcArrCnt; Sub1++) {
printf("SrcArr[%d] = %s\n", Sub1, SrcArr[Sub1]);
}
fclose(InpFilPtr);
return 0;
}
void LodSrcArr(FILE * InpFilPtr, char ** SrcArr, unsigned * SrcArrCnt)
{
char SrcLin[SRC_LIN_SIZ + 1];
char * GetStrPtr;
GetStrPtr = GetStr(SrcLin, SRC_LIN_SIZ, InpFilPtr);
while (GetStrPtr != NULL) {
SrcArr[*SrcArrCnt] = (char *)malloc(SRC_LIN_SIZ + 1);
// CpySiz(SrcArr[*SrcArrCnt], strlen(SrcLin) + 1, SrcLin);
errno = strncpy_s(SrcArr[*SrcArrCnt], SRC_LIN_SIZ + 1, SrcLin, strlen(SrcLin));
(*SrcArrCnt)++;
GetStrPtr = GetStr(SrcLin, SRC_LIN_SIZ, InpFilPtr);
}
}
char * GetStr(char * Str, const int MaxChr, FILE * InpFilPtr)
{
char * InpRtnVal = NULL;
unsigned Sub1;
// Get string from input file. Find the end of the string if something entered.
InpRtnVal = fgets(Str, MaxChr + 1, InpFilPtr);
if (InpRtnVal != NULL) {
Sub1 = 0;
while (Str[Sub1] != '\n' && Str[Sub1] != '\0') {
Sub1++;
}
// Replace newline with null.
if (Str[Sub1] == '\n') {
Str[Sub1] = '\0';
}
}
return InpRtnVal;
The following program doesn't even come close:
#include "pch.h"
#include "$StdHdr.h"
#include "TmpTstPtr2.h"
#define SRC_LIN_SIZ 150
int main(int ArgCnt, char * ArgVal[])
{
char InpFilPth[MAX_PATH + 1];
FILE * InpFilPtr;
char ** SrcArr;
unsigned Sub1;
unsigned SrcArrCnt = 0;
char *** SrcArrPtr = NULL;
strncpy_s(InpFilPth, "TmpTstPtr2.cpp", strlen("TmpTstPtr2.cpp"));
fopen_s(&InpFilPtr, InpFilPth, "r");
SrcArr = (char **)malloc(999999 * sizeof(char *));
SrcArrPtr = &SrcArr;
LodSrcArr(InpFilPtr, SrcArrPtr, &SrcArrCnt);
SrcArrPtr = &SrcArr;
for (Sub1 = 0; Sub1 < SrcArrCnt; Sub1++) {
// printf("SrcArr[%d] = %s\n", Sub1, SrcArr[Sub1]); // got "Exception thrown: read access violation. it was 0xCDCDCDCD."
printf("SrcArr[%d] = %s\n", Sub1, **SrcArrPtr); // get 75 lines of garbage
(**SrcArrPtr) += sizeof(char *);
}
fclose(InpFilPtr);
return 0;
}
void LodSrcArr(FILE * InpFilPtr, char *** SrcArrPtr, unsigned * SrcArrCnt)
{
char SrcLin[SRC_LIN_SIZ + 1];
char * GetStrPtr;
GetStrPtr = GetStr(SrcLin, SRC_LIN_SIZ, InpFilPtr);
// while (GetStrPtr != NULL and *SrcArrCnt == 0) {
while (GetStrPtr != NULL) {
**SrcArrPtr = (char *)malloc(SRC_LIN_SIZ + 1);
// CpySiz(SrcArr[*SrcArrCnt], strlen(SrcLin) + 1, SrcLin);
errno = strncpy_s(**SrcArrPtr, SRC_LIN_SIZ + 1, SrcLin, strlen(SrcLin));
(**SrcArrPtr) += sizeof(char *);
(*SrcArrCnt)++;
GetStrPtr = GetStr(SrcLin, SRC_LIN_SIZ, InpFilPtr);
}
}
char * GetStr(char * Str, const int MaxChr, FILE * InpFilPtr)
{
char * InpRtnVal = NULL;
unsigned Sub1;
// Get string from input file. Find the end of the string if something entered.
InpRtnVal = fgets(Str, MaxChr + 1, InpFilPtr);
if (InpRtnVal != NULL) {
Sub1 = 0;
while (Str[Sub1] != '\n' && Str[Sub1] != '\0') {
Sub1++;
}
// Replace newline with null.
if (Str[Sub1] == '\n') {
Str[Sub1] = '\0';
}
}
return InpRtnVal;
}
As the comments say, when I try to access SrcArr via a subscript, I get a run-time error. When I try to access via the pointer, I get garbage. The problem may be where I say SrcArrPtr = &SrcArr;. I don't know if it's significant, but the garbage printed is 4 characters shorter with each subsequent line. As if it's actually printing the array of pointers itself, rather than the strings they point to. I dunno.
The reason I coded it as above is in order to get the program to compile. I've never tried to use 3 pointers before. Is what I'm trying to do even possible? If so, can someone show me how? An explanation of how it works would be nice, but not necessary. (I'm using Visual Studio 2017, though I don't think it matters.)
TIA.
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
void foo(char* bar[10]) { // a real array
for (int i = 0; i < 10; ++i) {
bar[i] = calloc(2, 1);
bar[i][0] = '0' + i;
}
}
void xox(char **qux) { // pointer to some char-pointers on the heap
for (int i = 0; i < 10; ++i) {
qux[i] = calloc(2, 1);
qux[i][0] = '0' + i;
}
}
int main(void)
{
char* bar[10]; // a "real" array
foo(bar);
for (size_t i = 0; i < 10; ++i)
puts(bar[i]);
putchar('\n');
// cleanup:
for (size_t i = 0; i < 10; ++i)
free(bar[i]);
// plan b:
char **qux = calloc(10, sizeof(*qux));
xox(qux);
for (size_t i = 0; i < 10; ++i)
puts(qux[i]);
putchar('\n');
// cleanup:
for (size_t i = 0; i < 10; ++i)
free(qux[i]);
free(qux);
}
What I would like to do is pass a single pointer to the memory
allocated for the array of pointers.
Suppose you have some integers on the heap, like this:
int *integers = (int*)malloc(4 * sizeof(int));
And now suppose you have some pointers, also on the heap:
int **pointers = (int**)malloc(4*sizeof(int*));
Now let's assign the pointers to the addresses of the integers:
pointers[0] = &integers[0];
pointers[1] = &integers[1];
pointers[2] = &integers[2];
pointers[3] = &integers[3];
In this example, pointers is a pointer to an array of pointers (on the heap) pointing to some integers (also on the heap). You can freely pass pointers around and use it in another function.
Or, if you wanted the array of pointer to be on the stack:
int* pointers[4];
pointers[0] = &integers[0];
pointers[1] = &integers[1];
pointers[2] = &integers[2];
pointers[3] = &integers[3];
int **ppointer = pointers;
Now ppointer is also a pointer pointing to an array of pointers that point to some integers on the heap. Just notice that this time, those pointers are on the stack, not on the heap. So if you return from this function, they're out of scope and you may not access them anymore.
You're operating under a misconception. Neither C nor C++ pass a copy of an array to a function, nor can they return an array from a function.
Except when it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression is the address of the first element.
Thus, if you declare an array like
char *ptrs[N];
and pass it to a function as
foo( ptrs );
the expression ptrs is implicitly converted from "N-element array of char *" to "pointer to char *", and what foo actually receives is a pointer to the first element of the array - it's effectively the same as writing
foo( &ptrs[0] );
The prototype can be written as either
void foo( char **ptrs )
or
void foo( char *ptrs[] )
or
void foo( char *ptrs[N] )
In a function parameter declaration, array declarators are "adjusted" to be pointer declarators - IOW, T a[N] and T a[] are both interpreted to mean T *a. This is only true in a function parameter declaration, though.
As a matter of style...
In C, the cast on malloc is unnecessary1, and under C89 it can suppress a useful diagnostic if you forget to include stdlib.h or otherwise don't have a declaration for malloc (or calloc or realloc) in scope. Under C99 and later, you'll get a diagnostic for not having a declaration, but C89 still allowed implicit int declarations, and the cast will prevent the compiler from yelling at you because int and pointer types are not compatible. I bring this up because MS's support for C past C89 is a bit spotty.
To minimize your maintenance burden, it's better to avoid explicitly naming types in a malloc call. You can rewrite
SrcArr = (char **)malloc(999999 * sizeof(char *));
as
SrcArr = malloc( 999999 * sizeof *SrcArr ); // you sure you need that many elements??!
Since SrcArr has type char **, the expression *SrcArr has type char *, so sizeof *SrcArr is the same as sizeof (char **). In general, a malloc call can be written
T *p = malloc( N * sizeof *p );
or
T *p;
...
p = malloc( N * sizeof *p );
The same is true for calloc and realloc.
This is not the cast in C++, since C++ doesn't allow implicit conversion from void * to other pointer types, but if you're writing C++ you shouldn't be using malloc anyway.
I am using a char * array to make a buffer to move information from multiple mapping threads to a reducing thread. I need to make the array circular, however, i keep getting segmentation faults when the array runs out of room. How do I make the array circular? I currently have
for(j = 0; j < i; j++){
int next = mr->nextIndex + j;
if(next > 1023){
next = 0;
}
mr->buffer[next] = temp[j];
}
The array is set up as,
new_mr->buffer = malloc(sizeof(char *) * MR_BUFFER_SIZE);
with the macro being 1024. Any help is appreciated.
temp is
char *temp = malloc(sizeof(char *));
and it gets its value from
memcpy(temp, kv, i);
and kv is passed into the function from the main.
This is wrong:
char *temp = malloc(sizeof(char *));
You're storing some data into there using memcpy() but the storage space is only sizeof(char*) which is 4 or 8 bytes. You probably meant to use some other size there, e.g. the value of i you pass to memcpy().
char *temp = malloc(sizeof (char *));
should be
char *temp = malloc(sizeof (char) * i); // sizeof (char) can be omitted
because temp is expected to point to an array of char.
mr->buffer[next] = temp[j];
should be
mr->buffer[next] = &temp[j];
because mr->buffer[next] is of type char *.
I just cannot assign string array to my char** pointer.
I have my strings in char *tempArr[12];
But I don't know how to assign them to my char** arr variable.
First, I allocate memory using: arr = (char**)malloc(numberOfElements * sizeof(char*));
Then I tried to allocate memory to each element:
arr[i] = malloc(256 * sizeof(char));
I also tried to alocate just the memory for char pointer but neither works. The result in my arr variable is 2 to 3 nonsense characters.
What could be wrong? I tried everything I was able to find and the result is either crash or nonsense content.
EDIT: Sorry I'll try to clarify it more. Background is, I am loading data from file into structs. Each struct has char** variable that is suppose to hold strings array.
In my reading code, I am using my temp array char* tempArr[12] and successfully loading strings into it. Then I pass it allong to my function that is creating my structs.
The problem starts here, I was trying to "convert" my passed array so it can be stored in char** arr variable.
char *tempArr[12];
Is array of pointers. So if you have something like
tempArr[0] = malloc(20);
strcpy(tempArr[0],"hello");
Then after what you are doing you can do. i.e. After allocating memory to your the pointer arr[i]
char **arr = malloc(numberOfElements * sizeof(char*));
arr[i] = malloc(256);
strcpy(arr[i],tempArr[0]);
You can run the above steps in a loop to copy values for all your pointers
I think that you mean the following
#include <string.h>
//...
size_t i;
char **arr = ( char** )malloc( numberOfElements * sizeof( char* ) );
for ( i = 0; i < numberOfElements; i++ ) arr[i] = malloc( 256 * sizeof( char ) );
for ( i = 0; i < sizeof( tempArr ) / sizeof( *tempArr ); i++ ) strcpy( arr[i], tempArr[i] );
I am having trouble understanding how to assign memory
to a double pointer.
I want to read an array of strings and store it.
char **ptr;
fp = fopen("file.txt","r");
ptr = (char**)malloc(sizeof(char*)*50);
for(int i=0; i<20; i++)
{
ptr[i] = (char*)malloc(sizeof(char)*50);
fgets(ptr[i],50,fp);
}
instead of this I just assign a large block of memory and
store the string
char **ptr;
ptr = (char**)malloc(sizeof(char)*50*50);
would that be wrong? And if so why is it?
Your second example is wrong because each memory location conceptually would not hold a char* but rather a char. If you slightly change your thinking, it can help with this:
char *x; // Memory locations pointed to by x contain 'char'
char **y; // Memory locations pointed to by y contain 'char*'
x = (char*)malloc(sizeof(char) * 100); // 100 'char'
y = (char**)malloc(sizeof(char*) * 100); // 100 'char*'
// below is incorrect:
y = (char**)malloc(sizeof(char) * 50 * 50);
// 2500 'char' not 50 'char*' pointing to 50 'char'
Because of that, your first loop would be how you do in C an array of character arrays/pointers. Using a fixed block of memory for an array of character arrays is ok, but you would use a single char* rather than a char**, since you would not have any pointers in the memory, just chars.
char *x = calloc(50 * 50, sizeof(char));
for (ii = 0; ii < 50; ++ii) {
// Note that each string is just an OFFSET into the memory block
// You must be sensitive to this when using these 'strings'
char *str = &x[ii * 50];
}
char **ptr;
fp = fopen("file.txt","r");
ptr = (char**)malloc(sizeof(char*)*50);
for(int i=0; i<50; i++)
{
ptr[i] = (char*)malloc(sizeof(char)*50);
fgets(ptr[i],50,fp);
}
fclose(fp);
may be your typo mistake but your loop should be of 50 instead of 20 if you are looking for 50 x 50 matrix. Also after allocation of memory mentioned above you can access the buffer as ptr[i][j] i.e in the 2D format.
A double pointer is just a pointer to another pointer. So you can allocate it like this:
char *realptr=(char*)malloc(1234);
char **ptr=&realptr;
You have to keep in mind where your pointer is stored at (in this example the double pointer points to a pointer variable on the stack so it's invalid after the function returns).
i will give one example, which might clear of the doubt,
char **str; // here its kind a equivalent to char *argv[]
str = (char **)malloc(sizeof(char *)*2) // here 2 indicates 2 (char*)
str[0]=(char *)malloc(sizeof(char)*10) // here 10 indicates 10 (char)
str[1]=(char *)malloc(sizeof(char)*10) // <same as above>
strcpy(str[0],"abcdefghij"); // 10 length character
strcpy(str[1],"xyzlmnopqr"); // 10 length character
cout<<str[0]<<endl; // to print the string in case of c++
cout<<str[1]<<endl; // to print the string in case of c++
or
printf("%s",str[0]);
printf("%s",str[1]);
//finally most important thing, dont't forget to free the allocated mem
free(str[0]);
free(str[1]);
free(str);
other simpler way to memorize
Case -1 :
step-1 : char *p;
step -2 :
please read it like below
char (*p); ==> p is a pointer to a char
now you just need to do malloc for the type (step-2) without braces
i.e., p = malloc(sizeof(char) * some_len);
Case -2 :
step-1 : char **p;
step -2 :
please read it like below
char* (* p); ==> p is a pointer to a char *
now you just need to do malloc for the type (step-2) without braces
i.e., p = malloc(sizeof(char *) * some_len);
Case -3 :
No one uses this but just for sake of explanation
char ***p;
read it as,
char** (*p); ==> p is a pointer to a char** (and for this check case-2 above)
p = malloc(sizeof(char**) * some_len);
Adding to Pent's answer, as he correctly pointed out, you will not be able to use this double pointer once the function returns, because it will point to a memory location on the function's activation record on stack which is now obsolete (once the function has returned). If you want to use this double pointer after the function has returned, you may do this:
char * realptr = (char *) malloc(1234);
char ** ptr = (char **) malloc(sizeof(char *));
*ptr = realptr;
return ptr;
The return type of the function must obviously be char ** for this.
well, this is how I do it:
#include <stdlib.h>
int main(void)
{
int i = -1; // just a counter
int j = 5; // how many strings
char *s[j];
while(++i < j)
s[i] = malloc(sizeof(char*)); // allocating avery string separately
return (0);
}
this also works:
char **allocate(int lines)
{
int i = -1;
char **s = malloc(sizeof(char *) * lines); // allocating lines
while (++i < lines)
{
s[i] = malloc(sizeof(char*)); // alicating line
scanf("%s", s[i]);
}
return (s);
}
int main(int ac, char *av[])
{
int lines = 5; // how many lines
char **s = allocate(lines);
return (0);
}
Double pointer is, simply put, a pointer to a pointer,
In many cases it is used as an array of other types.
For example, if you want to create an array of strings you can simply do:
char** stringArray = calloc(10, 40);
this will create an array of size 10, each element will be a string of length 40.
thus you can access this by stringArray[5] and get a string in the 6th position.
this is one usage, the others are as mentioned above, a pointer to a pointer, and can be allocated simply by:
char* str = (char*)malloc(40);
char** pointerToPointer = &str //Get the address of the str pointer, valid only in the current closure.
read more here:
good array tutorial