What is the purpose of this code section? - c

#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.

Related

difference between static and dynamic declarations of 2D arrays

These two are different programs for declaring a 2D array
1)i think they are same because both are 2D array?
2)can we access both using a[i][j] and p[i][j]?
3)Why *a or a are same and p or *p are different
#include<stdio.h>
#include<stdlib.h>
int main(){
int a[100][100];
printf("%d\n",a);
printf("%d\n",*a);
int **p=malloc(sizeof(int*)*100);
for(int i=0;i<100;i++){
p[i]=malloc(sizeof(int)*100);
}
printf("%d",p);
printf("%d",*p);
}
the big difference is that in case with a[100][100] the compiler knows the full size of the array and allocates a contiguous memory region on a stack (as in your case) or in static area. When accessing an array element, the compiler is free to calculate its address based on the array dimensions and use a single reference to access it. like this
[0,0][0,1][0,2]...[0,99][1,0][1,1][1,2]...[99,0]...[99,99]
+-------0------...-----+----- 1 -------...+----- 99 -----+
In case of the dynamic allocation, which you used, the memory is allocated contiguously only for a single dimension of the array. So, you allocate 100 pointers, every one of each points to a single dimensional array of integers. Those arrays can be placed at arbitrary memory locations. As a result, the compiler has to do at least 2 references in this case, use first index to get a pointer to the second array, than use the second index to get the element in the second array.
pointers[index0] : [0][1][2]..[99]
/ | \
/ | |
V V V
[0] [0] [0]
[1] [1] [1]
... ... ...
some addition about a and *a. In 'c' when the name of the array is used in a pointer like context, it is interpreted as an address of the array. So, in printf a points to the beginning of the two-dimensional array. *a for same reason is supposed to provide you an address of the first column. Which in this case is the same as the start or the array. **a will point you to the very first array element a[0][0]. And by the way, it is better to use %p there instead of %d for pointers.
You can see that for the dynamic array p gives you the address of the array of pointers, whether *p gives you the value of its first element p[0] which by itself is a pointer to the column. The addresses are definitely different.
But in both cases you can use a[i][j] and p[i][j] to access array elements.
They are not the same. The first (int a[100][100]) is a single variable that is a compound object. The other (int **p) is a collection of arrays that you are using as a data structure for matrices.
If you want to have an actual 2D array in dynamic storage, this is how you do it:
#include <stdlib.h>
int main()
{
int (*m)[100][100];
m = malloc(sizeof *m);
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
(*m)[i][j] = 0;
}
Of course, the syntax is a bit weird, and you would rather have a dynamic matrix with variadic number of columns and rows, which is why you would prefer to declare a matrix pointed by int **p.
The reason why a and *a give the same output is because both decay to a pointer to the first element of a, which is a[0][0]. On the other hand, p is a pointer itself, and *p is the contents of the variable pointed by p. They are just as different as they would be if you did this:
int d = 0;
int *p = &d;
printf("%p\n", p);
printf("%d\n", *p);
Now back to your int **p.
Yes, you can access both int a[][100] and int **p with double indexing. However, there is a fundamental difference in the way the compiler treats a[i][j] and p[i][j].
In a[i][j], each a[i] is an array of 100 integer objects. So in order to access the i-th element, and then the j-th element, the compiler has to acess the i*100+j-th element from a[0][0]. This access can be performed in a single step with some index arithmetic.
In v[i][j], each v[i] is a pointer which may point to objects far from each other in memory. In order to acess the element v[i][j], the compiler must first follow p to the array *p, then find the i-th element in this array, which is a pointer to the array p[i]. And then with some pointer arithmetic it will find the j-th element of this array.
a is the address of the array in memory, its value depends on how your compiler and operating system layout memory. *a is the value in memory at that location, again depending on your operating system this is either random or set to some pre-determined value. Similarly for p and *p
For ease of debugging most operating systems set memory to some deliberate fixed value. Unix typically sets malloc() memory to zero.
Windows has a range of default contents depending on how the memory was allocated see: When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?

How to clear in memory array of char*?

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?

What is the size of pointer to an array of type int?

I have the following code
#include <stdio.h>
int main(void) {
int arr[] = {10,20,30,40};
int* ptr = arr;
printf("%d\n",sizeof(arr));
printf("%d",sizeof(ptr));
return 0;
}
The output is
16
4
size of pointer in C is 4. 'arr' is also a pointer to an integer but its size comes out to be 16, which is product of size of one element and number of elements.
On the other hand if I store the same pointer into another pointer variable then its size becomes 4. This is very confusing. The same thing happens if I try to send arr as an argument to a function and then print the size of arr in that function. How does C handle a pointer to an array?
'arr' is also a pointer to integer
No, it's not. arr is an array. The size of an array is the size of an element times the number of elements. If it were a pointer, it's size would be the same as any other pointer.
How does C handles pointer of array?
C handles pointers to arrays the same way it handles all other pointers. However there are no pointers to arrays in your code, only a pointer to int (ptr).
A pointer is just a memory address, therefore on 32-bit systems it is always 4 bytes. Depending on the environment it is 4 or 8 bytes on 64-bit systems.
There is no real confusion in your example. arr is an array of 4 32-bit integers, therefore 16 bytes. It is 'handled', or 'passed around', as a pointer to the first int, an int*, which is why you can copy it to other variables of that type, either explicitly or as a parameter. At which time there is no longer a relationship to the original array, and it is just a pointer - 4 bytes on your system.
The best way to look at it is that there is an implicit conversion possible from int[] to int*, like there is from char to int.
When you do sizeof(arr) you will get the size of array which is number of elements * size of int.
When you do sizeof(ptr) you will get the size of pointer which is size of int.
This is very confusing. The same thing happens if I try to send arr as an argument to a function and then print the size of arr in that function.
When you send the array like this foo(arr), you are actually sending the base address of arr. And when we pass address of a variable to a function, it will store the address in a pointer. So again if you try to get the size of arr you'll get the size of pointer.
sizeof only works to find the length of the array if you apply it to the original array.
int a[5]; //real array. NOT a pointer
sizeof(a); // :)
However, by the time the array decays into a pointer, sizeof will give the size of the pointer and not of the array.
int a[5];
int * p = a; // assigning address of the array to pointer
sizeof(p); // :(
It will return always 4 bytes on 32-bit system and 8 bytes on 64-bit system!
Arrays decaying into pointers when they are passed to a function and continuing to keep the array length in the type system.
When you pass an array to a function it decays to pointer. So the sizeof function will return the size of int *
So when you pass the array to the function you need to pass the Number of elements also-
void function (size_t sz, int *arr) { ... }
:
{
int x[20];
function (sizeof(x)/sizeof(*x), x);
}

How to get the size of dynamically allocated 2d array

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.

C dynamic memory allocation and sizeof()

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];

Resources