Переменная типа void. Смотреть что такое "void" в других словарях

В уроке 1 вы создали несколько программ на C++. В то время ваша цель заключалась в том, чтобы понять процесс создания и компиляции программ на C++, а не в том, чтобы понять операторы C++. В данном уроке вы впервые более внимательно рассмотрите операторы, из которых состоит программа на C++. Вы увидите, что большинство программ на C++ придерживаются одного и того же формата: начинаются с одного или нескольких операторов # include, содержат строку void main(void), а затем набор операторов, сгруппированных между левой и правой фигурными скобками. Из этого урока вы поймете, что эти несколько запугивающие операторы реально очень просто освоить. К концу данного урока вы изучите следующие основные концепции:

  • Оператор # include обеспечивает преимущества использования заголовочных файлов, которые содержат операторы C++ или программные определения.
  • Основная часть программы на C++ начинается с оператора void main(void).
  • Программы состоят из одной или нескольких функций, которые, в свою очередь, состоят из операторов, предназначенных для решения определенной задачи.
  • При выводе на экран ваши программы будут широко использовать выходной поток cout.

Когда вы создаете программы на C++, вы реально работаете в терминахоператоров, но не инструкций. Позже вы изучите оператор присваивания, который присваивает значения переменным, оператор if , который позволяет программе принимать решения и т. д. А пока мы просто будем ссылаться на содержимое вашей программы, как на операторы программы.


ВЗГЛЯД НА ОПЕРАТОРЫ ПРОГРАММЫ

В уроке 1 вы создали на C++ программу FIRST.CPP, которая содержала следующие операторы:

#include

void main(void)

{
cout << «Учимся программировать на языке С++!»;
}

В данном случае программа содержит три оператора. Фигурные скобки (называемые группирующими символами) группируют связанные операторы:

#include

void main (void)

{
cout << «Учимся программировать << «на языке С++!»;
}

В следующем разделе каждый из операторов программы описывается более подробно.

ПРЕДСТАВЛЕНИЕ ОБ ОПЕРАТОРЕ #include

Каждая программа, представленная в уроке 1, начинается со следующего оператора # include:

#include

При создании программ на C++ вы получаете преимущества от использования операторов и определений, которые обеспечивает вам компилятор. При компиляции программы оператор # include заставляет компилятор включить содержимое заданного файла в начало вашей программы. В данном случае компилятор включит содержимое файлаiostream.h.

Файлы с расширением h, которые вы включаете в начало (или заголовок) вашей программы, называются заголовочными файлами. Если вы посмотрите на каталог, содержащий файлы вашего компилятора, то найдете подкаталог с именем INCLUDE, в котором находятся разные заголовочные файлы. Каждый заголовочный файл содержит определения, предоставляемые компилятором для различных операций. Например, существует заголовочный файл, который содержит определения для математических операций, другой заголовочный файл описывает файловые операции и т. д.

Заголовочные файлы представляют собой файлы в формате ASCII, следовательно, вы можете вывести их содержимое на экран или принтер. В данный момент не беспокойтесь о содержимом заголовочных файлов. Просто поймите, что оператор # include позволяет вам использовать эти файлы. Все программы на C++, созданные вами в процессе изучения этой книги, содержат операторы # include, которые вы должны применять в ваших программах.

Заголовочные файлы C++

Каждая создаваемая вами программа на C++ начинается с одного или нескольких операторов #include. Эти операторы указывают компилятору включить содержимое заданного файла (заголовочного файла) в вашу программу, как если бы программа содержала операторы, которые находятся во включаемом файле. Заголовочные файлы содержат определения, используемые компилятором для операций различных типов. Существуют заголовочные файлы, которые определяют операции В/В (ввода/вывода) C++, системные функции (например, функции, возвращающие текущие дату и время) и многое другое.

Заголовочные файлы, подобно программам на C++, представляют собой файлы в формате ASCII, содержимое которых вы можете просмотреть или напечатать. Чтобы лучше понять содержимое заголовочных файлов, найдите время для того, чтобы напечатать заголовочный файл IOSTREAM.H, содержимое которого вы будете использовать в каждой создаваемой вами программе на C++. Обычно заголовочный файл IOSTREAM.H расположен в подкаталоге с именем INCLUDE, который находится в каталоге, содержащем файлы компилятора C++. Используйте текстовый редактор, чтобы просмотреть и напечатать содержимое заголовочных файлов.

