So, to start off I've already looked at a few questions including this one and none of them seem to help.
I'm simply trying to write a function that extends the size of an array using realloc().
My code currently looks like this:
unsigned char *xtnd = malloc(4);
xtndc(&xtnd, 4);
// sizeof(*xtnd) should now be 8
void xtndc ( unsigned char ** bytesRef , uint8_t count ) {
*bytesRef = realloc(*bytesRef, (sizeof(**bytesRef)) + count);
}
But no matter what I do it seems that the size of xtnd is always 4. After running xtndc() on it it should now be 8 bytes long.
Any suggestions?
The type of **bytesRef is unsigned char, so sizeof(**bytesRef) is 1. sizeof doesn't keep track of dynamic allocations, it's a compile time tool that gives you the size of a type, in this case unsigned char.
You have to keep track of the array size manually to calculate the new required size.
Your program does in fact change the size of the memory block. It changes the size of your original memory block from 4 bytes to 5 bytes. It changes to 5 bytes because you are essentially doing sizeof(unsigned char) + 4 which 1 + 4 = 5. If you want to double the size instead, do count*sizeof(unsigned char) + count. There are two points to be noted here:
The sizeof function returns the size of the data type, not the size of the allocated bytes. There is no way to know the size of the dynamically allocated memory.
The function realloc (and malloc and calloc as well) is not always guaranteed to return the requested reallocation. It may or may not succeed all the time.
I fixed the problem with the following code.
typedef struct CArrPtr {
unsigned char* ptr;
size_t size;
} CArrPtr;
void xtndc ( CArrPtr *bytesRef, uint8_t count );
. . .
CArrPtr xtnd = { .ptr = malloc(4), .size = 4 };
xtndc( &xtnd, 4 );
// xtnd.size is now 8 bytes
. . .
void xtndc ( CArrPtr *bytesRef, uint8_t count ) {
unsigned char *nptr;
if((nptr = realloc(bytesRef->ptr, bytesRef->size + count)) != 0)
{
bytesRef->ptr = nptr;
bytesRef->size = bytesRef->size + count;
}
}
As I am somewhat new to C, what I learned from this is that malloc specifically creates a pointer to a memory block, but you have no direct access to information about the memory block. Instead, you must store the size of the array that you created with malloc somewhere as well.
Since in the past I'd been initializing arrays with unsigned char arr[size]; and then using sizeof on it, I was under the impression that sizeof returned the size of the array, which is of course wrong as it gives you the size of a type.
Glad I could learn something from this.
sizeof is used to calculate size of data type or array. Pointer and array are very similar, but they are different things. For int *ap, sizeof(ap) will return 4 on x86, sizeof(*ap) will return 4; for int a[10], sizeof(a) will return 40.
sizeof expression is processed at compile time, so it will be a constant written into the executable file before you run the program.
malloc and realloc don't maintain size.
If realloc succeeds, it will reallocate the requested size. So you don't need to check the size after realloc returns, but you should check the return value of realloc to ensure that realloc succeeds.
Related
i have code like this:
int main()
{
double *u;
int len;
u=(double *)malloc(sizeof(double)*10);
len = sizeof(u);
printf("Length Of Array = %d\n", len);
return 0;
}
but the length is 4 Not 10.
how can i extract 10 from pointer u?!
please help me
thank you
That's your job. C does not provide a portable way of knowing, given a pointer, how much memory has been allocated.
sizeof will give you sizeof(double*), that's all. That's 4 on your system.
It is not possible. sizeof is giving the size of the object. In your case the object is u which is a pointer. Your system is 32 bits as pointers are 4 bytes.
if you sizeof(*u)- you will get the size of referenced type. In this case it is the double . It will be 8 bytes long at most systems.
using sizeof to get the size of the length of the string is one of the most frequent questions asked here.
A pointer doesn't include information about the size of the memory area. You have to keep track of the size yourself. For instance, you can make a custom type (for example, a struct) that contains both the pointer and the size of the allocation at the same time.
Here's a simple implementation to get you started:
typedef struct {
double* ptr;
size_t len;
} double_arr_t;
// prototype
double_arr_t alloc_double_arr(size_t len);
int main(void) {
// alloc the new array of 10 `double` elements
double_arr_t arr = alloc_double_arr(10);
printf("Length of 'arr' is %zu\n", arr.len); // Length of 'arr' is 10
// assign a value to the first element
arr.ptr[0] = 3.14;
// get the value of the first element
double first_element = arr.ptr[0];
// free the array when you're done using it
free(arr.ptr);
}
double_arr_t alloc_double_arr(size_t len) {
double_arr_t res;
res.ptr = malloc(len * sizeof(double));
res.len = len;
return res;
}
How can i know the size of the array using a pointer that is allocated using malloc?
#include <stdio.h>
int main(){
int *ptr = (int *)malloc(sizeof(int * 10));
printf("Size:%d",sizeof(ptr));
free(ptr_one);
return 0;
}
I get only the size of the pointer in this case which is 8.How to modify the code to get the size of array which will be 40.
You cannot.
You will need to do the bookkeeping and keep track of it yourself. With new you allocate dynamic memory and while deallocating the memory you just call delete, which knows how much memory it has deallocate because the language takes care of it internally so that users do not need to bother about the bookkeeping. If you still need it explicitly then you need to track it through separate variable.
if your machine is 32 bit you will get pointer size always 4 bytes of any data type
if your machine is 64 bit you will get pointer size always 8 bytes of any data type
if you declare static array you will get size by using sizeof
int a[10];
printf("Size:%lu",sizeof(a));
But you did not get the size of array which is blocked by pointer. where the memory to the block is allocated dynamically using malloc .
see this below code:
#include <stdio.h>
#include<stdlib.h>
int main()
{
int i;
int *ptr = (int *)malloc(sizeof(int) * 10);
// printf("Size:%lu",sizeof(ptr));
// In the above case sizeof operater returns size of pointer only.
for(i=1;ptr && i<13 ;i++,ptr++)
{
printf("Size:%d %p\n",((int)sizeof(i))*i,ptr);
}
return 0;
}
output:
Size:4 0x8ec010
Size:8 0x8ec014
Size:12 0x8ec018
Size:16 0x8ec01c
Size:20 0x8ec020
Size:24 0x8ec024
Size:28 0x8ec028
Size:32 0x8ec02c
Size:36 0x8ec030
Size:40 0x8ec034 //after this there is no indication that block ends.
Size:44 0x8ec038
Size:48 0x8ec03c
I have a macro for calculating array sizes in my C code:
#define sizearray(a) (sizeof(a) / sizeof((a)[0]))
When I test it, it works fine for statically defined arrays, but not so for dynamically defined arrays (see below). Not sure I understand why this is the case. Is there any way of calculating the size of an array allocated on the heap?
/* test sizearray macro */
void testSIZEARRAY(void)
{
/* test case for statically defined array */
int a[5] = {0,0,0,0,0};
assert(sizearray(a) == 5);
/* test case for dynamically defined array */
int *b;
b = calloc(5, sizeof(int));
assert(sizearray(b) == 5);
free(b);
}
The answer is no, there is no standard way to get the size of a dynamically allocated array.For all practical purposes, you have to keep track it yourself.
However, there are some compiler-specific methods that do that:
Windows (Visual Studio): _msize()
GCC: msize() Can't find it in the GCC docs...
int *b;
...
assert(sizearray(b) == 5);
A pointer is not an array. b is declared as pointer to int
Here
sizeof b == sizeof (int *)
The sizeof operator applied to an object of a pointer type is the same as the size of the pointer type and is not equivalent to the size of the allocated array.
To know the size of your allocated array object you have to inspect what was allocated. In your example you allocate an object of 5 int, so the size of your array is:
5 * sizeof (int)
(or equivalent, 5 * sizeof *b)
There is no way to calculate the size of an array if you only have a pointer to its first element (as you do in the above case with int *b). You need to either store the array size separately and use it together with your pointer, or somehow mark the end of the array. The latter solution is used in character arrays, which are usually null-terminated (have \0 as their last character). In this case, you can calculate the size by looping till you encounter such a termination character.
The followng is bad advice, do not do that.
To get the memory allocated by the current glibc's malloc() (et al) you could try the following:
#include <stdlib.h>
#include <stdio.h>
#define GLIB_MSIZE_T size_t /* We need to have a four byte unsigned integer type
here. */
#define GLIB_MSIZE(p) \
*((GLIB_MSIZE_T*) (((char*) p) - sizeof(GLIB_MSIZE_T)))
int main(int iArgC, char ** ppszArgV)
{
if (1 >= iArgC)
{
fprintf(stderr, "usage: %s <bytes to allocate>\n", ppszArgV[0]);
return EXIT_FAILURE;
}
{
/* This conversion uing 'atol()' only works up until to a certain size
of the integer represented by 'ppszArgV[1]'. */
size_t size = atol(ppszArgV[1]);
void * pv = malloc(size);
if (!pv)
{
fprintf(stderr, "Allocation of %u bytes failed.\n", size);
return EXIT_FAILURE;
}
printf("Asked for %u bytes, got %u bytes.\n", size, GLIB_MSIZE(pv));
}
return EXIT_SUCCESS;
}
Besides the fact one indeed could get the amount of memory allocated, the interesting thing to see when paying with this code is, that in most of the cases more then the size of memory requested is assigned.
Anyhow, the latter makes it unsafe trying to pull information from this on the exact size originally requested.
I have allocated a chunk of memory of type char and size is say 10 MB (i.e mem_size = 10 ):
int mem_size = 10;
char *start_ptr;
if((start_ptr= malloc(mem_size*1024*1024*sizeof(char)))==NULL) {return -1;}
Now I want to store the size information in the header of the memory chunk.To make myself more clear, let's say: start_ptr = 0xaf868004 (This is the value I got from my execution, it changes every time).
Now I want to put the size information in the start of this pointer, i.e *start_ptr = mem_size*1024*1024;.
But I am not able to put this information in the start_ptr. I think the reason is because my ptr is of type char which only takes one byte but I am trying to store int which takes 4 bytes, is the problem .
I am not sure how to fix this problem..
You'll need to cast your char pointer to an int pointer. In two steps:
int *start_ptr_int = (int*)start_ptr;
*start_ptr_int = mem_size * 1024 * 1024;
In one step:
*((int*)start_ptr) = mem_size * 1024 * 1024;
The (int*) in front of your pointer name tells the compiler: "Yeah, I know this is not actually a pointer to int, but just pretend for the time being, okay?"
*((int*)start_ptr) = mem_size*1024*1024
You could also just memcpy the value in ...
ie
int toCopy = mem_size * 1024 * 1024;
memcpy( start_ptr, &toCopy, 4 );
You'd even be surprised how most compilers won't even make the memcpy call and will just set the value.
One way to do it without casts:
#include <stdlib.h>
struct Block {
size_t size;
char data[];
};
#define SIZE (1024*1024)
int main()
{
struct Block* block = malloc(sizeof(struct Block) + SIZE);
block->size = SIZE;
char* start_ptr = block->data;
// ...
}
Or, to get the effect you want, change one line:
char* start_ptr = (char*)block;
A comment on style: Don't do this:
if ((ptr=malloc()) == NULL)
There is nothing wrong with
ptr = malloc();
if (ptr == NULL) ...
Good programmers know what they could do with the language. Excellent programmers know why they shouldn't do it. ;)
And -1 to all posters who assume an int in C to always be 32 bits, including the OP in the thread title. An int is guaranteed to have at least 16 bits, and on 32 bit machines it is usually a safe assumption to have 32 bits, but your code may fail as soon as you move to a 64 bit machine.
I am writing the calloc function in a memory management assignment (I am using C). I have one question, I wrote the malloc function and thinking about using it for calloc as it says calloc will take num and size and return a block of memory that is (num * size) which I can use malloc to create, however, it says that I need to initialize all bytes to 0 and I am confused about how to do that in general?
If you need more info please ask me :)
So malloc will return a pointer (Void pointer) to the first of the usable memory and i have to go through the bytes, initialize them to zero, and return the pointer to that front of the usable memory.
I am assuming you can't use memset because it's a homework assignment assignment, and deals with memory management. So, I would just go in a loop and set all bytes to 0. Pseudocode:
for i = 1 to n:
data[i] = 0
Oh, if you're having trouble understanding how to dereference void *, remember you can do:
void *b;
/* now make b point to somewhere useful */
unsigned char *a = b;
When you need to set a block of memory to the same value, use the memset function.
It looks like this: void * memset ( void * ptr, int value, size_t num );
You can find more information about the function at: http://www.cplusplus.com/reference/clibrary/cstring/memset/
If you can't use memset, then you'll need to resort to setting each byte individually.
Since you're calling malloc from your calloc function, I'm going to assume it looks something like this:
void *calloc (size_t count, size_t sz) {
size_t realsz = count * sz;
void *block = malloc (realsz);
if (block != NULL) {
// Zero memory here.
}
return block;
}
and you just need the code for "// Zero memory here.".
Here's what you need to know.
In order to process the block one byte at a time, you need to cast the pointer to a type that references bytes (char would be good). To cast your pointer to (for example) an int pointer, you would use int *block2 = (int*)block;.
Once you have the right type of pointer, you can use that to store the correct data value based on the type. You would do this by storing the desired value in a loop which increments the pointer and decrements the count until the count reaches zero.
Hopefully that's enough to start with without giving away every detail of the solution. If you still have problems, leave a comment and I'll flesh out the answer until you have it correct (since it's homework, I'll be trying to get you to do most of the thinking).
Update: Since an answer's already been accepted, I'll post my full solution. To write a basic calloc in terms of just malloc:
void *calloc (size_t count, size_t sz) {
size_t realsz, i;
char *cblock;
// Get size to allocate (detect size_t overflow as well).
realsz = count * sz;
if (count != 0)
if (realsz / count != sz)
return NULL;
// Allocate the block.
cblock = malloc (realsz);
// Initialize all elements to zero (if allocation worked).
if (cblock != NULL) {
for (i = 0; i < realsz; i++)
cblock[i] = 0;
}
// Return allocated, cleared block.
return cblock;
}
Note that you can work directly with char pointers within the function since they freely convert to and from void pointers.
Hints:
there is already a posix library function for zeroing a block of memory
consider casting the void * to some pointer type that you can dereference / assign to.