C language array byte size - c

char *myArray[] = { "aaaaaa", "ccccc", "bbbbbb", "111111" };
printf("%d\n", sizeof(myArray));
printf("%d\n", (int)(&myArray + 1) - (int)(&myArray));
My question is about why passing myArray into sizeof can get the same result as the second method.
I know myArray represent a address which points to the first of four int space addresses, but how does sizeof recognize the size of bytes of 4 int space?
sizeof is not a function, what is it?

why passing myArray into sizeof can get the same result as the second method.
char *myArray[] = { "aaaaaa", "ccccc", "bbbbbb", "111111" };
myArray is array of 4 pointers to char. So sizeof(myArray) = 4*sizeof(pointer_to_char). Typically in 64 bit machine sizeof(pointer) is 64 bit (8 bytes), and so it's 32 bytes.
As for your second printf
printf("%d\n", (int)(&myArray + 1) - (int)(&myArray));
Because myArray is array, then &myArray is pointer to array. Here (&myArray + 1) points to the next array of pointers. Think of that as the next block of 4 pointers to char. And so (&myArray + 1) - (&myArray) is the same as the size of the original array of pointers.
Btw, you should use proper printf control string:
For sizeof, use %zu:
printf("%zu\n", sizeof(myArray));
Your 2nd printf works but would give an warning with regard the cast to int:
warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
That warning can be get rid of by:
char *p_start = (char *)(&myArray + 1);
char *p_end = (char *)(&myArray);
printf("%td", p_start - p_end );

sizeof(myArray) gives you the size of an array of 4 character pointers, probably 4x4=16. sizeof is an operator, which is in most cases evaluated at compile-time. It is defined by the language to do this task - the language says that sizeof's job is to know the size of things, so that's how it knows.
&myArray gives you an array pointer of type char (*)[4]. &myArray+1 does arithmetic on such an array, giving the address of an array pointer pointing just past the 4x4 array. If you subtract that address with the original address, you will get the size of the array in bytes.
There is no real difference between the two forms functionality-wise, except sizeof is so much more readable.
(As a side note, the second version results in a type called ptrdiff_t, and if you wish to print this with printf, you should use the %tu format specifier.)

Related

Size of pointer, pointer to pointer in C