Замечание: Никогда не изменяйте содержимое заголовочных файлов. Это может привести к ошибкам компиляции в каждой создаваемой вами программе.

ЧТО ТАКОЕ void main(void)

При создании программы на C++ ваш исходный файл будет содержать множество операторов. Как вы поймете в процессе изучения, порядок, в котором операторы появляются в программе, не обязательно должен совпадать с порядком, в котором операторы будут выполняться при запуске программы. Каждая программа на C++ имеет один вход, с которого начинается выполнение программы, - главную программу. В программах на C++ оператор void main(void) указывает стартовую точку вашей программы.

По мере того как ваши программы становятся больше и сложнее, вы будете делить их на несколько небольших легко управляемых частей. При этом оператор void main(void) указывает начальные (или главные) операторы программы - часть программы, которая выполняется первой.

Представление о главной программе

Исходные файлы C++ могут содержать очень много операторов. При запуске программы оператор void main(void) определяет главную программу, содержащую первый выполняемый оператор. Ваши программы на C++ должны всегда включать один и только один оператор с именем main.

При рассмотрении больших программ на C++ ищите main, чтобы определить операторы, с которых начинается выполнение программы.

Использование void

Как только ваша программа становится более сложной, вы должны разделить ее на небольшие более легко управляемые части, называемыефункциями. Функция представляет собой простой набор операторов внутри программы, выполняющих определенную задачу. Например, при создании программы платежных документов, вы могли бы создать функцию с именем salary, вычисляющую оклад служащих. Аналогичным образом, если вы пишете математическую программу, вы могли бы создать функции с именами square_root или cube, которые возвращают результат определенных математических операций. Если ваша программа использует функцию, функция выполняет свою задачу и затем возвращает свой результат программе.

Каждая функция в вашей программе имеет уникальное имя. А каждая программа имеет по крайней мере одну функцию. Каждая программа из урока 1 имела только одну функцию с именем main. Урок 9 предоставляет более подробный обзор функций. В данный момент просто имейте в виду, что функция состоит из нескольких связанных по смыслу операторов, выполняющих определенную задачу.

При исследовании различных программ на C++ вы будете постоянно сталкиваться со словом void. Программы используют слово void для указания того, что функция не возвращает значения или не имеет значений, передаваемых в нее. Например, если вы используете среду MS-DOS или UNIX, программа может завершить свое выполнение с возвратом операционной системе значения статуса, которое может быть проверено командным файлом. Командные файлы MS-DOS проверяют выходной статус программы, используя команду IF ERRORLEVEL. Например, предположим, что программа с именем PAYROLL. EXE завершается с одним из следующих выходных значений статуса в зависимости от результата обработки:

Внутри командного файла MS-DOS вы можете проверить результат работы программы, используя команду IF ERRORLEVEL:

PAYROLL

IF ERRORLEVEL 0 IF NOT ERRORLEVEL 1 GOTO SUCCESSFUL
IF ERRORLEVEL 1 IF NOT ERRORLEVEL 2 GOTO NO_FILE
IF ERRORLEVEL 2 IF NOT ERRORLEVEL 3 GOTO NO_PAPER
REM Далее идут другие команды

Большинство простых программ на C++, которые будут созданы вами в процессе изучения этой книги, не возвращают выходное значение статуса операционной системе. Поэтому вы должны размещать слово void передmain, как показано ниже:

void main (void) //- ——-> Программа не возвращает значение

В следующих уроках вы узнаете, что ваши программы могут использовать информацию (например, имя файла), которую пользователь указывает в командной строке при запуске программы. Если программа не использует информацию командной строки, вы должны разместить слово void внутри круглых скобок после main, как показано ниже:

void main (void ) //———————-> Программа не использует аргументы командной строки

По мере усложнения ваши программы могут возвращать значения в операционную систему или использовать параметры командной строки. Однако в настоящий момент просто используйте void в операторе с main, как показано в этой программе.

ПРЕДСТАВЛЕНИЕ О ГРУППИРУЮЩИХ ОПЕРАТОРАХ { }

