In response to your update (being concerned about sizeof(foo+1)
type situations:
Yes, sizeof
applied to array_name + int
is equivalent to sizeof &(array_name[int]);
, on the basis that an array, decays into a pointer in those cases. Likewise, to get to the actual value out of the array you don't write arr_name + 1
, but rather *(arr_name + 1)
.
So, taking the footnote into account, when will a sizeof
yield the actual array size (in bytes)? For that, look at what the standard says about arrays decaying into pointers:
Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue.
Meaning:
- Using
sizeof
directly on the array variable (sizeof array_var
)
- Dereferencing a pointer to an array (
sizeof *(&array_var)
) Note: This also applies when you pass this pointer to an array to another function, but isn't always the best way to go (see example below)
- string literals (like the Rvalue in
char foo[] = "foobar";
=> sizeof("foobar");
)
In all other cases (AFAIK), the array decays into a pointer, and sizeof
will yield the size of a pointer:
- Arithmetic on array => pointer arithmetic (
sizeof (array_var +1 )
)
- Passing array to function (decays into pointer)
- ...
passing an array to a function
So using the unary &
operator, it is possible to pass a pointer to an array to a function, but it's rarely done. Still, here's an example:
void pointer_to_array(char (*ptr)[]);//pointer to array type
void error_p_to_arr(char (*ptr)[]);
int main ( void )
{
char str[] = "some random string";//array of 18 bytes
printf(
"Sizeof array %zu\n",
sizeof str
);
pointer_to_array(&str);
return 0;
}
//we need to specify the exact type, including size!
//replace 18 with 10, you're fine, but use 20 and you're in trouble
void pointer_to_array(char (*ptr)[18])
{
printf(
"sizeof argument: %zu\nsizeof array %zu",
sizeof ptr,//4 or 8
sizeof *ptr//18!! YaY
);
}
//if we don't specify the array size here
void error_p_to_arr(char (*ptr)[])
{
printf(
"sizeof argument: %zu\nsizeof array %zu",
sizeof ptr,//4 or 8
sizeof *ptr//ERROR!
);
}
The latter sizeof *ptr
will cause an error ("invalid application of ‘sizeof’ to incomplete type ‘char[]’"). Because this way of passing an array around is quite error prone (the correct size must be defined everywhere), it's a lot more common common to simply let the array decay, and pass a second argument along with it:
void common_usage(const char *ptr, size_t arr_len);
int main ( void )
{
char str[] = "some random string";
common_usage(str, sizeof str/sizeof *str);
return 0;
}
It looks a lot cleaner, it's a lot more common and just so much easier to maintain.
See examples here
sizeof
on an array that is passed to you as a parameter. – Paul Rvoid f(char p[])
declares the parameterp
to have pointer type. – user253751