I have such array with size of 24 byte:
char* arr[3] = {"CERN", "0", "ALK"};
printf("%ld\n", sizeof(arr));
Then I try to clear this array from memory by assigning \0 to each element of array:
for (size_t i = 0; i < sizeof(arr)/ sizeof(char*); ++i) {
arr[i] = '\0';
}
But when I want to check the size of array, it still gives me 24 byte:
printf("%ld\n", sizeof(arr));
> 24
How to completely clear this array from memory that sizeof(arr) would give 0?
sizeof(arr) is the size of three char*. It doesn't change when you set each of the pointers to 0.
How to completely clear this array from memory that sizeof(arr) would
give 0?
There's no way to "clear" an array allocated on automatic storage. You really don't need to "clear" it at all.
Note that you should use %zu to print a size_t value, which is what sizeof operator yields. Using an incorrect format specifier is undefined behaviour.
No, no, no. There are several different issues here:
If you want to clear a block of memory, use memset()
If you want to zero out a string, all you need to do is set the FIRST character to null: arr[0] = 0;
The sizeof operator tells you the size of your array.
The strnlen() tells you the length of your string.
Even if you've allocated 3 bytes for your array, the actual length of the string might be 0, 1 or 2.
It can never be "3" ... because you need at least one byte for your terminator.
You have assigned zeroes to the array, but that's all. You have not changed (and cannot, since you didn't malloc() it) the amount of memory allocated to the array, only cleared that data inside it.
How to completely clear this array from memory that sizeof(arr) would give 0?
It is not possible given your declaration.
You'll have to come up with a different logic to come up with 0 -- the number of items in arr that are not NULL.
int my_own_array_size(char* arr[], int numElements)
{
int count = 0;
for ( int i = 0; i < numElements; ++i )
{
if ( arr[i] != NULL )
++count;
}
return count;
}
and then use it as:
int count = my_own_array_size(arr, 3);
char* arr[3] = {"CERN", "0", "ALK"};
Here arr is an array of 3 char pointers. Each element is of size 8 bytes (on 64 bit system).
So size of arr will always be 24 (3* sizeof(void *)) irrespective of the memory referenced by pointers (viz. An address or NULL, which is further interpreted as char or string.This has nothing to do with arr size)
Above for loop will only initialize the pointers to NULL.
How to completely clear this array from memory that sizeof(arr) would give 0?
It is a static allocation (either an auto/global variable) . memory assigned for arr cannot be cleared.
note : In this case "CERN", "0", "ALK" are probably stored in read only segment.
You may a look at this post since it explains the difference between statically and dynamically allocated memory:
What and where are the stack and heap?
Related
I'm trying to create a int and a float array without a size (it might be 0 or it might increment while the user use the program).
I was trying to do the follow:
int bills[];
float totalAmount[];
I can't assign a max size because I'm printing each array with a for loop (If I assign a size of 99 I'll print 99 lines, and I don't want that).
C does not support arrays with a dynamic number of elements. The number of elements of an array must be determined either at compile time or since C99 can be evaluated at runtime at the point of creation. Once the array is created, its size is fixed and cannot be changed. There are a few cases where the size is not explicitly specified between the [], either in array definitions or in array declarations.
You can define an array without an explicit size for the leftmost dimension if you provide an initializer. The compiler will infer the size from the initializer:
int a[] = { 1, 2, 3 }; // equivalent to int a[3] = { 1, 2, 3 };
int m[][2] = {{ 1, 2 }, { 3, 4 }}; // equivalent to int m[2][2] = {{ 1, 2 }, { 3, 4 }};
char s[] = "Hello world\n"; // equivalent to char s[13] = "Hello world\n";
Note how the compiler adds the implicit null terminator in the string case.
You can declare an array without a size specifier for the leftmost dimension in multiples cases:
as a global variable with extern class storage (the array is defined elsewhere),
as a function parameter: int main(int argc, char *argv[]). In this case the size specified for the leftmost dimension is ignored anyway.
as the last member of a struct with more than one named member. This is a C99 extension called a flexible array.
The compiler has no information on the actual size of these arrays. The programmer will use some other information to determine the length, either from a separate variable or from the array contents.
In the case of a function argument, the array is passed as a pointer and even if the number of elements is specified, sizeof(argv) evaluates to the size of a pointer.
You don't declare an array without a size, instead you declare a pointer to a number of records.
so, if you wanted to do
int bills[];
The proper way to do this in C is
int* bills;
And you will have to allocate the size at some point in time and initialize the array.
bills = (int*)malloc(sizeof(int)*items);
The same goes for arrays of other data types. If you don't know the size of the array until runtime, you should use pointers to memory that are allocated to the correct size at runtime.
You could use a combination of malloc() (or calloc()), realloc() and free() to achieve this.
Memory can be allocated as blocks of a fixed size rather than reallocating memory for each number to be stored.
Let's define a macro (or a const if you like) BLOCK_SIZE.
#define BLOCK_SIZE 10
First declare a pointer of appropriate type and allocate the first block.
Note that malloc() as well as realloc() return NULL if some error occurred due to reasons like insufficient memory.
int *ptr=malloc(sizeof(int)*BLOCK_SIZE);
if(ptr==NULL)
{
perror("some error");
return 1;
}
Now declare a variable to store the maximum possible index as per the currently allocated memory (to avoid illegal memory access).
int max_index = BLOCK_SIZE-1;
Now use a loop.
for(int i=0; ; ++i)
{
if(i > max_index)
{
ptr=realloc(ptr, (max_index+1 + BLOCK_SIZE)*sizeof(int));
if(ptr == NULL)
{
perror("insufficient memory!");
break;
}
printf("\nRealloced!");
max_index += BLOCK_SIZE;
}
scanf("%d", &ptr[i]);
printf("\n%d: %d", i, ptr[i]);
}
In each iteration, we check if i is greater than max_index. If it is, another block is allocated using realloc() before reading the value.
Don't forget to deallocate the memory once you are done using it.
free(ptr);
Also, as discussed in this post, malloc() is effectively the same as realloc() with the latter's first argument NULL.
And in the code you posted, there's no need to explicitly cast the return value of calloc() as what's returned is a void pointer which would implicitly be converted to the target pointer type.
See this and this.
i think you can give it a max size ,if you only want to show the first few elements you can put a a for loop upto that element only,same goes for input if u want to initiallize first 30 elements put a for loop upto 30.
My concept of the way malloc()/calloc() create memory has always been that once an item is created, the address of the object stays the same. But a function I often use to create an array of strings, and one that seems to have always worked well, recently caused me to question my understanding, that is, memory addresses of objects can be (and are) moved simply by calling calloc/malloc.
To illustrate, here is the function I have used to create memory for an array of strings - char **:
char ** CreateArrayOfStrings(char **a, int numWords, int maxWordLen)
{
int i;
a = calloc(numWords, sizeof(char *)); //create array of pointers
if(!a) return a; //required caller to check for NULL
for(i=0;i<numWords;i++)
{
a[i] = calloc(maxWordLen + 1, 1); //create memory for each string
}
return a;
}
On my system, (Win7, 32bit compile, ANSI C) The line:
a = calloc(numWords, sizeof(char *)); //create array of pointers
Creates a block of contiguous memory, sized for numWords char *, in this case 7, yielding 28 bytes:
Memory spans from address 0x03260080 + 1C (0x0326009C)
Or:
a[0] is at 0x3200260080
a[1] is at 0x3200260084
a[2] is at 0x3200260088
a[3] is at 0x320026008C
a[4] is at 0x3200260090
a[5] is at 0x3200260094
a[6] is at 0x3200260098
Then, I create memory for each of numWords (7) strings
for(i=0;i<numWords;i++)
{
a[i] = calloc(maxWordLen + 1, 1); //maxWordLen == 5 in this example
}
Which results in the following:
This shows that the memory locations of the pointers a[1] - a[6] have been changed.
Can someone explain how/why this happens in malloc()/calloc()?
It appears that you are comparing apples to oranges:
When you print a[i] is at ... pointers, you show the addresses of elements inside the array a
However, when you shoe the memory layout, you show the values at these addresses, which are themselves pointers, so the whole picture looks confusing.
If you print the values at a[i] before assigning calloc results to them, you should get all zeros, because calloc NULLs out the memory. After the assignments, you see pointers to 6-byte blocks at each a[i], which makes perfect sense.
To summarize, your initial understanding of what happens when you allocate memory with malloc and calloc is correct: once a chunk of memory is allocated, its address* remains the same.
* On systems with virtual memory, I should say "its virtual address".
The memory of those addresses has not been changed. You are creating a 28-byte large block of space (a) and then at each element, dynamically allocating a second 6-byte block of space with its own address.
In other words, at a[1] (memory address 0x03260084), the value that is stored there is a pointer to memory address 0x32600D0.
To check the memory locations and the values at each one, try this:
for ( i = 0; i < 8; i++ )
{
printf("a[%d] %p %p\n",i,&(a[i]),a[i]);
}
When you call calloc(numWords, sizeof(char *)) you ask the operating system to allocate numWords pointers of size ``4 bytes each, on your system'', which is why the resulting block is 4 * numWords bytes, and it returns the address to the first one of them. So now you can store the addresses of the pointers that will hold the actual data. The nth call to calloc(maxWordLen + 1, 1) will then return the address to a block of size maxWordLen and store it at the memory location pointed to by a[n] which is simply the address returned by the first call to calloc plus n * sizeof(char *).
I have dynamically allocated 2D array.
Here is the code
int **arrofptr ;
arrofptr = (int **)malloc(sizeof(int *) * 2);
arrofptr[0] = (int *)malloc(sizeof(int)*6144);
arrofptr[1] = (int *)malloc(sizeof(int)*4800);
Now i have to know that how many bytes are allocated in arrofptr,arrofptr[0],arrofptr[1]?
is there any way to know the size?
if we will print
sizeof(arrofptr);
sizeof(arrofptr[0]);
sizeof(arrofptr[1]);
then it will print 4.
You can't find size of arrofptr, because it is only a pointer to pointer. You are defining an array of arrays using that. There's no way to tell the size information with only a pointer, you need to maintain the size information yourself.
The only return value you get from malloc() is a pointer to the first byte of the allocated region (or NULL on failure). There is no portable, standard, way of getting the associated allocation size from such a pointer, so in general the answer is no.
The C way is to represent arrays and buffers in general with a pair of values: a base address and a size. The latter is typically of the type size_t, the same as the argument to malloc(), by the way.
if you want to keep track of the size of an allocated block of code you would need to store that information in the memory block that you allocate e.g.
// allocate 1000 ints plus one int to store size
int* p = malloc(1000*sizeof(int) + sizeof(int));
*p = (int)(1000*sizeof(int));
p += sizeof(int);
...
void foo(int *p)
{
if (p)
{
--p;
printf( "p size is %d bytes", *p );
}
}
alt. put in a struct
struct
{
int size;
int *array;
} s;
You can't get the length of dynamically allocated arrays in C (2D or otherwise). If you need that information save it to a variable (or at least a way to calculate it) when the memory is initially allocated and pass the pointer to the memory and the size of the memory around together.
In your test case above sizeof is returning the size of the pointer, and thus your calculation the size of the pointers is usually 4, this is why you got 4 and is likely to have the trivial result of 4, always.
#include <stdio.h>
#include <stdlib.h>
#define MAX 10
void main()
{
int *ptr, *arr[MAX];
int i, j;
for (i=MAX-1; i>=0; i--)
if (arr[i]=(int*)malloc(i*sizeof(int))) // <= that line!
for (j=0; j<i; j++)
*(*(arr+i)+j) = j*i;
ptr = *(arr+MAX-1);
while (*ptr)
printf ("%d ", *ptr--);
}
I am not understand what the purpose of this command:
arr[i]=(int*)malloc(i*sizeof(int))
I know that this malloc dynamic allocation.
But what is meant by arr[i] it gives the sizeof*i ?
Thanks.
The command that you are talking about allocates a block of length that is sufficient to store i items of type int, and stores the result at the i-th position in the array of pointers called arr. The program creates a "triangular" arr array: its elements are arrays of different lengths, arranged in such an order that arr[i] can hold i elements.
By the way, this code is missing calls to free for the items it has allocated.
int *ptr, *arr[MAX]
creates a pointer to int and an array with MAX elements of pointers to int.
arr[i]=(int*)malloc(i*sizeof(int))
Allocates space for i ints for every int pointer.
At first sizeof() "returns" (it should be replaced with numeric value during compilation) the size of provided type. Means 4 for int (8 on 64b machines), 1 for char and so on.
Therefore i*sizeof(int) means size for i ints (i = 4; sizeof( int) = 4; than it's 16).
malloc() uses number of bytes to allocate as parameter, therefore malloc(16) allocate 16bytes, enough space for 4 4B integers.
(int*) is just something like C-hack to have correct types (because you want to use those 16B as int[4] not as void *).
The whole code means to allocate space for i ints on i-th place of array (1 on first, 2 on second...). However I wander what will happen for 0, when you'll try to allocate 0 Bytes :)
It's allocating increasingly longer arrays as each element of the arr. so arr[0] points to a 0 size array, arr[2] points to an array of 2 ints and so on.
arr is an array of pointers to int. Every element of it - arr[x] - is a pointer to int, so an array. It's an array of arrays of ints.
For each element of the array, you create an array with size of the current index.
Note though that your code is illegal, since when i==0, you will call malloc(0).
Also, it's good practice not to cast the return type of malloc.
I'm having some trouble understanding the difference between these two code segments:
I allocate space for an array of integers dynamically within my code with the following statement
int *arr = calloc(cnt, sizeof(int));
In another function, where I pass in arr, I would like to determine the size (number of elements) in arr.
When I call
int arr_sz = sizeof(arr)/sizeof(int);
it only returns 1, which is just the number of bytes in an int for both arguments I am assuming (4/4)=1.
I just assumed it would be the same as using an array
int arr[8];
int arr_sz = sizeof(arr)/sizeof(int);
which returns the actual number of elements in the array.
If anyone could clear this up, that would be great. Thanks!
int *arr; ----> Pointer
int arr[8]; ----> Array
First up what you got there - int *arr is a pointer, pointing to some bytes of memory location, not an array.
The type of an Array and a Pointer is not the same.
In another function where I pass in arr, I would like to determine the size (number elements) in arr. When I call
int arr_sz = sizeof(arr)/sizeof(int);
it only returns 1, which is just the number of bytes in an int for both arguments I am assuming (4/4)=1. I just assumed it would be the same as using an array
Even if it is assumed to be an Array -- that's because Arrays get decayed into pointers when passed into functions. You need to explicitly pass the array size in functions as a separate argument.
Go through this:
Sizeof an array in the C programming language?
There is a difference between a static array and dynamic memory allocation.
The sizeof operator will not work on dynamic allocations.
AFAIK it works best with stack-based and predefined types.
well, int *arr declares a pointer, a variable which keeps the address of some other variable, and its size is the size of an integer because it's a pointer, it just have to keep the address, not the pointee itself.
int arr[8] declares an array, a collection of integers. sizeof(arr) refers to the size of the entire collection, so 8*sizeof(int).
Often you hear that "array and pointers are the same things". That's not true! They're different things.
Mike,
arr is a pointer and as such, on your system at least, has the same number of bytes as int. Array's are not always the same as pointers to the array type.
sizeof(arr) is the same as sizeof(int*), i.e. the size of a single pointer. You can however calculate arr_sz as ... cnt!
*arr is not the same as arr[8] since it's size is not known in compile time, and sizeof is a function of the compiler. So when your arr is *arr sizeof will return the size of the pointer (sizeof(int *))in bytes, while when your arr is arr[8], the sizeof will return the size of array of 8 integers in bytes (which is sizeof(int) * 8).
When you pass a pointer to array to a function, you must specify its size, because the compiler can't do it for you. Another way is to end the array with null element, and perform a while loop.
If you have int arr1[8] the type of arr1 (as far as the compiler is concerned) is an array ints of size 8.
In the example int * arr2 the type of arr2 is pointer to an integer.
sizeof(arr1) is the size of an int array
sizeof(arr2) is the size of an int pointer (4 bytes on a 32 bit system, 8 bytes on a 64 bit system)
So, the only difference is the type which the compiler thinks that variable is.
You can't use sizeof with memory pointers:
int *arr = calloc(cnt, sizeof(int));
But it's ok to use it with arrays:
int arr[8];