I want to allocate a memory to an array of pointers in struct, but I receive the following error:
expression must be a modifiable lvalue
Here's struct code:
typedef struct {
int id;
char *entity[];
}entity;
Here's memory allocation in main function:
entity s;
s.entity= malloc(30 * sizeof(char *));
IDE underlines s.entity and pops the error I mentioned.
Please, help me out to solve this issue.
Your structure does not have a member called entity, only id and set.
You apparently want to allocate the whole structure. This type of struct member called flexible array member is useful if you want to allocate the whole structure in one malloc.
entity *s;
s = malloc(sizeof(*s) + 30 * sizeof(s -> set[0]));
This kind of struct members are very useful as you can realloc or free them in a single call.
Increase the size of the set array to 50
entity *tmp = realloc(s, sizeof(*s) + 50 * sizeof(s -> set[0]));
if(tmp) s = tmp;
Thats how you would allocate the pointers:
typedef struct {
int id;
char **set;
}entity;
int how_many_pointers = 30;
entity s;
s.set= malloc(how_many_pointers * sizeof(char *));
And for each pointer you would have to allocate the space for the corresponding string:
int i, string_size;
for(i = 0; i < how_many_pointers; i++)
{
printf("How many chars should have string number %d ?", i + 1);
scanf("%d", &string_size);
s.set[i] = malloc((string_size + 1) * sizeof(char)); // string + 1 due to space for '\0'
}
Related
I'm learning C.
I have a structure, and if I need to set array of structures -> so I allocate memory for this array. But do I need separately allocate memory for fields in this structure?
Like this:
struct Call{
char *country;
int duration;
};
int main(){
struct Call *calls;
int n;
scanf_s("%d", n);
calls = (struct Call *) calloc(n+1 , sizeof(struct Call));
}
You need not to allocate space for data members of objects of the structure type because they belong to the objects.
But it seems you will need to allocate a character array the pointer to which will be stored in the data member country if you want that objects will be owners of the corresponding strings.
For example
struct Call *calls = calloc( 1, sizeof( struct Call ) );
const char *country = "Some country";
calls->country = malloc( strlen( country ) + 1 );
strcpy( calls->country, country );
When you will deallocate memory for objects of the type struct Call you will need at first to free the memory allocated for character arrays pointed to by data members country.
Yes, you must initialize any pointer before you can dereference it. This means allocating memory for it, or assigning it to already-allocated memory. That's a universal rule in C, there's no special cases for pointers in structures. C will not "recursively" allocate memory for you. Among other things, how would it know how much you need? Consider your simplified code below
int main(){
struct Call *calls;
calls = calloc(1 , sizeof(struct Call));
}
Assuming calloc succeeded, calls now points to a memory block that contains space for a single struct Call, which includes space for the char pointer and int. However, country itself is still an unintialized pointer, and you must allocate space for it or point it to something already-allocated before you can safely dereference it
calls->country = malloc(25);
if (calls->country == NULL) exit(-1); // handle error how you want
strcpy(calls->country, "Portugal");
printf("%s\n", calls->country); // prints Portugal
or something like
char myCountry[] = "Spain";
calls->country = myCountry;
myCountry[0] = 'X';
printf("%s\n", calls->country); // prints Xpain
Also see Do I cast the result of malloc?
You need to allocate space for the struct and for char array.
You probably want to dynamically add calls to the array so you need to know the size of the array as well:
typedef struct Call{
char *country;
int duration;
}Call;
typedef struct
{
size_t size;
Call call[];
}Calls_t;
Calls_t *addCall(Calls_t *calls, const int duration, const char *country)
{
size_t newsize = calls ? calls -> size + 1 : 1;
calls = realloc(calls, sizeof(*calls) + newsize * sizeof(calls -> call[0]));
if(calls)
{
calls -> size = newsize;
calls -> call[newsize - 1].country = malloc(strlen(country) + 1);
if(!calls -> call[newsize - 1].country)
{
/* error handling */
}
strcpy(calls -> call[newsize - 1].country, country);
calls -> call[newsize - 1].duration = duration;
}
return calls;
}
void printCalls(const Calls_t *calls)
{
if(calls)
for(size_t i = 0; i < calls -> size; i++)
printf("Call %zu: Country:%s Duration:%d\n", i + 1, calls -> call[i].country, calls -> call[i].duration);
}
int main(void)
{
Calls_t *calls = NULL, *tmp;
tmp = addCall(calls, 10, "Poland");
if(tmp) calls = tmp;
tmp = addCall(calls, 20, "UK");
if(tmp) calls = tmp;
tmp = addCall(calls, 30, "US");
if(tmp) calls = tmp;
printCalls(calls);
/* free allocated memory */
}
https://godbolt.org/z/Kb5bKMfYY
I'm having trouble accessing my double pointer struct within my structure.
typedef struct monster
{
char *name;
char *element;
int population;
} monster;
typedef struct region
{
char *name;
int nmonsters;
int total_population;
monster **monsters;
} region;
region **
readRegion (FILE * infile, int *regionCount)
{
region **temp;
char garbage[50];
char garbage2[50];
char rName[50];
int monsterNum;
fscanf (infile, "%d %s", regionCount, garbage);
temp = malloc (*regionCount * sizeof (region *));
for (int i = 0; i < *regionCount; i++)
{
fscanf (infile, "%s%d%s", rName, &monsterNum, garbage2);
temp[i] = createRegion (inFile, rName, monsterNum);
}
return temp;
}
region *
createRegion (FILE * inFile, char *rName, int nMonsters)
{
region *r = malloc (sizeof (region));
char rMonster[50];
int rLength;
r->name = malloc ((strlen (rName) + 1) * sizeof (char));
strcpy (r->name, rName);
r->nmonsters = nMonsters;
for (int i = 0; i < nMonsters; i++)
{
r->monsters.name = (nMonsters * sizeof (r->monsters.name));
fscanf (in, "%s", rMonster);
r->monsters.name = malloc ((strlen (rMonster) + 1) * sizeof (char));
strcpy (r->monsters.name, rMonster);
}
return r;
}
Hopefully my code is readable where you can get the jist of what im trying to do with the monster** monsters pointer in my region struct. Any explnation on how to access and use a double struct pointer within a structure would help.
I've tried to clean up and re-interpret your createRegion to read a lot more like traditional C:
region* createRegion(FILE * inFile, char *rName, int nMonsters) {
region *r = malloc(sizeof(region));
char buffer[1024];
r->name = strdup(rName);
r->nmonsters = nMonsters;
r->monsters = calloc(nMonsters, sizeof(monster*));
for (int i=0; i < nMonsters; i++) {
// Allocate a monster
monster *m = malloc(sizeof(monster));
fscanf(in,"%s", buffer);
m->name = strdup(buffer);
m->element = NULL; // TBD?
m->population = 1; // TBD?
// Put this monster in the monsters pointer array
r->monsters[i] = m;
}
return r;
}
Where the key here is you must allocate the monsters. Here it's done individually, but you could also allocate as a slab:
region* createRegion(FILE * inFile, char *rName, int nMonsters) {
region *r = malloc(sizeof(region));
char buffer[1024];
r->name = strdup(rName);
r->nmonsters = nMonsters;
// Make a single allocation, which is usually what's returned from
// C functions that allocate N of something
monsters* m = calloc(nMonsters, sizeof(monster));
// Normally you'd see a definition like m in the region struct, but
// that's not the case here because reasons.
r->monsters = calloc(nMonsters, sizeof(monster*));
for (int i=0; i < nMonsters; i++) {
fscanf(in,"%s", buffer);
m[i].name = strdup(buffer);
m[i].element = NULL; // TBD?
m[i].population = 1; // TBD?
// Put this monster in the monsters pointer array
r->monsters[i] = &m[i];
}
return r;
}
Note I've switched out the highly quirky strlen-based code with a simple strdup call. It's also very odd to see sizeof(char) used since on any computer you're likely to interface with, be it an embedded microcontroller or a fancy mainframe, that will be 1.
Inasmuch as you are asking about accessing a double pointer inside a structure, I think your issue is mostly about this function:
region *
createRegion (FILE * inFile, char *rName, int nMonsters)
{
region *r = malloc (sizeof (region));
char rMonster[50];
int rLength;
r->name = malloc ((strlen (rName) + 1) * sizeof (char));
strcpy (r->name, rName);
r->nmonsters = nMonsters;
[Point A]
So far, so good, but here you start to run off the rails.
for (int i = 0; i < nMonsters; i++)
{
r->monsters.name = (nMonsters * sizeof (r->monsters.name));
Hold on. r->monsters has type monster **, but you are trying to access it as if it were a monster. Moreover, r->monsters has never had a value assigned to it, so there's very little indeed that you can safely do with it.
I think the idea must be that r->monsters is to be made to point to a dynamically-allocated array of monster *, and that the loop allocates and initializes the monsters, and writes pointers to them into the array.
You need to allocate space for the array, then, but you only need or want to allocate the array once. Do that before the loop, at Point A, above, something like this:
r->monsters = malloc(nMonsters * sizeof(*r->monsters)); // a monster **
Then, inside the loop, you need to allocate space for one monster, and assign a pointer to that to your array:*
r->monsters[i] = malloc(sizeof(*r->monsters[i])); // a monster *
Then, to access the actual monster objects, you need to either dererference and use the direct member selection operator (.) ...
(*r->monsters[i]).name = /* ... */;
... or use the indirect member selection operator (->) ...
r->monsters[i]->name = /* ... */;
. The two are equivalent, but most C programmers seem to prefer the latter style.
At this point, however, I note that in the body of the loop, you seem to be trying to make two separate assignments to the monster's name member. That doesn't make sense, and the first attempt definitely doesn't make sense, because you seem to be trying to assign a number to a pointer.
fscanf (in, "%s", rMonster);
r->monsters.name = malloc ((strlen (rMonster) + 1) * sizeof (char));
strcpy (r->monsters.name, rMonster);
Using the above, then, and taking advantage of the fact that sizeof(char) is 1 by definition, it appears that what you want is
// ...
r->monsters[i]->name = malloc(strlen(rMonster) + 1);
strcpy (r->monsters[i]->name, rMonster);
And finally,
}
return r;
}
Note well that corresponding to the two levels of indirection in type monster **, each access to an individual monster property via r->members requires two levels of derferencing. In the expressions above, one is provided by the indexing operator, [], and the other is provided by the indirect member access operator, ->.
* Or you could allocate space for all of the monsters in one go, before the loop, and inside the loop just initialize them and the array of pointers to them. The use of a monster ** suggests the individual allocation approach, but which to choose depends somewhat on how these will be used. The two options are substantially interchangeable, but not wholly equivalent.
here is what i have in done so far
struct test_case {
int n;
int *test[];
};
struct test_case *test_case_struct = (struct test_case *)malloc(
sizeof(struct test_struct) + 100 * sizeof(int));
I need to allocate n pointers in the "test" pointer array. As far as i know i need to allocate space to the structure and then some more for the pointer array, but when i try to compile this, i get the error
invalid use of sizeof operator for to incomplete type struct test_struct
if someone could please inform me how i can take the value of n as a user input and have int *test [n] made possible.
Don't repeat type names. You already stumbled over your own code twice because you did that. You made the mistake of typing the wrong struct tag and confusing int* for int.
A more hardy allocation would look like this
struct test_case *test_case_struct =
malloc(sizeof (*test_case_struct) + sizeof (test_case_struct->test[0]) * 100);
This here will allocate the size of whatever test_case_struct points at, plus 100 more of whatever test_case_struct->test[0] should be. Now you can play with the structure definition without breaking this call to malloc. And if you do perform a breaking change (like renaming test), you'll be notified by your compiler promptly.
You need to change
sizeof(struct test_struct)
to
sizeof(struct test_case)
as test_struct is not the correct structure type.
In a better way, you can also use the already-declared variable name, like
struct test_case *test_case_struct = malloc(
sizeof (*test_case_struct) + n * sizeof(int*));
That said, you need to allocate memory worth of int *s, not ints, for the flexible member.
Also, below is a snippet which shows the count is taken as user input
int main(void)
{
int n = 0;
puts("Enter the count of pointers");
if (scanf("%d", &n) != 1) {
puts("Got a problem in the input");
exit (-1);
}
struct test_case *test_case_struct = malloc( sizeof(struct test_case) + n * sizeof(int*));
printf("Hello, world!\n");
return 0;
}
Currently you are using flexible array(aka zero length array).
Which can be allocated as below.
struct test_case *test_case_struct =
malloc(sizeof (*test_case_struct) + 100 * sizeof (int *));
Note missing * for int and typo sizeof(struct test_struct) in your code.
Alternatively you can use pointer to pointer as below.
struct test_case {
int n;
int **test;
};
struct test_case *test_case_struct = malloc(
sizeof(*test_case_struct));
test_case_struct->test = malloc(100 * sizeof(int *)); // Allocates 100 pointers
I've read and looked at some example of flexible array members but I am not exactly sure how to add and read elements of this variable length array.
typedef struct School {
char *name;
char *courses[]; //Flexible Array Member
} School;
1) Can someone please show me an example of how I can add an element to this Flexible Length Member and print it after it is stored.
2) I also would like to know how to malloc it correctly. Based on what I have read about Flexible Array Members, we would need to add more space for the flexible array member and can't just use sizeof(School);. My only issue is how do I know how much do add for that flexible member.
You should modify the struct to add the number of courses present in the allocated structure:
typedef struct School {
char *name;
int ncourses;
char *courses[]; //Flexible Array Member
} School;
Say you have 2 schools, one with 3 courses, one with 2. You would allocate the structures this way:
School *mc = malloc(offsetof(struct School, courses) + 3 * sizeof(char *));
mc->name = strdup("Math College");
mc->ncourses = 3;
mc->courses[0] = strdup("Math 101");
mc->courses[1] = strdup("Math 102");
mc->courses[2] = strdup("Math 103");
School *ps = malloc(offsetof(struct School, courses) + 2 * sizeof(char *));
ps->name = strdup("Psycho School");
ps->ncourses = 2;
ps->courses[0] = strdup("Psycho 101");
ps->courses[1] = strdup("Unknown 404");
As you can see, elements of the variable array are accessed like any other array elements. The malloc call allocates the appropriate size in bytes for the struct members and the array elements (here char * pointers), that are located at the end of the structure.
You could use a generic function to allocate and initialize such structures:
School create_school(const char *school_name, int ncourses, char *courses[]) {
School *sp = malloc(offsetof(struct School, courses) + ncourses * sizeof(char *));
sp->name = strdup(school_name);
sp->ncourses = ncourses;
for (int i = 0; i < ncourses; i++) {
sp->courses[i] = strdup(courses[i]);
}
return sp;
}
The exact formula for computing the required size of your structure is:
size_t need = offsetof(struct School, courses) + num_courses * sizeof(char *);
Note the use of offsetof. Some people use sizeof, but this can introduce memory overhead due to structure padding.
Essentially the technique is to dynamically allocate enough memory for the struct, plus the elements of the last array.
School *data = malloc(sizeof(*data) + number * sizeof(*(data->courses)));
for (i = 0; i < number; ++i)
{
const char hello[] = "Hello";
data->courses[i] = malloc(strlen(hello) + 1)); /* sizeof char is 1 by definition */
strcpy(courses[i], hello);
}
I have been looking online but so far nothing has helped me understand my problem. Currently I am trying to make two lists that each contain a list of words. Each space contains a word struct and within each word struct is list of 30 doc_list structs. I have been able to allocate memory and store a char*s within the word list struct but when I try to allocate memory and store a char* within a doc_list struct I get a segmentation error. I am confused because I declared my doc_list struct the same exact way as I did my word_list struct.
Below is the initialization of my structs
In my C file I initialize my Hash Table
#define BUFFSIZE 1000
#define STOPLIST_INDEX 0
#define DOCUMENTS_INDEX 1
struct HashTable{
int tableSize;
struct word_list** wordList;
};
struct word_list{
char* word;
struct doc_list** docList;
};
struct doc_list{
char* docName;
int timesAppear;
};
//Initialing lists associated with hash table
struct HashTable** initialize_hash_table(int argc, char** argv)
{
int k; //HashTables
int i; //Words
int q; //Document names
struct HashTable** hashTable = calloc(2, sizeof(struct HashTable **));
for(k =0; k < 2; k++)
{
hashTable[k] = calloc (1, sizeof(struct HashTable *));
hashTable[k]->wordList = calloc(BUFFSIZE, sizeof(struct word_list **));
for(i = 0; i < BUFFSIZE; i++)
{
hashTable[k]->wordList[i] = calloc(1, sizeof(struct word_list *));
hashTable[k]->wordList[i]->docList = calloc(30, sizeof(struct doc_list**));
for(q = 0; q < 30; q++)
{
hashTable[k]->wordList[i]->docList[q] = calloc(1, sizeof(struct doc_list*));
}
}
}
return hashTable;
}
then in my insert function where I store the document name char* value is where I get a segmentation error. I don't understand why this happens because I initialized my doc_list structure the exact same way that I initialized my word_list structure.
int insert(struct HashTable** hashTable, char* document_word, char* filename, int index)
{
//create the hash key
int key = hashFunction(document_word, BUFFSIZE);
//Check if word exists in Stop List
if(index == 0 || hashTable[STOPLIST_INDEX]->wordList[key]->word == NULL)
{
//insert into list
hashTable[index]->wordList[key] = malloc(sizeof(struct word_list*));
hashTable[index]->wordList[key]->word = strdup(document_word);
printf("%s%s\n", "INSERTED VALUE: ", hashTable[index]->wordList[key]->word);
//Add filename to words' document list
int w = 0;
puts("segfaulting here");
puts("1");
hashTable[index]->wordList[key]->docList[w] = malloc(sizeof(struct doc_list*));
hashTable[index]->wordList[key]->docList[w]->docName = strdup(filename);
printf("%s%s\n", "INSERTED ", filename);
printf("\n");
}
return 0;
}
What I believe is happening is that all the word structs are being declared NULL if they are not allocated memory for a word but none of the doc_list structs are being declared NULL for some reason. I allocated memory for them the exact same way I did the word_list structs.
The output when I run the program is this:
Hashing filename:stopwords.txt
---------
INSERTED VALUE: a
segfaulting here
1
Segmentation fault (core dumped)
What am I doing wrong??
Problems I see:
hashTable[k] = calloc (1, sizeof(struct HashTable *));
needs to be changed to
hashTable[k] = calloc (1, sizeof(struct HashTable));
Type of hasTable[k] is struct HashTable*. The object that it points to has to be of size struct HashTable, not struct HashTable*.
There is a similar error in:
struct HashTable** hashTable = calloc(2, sizeof(struct HashTable **));
It needs to be:
struct HashTable** hashTable = calloc(2, sizeof(struct HashTable*));
You won't see the error easily since sizeof(struct HashTable*) is equal to sizeof(struct HashTable**) in most cases.
More of such errors are in initialize_hash_table.
hashTable[k]->wordList[i]->docList = calloc(30, sizeof(struct doc_list**));
needs to be
hashTable[k]->wordList[i]->docList = calloc(30, sizeof(struct doc_list*));
hashTable[k]->wordList[i]->docList[q] = calloc(1, sizeof(struct doc_list*));
needs to be
hashTable[k]->wordList[i]->docList[q] = calloc(1, sizeof(struct doc_list));
You have similar errors in insert.
hashTable[index]->wordList[key] = malloc(sizeof(struct word_list*));
needs to be
hashTable[index]->wordList[key] = malloc(sizeof(struct word_list));
hashTable[index]->wordList[key]->docList[w] = malloc(sizeof(struct doc_list*));
needs to be
hashTable[index]->wordList[key]->docList[w] = malloc(sizeof(struct doc_list));
Tip: Only use calloc if you actually need your memory zeroed. malloc is faster.
Also, there is no need to test unequality to 0 NULL \0, unless you need your truth value normalized to 0|1, and even then !! is preferrable. ! for equality to 0 in any of its guises.
But your real problem is something else:
struct HashTable** hashTable = calloc(2, sizeof(struct HashTable **));
The above line alloates zeroed memory for 2 struct HashTable**, and stores the pointer in hashTable, which has type sttruct HashTable** too!!
You actually want to allocate space for 2 struct HashTable*.
In this one specific case it does not kill you, because those two pointer types happen to use the same amount of space on this architecture, but it's a pattern which is repeated with worse results later, and allocating too little memory leads to buffer overruns, which as Undefined Behavior mean anything can happen (and naturally mostly bad things).
When you want to point with pointer p to a memory block, allocate it thus:
p = malloc(count * sizeof *p);
p = calloc(count, sizeof *p); /* only for zeroed memory */
You do not want to use sizeof on the type, because it is far too easy to get it wrong, adding or leaving off one or more levels of indirection or taking a completely unrelated type.
Unless you name a VLA to sizeof, it will not evaluate its arguments, but only get the type and derive a compile-ime-constant.
Some more things you should read:
How to Debug Small Programs
C99 with Technical corrigenda TC1, TC2, and TC3 included
MCVE