Що означає порожнеча в C, C ++ та C #?


170

Шукаємо основи того, звідки походить термін " недійсність " і чому його називають недійсним. Намір питання полягає в тому, щоб допомогти тому, хто не має досвіду роботи з C, і раптом дивиться на кодову базу на основі С.


2
Це питання поєднує 3 мови ... це застаріле питання слід розділити на 3 різні питання.
Stargateur

Відповіді:


225

В основному це означає "нічого" або "немає типу"

Існує 3 основних способи використання недійсності:

  1. Аргумент функції: int myFunc(void) - функція нічого не бере.

  2. Значення повернення функції: void myFunc(int) - функція нічого не повертає

  3. Загальний покажчик даних: void* data - 'data' - це вказівник на дані невідомого типу, і його неможливо відкинути

Примітка: voidаргумент функції в опції C ++ необов’язковий, тому int myFunc()він точно такий же, як int myFunc(void)і повністю вичерпаний у C #. Він завжди потрібен для повернутого значення.


7
недійсним у списку аргументів необов’язково в C ++, див. stackoverflow.com/questions/416345/…
Daniel Earwicker

1
Я б використав "без типу", а не "без розміру"
Kjetil Joergensen,

@Earwicker і k безпекиor, обидва хороші моменти, про які я обговорював, але мій сонний розум потребував допомоги;) ​​Дякую
Джеральд

9
Не погоджуючись, але додаткове використання недійсності полягає в фокусі "приведення в недійсність" для придушення попереджень про невикористані значення. Це трохи розтягнення, оскільки він насправді не відповідає тому, як компілятор інтерпретує речі, але ви можете інтерпретувати це як "Я використовую це значення, щоб нічого не робити".
Стів Джессоп

22
У C ++ недійсність у списку аргументів необов’язкова. Однак у C це НЕ обов'язково: foo () означає, що він приймає будь-яку кількість параметрів будь-якого типу, тоді як foo (void) означає, що він приймає нульові параметри.
Адам Розенфілд

33

Я завжди вважав це відсутнім . Ось чотири випадки на мові С, які відповідають цьому вжитку відсутні

  • R f(void)- Параметри функції відсутні
  • void f(P)- Повернене значення відсутнє
  • void *p- Тип того, на що вказується, відсутній
  • (void) p- Використання значення відсутнє

Інші нащадки С використовують його для інших речей. Мова Dпрограмування використовує його у випадках, коли ініціалізатор відсутній

  • T t = void;- значення ініціалізації відсутнє

4
Що робить (void)p? Я не зовсім зрозумів, що ви мали на увазі під "використанням вартості відсутня".
Яшас

@Yashas Якщо хтось також плутає (void) var;твердження, я знайшов детальні відповіді на сайті stackoverflow.com/q/21045615 .
Arnie97

14

Існує два способи використання пустоти:

void foo(void);

або

void *bar(void*);

Перший вказує на те, що жоден аргумент не передається або що аргумент не повертається.

Другий повідомляє компілятору, що не існує жодного типу, пов'язаного з даними, що фактично означає, що ви не можете використовувати дані, вказані до тих пір, поки вони не будуть передані відомому типу.

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

Наприклад, в ядрі Linux при відкладанні роботи ви встановите функцію, яку потрібно запустити в останній час, надавши їй вказівник на функцію, яку потрібно запустити, і покажчик на дані, що передаються функції:

struct _deferred_work {
sruct list_head mylist;
.worker_func = bar;
.data        = somedata;
} deferred_work;

Потім потік ядра переходить список відкладених робіт, і коли він потрапляє до цього вузла, він ефективно виконує:

bar(somedata);

Потім у барі у вас є:

void bar(void* mydata) {
    int *data = mydata;
    /* do something with data */;
}

13

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


4

Він вказує на відсутність повернутого значення у функції.

Деякі мови мають два типи підпрограм: процедури та функції. Процедури - це лише послідовність операцій, тоді як функція - це послідовність операцій, що повертають результат.

У C та його похідних різниця між ними не є явною. Все в основному є функцією. voidключове слово вказує на те, що це не «фактичний» функція, так як вона не повертає значення.


3

Подумайте про недійсність як "порожню структуру". Дозволь пояснити.

Кожна функція приймає послідовність параметрів, де кожен параметр має тип. Насправді, ми могли б упакувати параметри в структуру з відповідними параметрами структурними слотами. Це змушує кожну функцію мати точно один аргумент. Аналогічно, функції дають результат, який має тип. Це може бути булева або може бути плаваючою, або це може бути структура, що містить довільний набір інших набраних значень. Якщо ми хочемо, щоб язик мав кілька повернених значень, легко просто наполягати, щоб вони були упаковані в структуру. Насправді ми завжди могли наполягати на тому, що функція повертає структуру. Тепер кожна функція бере рівно один аргумент і виробляє рівно одне значення.

Тепер, що станеться, коли мені потрібна функція, яка виробляє значення "ні"? Ну, подумайте, що я отримую, коли формую структуру з 3-х слотів: вона містить 3 значення. Коли у мене є 2 слота, він містить два значення. Коли він має один слот, одне значення. І коли він має нульові слоти, він містить ... е, нульові значення або "не" значення ". Отже, я можу вважати функцію, що повертає недійсність як повернення структури, що не містить значень. Ви навіть можете вирішити, що" недійсна " є лише синонімом типу, представленого порожньою структурою, а не ключовим словом у мові (можливо, це лише попередньо визначений тип :)

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