How can I justify the output of the below C program?
#include <stdio.h>
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
char *a;
char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;
int main(void) {
printf("%d %d %d %d ",sizeof(a),sizeof(c),sizeof(cp),sizeof(cpp));
return 0;
}
Prints
4 16 16 4
Why?
Here is the ideone link if you want to fiddle with it.
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
c is an array of char* pointers. The initializer gives it a length of 4 elements, so it's of type char *[4]. The size of that type, and therefore of c, is 4 * sizeof (char*).
char *a;
a is a pointer of type char*.
char **cp[] = {c+3, c+2, c+1, c};
cp is an array of char** pointers. The initializer has 4 elements, so it's of type char **[4]. It size is 4 * sizeof (char**).
char ***cpp = cp;
cpp is a pointer to pointer to pointer to char, or char***. Its size is sizeof (char***).
Your code uses %d to print the size values. This is incorrect -- but it happens to work on your system. Probably int and size_t are the same size. To print a size_t value correctly, use %zu -- or, if the value isn't very large, you can cast it to int and use %d. (The %zu format was introduced in C99; there might still be some implementations that don't support it.)
The particular sizes you get:
sizeof a == 4
sizeof c == 16
sizeof cp == 16
sizeof cpp == 4
are specific to your system. Apparently your system uses 4-byte pointers. Other systems may have pointers of different sizes; 8 bytes is common. Almost all systems use the same size for all pointer types, but that's not guaranteed; it's possible, for example, for char* to be larger than char***. (Some systems might require more information to specify a byte location in memory than a word location.)
(You'll note that I omitted the parentheses on the sizeof expressions. That's legal because sizeof is an operator, not a function; its operand is either an expression (which may or may not be parenthesized) or a type name in parentheses, like sizeof (char*).)
a is an usually pointer, which represents the memory address. On 32-bit operating system, 32bit (4 Byte) unsigned integer is used to represent the address. Therefore, sizeof(a) is 4.
c is an array with 4 element, each element is a pointer, its size is 4*4 = 16
cp is also an array, each element is a pointer (the first *, wich point to another pointer (the second *). The later pointer points to an string in the memory. Therefore its basic element size should represent the size of a pointer. and then sizeof(cp) = 4*4 = 16.
cpp is a pointer's pointer's pointer. It is as well represent the 32bit memory address. therefore its sizeof is also 4.
a is a pointer. cpp is also a pointer just to different type (pointer to pointer to pointer).
Now c is an array. You have 4 elements, each is a pointer so you have 4 * 4 = 16 (it would be different if you would run it on x64).
Similar goes for cp. Try changing type to int and you will see the difference.
So the reason you got 4 16 16 4, is because 'a' is simply a pointer, on its own, which only requires 4 bytes (as a pointer is holding a 32bit address depending on your architecture) and so when you have a **pointer which is == to a *pointer[], your really making an array of pointers, and since you initalized 4 things that created 4 pointers, thus the 4x4 = 16. And for the cpp you may ask "well wouldn't it then be 16 as it was initalized?" and the answer is no, because a ***pointer is its own separate variable and still just a pointer(a pointer to a pointer to a pointer, or a pointer to an array of pointers), and requires only 4bytes of memory.

Size of char pointer array from function

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().

Find size of array without using sizeof

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

Confusion: Dynamic Allocation of 2D array, C

I yesterday came across a question on SO, that wanted to dynamically allocate a 2-D array in C.
One of the answers was to allocate it this way:
int (*place)[columns] = malloc(rows * sizeof *place);
This apart from being beautiful, brought a question to my head. The question goes below:
Following is the code in which i allocate a 4x4
int (*arr)[4] = (int (*)[4]) malloc(4 * sizeof *arr);
printf("%d\n", sizeof arr); //Dynamic 2-D array by above method
int **arr1 = (int**) malloc(4 * sizeof(int*));
for(int i = 0; i < 4; i++)
arr1[i] = (int *) malloc(sizeof(double));
printf("%d\n", sizeof arr1); //Usual dynamic 2-D array
int *arr2 = (int*) malloc(4 * sizeof(int));
printf("%d\n", sizeof arr2); //Dynamic 1-D array
The usual output is:
4
4
4
However, if i try to print sizeof *arr, sizeof *arr1 and sizeof *arr2, the output is:
16
4
4
I don't understand why this is happening. Any idea why the output for sizeof *arr is 16? How is the memory being being allocated in the first case?
Also, when i try to print the address of arr and *arr, both the printed values are same. *arr means "value at" arr. So does that mean arr stores its own address, i.e., it is pointing to itself (which i don't think is possible)? Am slightly confused. Any idea where am I going wrong?
Thanks for your help!
However, if I try to print sizeof *arr, sizeof *arr1 and sizeof *arr2, I get 16, 4, and 4.
where:
int (*arr)[4];
int **arr1;
int *arr2;
You must be working on a 32-bit machine, not a 64-bit machine.
The type of arr is 'pointer to an array of 4 int'. When you dereference it, you get an 'array of 4 int'. When passed to sizeof, the array is of size 16 (4 * sizeof(int)). Most of the time, when you reference an array, the type is adjusted to 'pointer to zeroth element of the array', but sizeof() is the primary exception to that rule; it sees an array as an array and returns the size of the whole array.
The type of arr1 is 'pointer to pointer to int'. When you dereference it, you get a 'pointer to int'. When passed to sizeof, the pointer is of size 4 (sizeof(int *)).
The type of arr2 is 'pointer to int'. When you dereference it, you get an int. When passed to sizeof, the int is of size 4.
Okay! I get most of it. But ... why isn't the output 16 when I do sizeof arr2?
As James noted in his comment:
because sizeof(arr2) reduces to sizeof(int*) which on a 32-bit machine is 4.
That is, arr2 is a pointer; the size of a pointer is 4 on a 32-bit machine.
Also, arr is a 'pointer to an array of 4 int', i.e., a single pointer. Then how do I get a 4×4 matrix.
You can use either of these:
int mat1[4][4];
int (*mat2)[4][4];
The first is a straight-forward 4×4 matrix. The result of sizeof(mat1) will be 64 on a 32-bit machine (and most 64-bit machines, as it happens).
The second is a pointer to a 4×4 matrix of int. The result of sizeof(mat2) will be 4 on a 32-bit machine; mat2 is a pointer (to a 4×4 matrix of int), so it is of size 4, the same as every other object pointer (and, in practice, the same size as every function pointer, though the C standard does not guarantee that function pointers and object pointers are the same size; POSIX does guarantee that, though).
The result of sizeof(*mat2) is the size of the object that mat2 points at, which is a 4×4 matrix of int, so the size is 64 again.
In a 32 bit system it needs 4 bytes or 32 bit to identify each memory address uniquely. A pointer is nothing just the holder of the address. so it takes 4 byte. In the first case arr is an array of pointer of length 4. so it takes 4*4 =16 bytes. in the other two case arr1 and arr2 are just a single pointer. so they take 4 bytes.

Why does my homespun sizeof operator need a char* cast?

Below is the program to find the size of a structure without using sizeof operator:
struct MyStruct
{
int i;
int j;
};
int main()
{
struct MyStruct *p=0;
int size = ((char*)(p+1))-((char*)p);
printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);
return 0;
}
Why is typecasting to char * required?
If I don't use the char* pointer, the output is 1 - why?
Because pointer arithmetic works in units of the type pointed to. For example:
int* p_num = malloc(10 * sizeof(int));
int* p_num2 = p_num + 5;
Here, p_num2 does not point five bytes beyond p_num, it points five integers beyond p_num. If on your machine an integer is four bytes wide, the address stored in p_num2 will be twenty bytes beyond that stored in p_num. The reason for this is mainly so that pointers can be indexed like arrays. p_num[5] is exactly equivalent to *(p_num + 5), so it wouldn't make sense for pointer arithmetic to always work in bytes, otherwise p_num[5] would give you some data that started in the middle of the second integer, rather than giving you the sixth integer as you would expect.
In order to move a specific number of bytes beyond a pointer, you need to cast the pointer to point to a type that is guaranteed to be exactly 1 byte wide (a char).
Also, you have an error here:
printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);
You have two format specifiers but only one argument after the format string.
If I don't use the char* pointer, the output is 1 - WHY?
Because operator- obeys the same pointer arithmetic rules that operator+ does. You incremented the sizeof(MyStruct) when you added one to the pointer, but without the cast you are dividing the byte difference by sizeof(MyStruct) in the operator- for pointers.
Why not use the built in sizeof() operator?
Because you want the size of your struct in bytes. And pointer arithmetics implicitly uses type sizes.
int* p;
p + 5; // this is implicitly p + 5 * sizeof(int)
By casting to char* you circumvent this behavior.
Pointer arithmetic is defined in terms of the size of the type of the pointer. This is what allows (for example) the equivalence between pointer arithmetic and array subscripting -- *(ptr+n) is equivalent to ptr[n]. When you subtract two pointers, you get the difference as the number of items they're pointing at. The cast to pointer to char means that it tells you the number of chars between those addresses. Since C makes char and byte essentially equivalent (i.e. a byte is the storage necessary for one char) that's also the number of bytes occupied by the first item.

Resources