foo (void) vs foo (пустота *)


9

Функціонально та синтаксично кажучи, чи є різниця між функцією, прототипом якої є int foo(void)і int foo(void *)?

Я знаю різницю між, наприклад, int bar(int)і int bar(int *)- один з них шукає int, а другий шукає int pointer. Чи voidповодиться так само?


Відповідь на пов’язане запитання: stackoverflow.com/a/1043209/434551 .
R


Що може бути цікавішим, є різниця між foo(void)та foo().
Максим

Відповіді:


10

З цієї відповіді на програмування інженерії void розглядаються спеціально залежно від способу використання. В Cі C++, voidвикористовується для вказівки на відсутність типу даних, тоді void *як використовується для позначення вказівника, який вказує на деякі дані / простір у пам'яті, які не мають типу. void *не може бути відмежовано самостійно, і його слід спочатку передати іншому типу. Цей склад не повинен бути явним в C, але повинен бути явним в C++. (Ось чому ми не відкидаємо повернене значення malloc, яке є void *.)


Якщо використовується з функцією в якості параметра, voidозначає повну відсутність будь-яких параметрів і є єдиним дозволеним параметром. Спроба використання void як типу змінної або включення інших аргументів призводить до помилки компілятора:

int foo(void, int);     //trying to use "void" as a parameter
int bar(void baz);      //trying to use "void" as an argument's type
main.c:1:8: error: 'void' must be the first and only parameter if specified
int foo(void, int);
       ^
main.c:2:14: error: argument may not have 'void' type
int bar(void baz);
             ^

Так само неможливо оголосити змінну з типом void:

int main(void) {
  void qux;         //trying to create a variable with type void
}
main.c:5:8: error: variable has incomplete type 'void'
  void qux;

voidяк значення повернення для функції вказує, що дані не повертаються. Оскільки неможливо оголосити змінну типу void, неможливо зловити повернене значення voidфункції навіть з недійсним вказівником.

void foo(int i) { return; }

int main(void) {
  void *j;
  j = foo(0);

  return 0;
}
main.c:5:5: error: assigning to 'void *' from
      incompatible type 'void'
  j = foo(0);
    ^ ~~~~~~

Нетиповий void *- це інший випадок. Недійсний вказівник вказує на вказівник на місце в пам'яті, але не вказує тип даних у цьому покажчику. (Це використовується для досягнення поліморфізму в C , наприклад, за допомогою функції qsort () . Однак, ці покажчики можуть бути складними у використанні, оскільки дуже легко випадково відкинути їх на неправильний тип. Нижче наведений код не призведе до помилок компілятора C, але призводить до невизначеної поведінки:

#include <stdio.h>

int main(void) {
  double foo = 47.2;    //create a double
  void *bar = &foo;     //create a void pointer to that double
  char *baz = bar;      //create a char pointer from the void pointer, which
                        //is supposed to hold a double

  fprintf(stdout, "%s\n", baz);
}

Наступний код, однак, цілком законний; кастинг до та недійсного вказівника ніколи не змінює значення, яке він має.

#include <stdio.h>

int main(void) {
  double foo = 47.2;
  void *bar = &foo;
  double *baz = bar;

  fprintf(stdout, "%f\n", *baz);
}

47.200000

Як параметр функції void *вказується, що тип даних у вказівнику, який ви передаєте, не відомий, і ви, програміст, вирішувати, як правильно обробляти все, що знаходиться в цьому місці пам'яті. Як повернене значення void *вказує, що тип даних, що повертаються, не відомий або є безтиповим і повинен оброблятись програмою.

int quux(void *);   //a function that receives a pointer to data whose type is not known, and returns an int.
void *quuz(int);    //a function that receives an int, and returns a pointer to data whose type is not known.

tl; dr void в прототипі функції означає "немає даних" і не вказує значення повернення або відсутні параметри, void *у прототипі функції означає "дані вказівника, яким ця функція задана, не мають відомого типу" і вказують параметр або повернене значення чий вказівник повинен бути переданий на інший тип, перш ніж дані вказівника можуть бути використані.


void * ... must be cast to another type first, but may be done so without an explicit cast.Не вірно в C ++. У C ++ форма перетворення void*повинна бути явною. PS, що викликає явний вираз, є зайвим, оскільки cast є за визначенням явним перетворенням.
eerorika

Оновлено, щоб відобразити C / C ++ відмінності, дякую, що повідомили мені!
Нік Рід

4

foo(void) - функція без параметрів

foo(void *)- функція з одним void *параметром

Що таке void *? Це просто вказівник на дані без вказаного типу. Він може бути переданий на будь-який інший тип вказівника

unsigned add(void *arr)
{
   unsigned *uarr = arr;
   return uarr[0] + uarr[1];
}

Важлива відповідь, тому вона найкраща. Я б просто зрозумів, як це виняток у (type) vs. (type *)Всесвіті пар, тому що пустота насправді не є типом.
Роберто Кабоні

2

Функціонально та синтаксично кажучи, чи існує різниця між функцією, прототипом якої є int foo (void) та int foo (void *)?

Є різниця:

int foo(void) оголошує функцію, яка не приймає аргументів.

int foo(void *)оголошує функцію, яка приймає єдиний аргумент типу void*.

У C ++ int foo(void)рівносильно int foo().

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.