Шукаємо основи того, звідки походить термін " недійсність " і чому його називають недійсним. Намір питання полягає в тому, щоб допомогти тому, хто не має досвіду роботи з C, і раптом дивиться на кодову базу на основі С.
Шукаємо основи того, звідки походить термін " недійсність " і чому його називають недійсним. Намір питання полягає в тому, щоб допомогти тому, хто не має досвіду роботи з C, і раптом дивиться на кодову базу на основі С.
Відповіді:
В основному це означає "нічого" або "немає типу"
Існує 3 основних способи використання недійсності:
Аргумент функції: int myFunc(void)
- функція нічого не бере.
Значення повернення функції: void myFunc(int)
- функція нічого не повертає
Загальний покажчик даних: void* data
- 'data' - це вказівник на дані невідомого типу, і його неможливо відкинути
Примітка: void
аргумент функції в опції C ++ необов’язковий, тому int myFunc()
він точно такий же, як int myFunc(void)
і повністю вичерпаний у C #. Він завжди потрібен для повернутого значення.
Я завжди вважав це відсутнім . Ось чотири випадки на мові С, які відповідають цьому вжитку відсутні
R f(void)
- Параметри функції відсутніvoid f(P)
- Повернене значення відсутнєvoid *p
- Тип того, на що вказується, відсутній(void) p
- Використання значення відсутнєІнші нащадки С використовують його для інших речей. Мова D
програмування використовує його у випадках, коли ініціалізатор відсутній
T t = void;
- значення ініціалізації відсутнє(void)p
? Я не зовсім зрозумів, що ви мали на увазі під "використанням вартості відсутня".
(void) var;
твердження, я знайшов детальні відповіді на сайті stackoverflow.com/q/21045615 .
Існує два способи використання пустоти:
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 */;
}
Це означає "немає значення". Ви використовуєте void
для вказівки, що функція не повертає значення або що вона не має жодних параметрів або обох. Він майже відповідає типовому використанню слова void в англійській мові.
Він вказує на відсутність повернутого значення у функції.
Деякі мови мають два типи підпрограм: процедури та функції. Процедури - це лише послідовність операцій, тоді як функція - це послідовність операцій, що повертають результат.
У C та його похідних різниця між ними не є явною. Все в основному є функцією. void
ключове слово вказує на те, що це не «фактичний» функція, так як вона не повертає значення.
Подумайте про недійсність як "порожню структуру". Дозволь пояснити.
Кожна функція приймає послідовність параметрів, де кожен параметр має тип. Насправді, ми могли б упакувати параметри в структуру з відповідними параметрами структурними слотами. Це змушує кожну функцію мати точно один аргумент. Аналогічно, функції дають результат, який має тип. Це може бути булева або може бути плаваючою, або це може бути структура, що містить довільний набір інших набраних значень. Якщо ми хочемо, щоб язик мав кілька повернених значень, легко просто наполягати, щоб вони були упаковані в структуру. Насправді ми завжди могли наполягати на тому, що функція повертає структуру. Тепер кожна функція бере рівно один аргумент і виробляє рівно одне значення.
Тепер, що станеться, коли мені потрібна функція, яка виробляє значення "ні"? Ну, подумайте, що я отримую, коли формую структуру з 3-х слотів: вона містить 3 значення. Коли у мене є 2 слота, він містить два значення. Коли він має один слот, одне значення. І коли він має нульові слоти, він містить ... е, нульові значення або "не" значення ". Отже, я можу вважати функцію, що повертає недійсність як повернення структури, що не містить значень. Ви навіть можете вирішити, що" недійсна " є лише синонімом типу, представленого порожньою структурою, а не ключовим словом у мові (можливо, це лише попередньо визначений тип :)
Так само я можу вважати функцію, яка не потребує значень як прийняття порожньої структури, наприклад, "void".
Я навіть можу програмування реалізувати таким чином. Передача значення пустоти займає нульові байти, тому передача недійсних значень є лише особливим випадком передачі інших значень довільного розміру. Це полегшує компілятору обробляти результат або аргумент "недійсності". Ви, мабуть, хочете функцію мови, яка може викинути результат функції; в C, якщо ви викликаєте недійсну функцію результату foo у наступному викладі: foo (...); компілятор знає, що foo видає результат і просто ігнорує його. Якщо void - значення, це прекрасно працює, і тепер "процедури" (які є лише прикметником для функції з недійсним результатом) - лише тривіальні особливі випадки загальних функцій.
Пустота * трохи смішніша. Я не думаю, що дизайнери C думали про недійсність вище; вони просто створили ключове слово. Це ключове слово було доступне, коли комусь потрібен вказівник на довільний тип, таким чином, недійсним є * як ідіома в C. Це насправді працює досить добре, якщо інтерпретувати порожнечу як порожню структуру. Вказівник на пустоту * - це адреса місця, де була поставлена порожня структура.
Записи від void * до T * для інших типів T також працюють з цією перспективою. Відсилки покажчиків - це повний обман, який працює у більшості поширених архітектур, щоб скористатися тим фактом, що якщо у складі типу T є елемент із підтипом S, розміщений фізично на початку T у його макеті зберігання, то кастинг S * до T * і навпаки, використання однієї і тієї ж фізичної адреси машини має тенденцію працювати, оскільки більшість машинних покажчиків мають єдине представлення. Заміна типу S на тип void дає точно такий же ефект, і, таким чином, кастинг в / з void * працює.
Мова програмування PARLANSE досить чітко реалізує вищезазначені ідеї. Ми вирішили його дизайн, і не звернули пильної уваги на "недійсність" як тип повернення і, таким чином, маємо ключові слова для мови. Це здебільшого просто проста зміна синтаксису, але це одна з речей, до якої ти не обійдешся, як тільки отримаєш великий робочий код тіла мовою.
У c # ви використовуєте ключове слово "void", щоб вказати, що метод не повертає значення:
public void DoSomeWork()
{
//some work
}
Три випадки використання недійсних:
Підписи функції. void foo(int bar)
не повертає значення. int bar(void)
не приймає ніяких параметрів , але це, як правило , виражається з порожнім списком аргументів: int bar()
. Використання ключового слова void тут відповідає його значенню англійською мовою.
Універсальний покажчик верхнього типу, void *
який вказує на не визначені дані і не може бути відмежований. Тут значення void відрізняється від інших значень void: універсальний тип проти no type.
У ролях, (void) new Foo(this)
що означають, що повертається значення навмисно викидається. Тут використання ключового слова також відповідає його значенню англійською мовою.
Випадки 1 і 2 вже висвітлювались @Gerald, але справа 3 ще не розглядалася.
Якщо ви пояснюєте концепцію початківцю, може бути корисним застосувати аналогію. Використання пустоти в усіх цих випадках є аналогічним змісту до сторінки книги, яка має такі слова: "Ця сторінка навмисно залишена порожньою". Це розрізняти компілятор між тим, що повинно бути позначено як помилку, порівняно з типом, який навмисно слід залишити порожнім, тому що це поведінка, яку ви хочете.
Він завжди відображається в коді, де зазвичай слід очікувати появи типу, наприклад, типу повернення чи типу вказівника. Ось чому в C # недійсні карти відображаються на фактичний тип CLR, System.Void, оскільки він сам по собі тип.
Деякі мови програмування ніколи не розробляли поняття нікчемності, як і деякі людські культури ніколи не вигадували поняття числа нуль. Пустота являє собою те саме просування в мові програмування, як поняття нуля, що представляє людську мову.
Це означає "немає значення". Ви використовуєте void, щоб вказати, що функція не повертає значення або не має жодних параметрів або обох. Це набагато відповідає типовому використанню слова void в англійській мові.
Пустоту не слід плутати з null. Null означає для змінної, адреса якої знаходиться у стеці, значення на купі для цієї адреси порожнє.
Пустота використовується лише в підписах методів. Для типів повернення це означає, що метод нічого не поверне в код виклику. Для параметрів це означає, що параметри методу не передаються
напр
void MethodThatReturnsAndTakesVoid(void)
{
// Method body
}
У C # ми можемо опустити порожнечу для параметрів і можемо записати наведений вище код у вигляді:
void MethodThatReturnsAndTakesVoid()
{
// Method body
}
Пустоту не слід плутати з null. Null означає для змінної, адреса якої знаходиться у стеці, значення на купі для цієї адреси порожнє.
void означає, що ви не повернете жодне значення функції чи методу
Пустота означає, що значення, яке не потрібно, повертається від функції на всіх трьох мовах.