Using this code:
#include <stdio.h>
void printSize(char *messages[]) {
printf("%d", sizeof(messages) / sizeof(char *));
}
int main(void) {
printf("Size when through passing direct to function: ");
printSize((char *[]){"Zero", "One", "Two", "Three"});
printf("\n");
printf("Size when calculating in main: %d\n", sizeof((char *[]){"Zero", "One", "Two", "Three"}) / sizeof(char *));
return 1;
}
I get output:
Size when through passing direct to function: 1
Size when calculating in main: 4
I understand there is no way to get the correct amount of elements in a char* array, but I am curious as to why they are giving different results.
It's because char *messages[] is just syntactic sugar for char **messages, so you're just getting the size of a pointer, not the size of your whole array.
You can't, without passing the size along as another parameter.
You should check out the comp.lang.c FAQ section on Arrays & Pointers.
When you use an array as a parameter to a function, it "decays" to a pointer to the first element of the array. Since messages is an array of pointers to char, when the array is passed to the function, it becomes a pointer to a pointer to a char. This happens even though you are specifying it as an array in your parameter list; that is just how the language works.
So in void printSize(), when you use sizeof(messages), you get the size of a pointer. You are dividing that by the size of another pointer sizeof (char*). On your system, the size of a pointer is 4 bytes in both cases, so the result you get is 4 / 4, i.e., 1.
In main(), however, your array of char* is defined as, and treated as, an array. When the sizeof() operator is applied to an array, you get the size of all the bytes in the entire array. What is this an array of? It's an array of four pointers to char. Each pointer has the size 4. So the total size of the array is 4 * 4 = 16 bytes. You are dividing this 16 by the size of a single pointer to char, which is 4. So you are getting the result 16 / 4, i.e. 4 as the answer in main().
Related
This question already has answers here:
How can I get the size of an array from a pointer in C?
(16 answers)
Closed 1 year ago.
I have a pointer to an array in C which I would like to iterate through, but I don't know the size:
int *array;
I am unsure as to how I should proceed. I was thinking that I should probably try by finding the size by doing:
int array_size = sizeof(array) / sizeof(int);
But I don't know if that could work. I was wondering if there was a more optimal way of doing this?
In C, there is no way to tell the number of elements in an array from a pointer to an element. sizeof(array) / sizeof(*array) only works for an actual array, not for a pointer, which is what a function receives as an argument, even if the array syntax is used in the function prototype. In this case sizeof(array) evaluates to the size of the pointer, so dividing that by the size of an element is meaningless.
The best approach for your function to get the number of elements is to provide it as a separate argument.
If this is not practical, there are different ways to infer the number of elements, relying on a convention that must be adhered to by the callers:
the array could have a known fixed number of elements
the array could have a sentinel value as the last element of the array.
It is common to use a null pointer (NULL) as such a sentinel for arrays of pointers, such as the char *argv[] argument of the main() function, but note that int argc is also provided to this function.
The null byte (\0) is used to tell the end of C strings, which are arrays of char.
In your case, you could consider 0 or -1 to signify the end of the array, but this convention must be used consistently by all callers of your function.
You cannot iterate over an array in c without knowking the number of elements.
Please note that sizeof(array) / sizeof(array[0]) won't work on a pointer, i.e it will not give the number of elements in the array.
It will also not work inside a function, where the array was passed as an argument due to array decay to pointer.
If the array does not contain a known sentinel value (as for example character arrays that contain strings have as the sentinel value the terminating zero character '\0') then you can not find its end.
If you have a pointer like this
int *array;
then the expression sizeof( array ) will yield the size of the pointer itself that does not depend on whether the pointer points to a single object of the type int or to the first element of an integer array with a known number of elements in the array. That size for example can be equal either to 4 or 8 depending on the used system. Thus the expression sizeof( array ) / sizeof( int ) in general will always yield either 1 or 2.
So you have to pass to the function explicitly also the number of elements in the array.
You could determine the number of elements in an array if you pass a pointer to the whole array. For example
void f( int( *a )[10] );
//...
int a[10];
//...
f( &a );
In this case dereferencing the pointer within the function you will get an object of the array type. Thus the expression sizeof( *a ) will yield the size of the original array.
I have a pointer to an array in c to which I would like to iterate through but I don't know the size:
You are in luck if you truly have a pointer to an array as the type of a pointer to an array carries information about the array size.
int some_array[7] = {1, 2, 3, 4, 5, 6, 7};
int (*pointer_to_an_array)[7] = &some_array;
#define N (sizeof(*pointer_to_an_array) / sizeof(*pointer_to_an_array[0]))
for (size_t i = 0; i < N; i++) {
printf("%d\n", (*pointer_to_an_array)[i]);
}
Unfortunately, with int *array;, code does not have a pointer to an array, but a pointer to an int and information about the original array size of some_array[] is not available through array.
int some_array[7] = {1,2,3,4,5,6,7};
int *array = some_array; // Not a pointer to an array
Carry information about array size in another variable.
size_t some_array_n = sizeof some_array/ sizeof some_array[0];
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);
}
I was searching for a way to find the size of an array in C without using sizeof and I found the following code:
int main ()
{
int arr[100];
printf ("%d\n", (&arr)[1] - arr);
return 0;
}
Can anyone please explain to me how is it working?
&arr is a pointer to an array of 100 ints.
The [1] means "add the size of the thing that is pointed to", which is an array of 100 ints.
So the difference between (&arr)[1] and arr is 100 ints.
(Note that this trick will only work in places where sizeof would have worked anyway.)
&arr gives you a pointer to the array. (&arr)[1] is equivalent to *(&arr + 1). &arr + 1 gives you a pointer to the array of 100 ints that follows arr. Dereferencing it with * gives you that array that follows. Since this array is used in an additive expression (-), it decays to the pointer to its first element. The same happens to arr in the expression. So you subtract to pointers, one pointing to the non-existent element right after arr and the other pointing to the first element of arr. This gives you 100.
But it's not working. %d is used for int. Pointer difference returns you ptrdiff_t and not int. You need to use %td for ptrdiff_t. If you lie to printf() about the types of the parameters you're passing to it, you get well-deserved undefined behavior.
EDIT: (&arr)[1] may cause undefined behavior. It's not entirely clear. See the comments below, if interested.
Generally (as per visual studio),
for an array &arr is same as arr ,which return the starting base address of our function.
(&arr)[0] is nothing but &arr or arr
ex: it will return some address : 1638116
Now, (&arr)[1] means we are started accessing the array out of bounce means next array or next segment of the size of present array(100 ahead).
ex: it will return some address : 1638216
Now, subtracting (&arr)[1] - (&arr)[0]=100
&variable gives location of the variable (call it as P)
&variable + 1 gives address of the location next to the variable. (call it as N)
(char*)N-(char*)P gives how many characters are there between N and P. Since each character is 1 byte sized, so the above result gives the number of bytes P and N. (which equals to the size of array in bytes).
Similarly,
(char*) (a+1)-(char*)a; gives size of each element of the array in bytes.
So the number of elements in the array = (size of array in bytes)/(size of each element in the array in bytes)
#include<stdio.h>
int main()
{
int a[100];
int b = ((char*)(&a+1)-(char*)(&a));
int c = (char*) (a+1)-(char*)a;
b = b/c;
printf("The size of array should be %d",b);
return 0;
}
int arry[6]={1,2,3,4,5,6} //lets array elements be 6,
so...
size in byte = (char*)(arry+6)-(char *)(arry)=24;
int main ()
{
int arr[100];
printf ("%d\n", ((char*)(&arr+1) - (char*)(&arr))/((char*) (arr+1) -(char*) (arr)));
return 0;
}
#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];