По мере усложнения в ваших программах будет один набор операторов, которые компьютер должен выполнить определенное число раз, и другой набор операторов, которые компьютер должен выполнить, если выполняется определенное условие. В первом случае компьютер может выполнить один и тот же набор операторов 100 раз, чтобы добавить для 100 студентов тестовые очки. Во втором случае компьютер может вывести на экран одно сообщение, если все студенты прошли тест, и другое сообщение, если один или несколько студентов потерпели неудачу. Внутри своих программ на C++ вы будете использовать правую и левую фигурные скобки {}, чтобы сгруппировать связанные операторы. В простых программах, представленных в нескольких первых уроках книги, эти символы группируют операторы, которые соответствуют операторам вашей главной программы.

ИСПОЛЬЗОВАНИЕ cout ДЛЯ ОТОБРАЖЕНИЯ ВЫВОДА НА ЭКРАН

Все программы на C++, созданные вами в уроке 1, выводили сообщения на экран. Чтобы вывести сообщение, программы использовали cout и двойной знак «меньше» (<<), как показано ниже:

cout << «Привет, C++!»;

Слово cout представляет собой выходной поток, который C++ назначает на стандартное устройство вывода операционной системы. По умолчанию операционная система назначает стандартное устройство вывода на экран дисплея. Чтобы вывести сообщение на экран, вы просто используете двойной символ «меньше» (называемый оператором вставки) с выходным потоком cout. Из урока 3 вы узнаете, что можно использовать оператор вставки для передачи символов, чисел и других знаков на экран.

Представление о выходном потоке cout

Вы уже знаете, что программы на C++ используют выходной поток cout для вывода сообщений на экран. При использовании cout для вывода сообщений представляйте cout в виде потока символов, которые операционная система отображает на экране. Другими словами, порядок, в котором ваша программа посылает символы в cout, определяет порядок символов, которые будут появляться на экране. Например, для следующих операторов программы:

cout << «Это сообщение появляется первым,»;
cout << » а за ним следует настоящее сообщение.»;

Операционная система выводит поток символов следующим образом:

Это сообщение появляется первым, а за ним следует настоящее сообщение.

Оператор вставки (<<) называется так, потому что позволяет вашей программе вставлять символы в выходной поток.

Вы уже знаете, что выходной поток cout по умолчанию соответствует вашему экрану. Другими словами, когда ваши программы посылают вывод в cout, вывод появляется на экране. Однако, используя операторы переназначения вывода операционной системы, вы можете послать вывод программы на принтер или в файл. Например, следующая команда предписывает MS-DOS направить вывод программы FIRST.EXE на принтер, а не на экран:

С:\> FIRST > PRN

Как вы узнаете из Урока 3, с помощью cout в C++ можно выводить символы, целые числа, например 1001, и числа с плавающей точкой, например 3.12345. Из Урока 8 вы узнаете, что в C++ существует также входной поток с именем cin, который ваши программы могут использовать для чтения информации, вводимой с клавиатуры.

ЧТО ВЫ ДОЛЖНЫ ЗНАТЬ

В этом уроке обсуждались некоторые общие вопросы, с которыми вы столкнетесь в программах на C++. Из Урока 3 вы узнаете, как использовать cout для вывода символов, целых чисел и значений с плавающей точкой. Вы также узнаете, как форматировать вывод. До изучения урока 3 убедитесь, что вы освоили следующие основные концепции:

  1. Большинство программ на C++ начинаются с оператора #include, который предписывает компилятору включить содержимое заданного заголовочного файла в программу.
  2. Заголовочные файлы содержат определения, предоставляемые компилятором, которые ваши программы могут использовать.
  3. Исходный файл может состоять из множества операторов; оператор void main(void) указывает начало главной программы, которая содержит первый выполняемый оператор программы.
  4. По мере того как ваша программа становится более сложной, вы будете группировать связанные операторы в небольшие легко управляемые части, называемые функциями. Группируйте операторы программы с помощью правой и левой фигурных скобок {}.
  5. Большинство программ на C++ используют выходной потокcout для вывода информации на экран; однако, используя операторы переназначения В/В операционной системы, вы можете перенаправить вывод cout в файл, устройство (например, принтер) или даже сделать его входом другой программы.

В 1989г. В рамках языка Си++ void был стандартизован в 1998г.

Впоследствии ключевое слово void и связанные с ним языковые конструкции были унаследованы языками Java и C#, D.

Синтаксис