Я навіть можу програмування реалізувати таким чином. Передача значення пустоти займає нульові байти, тому передача недійсних значень є лише особливим випадком передачі інших значень довільного розміру. Це полегшує компілятору обробляти результат або аргумент "недійсності". Ви, мабуть, хочете функцію мови, яка може викинути результат функції; в C, якщо ви викликаєте недійсну функцію результату foo у наступному викладі: foo (...); компілятор знає, що foo видає результат і просто ігнорує його. Якщо void - значення, це прекрасно працює, і тепер "процедури" (які є лише прикметником для функції з недійсним результатом) - лише тривіальні особливі випадки загальних функцій.

Пустота * трохи смішніша. Я не думаю, що дизайнери C думали про недійсність вище; вони просто створили ключове слово. Це ключове слово було доступне, коли комусь потрібен вказівник на довільний тип, таким чином, недійсним є * як ідіома в C. Це насправді працює досить добре, якщо інтерпретувати порожнечу як порожню структуру. Вказівник на пустоту * - це адреса місця, де була поставлена ​​порожня структура.

Записи від void * до T * для інших типів T також працюють з цією перспективою. Відсилки покажчиків - це повний обман, який працює у більшості поширених архітектур, щоб скористатися тим фактом, що якщо у складі типу T є елемент із підтипом S, розміщений фізично на початку T у його макеті зберігання, то кастинг S * до T * і навпаки, використання однієї і тієї ж фізичної адреси машини має тенденцію працювати, оскільки більшість машинних покажчиків мають єдине представлення. Заміна типу S на тип void дає точно такий же ефект, і, таким чином, кастинг в / з void * працює.

Мова програмування PARLANSE досить чітко реалізує вищезазначені ідеї. Ми вирішили його дизайн, і не звернули пильної уваги на "недійсність" як тип повернення і, таким чином, маємо ключові слова для мови. Це здебільшого просто проста зміна синтаксису, але це одна з речей, до якої ти не обійдешся, як тільки отримаєш великий робочий код тіла мовою.



2

Три випадки використання недійсних:

  1. Підписи функції. void foo(int bar)не повертає значення. int bar(void)не приймає ніяких параметрів , але це, як правило , виражається з порожнім списком аргументів: int bar(). Використання ключового слова void тут відповідає його значенню англійською мовою.

  2. Універсальний покажчик верхнього типу, void *який вказує на не визначені дані і не може бути відмежований. Тут значення void відрізняється від інших значень void: універсальний тип проти no type.

  3. У ролях, (void) new Foo(this)що означають, що повертається значення навмисно викидається. Тут використання ключового слова також відповідає його значенню англійською мовою.

Випадки 1 і 2 вже висвітлювались @Gerald, але справа 3 ще не розглядалася.


2

Якщо ви пояснюєте концепцію початківцю, може бути корисним застосувати аналогію. Використання пустоти в усіх цих випадках є аналогічним змісту до сторінки книги, яка має такі слова: "Ця сторінка навмисно залишена порожньою". Це розрізняти компілятор між тим, що повинно бути позначено як помилку, порівняно з типом, який навмисно слід залишити порожнім, тому що це поведінка, яку ви хочете.

Він завжди відображається в коді, де зазвичай слід очікувати появи типу, наприклад, типу повернення чи типу вказівника. Ось чому в C # недійсні карти відображаються на фактичний тип CLR, System.Void, оскільки він сам по собі тип.

Деякі мови програмування ніколи не розробляли поняття нікчемності, як і деякі людські культури ніколи не вигадували поняття числа нуль. Пустота являє собою те саме просування в мові програмування, як поняття нуля, що представляє людську мову.


Лише зауваження щодо останнього речення - майте на увазі, що це стосується лише мов, що мають статичний набір. Мови, що динамічно набираються, не потребують недійсності, оскільки їхні методи просто нічого не повертають - "порожнеча" має на увазі відсутність повернення нічого іншого.
Марк Embling

Виправлення мого останнього коментаря - я мав на увазі сказати останній абзац (не речення).
Марк Embling

1

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

Пустоту не слід плутати з null. Null означає для змінної, адреса якої знаходиться у стеці, значення на купі для цієї адреси порожнє.


0

Пустота використовується лише в підписах методів. Для типів повернення це означає, що метод нічого не поверне в код виклику. Для параметрів це означає, що параметри методу не передаються

напр

void MethodThatReturnsAndTakesVoid(void)
{
// Method body
}

У C # ми можемо опустити порожнечу для параметрів і можемо записати наведений вище код у вигляді:

void MethodThatReturnsAndTakesVoid()
{
// Method body
}

Пустоту не слід плутати з null. Null означає для змінної, адреса якої знаходиться у стеці, значення на купі для цієї адреси порожнє.


0

Пустота - це незавершений тип, який, за визначенням, не може бути цінністю. Це означає, що вона не може присвоїти значення.

Тож воно також не може утримувати жодної цінності.



-1

Пустота означає, що значення, яке не потрібно, повертається від функції на всіх трьох мовах.


-1

Пустота - еквівалент Sub. Visual Basic.


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