Не удается передать size_t *arg[] функции, требующей массива пустых указателей

#c #pointers

#c #указатели

Вопрос:

f(void *data[]) Насколько я понимаю, моя функция должна получать массив общих указателей в качестве аргумента. Тем не менее, я получаю ошибку компиляции при попытке выполнить

 size_t *cnt[8];
... // initialize pointers in cnt
f(cnt);
 

В частности, g автоматически преобразует прототип f into f(void**) , затем преобразует cnt в size_t** , а затем сообщает, что он не может преобразовать size_t** в void** .

Комментарии:

1. Почему бы не использовать шаблон и фактические типы вместо void* ?

2. Это не относится к g . Это C . f(void *data[]) совпадает с f(void** data)

3. В любом случае, это ожидаемое поведение. Но в чем ваш вопрос?

4. Чтобы понять, почему это преобразование не разрешено, подумайте, что может произойти: void f(void* d[]) { d[0] = new int; } int main() { string * cnt[8] = {0}; f(cnt); *cnt[0] = "Oops"); }

Ответ №1:

g автоматически преобразует прототип f в f(void**)

Я считаю, что использование точной терминологии помогает лучше понимать языки программирования. Может сбивать с толку мысль, что f это преобразуется в f(void**) . Это не педантично говоря. f(void *data[]) это просто другой способ записи f(void** data) . Это, альтернативный синтаксис, является примером синтаксического сахара.

Преобразование обычно означает изменение одного типа на другой. При объявлении вашей функции преобразование не требуется.

Кроме того, этот синтаксический сахар не является специфичным для компилятора g . Это поведение указано в стандарте C .

 f(cnt);
 

затем он преобразуется cnt в size_t**

Это действительно преобразование. Это особый тип преобразования, называемый decaying . Это неявное преобразование также является синтаксическим сахаром case. Это семантически то же самое, что и запись:

 f(amp;cnt[0]);
 

Не удается передать size_t *arg[] функции, требующей массива пустых указателей

Это правильно.

Действительно, ваша функция ожидает a void** , но вы передали функцию a size_t** . A size_t** неявно преобразуется в void** , поэтому ваша программа неправильно сформирована.

Способы решения проблемы:

1) Используйте f(size_t**) вместо этого.

2) void* В первую очередь используйте массив

3) Скопируйте size_t *cnt[8] в другой массив void *temp[8] и передайте его функции.

4) (не рекомендуется) Приведите cnt к void** и надейтесь, что он выполняет то, что ожидает ваша функция.

Комментарии:

1. Больше похоже на синтаксический перец

2. @LightnessRacesinOrbit Я бы использовал «синтаксический сахарин»: пытается быть синтаксическим сахаром, но вызывает рак — если бы только аналогия не была ослаблена отсутствием доказательств того, что сахарин был связан с раком у людей .

3. Хех, да, это подойдет

Ответ №2:

В то время как C допускает неявное преобразование из любого типа указатель-указатель в void указатель-указатель, C не допускает этого. Вам нужно будет явно привести cnt к void ** .

Комментарии:

1. Обратите внимание, что любой приличный компилятор C, по крайней мере, предупредил бы, если вы неявно преобразуете произвольный указатель в void** .