Синтаксически, void является одним из спецификаторов типа, входящих в более общую группу спецификаторов объявления, но в некоторых языках программирования реализован в виде оператора. Например, в языке JavaScript void является оператором и всегда возвращает undefined:

Void expression === undefined ;

Семантика

Семантика ключевого слова void не подчиняется общей семантике спецификаторов типа и зависит от способа употребления:

  • В качестве имени типа значения, возвращаемого функцией: указывает на то, что функция не возвращает значения, а вызов такой функции является void-выражением. Тело такой функции не должно содержать операторов return с выражениями. Например:

    Void f() ;

  • В составе декларатора функции: указывает на то, что функция имеет прототип и не имеет параметров. Например:

    Int f(void ) ;

  • В качестве имени целевого типа операции приведения: такое void-приведение означает отказ от значения приводимого выражения. Например:

    #define promote_ptr() ((void) (ptr++))

  • В составе имени типа void-указателя: такой указатель способен представлять значения любых указателей на объектные и неполные типы, т.е. адреса любых объектов . Таким образом, void -указатель является обобщенным объектным указателем. void -указатели не способны представлять значения указателей на функции. За исключением случая приведения константного null-указателя к указателю на функцию в Си, явных и неявных преобразований между void -указателями и указателями на функции нет.

Тип void определен как неполный тип, который не может быть дополнен. Как следствие, этот тип не должен быть использован там, где допускаются только полные типы, например, в качестве типа параметра в определении функции.

Язык Си до введения void

До публикации первого стандарта Си в 1989г., которая ввела в язык ключевое слово void общепринятой практикой было объявлять функции, не возвращающие значений без использования спецификаторов типов. Хотя семантически такое объявление было эквивалентно объявлению функции, возвращающей значение типа int , намеренно опущенные спецификаторы типа подчеркивали, что функция не возвращает никакого определенного значения. Например:

F(long l) { /* ... */ }

Схожим образом, определения функций, не имеющие параметров записывались с пустыми круглыми скобками:

Int main() { /* ... */ }

В качестве обобщенного указателя использовался указатель на char. Более того, современные стандарты требуют, чтобы представление и требования по выравниванию для void -указателей были теми же, что для указателей на char , что означает взаимозаменяемость этих типов.

Первый стандартный диалект Си (C89), хотя уже позволял записи с ключевым словом void , все же допускал такое использование неявного int в целях поддержки совместимости с существующим кодом. Современный диалект Си (C99) не допускает отсутствия спецификаторов типов в именах типов и объявлениях.

Примеры

Показаны примеры объявления функции, возвращающей void.

C++

Void message()

Java

Void message()

C#

Void message()

C

Void message(void )

Objective-C

- (void ) message;

D

Void message()

ActionScript

Function message () : void

Примечания


Wikimedia Foundation . 2010 .

Для чего нужны функции в C?

Функции в Си применяются для выполнения определённых действий в рамках общей программы. Программист сам решает какие именно действия вывести в функции. Особенно удобно применять функции для многократно повторяющихся действий.

Простой пример функции в Cи

Пример функции в Cи:

#include #include int main(void) { puts("Functions in C"); return EXIT_SUCCESS; }

Это очень простая программа на Си. Она просто выводит строку «Functions in C». В программе имеется единственная функция под названием main. Рассмотрим эту функцию подробно. В заголовке функции, т.е. в строке

int – это тип возвращаемого функцией значения;

main - это имя функции;

(void) - это перечень аргументов функции. Слово void указывает, что у данной функции нет аргументов;

return – это оператор, который завершает выполнение функции и возвращает результат работы функции в точку вызова этой функции;

EXIT_SUCCESS - это значение, равное нулю. Оно определено в файле stdlib.h;

часть функции после заголовка, заключенная в фигурные скобки

{
puts("Functions in C");
return EXIT_SUCCESS;
}

называют телом функции.

Итак, когда мы работаем с функцией надо указать имя функции, у нас это main, тип возвращаемого функцией значения, у нас это int, дать перечень аргументов в круглых скобках после имени функции, у нас нет аргументов, поэтому пишем void, в теле функции выполнить какие-то действия (ради них и создавалась функция) и вернуть результат работы функции оператором return. Вот основное, что нужно знать про функции в C.

Как из одной функции в Cи вызвать другую функцию?

Рассмотрим пример вызова функций в Си:

