How Does Sizeof Know the Size of the Operand Array

How does sizeof know the size of array?

The name of an array decays to a pointer to the first element of the array in most situations. There are a couple of exceptions to that rule though. The two most important are when the array name is used as the operand of either the sizeof operator or the address-of operator (&). In these cases, the name of the array remains an identifier for the array as a whole.

For a non-VLA array, this means that the size of the array can be determined statically (at compile time) and the result of the expression will be the size of the array (in bytes), not the size of a pointer.

When you take the address of the array, you get the same value (i.e., the same address) as if you'd just used the name of the array without taking the address. The type is different though--when you explicitly take the address, what you get is a pointer of type "pointer to array of N items of type T". That means (for one example) that while array+1 points to the second element of the array, &array+1 points to another array just past the end of the entire array.

Assuming an array of at least two items, *(array+1) will refer to the second element of the array. Regardless of the array size, &array+1 will yield an address past the end of the array, so attempting to dereference that address gives undefined behavior.

In your case, given that the size of the array is 20, and the size of one element of the array is 4, if array was, say, 0x1000, then array+1 would be 0x1004 and &array+1 would be 0x1014 (0x14 = 20).

How does sizeof know the size of the operand array?

sizeof is interpreted at compile time, and the compiler knows how the array was declared (and thus how much space it takes up). Calling sizeof on a dynamically-allocated array will likely not do what you want, because (as you mention) the end point of the array is not specified.

How Does sizeof(Array) work

sizeof(array) is implemented entirely by the C compiler. By the time the program gets linked, what looks like a sizeof() call to you has been converted into a constant.

Example: when you compile this C code:

#include <stdlib.h>
#include <stdio.h>
int main(int argc, char** argv) {
int a[33];
printf("%d\n", sizeof(a));
}

you get

    .file   "sz.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $164, %esp
movl $132, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $164, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 (Gentoo 4.1.2 p1.1)"
.section .note.GNU-stack,"",@progbits

The $132 in the middle is the size of the array, 132 = 4 * 33. Notice that there's no call sizeof instruction - unlike printf, which is a real function.

How do sizeof(arr) / sizeof(arr[0]) work?

If you have an array then sizeof(array) returns the number of bytes the array occupies. Since each element can take more than 1 byte of space, you have to divide the result with the size of one element (sizeof(array[0])). This gives you number of elements in the array.

Example:

std::uint32_t array[10];

auto sizeOfInt = sizeof(std::uint32_t); // 4
auto numOfBytes = sizeof(array); // 10*sizeOfInt = 40
auto sizeOfElement = sizeof(array[0]); // sizeOfInt = 4
auto numOfElements = sizeof(array) / sizeof(array[0]); // numOfBytes / sizeOfElement = 40 / 4 = 10

LIVE EXAMPLE

Note that if you pass an array to a function, the above won't work since the array decays to a pointer and sizeof(array) returns the size of the pointer.

std::size_t function(std::uint32_t a[]) // same for void function(std::uint32_t a[10])
{
return sizeof(a); // sizeof(std::uint32_t*)!
}

std::uint32_t array[10];
auto sizeOfArray = function(array); // array decays to a pointer inside function()

LIVE EXAMPLE #2

How do I determine the size of my array in C?

Executive summary:

int a[17];
size_t n = sizeof(a)/sizeof(a[0]);

Full answer:

To determine the size of your array in bytes, you can use the sizeof
operator:

int a[17];
size_t n = sizeof(a);

On my computer, ints are 4 bytes long, so n is 68.

To determine the number of elements in the array, we can divide
the total size of the array by the size of the array element.
You could do this with the type, like this:

int a[17];
size_t n = sizeof(a) / sizeof(int);

and get the proper answer (68 / 4 = 17), but if the type of
a changed you would have a nasty bug if you forgot to change
the sizeof(int) as well.

So the preferred divisor is sizeof(a[0]) or the equivalent sizeof(*a), the size of the first element of the array.

int a[17];
size_t n = sizeof(a) / sizeof(a[0]);

Another advantage is that you can now easily parameterize
the array name in a macro and get:

#define NELEMS(x)  (sizeof(x) / sizeof((x)[0]))

int a[17];
size_t n = NELEMS(a);

how and why sizeof(a)/sizeof(a[0]) in c is used to calculate the number of elements in an array

According to the C Standard (6.5.3.4 The sizeof and alignof operators)

2 The sizeof operator yields the size (in bytes) of its operand, which
may be an expression or the parenthesized name of a type. The size is
determined from the type of the operand. The result is an integer. If
the type of the operand is a variable length array type, the operand
is evaluated; otherwise, the operand is not evaluated and the result
is an integer constant.

So if you have an array as for example

int a[N];

where N is some integer value then expression

sizeof( a )

yields the number of bytes occupied by the array. As the array has N elements and each element in turn occupies sizeof( int ) bytes then

sizeof( a ) == N * sizeof( int )

or what is the same

sizeof( a ) == N * sizeof( a[0] )

As result you can calculate N the following way

N = sizeof( a ) / sizeof( a[0] )

It is useful if you do not know the exact size of an array for example because its size depends on the number of initializers.

For example

int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const size_t N = sizeof( a ) / sizeof( *a );

Take into account that sometimes beginners make an error.

Let's assume that you have a function declaring an array as a parameter.

For example

void f( int a[10] );

and the function can be called like

int a[10];

f( a );

Beginners usually write in the body of the function the following expression

void f( int a[10] )
{
size_t n = sizeof( a ) / sizeof( a[0] );
//...
}

However it is a wrong code. The problem is that parameters declared like arrays are adjusted to pointers to the type of the array element. So the function declaration actually looks like

void f( int *a );

and within the function in expression

    size_t n = sizeof( a ) / sizeof( a[0] );

parameter a is pointer. That is it is equivalent to

    size_t n = sizeof( int * ) / sizeof( int );

Depending on the used system pointers occupy either 4 or 8 bytes. So you will get either 2 or 1 if sizeof( int ) is equal to 4.

You will not get the number of elements in the array that was used as the argument.

Pointers do not keep an information about whether they point to a single object or the first object of some array.

In this case you should declare the function with second parameter that specifies the number of elements in the array. For example

void f( int *a, size_t n );

How does `sizeof` distinguish a pointer from an array?

sizeof is a compile-time operator. It is computed by the compiler (and is almost always a constant, VLAs being the exception).

The compiler is obviously knowing when a variable refers to an array or to a pointer because it has to know the type of every variable (and an array type is not the same as a pointer type).

Notice that in C an array can decay into a pointer (e.g. when you pass an array as an argument to a routine). This is one of the most tricky points of the C language (so dive into a C programming book if you don't understand it).

Does sizeof returns the amount of memory allocated?

The text you quote is technically incorrect. sizeof variable_name does return the size of memory that the variable called variable_name occupies.

The text makes a common mistake of conflating a pointer with the memory it points to. Those are two separate things. If a pointer points to an allocated block, then that block is not allocated to the pointer. (Nor are the contents of the block stored in the pointer -- another common mistake).

The allocation exists in its own right, the pointer variable exists elsewhere, and the pointer variable points to the allocation. The pointer variable could be changed to point elsewhere without disturbing the allocation.

How does sizeof wоrk in this case?

At the time int[++i] is evaluated, i initially has the value 1. So int[++i] evaluates to int[2], i.e. an array of int of size 2.

Assuming an int is 4 bytes on your system, this array is 8 bytes in size.



Related Topics



Leave a reply



Submit