В ответ на ваше обновление (беспокоясь о sizeof(foo+1)
типа ситуаций:
Да, sizeof
применяется к array_name + int
эквивалентно sizeof &(array_name[int]);
, на том основании, что массив, затухает в указатель в тех случаях, Точно так же, к. добраться до фактического значения из массива вы не пишете arr_name + 1
, а *(arr_name + 1)
.
Таким образом, принимая во внимание сноску, когда будет sizeof
выход фактический размер массива (в байтах)?Для этого, обратите внимание на то, что говорит стандарт о массивах распадающихся на указатели:
исключением случаев, когда это операнд оператора SizeOf или одноместный & оператора, или строковый литерал используется для инициализации массива, выражение который имеет тип '' array of type '', преобразуется в выражение с указателем типа '' to type '', который указывает на начальный элемент объекта массива и не является lvalue.
Значение:
- Использование
sizeof
непосредственно на переменном массиве (sizeof array_var
)
- Разыменование указателя на массив (
sizeof *(&array_var)
) Примечания: Это относится также, когда вы передаете этот указатель на массив к другой функции, но не всегда лучший способ пойти (см. пример ниже)
- строковые литералы (например, Rvalue в
char foo[] = "foobar";
=>sizeof("foobar");
)
Во всех других случаях (AFAIK), массив распадается на указатель, и sizeof
даст размер указателя:
- Арифметика на массиве => арифметика указателей (
sizeof (array_var +1)
)
- Передача массива в функцию (распадается на указатель)
- ...
передачи массива в функцию
Таким образом, используя унарный оператор &
, это является можно передать указатель на массив в функцию, но это делается редко. Тем не менее, вот пример:
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!
);
}
Последнее sizeof *ptr
вызовет ошибку («недопустимое применение„SizeOf“неполного типа" обугливается []»). Поскольку этот способ передачи массива вокруг весьма подвержен ошибкам (правильный размер должен быть определен везде), это намного чаще распространены, чтобы просто позволить распад массива, и передать второй аргумент вместе с ним:
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;
}
Он выглядит намного чище, он намного более распространен и просто намного удобнее в обслуживании.
Смотрите примеры here
По сути, вы просто должны знать, что массивы распадаются на указатели при передаче в качестве параметров, поэтому не используйте 'sizeof' для массива, который передается вам в качестве параметра. –
Он просто повторяет, что 'void f (char p [])' объявляет параметр 'p' для указания типа указателя. – immibis