What Does Sizeof Do

What does sizeof do?

sizeof(x) returns the amount of memory (in bytes) that the variable or type x occupies. It has nothing to do with the value of the variable.

For example, if you have an array of some arbitrary type T then the distance between elements of that array is exactly sizeof(T).

int a[10];
assert(&(a[0]) + sizeof(int) == &(a[1]));

When used on a variable, it is equivalent to using it on the type of that variable:

T x;
assert(sizeof(T) == sizeof(x));

As a rule-of-thumb, it is best to use the variable name where possible, just in case the type changes:

int x;
std::cout << "x uses " << sizeof(x) << " bytes." << std::endl
// If x is changed to a char, then the statement doesn't need to be changed.
// If we used sizeof(int) instead, we would need to change 2 lines of code
// instead of one.

When used on user-defined types, sizeof still returns the amount of memory used by instances of that type, but it's worth pointing out that this does not necessary equal the sum of its members.

struct Foo { int a; char b; };

While sizeof(int) + sizeof(char) is typically 5, on many machines, sizeof(Foo) may be 8 because the compiler needs to pad out the structure so that it lies on 4 byte boundaries. This is not always the case, and it's quite possible that on your machine sizeof(Foo) will be 5, but you can't depend on it.

What does sizeof without () do?

So if we look at the grammar for sizeof in the C99 draft standard section 6.5.3 Unary operators paragraph 1 it is as follows:

sizeof unary-expression
sizeof ( type-name )

There is a difference you can not use a type-name without parenthesizes and section 6.5.3.4 The sizeof operator paragraph 2 says(emphasis mine):

The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type.[...]

For completeness sake you may wonder if we can use sizeof with an expression if we have parenthesizes and the answer is yes since a unary-expression can itself contain parenthesizes. The easiest way to see this would be to look section A.2.1 Expressions from the draft standard and work through the grammar like so:

unary-expression -> postfix-expression -> primary-expression -> ( expression )

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.

What does sizeof(int**) mean?

sizeof(int **) tells you how many bytes an int ** is, similarly to how sizeof(int *) tells you how many bytes an int * is. They just have different levels of indirection.

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 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 does sizeof work? How can I write my own?

You haven't provided any meaningful details about what it is you want to do, so it is hard to figure out what you need.

You can "wrap" sizeof by you own template function like

template <typename T> size_t my_sizeof() {
return sizeof(T);
}

and then use it as

size_t s = my_sizeof<int>();

From time to time one can come across a request to implement sizeof-like functionality without using sizeof. Requests like that make no practical sense whatsoever, yet sometimes are used as homework assignments. One can probably do it as follows

template <typename T> size_t my_sizeof() {
T t;
return (char *) (&t + 1) - (char *) &t;
}

which would require a default-constructible T. A less restricting but formally illegal solution (a hack) would be something like

template <typename T> size_t my_sizeof() {
return (char *) ((T *) NULL + 1) - (char *) (T *) NULL;
}

The above implementations implement type-based sizeof.

An attempt to emulate the functionality of value-based sizeof might look as follows

template <typename T> size_t my_sizeof(const T& obj) { 
return my_sizeof<T>();
}

but this will not be even remotely equivalent to the built-in sizeof, at least because the built-in sizeof does not evaluate its argument.

Finally, neither of these implementations will produce integral constant expressions (ICE), as the built-in sizeof does. Producing an ICE that way is impossible to achieve in the current version of the language.

In any case this all, of course, is totally devoid of any practical value. Just use sizeof when you want to know the size.

What does sizeof(char *) do?

Because otherwise you would get the number of bytes that words array takes up, not the number of elements (char pointers are either 4 or 8 bytes on Intel architectures)

What does sizeof (function(argument)) return?

Except with variable length arrays, sizeof does not evaluate its operand. So it will just yield the size of fun(a) type, i.e. sizeof(int) (without calling the function).

C11 (n1570) §6.5.3.4 The sizeof and _Alignof operators

2 [...] 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.



Related Topics



Leave a reply



Submit