C int array and pointer interaction [duplicate] - c

This question already has answers here:
How does sizeof know the size of the operand array?
(12 answers)
Arrays decaying into pointers
(2 answers)
What is array to pointer decay?
(11 answers)
Closed 5 years ago.
The following code...
int array[] = {17, 18, 19};
printf("Location of array: %p\n", array);
printf(" Value of array: %d\n", *array);
printf(" Size of array: %d bytes\n", sizeof(array));
Produces the output
Location of array: 0x7ffd0491c574
Value of array: 17
Size of array: 12 bytes
When I use variable array on the second line, it refers to the location of the "17". When I use it on the third like, it dereferences the pointer and prints out the number 17. Those, I understand.
On the last line, it prints out "12 bytes" as the size of the array. Why doesn't it print out 4 bytes, since in the previous two uses of the same variable, it seems to exclusively refer to the zero index of the array? How does sizeof know to look at the remainder of the array, instead of just printing out 4 bytes (as it would if I ran (sizeof(*array))?

When passed to sizeof, an array name doesn't decay into pointer, so the whole array size is found.
In the first case, it decays into pointer to the first element and the address is printed.
In the second case, we dereference the address, which is basically the value at the address pointed by the array name, namely the first element.
Why doesn't it print out 4 bytes?
From the C standard $6.5.3.4 (sizeof operator)
When applied to an operand that has array type, the result is the
total number of bytes in the array.
This answers your question why when passed an array name it shows the number of bytes. Here the array has 3 elements and each of size sizeof int or 4 Bytes in your system and so the total size = 3*4 = 12
What is *array?
*array is nothing other than array[0]. array decays into pointer to the first element of the array and then we dereference it. What is the value that is there? That is the value 17.
Why sizeof(*array)=4?
Well if you remember array is an array of 3 integers. So ofcourse the value contained in it is of type int. In your system sizeof int is 4 bytes. That's why you will get 4 as a result sizeof *array .
How sizeof works?
sizeof is implemented by the compiler. For non-VLA type of objects sizeof is a constant which is resolved compile time. But in case of VLA the array size is known at run time and that generates the result. So this is an expression for VLA.

Here,
sizeof(number of array elements * sizeof data_type)
sizeof(3 * 4)
sizeof int generally 4 bytes.
sizeof gives 12 bytes.

Here array is the pointer to an array of 3 integers, so if you are the printing size of the array, it will give you 12 bytes as each integer takes 4 bytes.
As you know array will have starting location of the array, now you are printing integer at the address "array" by using format specifier %d. It will print integer stored in first 4 bytes of the array,i.e. 17.

sizeof(*array) would give you sizeof(int) (seemingly 4 on your computer).
sizeof(array) gives 12 because sizeof(*array) gives 4, and you have 3 of these (int), 3 x 4.
array is an area in memory where the 3 integer are stored
<int0><int1><int2>
^
array
sizeof(array) gives the size of that space occupied by that area.
Mentioning array as itself in, for instance, int *p = array; stores the address of array in the pointer p.

Arrays in C are not exactly pointers, which is used to be in early days. Array names are decay into pointer based on the use of identifier(variable). Array names were pointer which caused problem with structure containing the array member, storing the pointer in array eventually lead to problem with structure members. So it was decided by the author of C to make array as name to location rather than the pointer some location. When used with * it will decay into pointer. Which allow us to use the array as a[i], i[a], *(a+i) .

sizeof() is a operand evaluated at compile time. The compiler knows the size, because it creates the array.

Related