/* Author: @author Subbotin B.P..h> #include int main(void) { puts("Functions in C"); int d = 1; int e = 2; int f = sum(d, e); printf("1 + 2 = %d", f); return EXIT_SUCCESS; }

Запускаем на выполнение и получаем:

В этом примере создана функция sum, которая складывает два целых числа и возвращает результат. Разберём подробно устройство этой функции.

Заголовок функции sum:

int sum(int a, int b)

здесь int - это тип возвращаемого функцией значения;

sum - это имя функции;

(int a, int b) - в круглых скобках после имени функции дан перечень её аргументов: первый аргумент int a, второй аргумент int b. Имена аргументов являются формальными, т.е. при вызове функции мы не обязаны отправлять в эту функцию в качестве аргументов значения перемнных с именами a и b. В функции main мы вызываем функцию sum так: sum(d, e);. Но важно, чтоб переданные в функцию аргументы совпадали по типу с объявленными в функции.

В теле функции sum, т.е. внутри фигурных скобок после заголовка функции, мы создаем локальную переменную int c, присваиваем ей значение суммы a плюс b и возвращаем её в качестве результата работы функции опрератором return.

Теперь посмотрим как функция sum вызывается из функции main.

Вот функция main:

Int main(void) { puts("Functions in C"); int d = 1; int e = 2; int f = sum(d, e); printf("1 + 2 = %d", f); return EXIT_SUCCESS; }

Сначала мы создаём две переменных типа int

Int d = 1; int e = 2;

их мы передадим в функцию sum в качестве значений аргументов.

int f = sum(d, e);

её значением будет результат работы функции sum, т.е. мы вызываем функцию sum, которая возвратит значение типа int, его-то мы и присваиваем переменной f. В качестве аргументов передаём d и f. Но в заголовке функции sum

int sum(int a, int b)

аргументы называются a и b, почему тогда мы передаем d и f? Потому что в заголовке функций пишут формальные аргументы, т.е. НЕ важны названия аргументов, а важны их типы. У функции sum оба аргумента имеют тип int, значит при вызове этой функции надо передать два аргумента типа int с любыми названиями.

Ещё одна тонкость. Функция должна быть объявлена до места её первого вызова. В нашем примере так и было: сначала объявлена функция sum, а уж после мы вызываем её из функции main. Если функция объявляется после места её вызова, то следует использовать прототип функции.

Прототип функции в Си

Рассмотрим пример функциив Си:

/* Author: @author Subbotin B.P..h> #include int sum(int a, int b); int main(void) { puts("Functions in C"); int d = 1; int e = 2; int f = sum(d, e); printf("1 + 2 = %d", f); return EXIT_SUCCESS; } int sum(int a, int b) { int c = 0; c = a + b; return c; }

В этом примере функция sum определена ниже места её вызова в функции main. В таком случае надо использовать прототип функции sum. Прототип у нас объявлен выше функции main:

int sum(int a, int b);

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

int f = sum(d, e);

а ниже функции main определяем функцию sum, которая предварительно была объявлена в прототипе:

Int sum(int a, int b) { int c = 0; c = a + b; return c; }

Чем объявление функции в Си отличается от определения функции в Си?

Когда мы пишем прототип функции, например так:

int sum(int a, int b);

то мы объявляем функцию.

А когда мы реализуем функцию, т.е. записываем не только заголовок, но и тело функции, например:

Int sum(int a, int b) { int c = 0; c = a + b; return c; }

то мы определяем функцию.

Оператор return

Оператор return завершает работу функции в C и возвращает результат её работы в точку вызова. Пример:

Int sum(int a, int b) { int c = 0; c = a + b; return c; }

Эту функцию можно упростить:

Int sum(int a, int b) { return a + b; }

здесь оператор return вернёт значение суммы a + b.

Операторов return в одной функции может быть несколько. Пример:

Int sum(int a, int b) { if(a > 2) { return 0;// Первый случай; } if(b < 0) { return 0;// Второй случай; } return a + b; }

Если в примере значение аргумента a окажется больше двух, то функция вернет ноль (первый случай) и всё, что ниже комментария «// Первый случай;» выполнятся не будет. Если a будет меньше двух, но b будет меньше нуля, то функция завершит свою работу и всё, что ниже комментария «// Второй случай;» выполнятся не будет.

И только если оба предыдущих условия не выполняются, то выполнение программы дойдёт до последнего оператора return и будет возвращена сумма a + b.

Передача аргументов функции по значению

Аргументы можно передавать в функцию C по значению. Пример:

/* Author: @author Subbotin B.P..h> #include int sum(int a) { return a += 5; } int main(void) { puts("Functions in C"); int d = 10; printf("sum = %d\n", sum(d)); printf("d = %d", d); return EXIT_SUCCESS; }

В примере, в функции main, создаём переменную int d = 10. Передаём по значению эту переменную в функцию sum(d). Внутри функции sum значение переменной увеличивается на 5. Но в функции main значение d не изменится, ведь она была передана по значению. Это означает, что было передано значение переменной, а не сама переменная. Об этом говорит и результат работы программы:

т.е. после возврата из функции sum значеие d не изменилось, тогда как внутри функции sum оно менялось.

Передача указателей функции Си

Если в качестве аргумента функции передавать вместо значения переменной указатель на эту переменную, то значение этой переменной может меняться. Для примера берём программу из предыдущего раздела, несколько изменив её:

/* Author: @author Subbotin B.P..h> #include int sum(int *a) { return *a += 5; } int main(void) { puts("Functions in C"); int d = 10; printf("sum = %d\n", sum(&d)); printf("d = %d", d); return EXIT_SUCCESS; }

В этом варианте программы я перешел от передачи аргумента по значению к передаче указателя на переменную. Рассмотрим подробнее этот момент.

printf("sum = %d\n", sum(&d));

в функцию sum передается не значение переменной d, равное 10-ти, а адрес этой переменной, вот так:

Теперь посмотрим на функцию sum:

Int sum(int *a) { return *a += 5; }

Аргументом её является указатель на int. Мы знаем, что указатель - это переменная, значением которой является адрес какого-то объекта. Адрес переменной d отправляем в функцию sum:

Внутри sum указатель int *a разыменовывается. Это позволяет от указателя перейти к самой переменной, на которую и указывает наш указатель. А в нашем случае это переменная d, т.е. выражение

равносильно выражению

Результат: функция sum изменяет значение переменной d:

На этот раз изменяется значение d после возврата из sum, чего не наблюдалось в предыдущм пункте, когда мы передавали аргумент по значению.

C/C++ в Eclipse

Все примеры для этой статьи я сделал в Eclipse. Как работать с C/C++ в Eclipse можно посмотреть . Если вы работаете в другой среде, то примеры и там будут работать.

Среди современных языков программирования ключевое слово void впервые появилось в Си++ для поддержки концепции обобщенных указателей . Тем не менее, благодаря скорому заимствованию у Си++, первым нормативным документом, содержащим это ключевое слово, стал стандарт языка Си, опубликованный ANSI в 1989 г. В рамках языка Си++ void был стандартизован в 1998 г.

Впоследствии ключевое слово void и связанные с ним языковые конструкции были унаследованы языками Java и C#, D.

Синтаксис

Синтаксически, void является одним из спецификаторов типа, входящих в более общую группу спецификаторов объявления , но в некоторых языках программирования реализован в виде оператора. Например, в языке JavaScript void является оператором и всегда возвращает undefined:

void expression === undefined;

Семантика

Семантика ключевого слова void не подчиняется общей семантике спецификаторов типа и зависит от способа употребления:

  • В качестве имени типа значения, возвращаемого функцией: указывает на то, что функция не возвращает значения, а вызов такой функции является void-выражением . Тело такой функции не должно содержать операторов return с выражениями. Например:

    Язык Си до введения void

    До публикации первого стандарта Си в 1989 г., которая ввела в язык ключевое слово void общепринятой практикой было объявлять функции, не возвращающие значений без использования спецификаторов типов. Хотя семантически такое объявление было эквивалентно объявлению функции, возвращающей значение типа int , намеренно опущенные спецификаторы типа подчеркивали, что функция не возвращает никакого определенного значения. Например:

    f(long l) { /* ... */ }

    Схожим образом, определения функций, не имеющие параметров записывались с пустыми круглыми скобками:

    int main() { /* ... */ }

    В качестве обобщенного указателя использовался указатель на char . Более того, современные стандарты требуют, чтобы представление и требования по выравниванию для void -указателей были теми же, что для указателей на char , что означает взаимозаменяемость этих типов.

    Первый стандартный диалект Си (C89), хотя уже позволял записи с ключевым словом void , все же допускал такое использование неявного int в целях поддержки совместимости с существующим кодом. Современный диалект Си (C99) не допускает отсутствия спецификаторов типов в именах типов и объявлениях.

    Примеры

    Показаны примеры объявления функции, возвращающей void.

    C++

    Java

    C#

    C

    void message(void)

    Objective-C

    -(void) message;

    D

    ActionScript

    function message() : void

    Напишите отзыв о статье "Void"

    Примечания

    Отрывок, характеризующий Void

    – Я не знаю, как отвечать на ваш вопрос, – сказал он, покраснев, сам не зная от чего. – Я решительно не знаю, что это за девушка; я никак не могу анализировать ее. Она обворожительна. А отчего, я не знаю: вот всё, что можно про нее сказать. – Княжна Марья вздохнула и выражение ее лица сказало: «Да, я этого ожидала и боялась».
    – Умна она? – спросила княжна Марья. Пьер задумался.
    – Я думаю нет, – сказал он, – а впрочем да. Она не удостоивает быть умной… Да нет, она обворожительна, и больше ничего. – Княжна Марья опять неодобрительно покачала головой.
    – Ах, я так желаю любить ее! Вы ей это скажите, ежели увидите ее прежде меня.
    – Я слышал, что они на днях будут, – сказал Пьер.
    Княжна Марья сообщила Пьеру свой план о том, как она, только что приедут Ростовы, сблизится с будущей невесткой и постарается приучить к ней старого князя.

    Женитьба на богатой невесте в Петербурге не удалась Борису и он с этой же целью приехал в Москву. В Москве Борис находился в нерешительности между двумя самыми богатыми невестами – Жюли и княжной Марьей. Хотя княжна Марья, несмотря на свою некрасивость, и казалась ему привлекательнее Жюли, ему почему то неловко было ухаживать за Болконской. В последнее свое свиданье с ней, в именины старого князя, на все его попытки заговорить с ней о чувствах, она отвечала ему невпопад и очевидно не слушала его.
    Жюли, напротив, хотя и особенным, одной ей свойственным способом, но охотно принимала его ухаживанье.
    Жюли было 27 лет. После смерти своих братьев, она стала очень богата. Она была теперь совершенно некрасива; но думала, что она не только так же хороша, но еще гораздо больше привлекательна, чем была прежде. В этом заблуждении поддерживало ее то, что во первых она стала очень богатой невестой, а во вторых то, что чем старее она становилась, тем она была безопаснее для мужчин, тем свободнее было мужчинам обращаться с нею и, не принимая на себя никаких обязательств, пользоваться ее ужинами, вечерами и оживленным обществом, собиравшимся у нее. Мужчина, который десять лет назад побоялся бы ездить каждый день в дом, где была 17 ти летняя барышня, чтобы не компрометировать ее и не связать себя, теперь ездил к ней смело каждый день и обращался с ней не как с барышней невестой, а как с знакомой, не имеющей пола.
    Дом Карагиных был в эту зиму в Москве самым приятным и гостеприимным домом. Кроме званых вечеров и обедов, каждый день у Карагиных собиралось большое общество, в особенности мужчин, ужинающих в 12 м часу ночи и засиживающихся до 3 го часу. Не было бала, гулянья, театра, который бы пропускала Жюли. Туалеты ее были всегда самые модные. Но, несмотря на это, Жюли казалась разочарована во всем, говорила всякому, что она не верит ни в дружбу, ни в любовь, ни в какие радости жизни, и ожидает успокоения только там. Она усвоила себе тон девушки, понесшей великое разочарованье, девушки, как будто потерявшей любимого человека или жестоко обманутой им. Хотя ничего подобного с ней не случилось, на нее смотрели, как на такую, и сама она даже верила, что она много пострадала в жизни. Эта меланхолия, не мешавшая ей веселиться, не мешала бывавшим у нее молодым людям приятно проводить время. Каждый гость, приезжая к ним, отдавал свой долг меланхолическому настроению хозяйки и потом занимался и светскими разговорами, и танцами, и умственными играми, и турнирами буриме, которые были в моде у Карагиных. Только некоторые молодые люди, в числе которых был и Борис, более углублялись в меланхолическое настроение Жюли, и с этими молодыми людьми она имела более продолжительные и уединенные разговоры о тщете всего мирского, и им открывала свои альбомы, исписанные грустными изображениями, изречениями и стихами.
    Жюли была особенно ласкова к Борису: жалела о его раннем разочаровании в жизни, предлагала ему те утешения дружбы, которые она могла предложить, сама так много пострадав в жизни, и открыла ему свой альбом. Борис нарисовал ей в альбом два дерева и написал: Arbres rustiques, vos sombres rameaux secouent sur moi les tenebres et la melancolie. [Сельские деревья, ваши темные сучья стряхивают на меня мрак и меланхолию.]
    В другом месте он нарисовал гробницу и написал:
    «La mort est secourable et la mort est tranquille
    «Ah! contre les douleurs il n"y a pas d"autre asile».
    [Смерть спасительна и смерть спокойна;
    О! против страданий нет другого убежища.]
    Жюли сказала, что это прелестно.
    – II y a quelque chose de si ravissant dans le sourire de la melancolie, [Есть что то бесконечно обворожительное в улыбке меланхолии,] – сказала она Борису слово в слово выписанное это место из книги.

