I came across something I don't understand why and I'd like to hear an explanation about it.
I have this struct:
typedef struct Student {
int age;
char *name;
} Student;
int main()
{
Student **test1 = calloc(2, sizeof(*test1));
Student **test2 = calloc(2, sizeof(**test2));
return 0;
}
I've noticed that test1 gets 2 memory allocations (as it should) while test2 gets 4. Why is that and which is the correct usage? I assume its the first one but i'm not sure why.
Thanks!
sizeof(*test1) is the size of a pointer Student*, while sizeof(**test) is the size of a structure Student.The structure has a pointer, so its size should be larger than the size of a pointer.
Student **test1 = calloc(2, sizeof(*test1));
Is the typical usage. This is allocating 2-element array of Student* and assigning the pointer to its first element to test1.
Two things here:
You're allocating two different amounts of memory here. In the first case, you allocate space for 2 objects of type Student *, while in the second case you allocate space for 2 objects of type Student. The latter is likely larger than the former, so you'll be able to put more object of type Student * there.
You don't show how you're verifying how much memory you've gotten, but it's undefined behavior to read or write past the bounds of allocated memory. Your program might crash, or it might not.
sizeof(*test) is a size in bytes of the pointer to Student. It will be on most systems 4 or 8.
sizeof(**test)gives you the size of the Student. The allocation (test2) makes no sense at all.
You can easily test it yourself by printing the sizes:
#include <stdio.h>
#include <malloc.h>
typedef struct Student {
int age;
char *name;
double somedata[100];
} Student;
int main()
{
Student **test1;
Student **test2;
printf("%zu\n", sizeof(*test1));
printf("%zu\n", sizeof(**test2));
return 0;
}
https://godbolt.org/z/W6e8YzKKf
Related
I used pointer while printing structure elements but its working without using pointer in the print statement but shouldn't we use pointers to gather the element from the variable address why is it different in the structure case and its different in string also . Can anyone tell me why is that ?
#include <stdio.h>
int main(){
struct books{
char name[10];
int page;
};
struct books b1={"book1",1};
struct books *ptr;
ptr=&b1;
printf("%s %d",ptr->name,ptr->page);
}
printf("%s %d",*ptr->name,*ptr->page);
is wrong. A->B means (*A).B. You should do either
printf("%s %d",ptr->name,ptr->page);
or
printf("%s %d",(*ptr).name,(*ptr).page);
What MikeCAT said.
Beware though that an array would also be a pointer so *ptr->name would compile but will produce the first character of 'name'.
struct books{
char name[10];
int page;
};
ptr=&b1;
printf("%c",*ptr->name);
Pointers used when the object is too big and copying such object vastes time. But in your struct it takes 10 bytes for char array + 4 bytes for int and it's not a problem. In 64 bit machine pointers take 8 bytes in 32 bit 4 bytes. Suppose you have a big a struct and per object it takes 50 bytes of memory if you copy it will take more space and will be slower and by copying a brand new object will be created and that won't change anything in original one.
Let's see in practice when pointers can be used:
#include <stdio.h>
struct person{
char name[10];
int age;
};
void grow(struct person p) {
++p.age;
}
int main(){
struct person Mike = { "Mike", 20 };
grow(Mike);
printf("Name: %s\tAge: %d", Mike.name, Mike.age);
}
OUTPUT:
Name: Mike Age: 20
This code won't change age of Mike because void grow(struct person p) function copies struct person by creating a new object then increments age and at the end destroys struct person p. If you pass it as pointer then Mike will be modified.
I have looked around but have been unable to find a solution to what must be a well asked question.
Here is the code I have:
#include <stdlib.h>
struct my_struct {
int n;
char s[]
};
int main()
{
struct my_struct ms;
ms.s = malloc(sizeof(char*)*50);
}
and here is the error gcc gives me:
error: invalid use of flexible array member
I can get it to compile if i declare the declaration of s inside the struct to be
char* s
and this is probably a superior implementation (pointer arithmetic is faster than arrays, yes?)
but I thought in c a declaration of
char s[]
is the same as
char* s
The way you have it written now , used to be called the "struct hack", until C99 blessed it as a "flexible array member". The reason you're getting an error (probably anyway) is that it needs to be followed by a semicolon:
#include <stdlib.h>
struct my_struct {
int n;
char s[];
};
When you allocate space for this, you want to allocate the size of the struct plus the amount of space you want for the array:
struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
In this case, the flexible array member is an array of char, and sizeof(char)==1, so you don't need to multiply by its size, but just like any other malloc you'd need to if it was an array of some other type:
struct dyn_array {
int size;
int data[];
};
struct dyn_array* my_array = malloc(sizeof(struct dyn_array) + 100 * sizeof(int));
Edit: This gives a different result from changing the member to a pointer. In that case, you (normally) need two separate allocations, one for the struct itself, and one for the "extra" data to be pointed to by the pointer. Using a flexible array member you can allocate all the data in a single block.
You need to decide what it is you are trying to do first.
If you want to have a struct with a pointer to an [independent] array inside, you have to declare it as
struct my_struct {
int n;
char *s;
};
In this case you can create the actual struct object in any way you please (like an automatic variable, for example)
struct my_struct ms;
and then allocate the memory for the array independently
ms.s = malloc(50 * sizeof *ms.s);
In fact, there's no general need to allocate the array memory dynamically
struct my_struct ms;
char s[50];
ms.s = s;
It all depends on what kind of lifetime you need from these objects. If your struct is automatic, then in most cases the array would also be automatic. If the struct object owns the array memory, there's simply no point in doing otherwise. If the struct itself is dynamic, then the array should also normally be dynamic.
Note that in this case you have two independent memory blocks: the struct and the array.
A completely different approach would be to use the "struct hack" idiom. In this case the array becomes an integral part of the struct. Both reside in a single block of memory. In C99 the struct would be declared as
struct my_struct {
int n;
char s[];
};
and to create an object you'd have to allocate the whole thing dynamically
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
The size of memory block in this case is calculated to accommodate the struct members and the trailing array of run-time size.
Note that in this case you have no option to create such struct objects as static or automatic objects. Structs with flexible array members at the end can only be allocated dynamically in C.
Your assumption about pointer aritmetics being faster then arrays is absolutely incorrect. Arrays work through pointer arithmetics by definition, so they are basically the same. Moreover, a genuine array (not decayed to a pointer) is generally a bit faster than a pointer object. Pointer value has to be read from memory, while the array's location in memory is "known" (or "calculated") from the array object itself.
The use of an array of unspecified size is only allowed at the end of a structure, and only works in some compilers. It is a non-standard compiler extension. (Although I think I remember C++0x will be allowing this.)
The array will not be a separate allocation for from the structure though. So you need to allocate all of my_struct, not just the array part.
What I do is simply give the array a small but non-zero size. Usually 4 for character arrays and 2 for wchar_t arrays to preserve 32 bit alignment.
Then you can take the declared size of the array into account, when you do the allocating. I often don't on the theory that the slop is smaller than the granularity that the heap manager works in in any case.
Also, I think you should not be using sizeof(char*) in your allocation.
This is what I would do.
struct my_struct {
int nAllocated;
char s[4]; // waste 32 bits to guarantee alignment and room for a null-terminator
};
int main()
{
struct my_struct * pms;
int cb = sizeof(*pms) + sizeof(pms->s[0])*50;
pms = (struct my_struct*) malloc(cb);
pms->nAllocated = (cb - sizoef(*pms) + sizeof(pms->s)) / sizeof(pms->s[0]);
}
I suspect the compiler doesn't know how much space it will need to allocate for s[], should you choose to declare an automatic variable with it.
I concur with what Ben said, declare your struct
struct my_struct {
int n;
char s[1];
};
Also, to clarify his comment about storage, declaring char *s won't put the struct on the stack (since it is dynamically allocated) and allocate s in the heap, what it will do is interpret the first sizeof(char *) bytes of your array as a pointer, so you won't be operating on the data you think you are, and probably will be fatal.
It is vital to remember that although the operations on pointers and arrays may be implemented the same way, they are not the same thing.
Arrays will resolve to pointers, and here you must define s as char *s. The struct basically is a container, and must (IIRC) be fixed size, so having a dynamically sized array inside of it simply isn't possible. Since you're mallocing the memory anyway, this shouldn't make any difference in what you're after.
Basically you're saying, s will indicate a memory location. Note that you can still access this later using notation like s[0].
pointer arithmetic is faster than arrays, yes?
Not at all - they're actually the same. arrays translate to pointer arithmetics at compile-time.
char test[100];
test[40] = 12;
// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
Working code of storing array inside a structure in a c, and how to store value in the array elements Please leave comment if you have any doubts, i will clarify at my best
Structure Define:
struct process{
int process_id;
int tau;
double alpha;
int* process_time;
};
Memory Allocation for process structure:
struct process* process_mem_aloc = (struct process*) malloc(temp_number_of_process * sizeof(struct process));
Looping through multiple process and for each process updating process_time dyanamic array
int process_count = 0;
int tick_count = 0;
while(process_count < number_of_process){
//Memory allocation for each array of the process, will be containting size equal to number_of_ticks: can hold any value
(process_mem_aloc + process_count)->process_time = (int*) malloc(number_of_ticks* sizeof(int));
reading data from line by line from a file, storing into process_time array and then printing it from the stored value, next while loop is inside the process while loop
while(tick_count < number_of_ticks){
fgets(line, LINE_LENGTH, file);
*((process_mem_aloc + process_count)->process_time + tick_count) = convertToInteger(line);;
printf("tick_count : %d , number_of_ticks %d\n",tick_count,*((process_mem_aloc + process_count)->process_time + tick_count));
tick_count++;
}
tick_count = 0;
the code generated will be identical (array and ptr). Apart from the fact that the array one wont compile that is
and BTW - do it c++ and use vector
I am fairly new to C, and am having trouble figuring out how to allocate contiguous memory to an array of structs. In this assignment, we are given a shell of the code, and have to fill in the rest. Thus, I cannot change the variable names or function prototypes. This is what has been given to me:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct student {
int id;
int score;
};
struct student *allocate() {
/* Allocate memory for ten students */
/* return the pointer */
}
int main() {
struct student *stud = allocate();
return 0;
}
I'm just not sure how to go about doing what those comments say in the allocate function.
The simplest way to allocate and initialize the array is this:
struct student *allocate(void) {
/* Allocate and initialize memory for ten students */
return calloc(10, sizeof(struct student));
}
Notes:
calloc(), unlike malloc() initializes the memory block to all bits zero. Hence the fields id and score of all elements in the array are initialized to 0.
It would be a good idea to pass the number of students as an argument to the function allocate().
It is considered good style to free() allocated memory when you no longer need it. Your instructor did not hint that you should call free(stud); before returning from main(): while not strictly necessary (all memory allocated by the program is reclaimed by the system when the program exits), it is a good habit to take and makes it easier to locate memory leaks in larger programs.
hi i have this structure
typedef struct STUDENT
{
char studName[20];
int timeEnter;
int timeUpdate;
}STUDENT;
and the local pointer to array of structure
STUDENT *studArr[100];
I'm trying to allocate memory for the structure by doing reading in the first line of the file then use it to allocate memory for the structure.
fscanf(fp, "%s", &first);
**studArr = (STUDENT**) malloc(sizeof(STUDENT*)*first);
I got an error saying that no operator "=" matches these operands on the allocation line
why am I gettting the error, what did i do wrong here?
thank in advance
I think you're confusing things, it looks like you're declaring an array of pointers, when all you need is a single pointer. Note that as long as you're indexing properly, a pointer to "one" struct is the same as a pointer to a hundred.
You should probably have:
STUDENT *studArr;
then, once you know how many you need (I'm assuming first is the number of students to allocate room for):
studArr = malloc(first * sizeof *studArr);
Also note that no casting is needed.
If you want to allocate an array of 100 students, you have two choices:
struct STUDENT
{
char studName[20];
int timeEnter;
int timeUpdate;
};
struct STUDENT studArr1[100];
... OR ...
struct STUDENT *studArr2 = (struct STUDENT *)malloc (sizeof (struct STUDENT) * 100);
If you just want a pointer, you can say:
struct STUDENT *p = studArr1;
PS:
I deliberately left the "typedef" stuff out so as not to confuse the basic issue (struct vs. array of struct vs pointer to array of struct).
You have defined an array of pointers to struct, not a pointer to an array of struct. The memory for the array is already allocated, as a global array.
The type of **studArr is STUDENT, and hence is not compatible with the expression to the right of the assignment operator, which is casted to (STUDENT**).
You probably meant:
STUDENT **studArr;
[...]
fscanf(fp, "%s", &first);
studArr = (STUDENT**) malloc(sizeof(STUDENT*)*first);
As you are using STUDENT *studArr[100]; then it means you have allocated the memory for 100 pointers for STUDENT structure type.
so for allocating the memory you should try.
studArr =malloc(sizeof(struct STUDENT)*first);
then you can access all the allocated members as studArr[i] ....so on.
You're not exactly clear on what your overall goal is.
First of all, you want to use %d if you want to read in an integer:
int count;
if (fscanf(fp, "%d", &count) != 1) { // error... }
Next, don't use STUDENT as both the struct name and the typdef. Just leave the struct name out:
typedef struct
{
char studName[20];
int timeEnter;
int timeUpdate;
} student_t;
Now, you're going to want just a pointer to an array of student_ts:
student_t* student_array = NULL;
Finally, allocate that array:
student_array = malloc(count * sizeof(student_t));
Now you can use it, like:
strncpy(student_array[0].studName, "Bobby", 20);
Or get a pointer to an individual student:
student_t* bob = &student_array[1];
bob->timeEnter = 42;
Let's say you have-
struct Person {
char *name;
int age;
int height;
int weight;
};
If you do-
struct Person *who = malloc(sizeof(struct Person));
How would C know how much memory to allocate for name variable as this can hold a large number of data/string? I am new to C and getting confused with memory allocation.
It won't know, You will have to allocate memory for it separately.
struct Person *who = malloc(sizeof(struct Person));
Allocates enough memory to store an object of the type Person.
Inside an Person object the member name just occupies a space equivalent to size of an pointer to char.
The above malloc just allocates that much space, to be able to do anything meaningful with the member pointer you will have to allocate memory to it separately.
#define MAX_NAME 124
who->name = malloc(sizeof(char) * MAX_NAME);
Now the member name points to an dynamic memory of size 124 byte on the heap and it can be used further.
Also, after your usage is done you will need to remember to free it explicitly or you will end up with a memory leak.
free(who->name);
free(who);
Don't assume that the memory storing the pointer for name is the same as the memory storing the data for name. Assuming a 4 byte word size, you have the following:
char * (4 bytes)
int (4 bytes)
int (4 bytes)
int (4 bytes)
================
total: 16 bytes
which is: sizeof(char*) + sizeof(int) + sizeof(int) + sizeof(int). C knows the size because you've told it the size of the elements in the struct definition.
I think what you are confused about is the following:
The contents at the char * will be a memory location (e.g. 0x00ffbe532) which is where the actual string will be stored. Don't assume that the struct contents are contiguous (because of the pointer). In fact, you can be pretty sure that they won't be.
So, to reiterate, for an example struct Person (this is just an example, the locations won't be the same in a real program.)
location : [contents]
0x0000 : [0x00ffbe532]
0x0004 : [10]
0x0008 : [3]
0x000C : [25]
0x00ffbe532 : [I am a string\0]
The name member is just a pointer. The size of a pointer varies with the underlying architecture, but is usually 4 or 8 bytes nowadays.
The data that name can point to (if assigned later) should be laid out in an area that does not coincide with the struct at all.
At the language level, the struct doesn't know anything about the memory that the name member is pointing to; you have to manage that manually.
It allocates memory for the just the pointer to a char. You need to do a separate allocation for the contents.
There are other options although:
If you are OK with having a fixed sized maximum length, you can do:
struct Person {
char name[PERSON_NAME_MAX_LENGTH+1];
int age;
int height;
int weight;
};
And allocate it as in your example.
Or you can declare a variable sized struct, but I wouldn't recommend this as it is tricky and you cannot have more than one variable size array per struct:
struct Person {
int age;
int height;
int weight;
char name[]; /*this must go at the end*/
};
and then allocate it like:
struct Person *who = malloc(sizeof(struct Person) + sizeof(char)*(name_length+1));
It will allocate 4 bytes for the name pointer, but no space for the "real" string. If you try to write there you will seg fault; you need to malloc (and free) it separately.
Using string (in C++) can save you some headache
For pointers the struct is allocated enough memory just for the pointer. You have to create the memory for the char* and assign the value to the struct. Assuming you had char* name somewhere:
struct Person *who = malloc(sizeof(struct Person));
who->name = malloc((strlen(name)+1) * sizeof(char));
strcpy(who->name, name)
It doesn't. You have to do that too.
struct Person *who = malloc(sizeof(struct Person));
who->name = malloc(sizeof(char) * 16); /* for a 15+1 character array */
You have a pointer to a name character array in your struct, ie. it will consume that much bytes that are needed to represent a memory address.
If you want to actually use the field, you must allocate additional memory for it.
Pointer members occupy one word in my experience (the address on witch the data actually resides) so the size will probably be 16 bytes (assuming one word is 4 bytes)
As the man said above you need to separately allocate memory for *name witch will free memory someplace else for the size you desire
I think you should also need to allocate memory for the name attribute