sizeof on array variable Vs sizeof on pointer in c [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 2 years ago.
See below example in c:
#include <stdio.h>
int main()
{
int arr[] = {1, 2 ,3};
int *ptr = arr;
printf("sizeof arr[] = %d ", sizeof(arr));
printf("sizeof ptr = %d ", sizeof(ptr));
return 0;
}
output: sizeof arr[] = 12 sizeof ptr = 4
Why sizeof on pointer "ptr" outputs 4 and on array variable "arr"(although "arr" is also being a pointer) outputs 12 ?
Operator sizeof returns the size of an object's type. Your array has 3 integers so it is sizeof(int)*3.
A pointer size in bytes is platform-specific and in this case it is 4 bytes = 32 bits.
An array variable has pointer semantics, so when it is passed to a function or used in an assignment such as int *p = arr, it represents the address of its first element, however its type is not simply the type of its elements.
In your snippet the size is inferred by the compiler from the initializer you used, so your array type is int[3] in this case,and not simply int.
size of int is 4 bytes so the size of arr = sizeof(int) * 3 which is 12 as it contains 3 integers.
but ptr is a pointer to an array of integers. With a 32bit all the pointer will be size 4 bytes (32 bits)
Hope it helps
although "arr" is also being a pointer
NO, array is not a pointer.
The sizeof pointer depends on the architecture. It does not depend on what it points to.
The size of array is amount of all element in array. In this case, arr content of 3 integer elements, each element has 4 bytes in your system,
(the size of int may be 2 in other systems). So the size of arr is 3*sizeof(int) = 3*4 = 12.
See What is the size of a pointer?
Very useful for your question How to find the 'sizeof' (a pointer pointing to an array)?
And How do I determine the size of my array in C?

Why does malloc() not allocate correct size of memory when using a pointer to `double`? [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 6 years ago.
Here is the essence of what I am trying to do:
double *E; //Array of doubles
int N; //The eventual size of the array, typically >1
// some code where variable N gets assigned
//inside of some function
E = malloc(sizeof(double)*N);
printf("size of E = %lu\n",sizeof(E)/sizeof(E[0])); //checking size of array E
The output of this code is "size of E = 1", regardless of the actual value of N. Why does the malloc() function not allocate the correct size in memory?
I know this seems very rudimentary, but I cannot understand why this would not work.
Any insight would be greatly appreciated.
You are essentially dividing the size of the pointer by the size of a double. Both take the same amount of bytes (8 typically) to store. therefore you get 1.
E's type is pointer to double. E's value is an address. When you get the sizeof(E), you are getting the size of the variable that is the pointer rather than the size of what is being pointed to by the variable. In order to get the size of what malloc allocated, you need to dereference the pointer in sizeof so your last line becomes :
printf("size of E = %lu\n",sizeof(*E) * N/sizeof(E[0]));
EDIT
There is no difference between *E and E[0] as pointed out by one of the comments. In C, there is no way of you knowing where you array ends because the array itself as a datatype does not store its length. This is partly why the vector datatype in C++ was necessary.
Also, since you already stored the length of the array in N, you might as well just print N. When you pass the array to any functions, pass the array along with the length. With strings, you can get away with iterating over the character array till you get '\0', the null terminating character. For integer and floating point datatype arrays, there is no such convention.
malloc is allocating a right size array, else your test is wrong.
sizeof(E) is the size of the pointer = 8
sizeof(*E) is the size of the first double = 8
you can know the size of your array multiplying sizeof(*E) * N
To put another spin on this explanation, if sizeof(E) worked as you expected (giving the size of the allocated memory, rather than the size of the pointer) then you could use that to get the size of dynamically allocated arrays. You can't do that in C.

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

sizeof operator returns different values when array is assigned to a pointer. Why? [duplicate]

This question already has answers here:
Sizeof arrays and pointers
(5 answers)
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 9 years ago.
Sample code :
#include <stdlib.h>
#include <stdio.h>
int main()
{
int arr[5] = {10,20,30,40,50};
int *p;
p = arr;
printf("Total size calculating from array = %ld\n", sizeof(arr));
printf("Total size calculating from pointer = %ld \n",sizeof(p));
return 0;
}
Output :
Total size calculating from array = 20
Total size calculating from pointer = 8
My understanding so far was that you can assign the address of the array to a pointer of same data type and do all the operations on it without any problem. But sizeof is returning different values.
So i have few questions here :
Is assigning good practice or not?
What things gets changed when we assign?
why 8?
Is assigning good practice or not?
Yes, for example if you pass an array to a function it will decay into a pointer. Let's say you need to keep the original pointer but you also need another one to iterate through the array. You declare a separate pointer that points to the same address and use that to iterate through it.
What things gets changed when we assign?
The pointer points to an address, that's it (previously it could have pointed to another address or NULL), the assignee (in your case the array) is not modified. There is a big difference between an array and a pointer which is why you get different results for it. Pointers and arrays are only seemingly equivalent.
You can still use the pointer to access and modify the contents of the array, but the two are not the same (as illustrated by the result of sizeof).
why 8?
On 32 bit machines a pointer is normally 4 bytes big, on 64 it is 8. If you take the size of a local array, the sizeof will multiply the number of elements in the array by how big each element is. Five integers each four bytes big equals 20.
array size denotes the total size of the array which in this case are 5 integers. But a pointer to the array actually stores a memory address whose size depends on the system you are using. So they are different
sizeof(arr) is giving size of array which is 20 Bytes in your case.When you perform p = arr; it is actually assigning address of first array element(&arr[0]) to integer pointer p.So now sizeof(p) is giving size of integer pointer only.
Remember array and pointer are not same.Array name is address of its first element.An array may decay as pointer.
why 8?
sizeof operator gives total byte size for statically defined array while for pointers it gives pointer size which can be 8 bytes for 64 bit systems and 4 bytes for 32 bit systems.
Is assigning good practice or not?
Yes, because in C you do not have much choice but a better way is using references in C++.
What things gets changed when we assign?
Nothing changes, original data is preserved.

sizeof() function in C [duplicate]

This question already has answers here:
What does sizeof(&array) return?
(4 answers)
Closed 9 years ago.
main()
{
char a[] = "Visual C++";
char *b = "Visual C++";
printf("\n %d %d",sizeof(a),sizeof(b));
printf("\n %d %d",sizeof(*a),sizeof(*b));
}
sizeof(a) gives me output: 11 ( that is length of the string)
Why is it so ?
Why isn't the output sizeof(a)=4 since when I try to print a it gives me an address value and hence an integer?
Whenever you refer to the name of the array in your program, It normally decays to a pointer to the first element of the array. One of the exception to this rule is the sizeof operator. So when you consider the following code.
int main()
{
char a[] = "Visual C++";
printf("sizeof(a)=%d\n",sizeof(a)); /* Here sizeof(a) indicates sizeof array */
printf("a=%p",a); /* Here the array name, passed as an argument to printf decays into a pointer of type (char *) */
return 0;
}
In the declaration char a[] = "Visual C++", a is an array of 11 char. So its size is 11 bytes.
In the declaration char *b = "Visual C++", b is a pointer to char. So its size is four bytes (in the C implementation you are using).
In the expression printf("%s", a), a is also an array. However, it is automatically converted to a pointer to the first element of the array. So a pointer to char is passed to printf.
This conversion happens automatically unless an array is the argument of &, sizeof, or _Alignof or is a string literal used to initialize an array of char. Because it happens automatically, people tend to think of array names as pointers. However, they are not.
Incidentally, sizeof is an operator, not a function.
When sizeof is applied to the name of a static array (not an array allocated through malloc), the result is the size in bytes of the whole array. This is one of the few exceptions to the rule that the name of an array is converted to a pointer to the first element of the array, and is possible just because the actual array size is fixed and known at compile time, when sizeof operator is evaluated.
There are lots of errors, here.
"sizeof(a) gives me output: 11 (length of the string)"
The length of the string is 10, not 11. sizeof(a) gives you the length of the array.
"why is it so, why isn't the output sizeof(a)=4 since when I try to print a it gives me an address value"
Here are two methods of "printing a" which do not "give you an address value":
puts(a);
and:
printf("%s\n", a);
so your logic is flawed, and this is the source of your confusion. "Printing a" only "gives you an address value" when you explicitly or implicitly elect to do so.
sizeof(a) gives 11 in this case because the C language defines the sizeof operator to give you the size of an array when an array is the operand. This, I'd argue, is the most natural behavior people would expect, so presumably that's why it is defined as such.
"and hence an integer."
In any case, an address is an address, not an integer. At best you could argue that it ought to give you the size of a pointer, but certainly not the size of an integer.

Resources