Теги: void*, пустые указатели, неопределённые указатели.

Указатели типа void

В си существует особый тип указателей – указатели типа void или пустые указатели. Эти указатели используются в том случае, когда тип переменной не известен. Так как void не имеет типа, то к нему не применима операция разадресации (взятие содержимого) и адресная арифметика, так как неизвестно представление данных. Тем не менее, если мы работаем с указателем типа void, то нам доступны операции сравнения.

Если необходимо работать с пустым указателем, то сначала нужно явно привести тип. Например

#include #include int main() { void *p = NULL; int intVar = 10; char charVar = "A"; float floatVar = 24.3; float *floatPtr = NULL; p = &intVar; *((int*) p) = 20; printf("intVar = %d\n", intVar); p = &charVar; printf("charVar = %c\n", *((char*) p)); p = &floatVar; floatPtr = (float*) p; printf("floatVar = %.3f", *floatPtr); getch(); }

Переменная не может иметь типа void, этот тип определён только для указателей. Пустые указатели нашли широкое применение при вызове функций. Можно написать функцию общего назначения, которая будет работать с любым типом. Например, напишем функцию swap, которая обменивает местами содержимое двух переменных. У этой функции будет три аргумента – указатели на переменные, которые необходимо обменять местами и их размер.

#include #include #include #include void swap(void *a, void *b, size_t size) { char* tmp; //создаём временную переменную для обмена tmp = (char*) malloc(size); memcpy(tmp, a, size); memcpy(a, b, size); memcpy(b, tmp, size); free(tmp); } int main() { float a = 10.f; float b = 20.f; double c = 555; double d = 777; unsigned long e = 2ll; unsigned long f = 3ll; printf("a = %.3f, b = %.3f\n", a, b); swap(&a, &b, sizeof(float)); printf("a = %.3f, b = %.3f\n", a, b); printf("c = %.3f, d = %.3f\n", c, d); swap(&c, &d, sizeof(double)); printf("c = %.3f, d = %.3f\n", c, d); printf("e = %ld, f = %ld \n", e, f); swap(&e, &f, sizeof(unsigned long)); printf("e = %ld, f = %ld \n", e, f); getch(); }

Наша функция может выглядеть и по-другому. Обойдёмся без дорогостоящего выделения памяти и будем копировать побайтно.

Void swap(void *a, void *b, size_t size) { char tmp; size_t i; for (i = 0; i < size; i++) { tmp = *((char*) b + i); *((char*) b + i) = *((char*) a + i); *((char*) a + i) = tmp; } }

Пустые указатели позволяют создавать функции, которые возвращают и принимают одинаковые параметры, но имеют разное название. Это пригодится в дальнейшем, при изучении указателей на функции. Например

Int cmpInt(void* a, void* b) { return *((int*) a) - *((int*) b); } int cmpString(void *a, void* b) { return strcmp((char*) a, (char*) b); } int cmpFloat(void* a, void* b) { float fdiff = *((float*) a) - *((float*) b); if (fabs(fdiff) < 0.000001f) { return 0; } if (fdiff < 0) { return -1; } else { return 1; } }

Ru-Cyrl 18- tutorial Sypachev S.S. 1989-04-14 [email protected] Stepan Sypachev students

Всё ещё не понятно? – пиши вопросы на ящик