struct busData{
int busNum;
char str[SIZE+1]; //SIZE = 1000
};
int main(){
struct busData *bus = (struct busData*)calloc(5, sizeof(struct busData));
printf("\n%d", sizeof(bus)); //result is 4
free(bus);
return 0;
}
Now It is showing '4' or '8'depending on platform as a result. I think it should display 5040 right? Because I gave 5 value with calloc(). So how can I get 5040? i am using the 3 elements until 'bus+2' and then I am freeing up with free(bus); And i want to know how many elements left (it should show 2008). so i need 5040?
sizeof(bus)
Here bus is a pointer so sizeof() will return 4 which is the size of the pointer in the platform you used.(depending on the platform used).
If you want to know the size of struct use sizeof(struct busData) or sizeof(*bus)
You are trying to output the size of the pointer bus instead of the 5 objects pointed to by the pointer.
Try the following demonstrative program
#include <stdio.h>
#include <stdlib.h>
#define SIZE 1000
struct busData
{
int busNum;
char str[SIZE+1]; //SIZE = 1000
};
int main(void)
{
struct busData *bus = (struct busData*)calloc(5, sizeof(struct busData));
printf("\n%zu\n", 5 * sizeof( *bus ) );
return 0;
}
The program output is
5040
Pay attention to the conversion specifier and the expression used as an argument of the printf call
printf("\n%zu\n", 5 * sizeof( *bus ) );
^^ ^^^^^^^^^^^^^^^^^
Take into account that pointers do not provide information whether they point to a single object or first object of an array of objects. So using the pointer bus you have to specify explicitly how many objects are pointed to by the pointer.
The same result you could get executing the following statement
printf("\n%zu\n", sizeof( struct busData[5] ) );
Now It is showing '4' as a result. I think it should display 5040 right?
No, you're wrong. Check the data types.
First of all, a little about sizeof operator, from C11, chapter ยง6.5.3.4
The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type. The size is determined from the type of
the operand. [...]
bus is a pointer, so, sizeof(bus) is the same as sizeof (struct busData*), which is the size of a pointer, which depending on your environment, can give you the result, of which, the common nones are 4 or 8.
After that, there can be padding in between structure elements and at the end, so a structure defined like
struct busData{
int busNum;
char str[SIZE+1]; //SIZE = 1000
};
defining a variable of that type and trying to check the size via sizeof may not give you (4+1000+1) == 1005 bytes, for most of the environments.
Quoting again,
[....] When
applied to an operand that has structure or union type, the result is the total number of
bytes in such an object, including internal and trailing padding.
So, you need to account for padding also.
That said,
printf("\n%d", sizeof(bus));
actually causes undefined behavior. You need to write
printf("\n%zu", sizeof(bus));
as sizeof yields a result of type size_t.
I think the code is screwed up from the beginning.
The problem with sizeof was already explained in other answers.
Another big problem is this:
Because I gave 5 value with calloc(). So how can I get 5040?
i am using the 3 elements until 'bus+2'
and then I am freeing up with free(bus);
And i want to know how many elements left (it should show 2008).
so i need 5040?
This sounds like you want to use the remaining 2 elemens after calling free.
First:
you have 1 pointer. The compiler can tell you the size of the pointer and the size of the single element that the pointer is pointing to.
The compiler has no idea that you allocated memory for more than 1 element of that type and hence cannot tell you anything different than size of pointer or size of 1 element.
Second:
There is no concept like "using" some memory. For the compiler and the OS it doesn't matter if you write something to the memory location or not. It doesn't care if some bytes are still (or again) filled with 0.
Third:
If you allocate a block of memory and free it again, the whole block is free'd and mustn't be used any longer. If you expect to have 2008 bytes that you still can use, you are wrong! Your pointer will point to an invalid address after free is called. Using that pointer to access the memory afterwards is undefined behaviour
How can i identify the size of structure member?
With a pointer to dynamic allocated memory, there is no way to know the size of memory that the pointer points to.
If you need to know the size after the malloc/calloc, you'll simply have to "remember" how much you malloc/calloced, i.e. save it in a variable.
You could wrap it inside another struct and provide a create function. Something like:
struct busData{
int busNum;
char str[SIZE+1]; //SIZE = 1000
};
struct busDataContainer{
size_t size;
struct busData* busData;
};
struct busDataContainer createBusData(size_t n)
{
struct busDataContainer c;
c.size = n * sizeof(struct busData);
c.busData = calloc(n, sizeof(struct busData));
return c;
}
int main(){
struct busDataContainer bus = createBusData(5);
printf("\n%zu", bus.size;
return 0;
}
Related
This question already has answers here:
How can I get the size of an array from a pointer in C?
(16 answers)
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Find malloc() array length in C? [duplicate]
(4 answers)
Closed 4 years ago.
Is there any way I could find how much bytes are allocated for RandomArray in this code
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *RandomArray;
int n;
srand(time(NULL));
RandomArray=malloc(sizeof *RandomArray * (rand()%11));
printf("%d %d",sizeof(RandomArray),sizeof(*RandomArray));
return 0;
}
Also I don't know whether above code will ever have any kind of practical usage. But I am looking from programming perspective.
Ah this is experimental code. Interesting things are there.
You will allocate memory for N integers where N is between 0 to 10 including 0 and 10.
Then you applied sizeof to the pointer (int*) and what it points to (int). It won't matter how much memory you allocate. The output from this line will be same.
There is no error check here. if it was you couldn't tell whether it is successful entirely surely because rand() may give 0 as result. You need to store it somewhere and check whether it is 0 because on that case malloc may or may not return NULL.
Printing what sizeof returns should be done using %zu format specifier. It returns size_t.
To be more clear remember it is a pointer pointing to dynamically allocated memory. RandomArray is not an array - it is an pointer pointing to contiguous memory. That doesn't make it array. It is still a pointer. And the sizeof trick that you wanted to apply thinking RandomArray is an array won't work. In general we keep track of it - using some variable. But here you don't know how much memory you allocated.
malloc may return NULL when you pass 0 to it. Handle that case separately. In case you get sz!=0 and get NULL in RandomArray throw error.
size_t sz = rand()%11;
RandomArray = malloc(sz);
if(!RandomArray && sz){
perror("malloc");
exit(EXIT_FAILURE);
}
After all this talk - the short answer is, with this setup there is no use of the code (code you have written) so far. You don't know what rand() returned on that case inside malloc.
Since the expression *RandomArray is of type int, sizeof(*RandomArray) evaluates to sizeof(int). It does not tell you how much memory was allocated.
When dynamically allocating memory, you need to keep track of how much was allocated yourself. In the case above, you would need to store the random number someplace so you know what that amount is.
Yes, by saving the size in a variable:
int main()
{
int *RandomArray;
int n;
srand(time(NULL));
size_t size = rand() % 11;
if(size == 0)
{
fprintf(stderr, "Size 0, no point in allocating memory\n");
return 1;
}
RandomArray = malloc(size * sizeof *RandomArray)
if(RandomArray == NULL)
{
fprintf(stderr, "no memory left\n");
return 1;
}
printf("%zu %zu\n", sizeof(RandomArray), size);
// don't forget to free the memory
free(RandomArray);
return 0;
}
Note that sizeof(RandomArray) returns you the size that a pointer to int
needs to be stored in memory, and sizeof(*RandomArray) returns you the size of
an int.
Also don't forget to free the memory.
sizeof(RandomArray) always results in 4 bytes(equal to pointer size), if you want to find how many bytes allocated for RandomArray
/* Since its implimentation dependent, so I'm not
advising you to access RandomArray[-1], also proper type casting needed */
printf("memory allocated = %d \n",RandomArray[-1]);
From
The C programming language by Denis Ritchie & Kernighan
typedef long Align; /* for alignment to long boundary */
union header { /* block header */
struct {
union header *ptr; /* next block if on free list */
unsigned size; /* size of this block */
} s;
Align x; /* force alignment of blocks */
};
typedef union header Header;
The Align field is never used;it just forces each header to be aligned on a worst-case boundary.
In malloc,the requested size in characters is rounded up to the proper number of header-sized units; the block that will be allocated contains
one more unit, for the header itself, and this is the value recorded in the
size field of the header.
The pointer returned by malloc points at the free space, not at the header itself.
RandomArray[-1]
-----------------------------------------
| | SIZE | |
-----------------------------------------
RandomArray
-> a block returned by malloc
The sizeof operator works at compile time, except for the case when the operand is variable length array, and the dynamic memory allocation is run time operation.
In the expression:
printf("%d %d",sizeof(RandomArray),sizeof(*RandomArray));
the type of RandomArray is int * and the type of *RandomArray is int.
Hence, the expression is equivalent to:
printf("%d %d",sizeof(int *),sizeof(int));
for which the sizeof will yield the result as an integer constant and therefore, you will get the same result every time irrespective of the size of memory allocate to RandomArray.
How to find the size of dynamic array
Keep the track of the size from the point where you are allocating memory dynamically.
Beware, you are multiplying the value returned by rand()%11 to the sizeof *RandomArray while allocating memory and rand() may return 0 as well which will lead to malloc(0). Good to know that (from C Standards#7.22.3):
....If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
So I'm experimenting and I'm trying to get a better understanding of how to manually place a pointer in memory in C.
So far What I've done is created a struct and assigned a pointer to it, and now I'm trying to create another struct exactly 'x' amount of memory spaces away from the first struct. for instance, if 'x' is 50 bytes, I would want both pointers to be 50 bytes away from each other.
any help would be appreciated!
edit***
I guess I left out a key point here where I used malloc() to set aside some memory to work with. and I'm trying to stay within the boundaries of that piece of memory that I've set aside. BUT i'm trying to give precise memory locations within that set aside piece of memory, relative to the starting location.
If 'x' is 50 bytes, I would want both pointers to be 50 bytes away from each other.
You are in luck, because C has a perfect mechanism for placing pointers exactly the size of a struct apart. OK, not exactly exactly*, but close enough for most practical purposes.
You get this behavior by declaring an array of two items. They will be placed in memory apart by at least sizeof(struct mystruct), depending on the alignment of the struct and its actual size:
struct mystruct { ... }; // This is your struct definition
...
struct mystruct array[2];
struct mystruct *a = &array[0];
struct mystruct *b = &array[1];
Now pointers a and b are apart by sizeof(struct mystruct).
* Alignment becomes important when placing pointers exactly the size of the struct apart creates performance issues, or even impossible for the program to run on a given platform. For example, some platforms require placing pointers only at even addresses; if the first element of a struct is a pointer, and a struct has an odd size, then adding an extra byte at the end is required to make it possible for the program to run.
Pointers are just numbers corresponding to a memory location. You can do math on them, but it works a bit differently than normal. It's called pointer arithmetic.
Adding 1 to a pointer moves it forward in memory not 1 byte, but the size of whatever it's pointing at. If it's a char * it will move 1 byte. If it's a int * it will move 4 or 8 bytes depending on the size of your integers. If its a 50 byte struct, it will move forward 50 bytes.
So all you need to do is add 1 to your pointer.
#include <stdio.h>
struct example {
char string[50];
};
int main() {
struct example foo;
struct example *bar = &foo + 1;
printf("%p %p\n", &foo, bar);
}
$ ./test
0x7fff5897b4a0 0x7fff5897b4d2
...except now bar is pointing to unallocated memory. If you try to use it, it will be undefined behavior.
If you want to make two structs adjacent to each other in memory that you can actually use, make an array.
#include <stdio.h>
struct example {
char string[50];
};
int main() {
struct example list[2];
printf("%p %p\n", &list[0], &list[1]);
}
$ ./test
0x7fff5ba21470 0x7fff5ba214a2
Or if you're using heap memory...
#include <stdio.h>
#include <stdlib.h>
struct example {
char string[50];
};
int main() {
struct example *list = malloc( 2 * sizeof(struct example) );
printf("%p %p\n", &list[0], &list[1]);
}
I'm not sure how to place a pointer at a certain address, but I think there's some way to make sure two things are aligned, or a certain amount of bytes apart.
In K&R 2e, on the top of page 186:
So I guess you can wrap your struct in a union, and typedef Align as some type with size of n, where n is the number of bytes you want them to be apart from each other.
I would like to know if there's a real difference between this:
c = (struct_t *) malloc(sizeof(struct_t));
and this
c = malloc(sizeof(struct_t *));
Besides avoid the cast, is the compiler takes any advantage in the second form respect the first? Or the two ways are completely the same and is just a "aesthetical" question ?
The first allocates sizeof(struct_t) bytes, the second sizeof(struct_t*) bytes.
Apart from that, there is no difference in what malloc does, whether you cast the result or not. Casting the result makes the code acceptable to C++ compilers, but it can hide the mistake of not including stdlib.h, therefore it is widely preferred to not cast the result in C.
The two are totally different. The first allocates an instance of the struct, whereas the second allocates a pointer to the struct.
In general, they won't even allocate the same number of bytes.
No, they are not the same. The latter allocates 4 or 8 bytes of space for a pointer to struct, the first allocates enough space for the struct it self.
When sizeof(struct_t) is small enough, and when the malloc allocates actually more than requested, the user may not see the difference.
Two forms are different. They both allocate memory, but with different amounts.
General rule is as follows:
when allocating type T, the result of malloc shall be casted to T*.
void sample1()
{
struct pollfd *pfd = (struct pollfd*)malloc(sizeof(struct pollfd));
// pfd is points to a memory with a size of struct pollfd
...
free(pfd);
}
void sample2()
{
struct pollfd *pfd = (struct pollfd*)malloc(sizeof(*pfd));
// same as above, but uses variable type instead
free(pfd);
}
If you specify incorrect type in malloc argument, generally that will lead to buffer overrun problems:
void sample3()
{
struct x *px= (struct x*)malloc(sizeof(struct x*));
x->field = 5; //<< error, as allocated only 4 or 8 bytes depending on pointer size
}
Both are different.
Usually malloc returns (void*). So you want to typecast void* to (struct_t*).
consider the code below:
#include "list.h"
struct List
{
int size;
int* data;
};
List *list_create()
{
List *list;
printf("%d %d",sizeof(list),sizeof(List));
list = malloc(sizeof(list));
assert(list != NULL);
if (list != NULL) {
list->size = 0;
}
return list;
}
The number printed out is "4 8", i assume this is the 4 bytes taken by "int size" in List object?and the size of "int* data" is 0 cause nothing has assigned to data?
the size of int pointer is also 4 bytes so the type List take 8 bytes in total? or there are some thing else going on? Can some one help me understand all this in detail?
then the malloc() get 4 bytes from the heap and assign the address to the pointer list? later in main if i do "list->data[i]=1;" this will give me a run time error why? Is it because I cant change contents in the heap? but if i do "list->size++" this would work,
isn't the whole list object is in the heap?
really need some help here
Thanks in advance.
sizeof(List*) is the size of a pointer to a List struct.
sizeof(list) in your case, since variable list is of type List* is the same as sizeof(List*).
sizeof(List) instead is the size of the struct List, it contains two 32 bit variables (I assume you are using a 32 bit compiler obviously), an integer and a pointer and your compiler decided that the right size for your struct is 8 bytes.
Pointers to types are usually 4 byte in 32 bit compilers and 8 bytes in 64 bit compilers.
As a side note, reading your code however i read you never initialize list->data, you should initialize it to something somewhere i guess.
This is C++ however, you should write
typedef struct { ... } List; // This is C.
Sizeof operator is evaluated at compile time, not at runtime, it gives only information of the size of a type.
You cannot, for example, know how much elements are in a dynamic array with sizeof, if you were trying to accomplish this, sizeof(pointer) will give you the size in byte of the pointer type.
As something to read about what is a pointer and what is an array i would suggest you to read http://www.lysator.liu.se/c/c-faq/c-2.html or http://pw1.netcom.com/~tjensen/ptr/pointers.htm
Technically your code has an error in it.
The code should read: sizeof(struct List) or have typedef struct List List; somewhere.
But yes, sizeof(list) is the size of the variable list. Since list is a pointer it is equivalent to sizeof(void*) which on your system/compiler is 4.
sizeof(struct List) is the size of the struct which is sizeof(int)+sizeof(int*)+any alignment issues. The alignment thing is often forgotten but is very important as it can change the size of the struct in unexpected ways.
I just learned that it's possible to increase the size of the memory you'll allocate to a struct when using the malloc function. For example, you can have a struct like this:
struct test{
char a;
int v[1];
char b;
};
Which clearly has space for only 2 chars and 1 int (pointer to an int in reality, but anyway). But you could call malloc in such a way to make the struct holds 2 chars and as many ints as you wanted (let's say 10):
int main(){
struct test *ptr;
ptr = malloc (sizeof(struct test)+sizeof(int)*9);
ptr->v[9]=50;
printf("%d\n",ptr->v[9]);
return 0;
}
The output here would be "50" printed on the screen, meaning that the array inside the struct was holding up to 10 ints.
My questions for the experienced C programmers out there:
What is happening behind the scenes here? Does the computer allocate 2+4 (2 chars + pointer to int) bytes for the standard "struct test", and then 4*9 more bytes of memory and let the pointer "ptr" put whatever kind of data it wants on those extra bytes?
Does this trick only works when there is an array inside the struct?
If the array is not the last member of the struct, how does the computer manage the memory block allocated?
...Which clearly has space for only 2 chars and 1 int (pointer to an
int in reality, but anyway)...
Already incorrect. Arrays are not pointers. Your struct holds space for 2 chars and 1 int. There's no pointer of any kind there. What you have declared is essentially equivalent to
struct test {
char a;
int v;
char b;
};
There's not much difference between an array of 1 element and an ordinary variable (there's conceptual difference only, i.e. syntactic sugar).
...But you could call malloc in such a way to make it hold 1 char and as
many ints as you wanted (let's say 10)...
Er... If you want it to hold 1 char, why did you declare your struct with 2 chars???
Anyway, in order to implement an array of flexible size as a member of a struct you have to place your array at the very end of the struct.
struct test {
char a;
char b;
int v[1];
};
Then you can allocate memory for your struct with some "extra" memory for the array at the end
struct test *ptr = malloc(offsetof(struct test, v) + sizeof(int) * 10);
(Note how offsetof is used to calculate the proper size).
That way it will work, giving you an array of size 10 and 2 chars in the struct (as declared). It is called "struct hack" and it depends critically on the array being the very last member of the struct.
C99 version of C language introduced dedicated support for "struct hack". In C99 it can be done as
struct test {
char a;
char b;
int v[];
};
...
struct test *ptr = malloc(sizeof(struct test) + sizeof(int) * 10);
What is happening behind the scenes here? Does the computer allocate
2+4 (2 chars + pointer to int) bytes for the standard "struct test",
and then 4*9 more bytes of memory and let the pointer "ptr" put
whatever kind of data it wants on those extra bytes?
malloc allocates as much memory as you ask it to allocate. It is just a single flat block of raw memory. Nothing else happens "behind the scenes". There's no "pointer to int" of any kind in your struct, so any questions that involve "pointer to int" make no sense at all.
Does this trick only works when there is an array inside the struct?
Well, that's the whole point: to access the extra memory as if it belongs to an array declared as the last member of the struct.
If the array is not the last member of the struct, how does the computer manage the memory block allocated?
It doesn't manage anything. If the array is not the last member of the struct, then trying to work with the extra elements of the array will trash the members of the struct that declared after the array. This is pretty useless, which is why the "flexible" array has to be the last member.
No, that does not work. You can't change the immutable size of a struct (which is a compile-time allocation, after all) by using malloc ( ) at run time. But you can allocate a memory block, or change its size, such that it holds more than one struct:
int main(){
struct test *ptr;
ptr = malloc (sizeof(struct test) * 9);
}
That's just about all you can do with malloc ( ) in this context.
In addition to what others have told you (summary: arrays are not pointers, pointers are not arrays, read section 6 of the comp.lang.c FAQ), attempting to access array elements past the last element invokes undefined behavior.
Let's look at an example that doesn't involve dynamic allocation:
struct foo {
int arr1[1];
int arr2[1000];
};
struct foo obj;
The language guarantees that obj.arr1 will be allocated starting at offset 0, and that the offset of obj.arr2 will be sizeof (int) or more (the compiler may insert padding between struct members and after the last member, but not before the first one). So we know that there's enough room in obj for multiple int objects immediately following obj.arr1. That means that if you write obj.arr1[5] = 42, and then later access obj.arr[5], you'll probably get back the value 42 that you stored there (and you'll probably have clobbered obj.arr2[4]).
The C language doesn't require array bounds checking, but it makes the behavior of accessing an array outside its declared bounds undefined. Anything could happen -- including having the code quietly behave just the way you want it to. In fact, C permits array bounds checking; it just doesn't provide a way to handle errors, and most compilers don't implement it.
For an example like this, you're most likely to run into visible problems in the presence of optimization. A compiler (particularly an optimizing compiler) is permitted to assume that your program's behavior is well-defined, and to rearrange the generated code to take advantage of that assumption. If you write
int index = 5;
obj.arr1[index] = 42;
the compiler is permitted to assume that the index operation doesn't go outside the declared bounds of the array. As Henry Spencer wrote, "If you lie to the compiler, it will get its revenge".
Strictly speaking, the struct hack probably involves undefined behavior (which is why C99 added a well-defined version of it), but it's been so widely used that most or all compilers will support it. This is covered in question 2.6 of the comp.lang.c FAQ.