Открыть Электронные книги
Категории
Открыть Аудиокниги
Категории
Открыть Журналы
Категории
Открыть Документы
Категории
Документация по языку C
Справочник по языку C
Справочник по языку C
Организация справочника по языку C
Организация справочника по языку C
Содержание данного руководства
Соответствие ANSI
Элементы языка C
Элементы языка C
Токены C
Токены C
Пробелы
Комментарии в C
Оценка токенов
Ключевые слова в C
Идентификаторы C
Идентификаторы C
Многобайтовая кодировка и расширенные символы
Триграфы
Константы в C
Константы в C
Константы с плавающей запятой в C
Константы с плавающей запятой в C
Ограничения на константы с плавающей запятой
Целочисленные константы в C
Целочисленные константы в C
Целочисленные типы
Пределы целых чисел в C и C++
Символьные константы в C
Символьные константы в C
Символьные типы
Кодировка исполнения
Escape-последовательности
Спецификации восьмеричных и шестнадцатеричных символов
Строковые литералы в C
Строковые литералы в C
Тип для строковых литералов
Хранение строковых литералов
Объединение строковых литералов
Максимальная длина строки
Знаки препинания и специальные символы
Структура программы
Структура программы
Исходные файлы и исходные программы
Файлы с исходным кодом и исходные программы
Директивы препроцессору
Прагмы C
Объявления и определения в C
Объявления и определения функций
Blocks
Пример программы
Функция main и выполнение программ
Функция main и выполнение программ
Использование wmain
Описание аргумента
Расширение аргументов-заполнителей
Анализ аргументов командной строки C
Настройка обработки командной строки C
Время жизни, область, видимость и компоновка
Время жизни, область, видимость и компоновка
Время существования
Область и видимость
Сводка времени существования и видимости
Компоновка
Компоновка
Внутренняя компоновка
Внешняя компоновка
Без компоновки
Пространства имен
Объявления и типы
Объявления и типы
Общие сведения об объявлениях
Классы хранения в C
C - классы хранения
Описатели классов хранения для объявлений внешнего уровня
Описатели классов хранения для объявлений внутреннего уровня
Описатели классов хранения для объявлений внутреннего уровня
Описатель класса хранения auto
Описатель класса хранения register
Описатель класса хранения static
Описатель класса хранения extern
Описатели классов хранения с объявлениями функций
Описатели типов C
Описатели типов C
Описатели и эквиваленты типов данных
Описатели типов
Деклараторы и объявления переменных
Деклараторы и объявления переменных
Простые объявления переменных
Объявления перечислений C
Объявления структур
Объявления структур
Битовые поля в C
Хранение и выравнивание структур
Объявления объединений
Объявления объединений
Хранение объединений
Объявления массивов
Объявления массивов
Хранение массивов
Объявления указателей
Объявления указателей
Хранение адресов
Основанные указатели (C)
Абстрактные деклараторы в C
Интерпретация сложных деклараторов
Инициализация
Инициализация
Инициализация скалярных типов
Инициализация агрегатных типов
Инициализация строк
Хранение базовых типов
Хранилище базовых типов
Тип char
Тип int
Целочисленные типы размеров C
Тип float
Тип double
Тип long double
Неполные типы
Объявления Typedef
Расширенные атрибуты классов хранения в C
Расширенные атрибуты классов хранения в C
Импорт и экспорт DLL
Naked (C)
Локальное хранилище потока
Выражения и присваивания
Выражения и присваивания
Операнды и выражения
Операнды и выражения
Первичные выражения в C
Первичные выражения в C
Идентификаторы в первичных выражениях
Константы в первичных выражениях
Строковые литералы в первичных выражениях
Выражения в скобках
Выражения L-Value и R-Value
Постоянные выражения C
Вычисление выражений (C)
Вычисление выражений (C)
Побочные эффекты
Точки следования в C
Операторы в C
Операторы в C
Приоритет и порядок оценки
Обычные арифметические преобразования
Постфиксные операторы
Постфиксные операторы
Одномерные массивы
Многомерные массивы (C)
Вызов функции (C)
Члены структур и объединений
Постфиксные операторы увеличения и уменьшения в C
Унарные операторы C
Унарные операторы C
Префиксные операторы инкремента и декремента
Операторы косвенного обращения и взятия адреса
Унарные арифметические операторы
Оператор sizeof (C)
Операторы приведения
Операторы умножения в C
Операторы сложения в C
Операторы сложения в C
Сложение (+)
Вычитание (-)
Использование операторов сложения
Расчеты указателей
Операторы побитового сдвига
Операторы отношения и равенства в C
Побитовые операторы в C
Логические операторы в C
Оператор Conditional-Expression
Операторы присваивания C
Операторы присваивания C
Простое присваивание (C)
Составное присваивание в C
Оператор последовательного вычисления
Преобразования типов (C)
Преобразования типов (C)
Преобразования присваиваний
Преобразования присваиваний
Преобразования из целочисленных типов со знаком
Преобразования из целочисленных типов без знака
Преобразования типов с плавающей запятой
Преобразования в типы указателей и из типов указателей
Преобразования из других типов
Преобразования приведений типов
Преобразования вызова функции
Операторы (C)
Операторы (C)
Операторы (C)
Общие сведения об операторах в C
Оператор break (C)
Составной оператор (C)
Оператор continue (C)
Оператор do-while (C)
Оператор выражений (C)
Оператор for (C)
goto и помеченные операторы (C)
Оператор if (C)
Оператор NULL (C)
Оператор return (C)
Оператор switch (C)
Оператор try-except (C)
Оператор try-finally (C)
Оператор while (C)
Функции (C)
Функции (C)
Общие сведения о функциях
Общие сведения о функциях
Устаревшие формы объявлений и определений функций
Определения функций в C
Определения функций в C
Атрибуты функций
Атрибуты функций
Указание соглашений о вызовах
Встраиваемые функции
Встроенный ассемблер (C)
Функции импорта и экспорта DLL
Функции импорта и экспорта DLL
Определения и объявления (C)
Определение встраиваемых функций C с помощью dllexport и dllimport
Правила и ограничения dllimport и dllexport
Функции с атрибутом naked
Функции с атрибутом naked
Правила и ограничения при использовании функций с атрибутом naked
Вопросы, связанные с написанием кода пролога и эпилога
Класс хранения
Возвращаемый тип
Параметры
Тело функции
Прототипы функций
Вызовы функций
Вызовы функций
Аргументы
Вызовы с переменным количеством аргументов
Рекурсивные функции
Краткие сведения о синтаксисе языка C
Краткие сведения о синтаксисе языка C
Определения и соглашения
Лексическая грамматика
Лексическая грамматика
Общие сведения о токенах
Общие сведения о ключевых словах
Общие сведения об идентификаторах
Общие сведения о константах
Общие сведения о строковых литералах
Операторы (C)
Символы пунктуации
Грамматика структуры фразы
Грамматика структуры фразы
Общие сведения о выражениях
Общие сведения об объявлениях
Общие сведения об операторах
Внешние определения
Поведение, определяемое реализацией
Поведение, определяемое реализацией
Перевод: Диагностика
Среда
Среда
Аргументы функции main
Интерактивные устройства
Поведение идентификаторов
Поведение идентификаторов
Значимые символы без внешней компоновки
Значимые символы с внешней компоновкой
Верхний и нижний регистр
Знаки
Знаки
Кодировка ASCII
Многобайтовые символы
Число битов на символ
Кодировки1
Непредставимые символьные константы
Расширенные символы
Преобразование многобайтовых символов
Диапазон значений типа char
Целые числа
Целые числа
Диапазон целочисленных значений
Понижение уровня целых чисел
Битовые операции со знаком
Остатки от деления
Сдвиги вправо
Вычисления с плавающей запятой
Вычисления с плавающей запятой
Значения
Приведение целочисленных значений к значениям с плавающей запятой
Усечение значений с плавающей запятой
Массивы и указатели
Массивы и указатели
Максимальный размер массива
Вычитание указателей
Регистры: Доступность регистров
Структуры, объединения, перечисления и битовые поля
Структуры, объединения, перечисления и битовые поля
Неправильный доступ к объединению
Заполнение и выравнивание членов структуры
Знак битовых полей
Хранение битовых полей
Тип перечисления
Квалификаторы: Доступ к временным объектам
Деклараторы: максимальное число
Операторы: Пределы операторов switch
Директивы предварительной обработки
Директивы предварительной обработки
Символьные константы и условное включение
Включение имен файлов в скобках
Включение имен файлов в кавычках
Последовательности символов
Директивы pragma
Дата и время по умолчанию
Функции библиотеки
Функции библиотеки
Макрос NULL
Диагностика, напечатанная функцией assert
Тестирование символов
Ошибки домена
Потеря точности значений с плавающей запятой
Функция fmod
Функция signal (C)
Сигналы по умолчанию
Завершающие символы новой строки
Пустые строки
Символы NULL
Позиция файла в режиме добавления
Усечение текстовых файлов
Буферизация файла
Файлы нулевой длины
Имена файлов
Ограничения доступа к файлам
Удаление открытых файлов
Переименование с использованием существующего имени
Чтение значений указателя
Диапазоны чтения
Ошибки положения файла
Сообщения, создаваемые функцией perror
Выделение обнуленной памяти
Функция abort (C)
Функция atexit (C)
Имена сред
Функция system
Функция strerror
Часовой пояс
Функция clock (C)
Справочник по препроцессору в C/C++
Справочник по библиотеке времени выполнения C (CRT)
Справочник по языку C
07.05.2020 • 2 minutes to read • Edit Online
См. также
Справочник по языку C++
Организация Справочника по языку C
07.05.2020 • 2 minutes to read • Edit Online
Элементы языка C
Структура программы
Объявления и типы
Выражения и присваивания
Операторы
Функции
См. также
Справочник по языку C
Содержание данного руководства
07.05.2020 • 2 minutes to read • Edit Online
C — гибкий язык, предоставляющий широкие возможности для программирования. При этом C накладывает
несколько ограничений на преобразование типов. Хотя возможности языка упрощают программирование,
для понимания того, как будут работать программы, необходимо хорошо знать язык. В данной книге
приведены сведения о компонентах языка C и возможностях реализации Microsoft. Синтаксис языка C
соответствует стандарту ANSI X3.159-1989, American National Standard for Information Systems -
Programming Language- C (Американский национальный стандарт для информационных систем — Язык
программирования — Язык C). Здесь и далее он называется стандартом ANSI C, хотя не является частью
этого стандарта. В статье Общие сведения о синтаксисе языка C рассмотрен синтаксис и описаны правила
чтения и использования определений синтаксиса.
Программирование на языке C++ в данной книге рассматривается. Сведения о языке C++ см. в справочнике
по языку C++.
См. также
Организация Справочника по языку C
Соответствие ANSI
07.05.2020 • 2 minutes to read • Edit Online
См. также
Организация Справочника по языку C
Элементы языка C
15.05.2020 • 2 minutes to read • Edit Online
В этом разделе описываются элементы языка программирования C, включая имена, числа и символы,
используемые в нем для составления программ. В синтаксисе ANSI C эти компоненты называются
токенами.
В этом разделе объясняется, как определять токены и как компилятор вычисляет их.
Лексемы
Комментарии
Ключевые слова
Идентификаторы
Константы
Строковые литералы
Операторы — это символы (представленные как одним знаком, так и комбинацией знаков), которые
указывают , каким образом должны обрабатываться значения. Каждый символ интерпретируется как
единый блок, который называется токеном. Дополнительные сведения см. в разделе Операторы.
См. также
Справочник по языку C
Токены C
07.05.2020 • 2 minutes to read • Edit Online
Базовым элементом программы на языке C, распознаваемым компилятором, является токен. Токен — это
такой фрагмент текста исходной программы. который компилятор не разбивает на составные элементы.
Синтаксис
token: keyword
identifier
constant
string-literal
operator
знак препинания
NOTE
Описание соглашений о синтаксисе ANSI вы найдете во введении к статье Общие сведения о синтаксисе языка C.
См. также
Элементы языка C
Пробелы
07.05.2020 • 2 minutes to read • Edit Online
Символы пробела, табуляции, перевода строки (новой строки), возврата каретки, перевода страницы и
вертикальной табуляции называются пробельными символами, поскольку они выполняют ту же функцию,
что и пробелы между словами и строками на печатной странице — они упрощают чтение. Токены
разделяются (разграничиваются) пробельными символами и другими токенами, например операторами и
символами пунктуации. При синтаксическом анализе кода компилятор C игнорирует пробельные
символы — кроме тех случаев, когда они используются как разделители или как компоненты символьных
констант или строковых литералов. Используйте пробельные символы, чтобы сделать программу более
удобочитаемой. Обратите внимание, что комментарии также обрабатываются компилятором как пробел.
См. также
Токены C
Комментарии в C
07.05.2020 • 3 minutes to read • Edit Online
Комментарий — это последовательность символов, которая начинается с косой черты и звездочки (/* ).
Компилятор воспринимает комментарий как один пробельный символ, в остальных случаях он
игнорируется. Комментарии могут включать любое сочетание символов из представимого набора
символов, который включает символы новой строки, но не включает разделитель конца комментария (*/ ).
Комментарии могут занимать несколько строк, но не могут быть вложенными.
Они могут располагаться в любом месте, где допускается использование пробельных символов. Поскольку
компилятор обрабатывает комментарий как один пробельный символ, его невозможно использовать в
составе токена. Символы, которые находятся в комментарии, компилятор игнорирует.
Перед функциями или программными модулями можно вставлять блоки комментариев с описаниями.
/* Open file */
fh = _open( "myfile.c", _O_RDONLY );
.
.
.
*/
Причина ошибки в том, что компилятор распознает первое сочетание символов, */ , расположенное после
слов Open file , как конец комментария. Он пытается обработать оставшийся текст , а обнаружив символы
*/ за пределами комментария, выдает сообщение об ошибке.
Хотя с помощью комментариев можно скрывать часть кода для тестирования, для этого есть полезная
альтернатива: директивы препроцессора #if и #endif и условная компиляция. Дополнительные сведения
см. в статье Preprocessor Directives (Директивы препроцессора) в справочника по препроцессору.
Комментарии, которые начинаются с двух косых черт ( // ), завершаются первым символом новой строки,
перед которым не стоит escape-символ. В следующем примере перед символом новой строки стоит
обратная косая черта ( \ ), которая создает escape-последовательность. В результате этого следующая
строка обрабатывается компилятором как часть текущей строки. Дополнительные сведения см. в статье
Escape Sequences (Escape-последовательности).
// my comment \
i++;
В Microsoft C расширения Microsoft по умолчанию включены. Отключить их можно при помощи параметра
/Za.
Завершение блока , относящегося только к системам Майкрософт
См. также
Токены C
Оценка токенов
07.05.2020 • 2 minutes to read • Edit Online
Когда компилятор интерпретирует токены, он включает в один токен максимально возможное количество
символов, а затем переходит к следующему. Поэтому если токены не разделены пробельными символами,
они могут интерпретироваться не так, как ожидается. Рассмотрим следующее выражение:
i+++j
Компилятор C обрабатывает символ CTRL+Z как индикатор конца файла. Весь текст , расположенный после
символа CTRL+Z, игнорируется.
См. также
Токены C
Ключевые слова в C
13.10.2020 • 4 minutes to read • Edit Online
Ключевыми словами называются слова, которые имеют особое значение для компилятора C. На 7 и 8 этапах
трансляции идентификатор не может иметь такое же написание и регистр записи, что и ключевое слово C.
Дополнительные сведения см. в разделе Этапы преобразования Справочника по препроцессору.
Дополнительные сведения об идентификаторах см. в этом разделе.
auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
inline 1, a
int
long
register
restrict 1, a
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
2, a
_Alignas 2, a
_Alignof 2, a
_Atomic 2, b
_Bool 1, a
_Complex 1, b
_Generic 2, a
_Imaginary 1, b
_Noreturn 2, a
_Static_assert 2, a
_Thread_local 2, b
__asm 5
dllimport 4
__int8 5
naked 4
__based 3, 5
__except 5
__int16 5
__stdcall 5
__cdecl 5
__fastcall
__int32 5
thread 4
__declspec 5
__finally 5
__int64 5
__try 5
dllexport 4
5
__inline 5
__leave 5
3 Ключевое слово __based имеет ограниченное применение: в компиляциях для 32- и 64-разрядных
платформ.
4 Если эти ключевые слова используются с ключевым словом __declspec , они являются особыми
идентификаторами. В других контекстах они могут использоваться без ограничений.
5 Для совместимости с предыдущими версиями эти ключевые слова доступны как с двумя символами
Расширения Microsoft по умолчанию включены. Чтобы помочь в создании переносимого кода, расширения
Microsoft можно отключить, указав во время компиляции параметр /Za (Отключить расширения языка) . При
этом некоторые ключевые слова для систем Microsoft будут отключены.
Когда расширения Microsoft включены, в программах можно использовать перечисленные выше ключевые
слова. Для совместимости со стандартами большинство этих ключевых слов начинаются с двух символов
подчеркивания. Четыре исключения, dllexport , dllimport , naked и thread , используются только с
ключевым словом __declspec и поэтому не требуют двойного знака подчеркивания. Для всех остальных
ключевых слов поддерживаются версии с одним символом подчеркивания. Это сделано для обеспечения
обратной совместимости.
См. также
Элементы языка C
Идентификаторы C
13.10.2020 • 6 minutes to read • Edit Online
"Идентификаторы" или "символы" — это имена, задаваемые в программе для переменных, типов, функций
и меток. Написание и регистр символов в именах идентификаторов должны отличаться от всех ключевых
слов. Не допускается использовать ключевые слова (C или Microsoft) в качестве идентификаторов; они
зарезервированы для специального применения. Идентификатор создается путем его указания в
объявлении переменной, типа или функции. В этом примере result представляет собой идентификатор
целой переменной, а main и printf — это имена идентификаторов для функций.
#include <stdio.h>
int main()
{
int result;
if ( result != 0 )
printf_s( "Bad file handle\n" );
}
Синтаксис
identifier:
nondigit
identifier nondigit
identifier digit
nondigit: один из следующих символов:
_ a b c d e f g h i j k l mn o p q r s t u v w x y z
A B C D E F G H I J K L MN O P Q R S T U V W X Y Z
digit: один из следующих символов:
0123456789
Первый символ имени идентификатора должен принадлежать к группе nondigit (т. е., первым символом
должен быть знак подчеркивания или прописная либо строчная буква). Стандарт ANSI допускает 6
значащих символов в имени внешнего идентификатора и 31 символ для имен внутренних (внутри
функции) идентификаторов. На имена внешних идентификаторов (идентификаторов, объявленных в
глобальной области или с классом хранения extern ) могут накладываться дополнительные ограничения,
поскольку эти идентификаторы должны обрабатываться другим программным обеспечением, таким как
компоновщики.
Хотя стандарт ANSI допускает 6 значащих символов в именах внешних идентификаторов и 31 символ в
именах внутренних (внутри функции) идентификаторов, компилятор Microsoft C допускает 247 символов в
именах внутренних и внешних идентификаторов. Если совместимость со стандартом ANSI не требуется,
можно увеличить или уменьшить это значение по умолчанию с помощью параметра /H (ограничение
длины внешних имен).
В компиляторе языка C прописные и строчные буквы считаются разными символами. Эта особенность,
называемая "учетом регистра", позволяет создавать различные идентификаторы, состоящие из
одинаковых букв в различных регистрах. Например, каждый из следующих идентификаторов является
уникальным:
add
ADD
Add
aDD
Не выбирайте для идентификаторов имена, которые начинаются с двух символов подчеркивания или с
одного символа подчеркивания и последующей прописной буквы. Стандарт ANSI языка C разрешает
резервировать имена идентификаторов, начинающиеся с таких сочетаний символов, для использования
компилятором. Идентификаторы с областью действия на уровне файлов также не должны начинаться со
знака подчеркивания и последующей строчной буквы. Имена идентификаторов, начинающиеся с таких
символов, также зарезервированы. По принятому соглашению в системах Microsoft символ подчеркивания
и прописная букву используются в начале имен макросов, а два символа подчеркивания используются для
специальных ключевых слова систем Microsoft. Во избежание каких-либо конфликтов имен никогда не
выбирайте имена идентификаторов, которые начинаются с одного или двух символов подчеркивания или
с символа подчеркивания и последующей прописной буквы.
j
count
temp1
top_of_page
skip12
LastNum
"Исходная кодировка" — это набор допустимых символов, которые могут использоваться в файлах
исходного кода. Для Microsoft C исходной кодировкой является стандартный набор символов ASCII.
Исходная кодировка и кодировка выполнения содержат символы ASCII, используемые в виде escape-
последовательностей. Сведения о кодировке выполнения см. в статье Константы символов в C.
См. также
Элементы языка C
Многобайтовая кодировка и расширенные
символы
13.10.2020 • 2 minutes to read • Edit Online
Расширенные символы — это коды многоязычных символов, которые всегда имеют размер 16 бит.
Символьные константы имеют тип char ; для расширенных символов используется тип wchar_t .
Поскольку расширенные символы всегда имеют фиксированный размер, их использование упрощает
программирование с использованием международных кодировок.
См. также
Идентификаторы C
Триграфы
13.10.2020 • 3 minutes to read • Edit Online
Кодировка исходного кода исходных программ на языке C содержится в 7-разрядной кодировке ASCII, но в
то же время является надмножеством инвариантной кодировки ISO 646-1983. Последовательности
триграфа позволяют писать программы на языке C с использованием только инвариантной кодировки,
соответствующей стандартам ISO. Триграфы — это последовательности из трех символов (которым
предшествует два вопросительных знака), которые компилятор заменяет соответствующими знаками
пунктуации. Триграфы можно использовать в файлах исходного кода на языке C с набором символов,
который не содержит удобных графических представлений некоторых знаков пунктуации.
C++17 удаляет триграфы из языка. Поддержка триграфов может сохраняться при определяемом
реализацией сопоставлении физического исходного файла с основной кодировкой исходного кода, хотя
обычно это не рекомендуется. C++14 обеспечивает такую же поддержку триграфов как в языке C.
Последовательности триграфов
ТРИГРАФ ЗНАК ПРЕПИНАНИЯ
??= #
??( [
??/ \
??) ]
??' ^
??< {
??! |
??> }
??- ~
Триграф всегда отображается как один символ исходного кода. Преобразование триграфов происходит на
первом этапе перевода перед распознаванием escape-символов в строковых литералах и символьных
константах. Распознаются только девять триграфов, отображаемых в таблице выше. Все другие
последовательности символов остаются непреобразованными.
printf( "What??!\n" );
напечатанная строка имеет вид What| , так как ??! — это триграфическая последовательность, которая
заменяется символом | . Напишите инструкцию следующим образом, чтобы правильно напечатать строку:
printf( "What?\?!\n" );
В этой инструкции printf escape-символ обратной косой черты перед вторым вопросительным знаком не
позволяет неверно интерпретировать ??! как триграф.
См. также
(подстановка триграфов)
/Zc:trigraphs
Идентификаторы C
Константы в C
13.10.2020 • 2 minutes to read • Edit Online
Константа — это число, символ или символьная строка, которую можно использовать в программе в
качестве значения. Константы служат для представления значений с плавающей запятой, целых чисел,
перечислений или символов, изменение которых невозможно.
Синтаксис
constant :
floating-point-constant
integer-constant
enumeration-constant
character-constant
См. также
Элементы языка C
Константы с плавающей запятой в C
13.10.2020 • 3 minutes to read • Edit Online
"Константа с плавающей запятой — это десятичное число, которое представляет знаковое вещественное
число. Представление знакового вещественного числа включает в себя целочисленную часть, дробную
часть и экспоненту. Константы с плавающей запятой служат для представления значений с плавающей
запятой, которые не могут быть изменены.
Синтаксис
floating-point-constant:
fractional-constant exponent-partopt floating-suffixopt
digit-sequence exponent-part floating-suffixopt
fractional-constant:
digit-sequenceopt . digit-sequence
digit-sequence .
exponent-part:
e signopt digit-sequence
E signopt digit-sequence
sign: один из указанных ниже знаков
+-
digit-sequence:
digit
digit-sequence digit
floating-suffix: один из указанных ниже знаков
flFL
Можно опустить либо цифры перед десятичной запятой (целочисленная часть значения), либо цифры
после десятичной запятой (дробная часть), но не и то и другое. Если включается только экспонента,
десятичную запятую можно опустить. Пробельные символы между цифрами или символами константы не
допускаются.
15.75
1.575E1 /* = 15.75 */
1575e-2 /* = 15.75 */
-2.5e-3 /* = -0.0025 */
25E-4 /* = 0.0025 */
Константы с плавающей запятой имеют положительное значение, если перед ними не стоит знак "минус" ( -
). А этом случае знак "минус" интерпретируется как унарный арифметический оператор изменения знака.
Константы с плавающей запятой относятся к типу float , double или long double .
Константы с плавающей запятой без суффикса f , F , l или L относятся к типу double . Если суффикс
представлен буквой f или F , константа относится к типу float . Если суффикс представлен буквой l или L ,
константа относится к типу long double . Пример:
10.0L /* Has type long double */
10.0F /* Has type float */
Обратите внимание, что компилятор Майкрософт для C внутренне представляет long double так же, как и
тип double . Дополнительные сведения о типах double , float и long double см. в статье Хранилище
базовых типов.
Целочисленную часть константы с плавающей запятой можно опустить, как показано в следующих
примерах. Число .75 можно выразить несколькими способами, включая следующие:
.0075e2
0.075e1
.075e1
75e-2
См. также
Константы в C
Ограничения на константы с плавающей запятой
07.05.2020 • 2 minutes to read • Edit Online
FLT_GUARD 0
FLT_NORMALIZE 0
Обратите внимание, что в будущих реализациях информация из приведенной выше таблицы может
отличаться.
См. также
Константы с плавающей запятой в C
Целочисленные константы в C
15.05.2020 • 3 minutes to read • Edit Online
Синтаксис
integer-constant:
decimal-constant integer-suffixopt
octal-constant integer-suffixopt
hexadecimal-constant integer-suffixopt
decimal-constant:
nonzero-digit
decimal-constant digit
octal-constant:
0
octal-constant octal-digit
hexadecimal-constant:
hexadecimal-prefix hexadecimal-digit
hexadecimal-constant hexadecimal-digit
hexadecimal-prefix: один из следующих символов:
0x 0X
nonzero-digit: одна из указанных ниже
123456789
octal-digit: одна из указанных ниже
01234567
hexadecimal-digit: одна из указанных ниже
0123456789
abcdef
ABCDEF
integer-suffix:
unsigned-suffix long-suffixopt
unsigned-suffix long-long-suffix
unsigned-suffix 64-bit-integer-suffix
long-suffix unsigned-suffixopt
long-long-suffix unsigned-suffixopt
64-bit-integer-suffix
unsigned-suffix: one of
uU
long-suffix: one of
lL
long-long-suffix: один из следующих символов:
ll LL
64-bit-integer-suffix: один из следующих символов:
i64 I64
Суффиксы i64 и I64 используются только в системах Майкрософт.
Целые константы имеют положительное значение, если перед ними не указан знак "минус" ( - ). Знак
"минус" интерпретируется как унарный арифметический оператор изменения знака. (Сведения об этом
операторе см. в статье Unary Arithmetic Operators (Унарные арифметические операторы).
Если целая константа начинается с символов 0x или 0X , она является шестнадцатеричной. Если константа
начинается с цифры 0 , она восьмеричная. В противном случае считается, что она десятичная.
28
0x1C /* = Hexadecimal representation for decimal 28 */
034 /* = Octal representation for decimal 28 */
Пробельные символы между цифрами целой константы не допускаются. В следующих примерах показаны
некоторые допустимые десятичные, восьмеричные и шестнадцатеричные константы.
/* Decimal Constants */
int dec_int = 28;
unsigned dec_uint = 4000000024u;
long dec_long = 2000000022l;
unsigned long dec_ulong = 4000000000ul;
long long dec_llong = 9000000000LL;
unsigned long long dec_ullong = 900000000001ull;
__int64 dec_i64 = 9000000000002I64;
unsigned __int64 dec_ui64 = 90000000000004ui64;
/* Octal Constants */
int oct_int = 024;
unsigned oct_uint = 04000000024u;
long oct_long = 02000000022l;
unsigned long oct_ulong = 04000000000UL;
long long oct_llong = 044000000000000ll;
unsigned long long oct_ullong = 044400000000000001Ull;
__int64 oct_i64 = 04444000000000000002i64;
unsigned __int64 oct_ui64 = 04444000000000000004uI64;
/* Hexadecimal Constants */
int hex_int = 0x2a;
unsigned hex_uint = 0XA0000024u;
long hex_long = 0x20000022l;
unsigned long hex_ulong = 0XA0000021uL;
long long hex_llong = 0x8a000000000000ll;
unsigned long long hex_ullong = 0x8A40000000000010uLL;
__int64 hex_i64 = 0x4a44000000000020I64;
unsigned __int64 hex_ui64 = 0x8a44000000000040Ui64;
См. также
Константы в C
Целочисленные типы
13.10.2020 • 2 minutes to read • Edit Online
Всем целым константам присваивается тип на основе их значения и способа представления. Для любой
целой константы можно принудительно задать тип long , добавив букву l или L в конец константы; для
принудительного задания типа unsigned добавьте в конец значения букву u или U . Следует избегать
использования буквы l в нижнем регистре, так как ее можно перепутать с цифрой 1. Ниже приведены
некоторые формы целых констант long :
Тип, присваиваемый константе, зависит от значения, которое она представляет. Значение константы
должно находиться в диапазоне представимых значений для ее типа. Тип константы определяет , какие
преобразования выполняются при использовании константы в выражении или при добавлении знака
"минус" ( - ). В этом списке перечислены правила преобразования целых констант.
Для десятичной константы без суффикса используется тип int , long int или unsigned long int .
Константе присваивается первый из этих 3 типов, в котором возможно представление значения
константы.
Константам с суффиксом u или U присваивается тип unsigned int или unsigned long int в
зависимости от размера.
Константам с суффиксом l или L присваивается тип long int или unsigned long int в зависимости
от размера.
См. также
Целочисленные константы в C
Пределы целых чисел в C и C++
13.10.2020 • 3 minutes to read • Edit Online
Ограничения для целочисленных типов в C и C++ представлены в следующей таблице. Эти ограничения
заданы в стандартном файле заголовка C <limits.h> . Стандартный файл заголовка C++ <limits>
содержит <climits> , который включает в себя <limits.h> .
LLONG_MIN Минимальное значение для –9 223 372 036 854 775 807 – 1
переменной типа long long .
LLONG_MAX Максимальное значение для 9 223 372 036 854 775 807
переменной типа long long .
ULLONG_MAX Максимальное значение для 18 446 744 073 709 551 615
переменной типа (0xffffffffffffffff)
unsigned long long .
См. также
Целочисленные константы в C
Константы символов в C
15.05.2020 • 2 minutes to read • Edit Online
"Константа символа" создается путем заключения одного символа из набора представимых символов в
одинарные кавычки ( ' ' ). Константы символов используются для представления символов в кодировке
выполнения.
Синтаксис
character-constant: ' c-char-sequence '
L' c-char-sequence '
c-char-sequence: c-char
c-char-sequence c-char
c-char: Любой член исходной кодировки, кроме одинарной кавычки ( ' ), обратной косой черты ( \ ) и
символа новой строки
escape-sequence
escape-sequence: simple-escape-sequence
octal-escape-sequence
hexadecimal-escape-sequence
simple-escape-sequence: один из символов: \a \b \f \n \r \t \v
\' \" \\ \?
octal-escape-sequence: \ octal-digit
\ octal-digit octal-digit
\ octal-digit octal-digit octal-digit
hexadecimal-escape-sequence: \x hexadecimal-digit
hexadecimal-escape-sequence hexadecimal-digit
См. также
Константы в C
Символьные типы
13.10.2020 • 2 minutes to read • Edit Online
Целочисленная символьная константа, в начале которой не указана буква L , имеет тип int . Значением
целой символьной константы, содержащей один символ, является численное значение символа,
интерпретированное как целое число. Например, численное значение символа a равно 97 в десятичном
представлении и 61 в шестнадцатеричном представлении.
Расширенные символьные константы имеют ширину 16 бит и указывают члены расширенной кодировки
выполнения. Они обеспечивают представление символов в алфавитах, слишком больших для
представления типом char . Дополнительные сведения о расширенных символах см. в статье
Многобайтовые и расширенные символы.
См. также
Константы символов в C
Набор символов исполнения
07.05.2020 • 2 minutes to read • Edit Online
См. также
Константы символов в C
Escape-последовательность
15.05.2020 • 3 minutes to read • Edit Online
Сочетания символов, состоящих из обратной косой черты ( \ ), за которой следует буква или набор цифр,
называются escape-последовательностями. Для представления знака новой строки, одиночной кавычки
или некоторых других символов в символьной константе, необходимо использовать escape-
последовательности. Escape-последовательность рассматривается как один символ и, следовательно,
является допустимой символьной константой.
Escape-последовательности обычно используются для указания действий, например возврата каретки или
табуляции, на терминалах и принтерах. Они также используются для обозначения буквенных
представлений непечатаемых символов, а также символов, которые обычно имеют специальное значение,
например двойных кавычек ( " ). В следующей таблице перечислены escape-последовательности ANSI и
представляемые ими значения.
Обратите внимание, что вопросительный знак, перед которым стоит обратная косая черта ( \? ),
обозначает литерал вопросительного знака в случаях, когда данная последовательность символов может
быть ошибочно интерпретирована как триграф. Дополнительные сведения см. в разделе Триграфы.
Escape -последовательность
ESC A P E- ПОСЛЕДОВАТЕЛЬНОСТЬ ПРЕДСТАВЛЯЕТ
\a Звонок (предупреждение)
\b Backspace
\f Перевод страницы
\n Новая строка
\r Возврат каретки
\t Горизонтальная табуляция
\v Вертикальная табуляция
Если обратная косая черта предшествует символу, которого нет в таблице, компилятор не обрабатывает
неопределенный символ сам как символ. Например, escape-последовательность \c обрабатывается как
символ c .
Кроме того, обратную косую черту ( \ ) можно использовать как символ продолжения. Если сразу за
обратной косой чертой следует символ новой строки (эквивалентен нажатию клавиши ВОЗВРАТ ),
компилятор игнорирует эту последовательность и обрабатывает следующую строку как продолжение
предыдущей. Эта возможность используется в основном для определений препроцессора, длина которых
превышает одну строку. Пример:
#define assert(exp) \
( (exp) ? (void) 0:_assert( #exp, __FILE__, __LINE__ ) )
См. также
Константы символов в C
Спецификации восьмеричных и
шестнадцатеричных символов
13.10.2020 • 3 minutes to read • Edit Online
Последовательность \ ooo означает , что можно указать любой набор символов в кодировке ASCII в качестве
трехразрядного восьмеричного кода знака. Числовое значение восьмеричного целого числа указывает
значение требуемого символа или расширенного символа.
Аналогичным образом последовательность \x hhh позволяет указать любой символ в кодировке ASCII в
качестве шестнадцатеричного кода знака. Например, символ backspace (ASCII) можно представить как
обычную escape-последовательность C ( \b ), закодировать как восьмеричный код \010 или
шестнадцатеричный код \x008 .
Аналогичным образом, необходимо использовать хотя бы одну цифру для шестнадцатеричной escape-
последовательности, но можно опустить вторую и третью цифры. Следовательно, шестнадцатеричную
escape-последовательность для символа backspace можно указать как \x8 , \x08 или \x008 .
Значение восьмеричной или шестнадцатеричной escape-последовательности должно находиться в
диапазоне представимых значений для типа unsigned char для символьной константы и типа wchar_t для
расширенной символьной константы. Дополнительные сведения о расширенных символьных константах см.
в статье Многобайтовая кодировка и расширенные символы.
В случае шестнадцатеричных значений можно разделить строку для четкого отображения правильного
значения.
См. также
Константы символов в C
Строковые литералы в C
15.05.2020 • 2 minutes to read • Edit Online
Синтаксис
string-literal:
" s-char-sequenceopt "
L" s-char-sequenceopt "
s-char-sequence:
s-char
s-char-sequence s-char
s-char:
любой член исходной кодировки, кроме двойной кавычки ("), обратной косой черты (\) и символа новой
строки
escape-sequence
Примечания
В приведенном ниже примере показан простой строковый литерал.
См. также
Элементы языка C
Тип для строковых литералов
13.10.2020 • 2 minutes to read • Edit Online
Строковые литералы имеют тип массива char (т. е., char[ ] ). (Строки расширенных символов имеют тип
массива wchar_t (т. е., wchar_t[ ] ).) Это означает , что строка является массивом с элементами типа char .
Число элементов в массиве равно числу символов в строке плюс один дополнительный элемент для
завершающего символа null.
См. также
Строковые литералы в C
Хранение строковых литералов
07.05.2020 • 2 minutes to read • Edit Online
Символы строкового литерала хранятся по порядку в смежных адресах памяти. Любая escape-
последовательность (например, \\ или \" ) внутри строкового литерала считается одним символом. В
каждый строковый литерал автоматически добавляется нуль-символ (представленный escape-
последовательностью \0 ), который обозначает его конец. (Это происходит на этапе преобразования 7.)
Обратите внимание, что компилятор не может сохранить две одинаковые строки отдельно с разными
адресами. Ключ /GF указывает , что компилятор должен сохранять в исполняемом файле только одну копию
одинаковых строк.
Примечания
Блок , относящийся только к системам Microsoft
См. также
Строковые литералы в C
Объединение строковых литералов
07.05.2020 • 3 minutes to read • Edit Online
Для создания строкового литерала, занимающего более одной строки, можно объединить две строки. Для
этого следует ввести обратную косую черту и нажать клавишу ВВОД. Обратная косая черта указывает
компилятору игнорировать следующий символ новой строки. Например, строковый литерал
идентичен строке
Вместо использования обратной косой черты с последующим символом новой строки для ввода строк,
длина которых превышает одну строку, можно использовать объединение строк.
Чтобы принудительно создать новую строку внутри строкового литерала, следует ввести escape-
последовательность новой строки ( \n ) в том месте строки, где требуется сделать разрыв:
Поскольку строки могут начинаться в любом столбце исходного кода и длинные строки можно продолжать
в любом столбце последующей строки, строки можно позиционировать для повышения удобства чтения
исходного кода. В любом случае их представление на экране при выводе результата не затрагивается.
Пример:
Так как каждая часть строки заключается в двойные кавычки, части объединяются и результат
отображается в виде одной строки. Такое объединение происходит в соответствии с последовательностью
событий во время компиляции, определенной этапами преобразования.
"This is the first half of the string, this is the second half"
Указатель на строку, инициализированный как два разных строковых литерала, разделенных только
пробелом, хранится в виде одной строки (указатели рассматриваются в разделе Объявления указателей).
При правильном выполнении ссылки (см. следующий пример) результат идентичен результату
предыдущего примера.
См. также
Строковые литералы в C
Максимальная длина строки
07.05.2020 • 2 minutes to read • Edit Online
В режиме совместимости с ANSI требуется, чтобы компилятор принимал до 509 символов в строковом
литерале после объединения. Максимальная допустимая длина строкового литерала в Microsoft C —
приблизительно 2048 байтов. Однако если строковый литерал состоит из двух частей, заключенных в
двойные кавычки, препроцессор объединяет эти части в одну строку, и для каждой объединенной строки
добавляет дополнительный байт к общему количеству байтов.
Например, предположим, что строка состоит из 40 строк с 50 символами в каждой строке (2000 символов) и
одной строки с 7 символами и что каждая строка заключена в двойные кавычки. Это значит , что
добавляется до 2007 байтов плюс один байт для завершающего нуль-символа, то есть всего 2008 байтов. В
объединении дополнительный символ добавляется для каждой из первых 40 строк. В результате мы
получаем 2048 байтов. Обратите внимание, что если вместо двойных кавычек используются продолжения
строк (\), препроцессор не добавляет дополнительный символ для каждой строки.
Хотя отдельные строки в кавычках не могут быть длиннее 2048 байтов, объединив строки, можно создать
строковый литерал, состоящий приблизительно из 65535 байтов.
См. также
Строковые литералы в C
Знаки препинания и специальные символы
07.05.2020 • 2 minutes to read • Edit Online
Знаки пунктуации и специальные символы в наборе символов языка C имеют различные применения, от
организации текста программы до определения задач, выполняемых компилятором или скомпилированной
программой. Эти знаки не определяют операции, подлежащие выполнению. Некоторые знаки пунктуации
также являются операторами (см. статью Операторы в C). Компилятор определяет их использование в
зависимости от контекста.
Синтаксис
punctuator : один из символов: [ ] ( ) { } * , : = ; ... #
Эти символы имеют специальное значение в языке C. Их применение описывается в настоящем руководстве.
Знак решетки ( # ) может использоваться только в директивах препроцессора.
См. также
Элементы языка C
Структура программы
07.05.2020 • 2 minutes to read • Edit Online
В этом разделе приводится обзор программ на языке C и описание их выполнения. Также здесь приводятся
термины и функции, важные для понимания программ и компонентов на языке C. В разделе
рассматриваются следующие темы.
Пространства имен
Поскольку в этом разделе приводятся общие сведения, в указанных выше темах представлен лишь вводный
материал. Для получения дополнительных сведений см. соответствующие перекрестные ссылки.
См. также
Справочник по языку C
Файлы с исходным кодом и исходные программы
15.05.2020 • 2 minutes to read • Edit Online
Исходную программу можно разделить на один или несколько исходных файлов. Когда такие файлы
передаются компилятору, они называются блоками трансляции.
Синтаксис
translation-unit:
external-declaration
translation-unit external-declaration
external-declaration:
function-definition
declaration
В статье Общие сведения об объявлениях описывается синтаксис нетерминала declaration , а в
справочнике по препроцессору поясняется, как происходит обработка записи преобразования.
NOTE
Описание соглашений о синтаксисе ANSI вы найдете во введении к статье Общие сведения о синтаксисе языка C.
Компонентами блока трансляции являются внешние объявления, которые включают в себя определения
функций и объявления идентификаторов. Эти объявления и определения могут находиться в исходных
файлах, файлах заголовков, библиотеках и других файлах, которые необходимы программе. Чтобы создать
программу, необходимо скомпилировать каждый блок трансляции и скомпоновать полученный объектный
файл.
Исходная программа языка C представляет собой набор директив, директив pragma, объявлений,
определений, блоков операторов и функций. Для того чтобы все они были допустимыми компонентами
программы на языке Microsoft C, они должны иметь синтаксис, описанный в настоящей книге. При этом они
могут находиться в программе в любом порядке (в пределах описанных здесь правил). Однако от
расположения этих компонентов в программе зависит то, каким образом в программе будут
использоваться переменные и функции. (Дополнительные сведения см. в статье Время существования,
область, видимость и компоновка.)
Исходные файлы не должны содержать исполняемых операторов. К примеру, в один исходный файл
можно поместить все определения переменных, а затем в другом исходном файле, в котором эти
переменные используются, объявить ссылки на них. Этот метод позволяет легко находить и при
необходимости изменять определения. По этой же причине константы и макросы часто организуются в
отдельные файлы — так называемые включаемые файлы, или файлы заголовка. По мере необходимости на
них можно ссылаться из исходных файлов. Сведения о макросах и включаемых файлах см. в справочнике
по препроцессору.
См. также
Структура программы
Директивы препроцессору
06.05.2020 • 2 minutes to read • Edit Online
Этот оператор указывает компилятору заменять каждое вхождение MAX на 100 перед компиляцией. Ниже
перечислены директивы препроцессора компилятора C.
См. также
Файлы с исходным кодом и исходные программы
Прагмы C
13.10.2020 • 2 minutes to read • Edit Online
deprecated
detect_mismatch
fenv_access
float_control
fp_contract
function
hdrstop
include_alias
inline_depth
inline_recursion
intrinsic
make_public
managed
message
omp
once
optimize
pack
pop_macro
push_macro
region , endregion
runtime_checks
section
setlocale
strict_gs_check
unmanaged
warning
Описание директив pragma для компилятора Microsoft C см. в статье Директивы Pragma и ключевое слово
__Pragma .
Завершение блока , относящегося только к системам Майкрософт
См. также
Файлы с исходным кодом и исходные программы
Объявления и определения в C
07.05.2020 • 2 minutes to read • Edit Online
Объявление устанавливает связь между указанной переменной, функцией или типом и их атрибутами. В
статье Общие сведения об объявлениях приводится синтаксис ANSI для нетерминального элемента
declaration . В объявлении также определяется, где и когда возможен доступ к идентификатору
("компоновка" идентификатора). Дополнительные сведения о компоновке см. в статье Время существования,
область, видимость и компоновка.
Например, функции main , find и count и переменные var и val определяются в одном исходном файле
в следующем порядке:
int main() {}
int var = 0;
double val[MAXVAL];
char find( fileptr ) {}
int count( double f ) {}
Переменные var и val могут использоваться в функциях find и count ; никакие дополнительные
объявления не требуются. Однако в функции main эти имена не видны (доступ к ним невозможен).
См. также
Файлы с исходным кодом и исходные программы
Объявления и определения функций
07.05.2020 • 2 minutes to read • Edit Online
Прототипы функций устанавливают имя функции, тип возвращаемого ею значения, а также тип и число ее
формальных параметров. Определение функции содержит тело функции.
Примечания
Объявления функции и переменных могут находиться внутри или вне определения функции. Считается, что
любое объявление, сделанное внутри определения функции, находится на "внутреннем", или "локальном",
уровне, а объявление, расположенное вне всех определений функций, находится на внешнем, глобальном
уровне или на уровне области видимости файла. Определения переменных, подобно объявлениям, могут
находиться на внутреннем (в определении функции) или внешнем (вне всех определений функций) уровне.
Определения функций всегда находятся на внешнем уровне. Подробнее определения функций
рассматриваются в статье Определения функций. Прототипы функций описаны в статье Прототипы
функций.
См. также
Файлы с исходным кодом и исходные программы
Blocks
07.05.2020 • 2 minutes to read • Edit Online
Обратите внимание, что хотя все составные операторы заключены в фигурные скобки, не все элементы,
заключенные в фигурные скобки, являются составным оператором. Например, несмотря на то что
спецификации элементов массива, структуры или перечисления могут быть заключены в фигурные скобки,
они не являются составными операторами.
См. также
Файлы с исходным кодом и исходные программы
Пример программы
13.10.2020 • 3 minutes to read • Edit Online
Следующая исходная программа на языке C состоит из двух файлов исходного кода. В ней показаны
различные объявления и определения, возможные в программе на языке C. В последующих разделах этого
документа описывается, как создавать такие объявления, определения и инициализации, и как использовать
ключевые слова C, например static и extern . Функция printf объявлена в файле заголовка C STDIO.H.
Предполагается, что функции main и max находятся в разных файлах, а выполнение программы
начинается с функции main . Перед функцией main не выполняются никакие явные пользовательские
функции.
/*****************************************************************
FILE1.C - main function
*****************************************************************/
#define ONE 1
#define TWO 2
#define THREE 3
#include <stdio.h>
/****************************************************************
FILE2.C - definition of max function
****************************************************************/
См. также
Файлы с исходным кодом и исходные программы
Функция main и выполнение программ
13.10.2020 • 3 minutes to read • Edit Online
Все программы, написанные на языке C, содержат основную функцию, которая должна иметь имя main .
Если код соответствует модели программирования Юникода, можно использовать версию функции
main для многобайтовых символов с именем wmain . Функция main является начальной точкой для
выполнения программы. Она обычно управляет выполнением программы, вызывая другие ее функции. Как
правило, выполнение программы завершается в конце функции main , но по разным причинам это может
случиться и в других местах программы. Иногда (возможно, при обнаружении некоторой ошибки) может
потребоваться принудительно завершить программу. Для этого используйте функцию exit . Сведения о
функции exit и пример ее использования см. в Справочнике по библиотеке времени выполнения.
Синтаксис
main( int argc, char *argv[ ], char *envp[ ] )
Примечания
Функции в исходном коде программы выполняют одну или несколько конкретных задач. Функция main
может вызывать эти функции для выполнения соответствующих задач. Когда функция main вызывает
другую функцию, она передает ей управление выполнением, и работа программы продолжается с первого
оператора вызываемой функции. Вызываемая функция возвращает управление функции main , когда
выполняется оператор return или достигается конец этой функции.
Для любой функции, включая функцию main , можно объявить наличие параметров. Термин "параметр"
или "формальный параметр" относится к идентификатору, получающему значение, передаваемое
функции. Сведения о передаче аргументов в качестве параметров вы найдете в статье Параметры. Когда
одна функция вызывает другую, вызываемая функция получает значения своих параметров от
вызывающей функции. Эти значения называются аргументами. Для функции main можно объявить
формальные параметры, и тогда она будет принимать аргументы из командной строки в следующем
формате.
Если в функцию main передаются параметры, они традиционно именуются argc и argv , хотя компилятор
C не обязывает использовать именно эти имена. Типы для параметров argc и argv определяются языком
C. Если в функцию main передается третий параметр, он по традиции называется envp . В приведенных
ниже в данном разделе примерах описывается использование этих трех параметров для доступа к
аргументам командной строки. Эти параметры объясняются в следующих разделах.
Описание версии main для расширенных символов см. в статье Использование wmain .
См. также
Функция main и аргументы командной строки (C++)
Анализ аргументов командной строки C
Использование wmain
07.05.2020 • 2 minutes to read • Edit Online
В модели программирования Юникода можно определить версию функции main для расширенных
символов. Используйте wmain вместо main , если вам нужен переносимый код, соблюдающий модель
программирования Юникода.
Синтаксис
wmain( int argc, wchar_t *argv[ ], wchar_t *envp[ ] )
Примечания
Формальные параметры для функции wmain объявляются в том же формате, что и для функции main .
Затем можно передать в качестве аргументов "широкие" символы и указатель среды кодировки Юникод
(необязательно) в программу. Параметры argv и envp для функции wmain относятся к типу wchar_t* .
Пример:
Если программа использует функцию main , окружение многобайтовой кодировки создается библиотекой
времени выполнения при запуске программы. Копия среды для Юникода создается только при
необходимости (например, для вызова функции _wgetenv или _wputenv ). При первом вызове _wputenv или
_wgetenv , если среда многобайтовой кодировки (MBCS) уже существует , создается соответствующая среда
широкосимвольной строки, на которую затем указывает глобальная переменная _wenviron ,
представляющая собой широкосимвольную версию глобальной переменной _environ . В этот момент две
копии среды (для многобайтовой кодировки и Юникода) существуют одновременно и поддерживаются
операционной системой в течение всего срока жизни программы.
Аналогичным образом, если программа использует функцию wmain , при запуске программы создается
окружение расширенных символов и ссылка на него сохраняется в глобальной переменной _wenviron .
Среда многобайтовой кодировки MBCS (ASCII) создается при первом вызове функции _putenv или getenv ,
и на нее указывает глобальная переменная _environ .
См. также
Функция main и выполнение программ
Описание аргумента
13.10.2020 • 3 minutes to read • Edit Online
Параметр argc в функциях main и wmain выражается целым числом и обозначает количество аргументов,
переданных в программу из командной строки. Поскольку имя программы считается аргументом, значение
argc по крайней мере равно единице.
Примечания
Параметр argv является массивом указателей на строки, завершающиеся значением NULL, который
представляет аргументы программы. Каждый элемент массива указывает на строковое представление
аргумента, переданного в main (или wmain ). (Дополнительные сведения о массивах см. в разделе
Объявления массивов.) Параметр argv можно объявить как массив указателей на тип char ( char *argv[] )
или как указатель на указатели на тип char ( char **argv ). Параметр argv в wmain можно объявить как
массив указателей на тип wchar_t ( wchar_t *argv[] ) или как указатель на указатели на тип wchar_t (
wchar_t **argv ).
По соглашению параметр argv [0] содержит команду, которая использовалась для вызова программы.
Однако процесс можно инициализировать с помощью CreateProcess, а если указаны и первый, и второй
аргументы ( lpApplicationName и lpCommandLine ), то argv [0] не будет содержать имени исполняемого файла.
Чтобы гарантированно получить имя исполняемого файла, используйте GetModuleFileName.
Последний указатель ( argv[argc] ) имеет значение NULL . (Альтернативный метод получения сведений о
переменной среды см. в разделе getenvСправочника по библиотеке времени выполнения.)
Параметр envp является указателем на массив строк, завершающихся значением NULL, которые
представляют значения, заданные в переменных среды пользователя. Параметр envp можно объявить как
массив указателей на тип char ( char *envp[] ) или как указатель на указатели на тип char ( char **envp ).
Параметр envp в функции wmain можно объявить как массив указателей на wchar_t ( wchar_t *envp[] ) или
как указатель на указатели на wchar_t ( wchar_t **envp ). Конец массива определяется указателем NULL *.
Обратите внимание, что передаваемый в main или wmain блок окружения является "замороженной"
копией текущего окружения. Если окружение будет позднее изменена путем вызова _putenv или _wputenv ,
изменится только текущее окружение (которое возвращают getenv / _wgetenv и переменные _environ или
_wenviron ); но не блок, на который указывает envp . Параметр envp совместим с ANSI в C, но не в C++.
См. также
Функция main и выполнение программ
Расширение аргументов заполнителей
07.05.2020 • 2 minutes to read • Edit Online
При выполнении программы на языке C можно использовать любой из двух подстановочных знаков, вопрос
(?) или звездочку (*), для задания аргументов имени файла и пути в командной строке.
По умолчанию подстановочные знаки в аргументах командной строки не разворачиваются. Вы можете
заменить обычную процедуру загрузки вектора аргументов argv на версию, которая разворачивает
подстановочные знаки, используя компоновку с файлом setargv.obj или wsetargv.obj. Если программа
использует функцию main , скомпонуйте ее с файлом setargv.obj. Если программа использует функцию
wmain , скомпонуйте ее с файлом wsetargv.obj. Они оба реализуют эквивалентное поведение.
Чтобы скомпоновать программу с файлом setargv.obj или wsetargv.obj, используйте параметр /link . Пример:
См. также
Параметры ссылок
Функция main и выполнение программ
Анализ аргументов командной строки C
07.05.2020 • 3 minutes to read • Edit Online
В коде запуска Microsoft C используются следующие правила при обработке аргументов, вводимых в
командной строке операционной системы.
Строка, заключенная в двойные прямые кавычки, обрабатывается как один аргумент , независимо от
пробельных символов, которые могут в ней присутствовать. Строку в кавычках можно встроить в
аргумент. Обратите внимание, что символ каретки ( ^ ) не воспринимается как escape-символ или
разделитель.
Символ двойной кавычки после обратной косой черты ( \" ) обрабатывается как литеральный символ
двойной кавычки ( " ).
Если двойная кавычка стоит после четного числа символов обратной косой черты, в массив argv
помещается по одному символу обратной косой черты ( \ ) для каждой пары символов обратной
косой черты ( \\ ), а двойная кавычка ( " ) обрабатывается как разделитель строк.
Если двойная кавычка стоит после нечетного числа символов обратной косой черты, в массив argv
помещается по одному символу обратной косой черты ( \ ) для каждой пары символов обратной
косой черты ( \\ ), а символ двойной кавычки с оставшимся символом обратной косой черты
интерпретируется как escape-последовательность, в результате чего в массив argv помещается
литеральный символ двойной кавычки ( " ).
ДАННЫЕ В КОМАНДНОЙ
СТРОКЕ A RGV[ 1] A RGV[ 2] A RGV[ 3]
"a b c" d e a b c d e
a\\\"b c d a\"b c d
Пример
Код
// Parsing_C_Commandline_args.c
// ARGS.C illustrates the following variables used for accessing
// command-line arguments and environment variables:
// argc argv envp
//
#include <stdio.h>
return;
}
Комментарии
Ниже приведен один пример данных, выводимых этой программой:
Command-line arguments:
argv[0] C:\MSC\TEST.EXE
Environment variables:
COMSPEC=C:\NT\SYSTEM32\CMD.EXE
PATH=c:\nt;c:\binb;c:\binr;c:\nt\system32;c:\word;c:\help;c:\msc;c:\;
PROMPT=[$p]
TEMP=c:\tmp
TMP=c:\tmp
EDITORS=c:\binr
WINDIR=c:\nt
См. также
Функция main и выполнение программ
Настройка обработки командной строки C
07.05.2020 • 2 minutes to read • Edit Online
Если программа не принимает аргументы командной строки, можно сохранить небольшой объем
пространства, подавив использование подпрограммы библиотеки, выполняющей обработку командной
строки. Эта подпрограмма называется _setargv (или _wsetargv в окружении расширенных символов), как
описано в статье Wildcard Expansion (Развертывание подстановочных знаков). Чтобы подавить ее
использование, в файле, содержащем функцию main , определите подпрограмму с именем _setargv (или
_wsetargv в окружении расширенных символов), которая не выполняет никаких действий. Тогда для
вызовов _setargv и _wsetargv будет использоваться ваше определение _setargv или _wsetargv , а версия
из библиотеки загружаться не будет.
Аналогичным образом, если вам не нужно обращаться к таблице окружения с помощью аргумента envp , вы
можете предоставить собственную пустую подпрограмму вместо подпрограммы обработки окружения
_setenvp (или _wsetenvp ).
Если программа вызывает подпрограммы из семейства _spawn или _exec , определенные в библиотеке
времени выполнения C, подпрограмму обработки окружения подавлять не следует , поскольку она
используется для передачи окружения из вызывающего процесса в новый процесс.
См. также
Функция main и выполнение программ
Время жизни, область, видимость и компоновка
07.05.2020 • 2 minutes to read • Edit Online
Чтобы понимать, как работает программа на языке C, необходимо знать правила, определяющие
использование переменных и функций в программе. Для понимания этих правил исключительно важны
следующие понятия:
Время существования
См. также
Структура программы
Время существования
13.10.2020 • 3 minutes to read • Edit Online
"Время жизни" представляет собой период во время выполнения программы, в течение которого
существует переменная или функция. Время жизни идентификатора определяется длительностью его
хранения.
Идентификатор, объявленный описателем класса хранения типа static , имеет статическую длительность
хранения. Идентификаторы со статической длительностью хранения (также называемые "глобальными")
имеют выделенную память и определенное значение в течение всего времени выполнения программы.
Выделение памяти и инициализация хранящегося значения идентификатора производятся только один раз
перед началом работы программы. Идентификатор, объявленный с внешней или внутренней компоновкой,
также имеет статическую длительность хранения (см. статью Компоновка).
Идентификатор, объявленный без описателя класса хранения типа static , имеет автоматическую
длительность хранения, если он объявлен внутри функции. Идентификатор с автоматической
длительностью хранения ("локальный идентификатор") имеет выделенную память и определенное
значение только внутри блока, в котором он определен или объявлен. Автоматическому идентификатору
выделяется новая память при каждом входе программы в соответствующий блок; при выходе программы из
этого блока память (и значение) идентификатора освобождается. Идентификаторы, объявленные в
функции без компоновки, также имеют автоматическую длительность хранения.
Если локальная переменная имеет инициализатор, она инициализируется при каждом создании (если
она не объявлена как static ). Параметры функции также имеют локальное время жизни. Для
идентификатора можно определить глобальное время существования в пределах блока, включив в
его объявление описатель класса хранения типа static . Если переменная объявлена как static ,
она сохраняет свое значение между последовательными входами в блок.
Память может выделяться по мере необходимости (динамически), если создается с помощью специальных
библиотечных процедур, таких как malloc . Поскольку динамическое выделение памяти использует
библиотечные процедуры, оно не считается составной частью языка. См. описание функции malloc в
справочнике по библиотеке времени выполнения.
См. также
Время жизни, область, видимость и компоновка
Область и видимость
13.10.2020 • 3 minutes to read • Edit Online
Область видимости файла. Декларатор или описатель типа идентификатора с областью видимости файла
отображается вне любого блока или списка параметров и доступен из любого места записи
преобразования после объявления. Имена идентификаторов с областью видимости файла часто
называются глобальными или внешними. Область глобального идентификатора начинается с момента его
определения или объявления и заканчивается в конце записи преобразования.
Область видимости функции. Метка — это единственный тип идентификатора, который имеет область
видимости функции. Метка объявляется неявно путем использования в операторе. Имена меток должны
быть уникальными внутри функции. (Дополнительные сведения о метках и именах меток см. в статье
Оператор goto и помеченные операторы.)
Область видимости блока. Декларатор или описатель типа идентификатора с областью видимости блока
отображаются внутри блока или в списке объявлений формальных параметров в определении функции.
Он является видимым только с момента его определения или объявления до конца блока, содержащего
объявление или определение. Его область ограничена данным блоком и любыми блоками, которые
является вложенными по отношению к данному блоку, и заканчивается на фигурной скобке, закрывающей
связанный блок. Эти идентификаторы иногда называются локальными переменными.
Область видимости прототипа функции. Декларатор или описатель типа идентификатора с областью
видимости прототипа функции отображается в списке объявлений параметров в прототипе функции (не
является частью объявления функции). Эта область заканчивается в конце декларатора функции.
См. также
Время жизни, область, видимость и компоновка
Сводка времени существования и видимости
13.10.2020 • 2 minutes to read • Edit Online
Пример
Описание
В следующем примере показаны блоки, вложение и видимость переменных:
Код
// Lifetime_and_Visibility.c
#include <stdio.h>
Комментарии
В этом примере имеется 4 уровня видимости: внешний уровень и 3 уровня блоков. Значения выводятся на
экран, как указано в комментариях после каждого оператора.
См. также
Время жизни, область, видимость и компоновка
Компоновка
13.10.2020 • 2 minutes to read • Edit Online
См. также
Использование ключевого слова extern для задания компоновки
Внутренняя компоновка
13.10.2020 • 2 minutes to read • Edit Online
Если объявление идентификатора области доступности файла для объекта или функции содержит
описатель класса хранения типа static , идентификатор имеет внутреннюю компоновку. В противном
случае идентификатор имеет внешнюю компоновку. Использование нетерминального параметра storage-
class-specifier приводится в статье Классы хранения.
В пределах одной записи преобразования каждый экземпляр идентификатора с внутренней компоновкой
обозначает тот же идентификатор или функцию. Идентификаторы с внутренней компоновкой уникальны
для конкретной записи преобразования.
См. также
Использование ключевого слова extern для задания компоновки
Внешняя компоновка
13.10.2020 • 2 minutes to read • Edit Online
Если в первом объявлении на уровне области видимости файла для идентификатора не используется
описатель класса хранения static , объект имеет внешнюю компоновку.
См. также
Использование ключевого слова extern для задания компоновки
Без компоновки
13.10.2020 • 2 minutes to read • Edit Online
Если объявление идентификатора в блоке не содержит описатель класса хранения extern , этот
идентификатор не имеет компоновки и уникален для функции.
идентификатор области доступности блока для объекта, объявленного без описателя класса
хранения extern .
Если идентификатор не имеет компоновки, повторное объявление того же имени (в деклараторе или
спецификаторе типа) на том же уровне области видимости приводит к появлению ошибки
переопределения символов.
См. также
Использование ключевого слова extern для задания компоновки
Пространства имен
13.10.2020 • 4 minutes to read • Edit Online
NOTE
Не следует путать ограниченную нотацию C пространства имен с возможностью пространства имен C++.
Дополнительные сведения см. в разделе Пространства имен (C++) в справочнике по языку C++.
Метки операторов. Именованные метки операторов являются частью операторов. За определениями меток
операторов всегда следует двоеточие, но определения не являются частью меток case . Метки операторов
всегда используются сразу за ключевым словом goto . Метки операторов не должны отличаться от других
имен или имен меток в других функциях.
Теги структур, объединений и перечислений. Эти теги являются частью указателей на тип структуры,
объединения и перечисления и при их наличии всегда следуют сразу за зарезервированными словами
struct , union или enum . Имена тегов должны отличаться от всех других тегов структур, перечислений
или объединений с такой же видимостью.
Элементы структур или объединений. Имена элементов выделены в пространствах имен, связанных с
каждыми типом структуры и объединения. То есть один и тот же идентификатор может быть именем
компонента в любом количестве структур или объединений одновременно. Определения имен
компонентов всегда находятся в описателях типа структуры или объединения. Имена компонентов всегда
следуют сразу за операторами выбора члена ( -> и . ). Имя члена должно быть уникальным в пределах
структуры или объединения, но оно не обязательно должно отличаться от других имен в программе,
включая имена членов различных структур и объединений или имя самой структуры.
Обычные идентификаторы. Все другие имена находятся в пространстве имен, которое содержит
переменные, функции (включая формальные параметры и локальные переменные) и константы
перечисления. Имена идентификаторов имеют вложенную видимость, поэтому их можно переопределять в
блоках.
Имена typedef. Эти имена нельзя использовать в качестве идентификаторов в одной и той же области.
Например, поскольку теги структуры, члены структуры и имена переменных находятся в трех разных
пространствах имен, три элемента с именем student в этом примере не конфликтуют. Контекст каждого
элемента позволяет правильно интерпретировать каждое вхождение student в программе.
(Дополнительные сведения о структурах см. в разделе Объявления структур.)
struct student {
char student[20];
int class;
int id;
} student;
Если student отображается после ключевого слова struct , компилятор распознает его как тег структуры.
Если student отображается после оператора выбора члена ( -> или . ), имя ссылается на член структуры. В
других контекстах student ссылается на переменную структуры. Однако не рекомендуется перегружать
пространство имен тега, поскольку это искажает смысл.
См. также
Структура программы
Объявления и типы
06.05.2020 • 2 minutes to read • Edit Online
Классы хранения в C
Описатели типов С
Квалификаторы типов
Инициализация
Неполные типы
Объявления Typedef
См. также
Справочник по языку C
Общие сведения об объявлениях
13.10.2020 • 7 minutes to read • Edit Online
Синтаксис
declaration :
declaration-specifiers attribute-seq необ. init-declarator-list необ. ;
declaration-specifiers :
storage-class-specifier declaration-specifiers необ.
type-specifier declaration-specifiers необ.
type-qualifier declaration-specifiers необ.
init-declarator-list :
init-declarator
init-declarator-list , init-declarator
init-declarator :
declarator
declarator = initializer
NOTE
Этот синтаксис для declaration не будет повторяться в следующих разделах. Синтаксис в следующих
разделах обычно начинается с нетерминального оператора объявления declarator .
В общей форме объявления переменных в параметре type-specifier задается тип данных для переменной.
type-specifier может быть составным, например иметь модификаторы const и volatile . В параметре
declarator содержится имя переменной, которое может быть изменено для объявления массива или типа
указателя. Например, примененная к объекту директива
int const *fp;
Объявление должно содержать по меньшей мере один декларатор, или его спецификатор типа должен
объявлять тег структуры, тег объединения или члены перечисления. Деклараторы предоставляют всю
остальную информацию об идентификаторе. Оператор объявления — это идентификатор, который
можно изменить с помощью квадратных скобок ( [ ] ), звездочек ( * ) или круглых скобок ( ( ) ) для
объявления типов массива, указателя или функции, соответственно. При объявлении простых переменных
(например символьных, целочисленных или с плавающей запятой) или структур и объединений простых
переменных декларатор ( declarator ) представляет собой только идентификатор. Дополнительные
сведения о деклараторах см. в статье Деклараторы и объявления переменных.
В объявлениях переменных должен быть указан класс хранения или тип (или и то, и другое). За
исключением ключевого слова __declspec , в объявлениях допускается только один описатель класса
хранения. Некоторые описатели класса хранения не допускаются в некоторых контекстах. Класс хранения
__declspec может использоваться с другими описателями класса хранения; его можно указывать более
одного раза. Спецификатор класса хранения для объявления влияет только на то, каким образом
объявленный элемент хранится и инициализируется, и какие части программы могут ссылаться на
элемент.
См. также
Краткие сведения о синтаксисе языка C
Объявления и типы
Общие сведения об объявлениях
Классы хранения в C
13.10.2020 • 2 minutes to read • Edit Online
"Класс хранения" переменной определяет время существования элемента: глобальное или локальное. В
языке С это время существования называется "статическое" или "автоматическое". Элемент с
глобальным временем существования присутствует и имеет значение на протяжении всего исполнения
программы. Все функции имеют глобальное время существования.
Синтаксис
storage-class-specifier:
auto
register
static
extern
typedef
__declspec ( extended-decl-modifier-seq ) /* Относится только к системам Майкрософт */
За исключением __declspec , в составе declaration-specifier в объявлении можно использовать только
один описатель storage-class-specifier. Если нет спецификации класса хранения, объявления в блоке
создают автоматические объекты.
Элементы, объявленные с описателем auto или register , имеют локальное время существования.
Элементы, объявленные с описателем static или extern , имеют глобальное время существования.
Размещение объявлений переменных и функций в файлах исходного кода также влияет на класс
хранения и видимость. Объявления вне определений функций отображаются на внешнем уровне.
Объявления в составе определений функций отображаются на внутреннем уровне.
В статьях Описатели классов хранения для объявлений внешнего уровня и Описатели классов хранения
для объявлений внутреннего уровня описаны терминалы storage-class-specifier для каждого типа
объявлений и поведение по умолчанию в случае отсутствия storage-class-specifier в декларации
переменной. Статья Описатели классов хранения с объявлениями функций поможет разобраться с
описателями storage-class, используемыми с функциями.
См. также
Объявления и типы
Спецификаторы классов хранения для объявлений
внешнего уровня
13.10.2020 • 7 minutes to read • Edit Online
Внешние переменные — это переменные в области видимости файла. Они определяются вне конкретной
функции и потенциально доступны для множества функций. Функции можно определить только на
внешнем уровне, и, следовательно, они не могут быть вложенными. По умолчанию все ссылки на внешние
переменные и функции с одинаковым именем являются ссылками на один и тот же объект , что означает ,
что они имеют внешнее связывание. (Чтобы переопределить такое поведение, можно использовать
ключевое слово static .)
В объявлениях переменных на внешнем уровне (т. е. вне любых функций) можно либо использовать
описатель класса хранения static или extern , либо полностью опустить его. Вы не можете использовать
терминальные описатели storage-class-specifier auto и register на внешнем уровне.
После определения переменной на внешнем уровне она становится видимой во всей оставшейся части
записи преобразования. Переменная невидима до ее объявления в том же исходном файле. Кроме того, она
будет невидима в других исходных файлах программы, пока объявление не сделает ее видимой, как
описано ниже.
Указать переменную на внешнем уровне можно только один раз в рамках программы. Можно указать
другую переменную с тем же именем и описатель класса хранения static в другой записи
преобразования. Так как каждое определение static является видимым только в пределах
собственной записи преобразования, конфликт не произойдет. Это удобный способ скрыть имена
идентификаторов, которые должны совместно использоваться функциями в одной единице
трансляции, но должны быть невидимы для других таких единиц.
Описатель класса хранения static также может применяться к функциям. Если функция объявлена
как static , ее имя невидимо вне файла, в котором она объявлена.
Чтобы ссылка extern стала допустимой, необходимо объявить переменную, на которую она
ссылается, один и только один раз на внешнем уровне. Это определение (без класса хранения extern
) может находиться в любой из единиц трансляции, составляющих программу.
Пример
В примере ниже показаны внешние объявления.
/******************************************************************
SOURCE FILE ONE
*******************************************************************/
#include <stdio.h>
int main()
{
i++;
printf_s( "%d\n", i ); // i equals 4
next();
}
int i = 3; // Definition of i
/******************************************************************
SOURCE FILE TWO
*******************************************************************/
#include <stdio.h>
int i = 3;
extern int x;
int x = 0;
Все три функции ( main , next и other ) выполняют одну и ту же задачу: они расширяют переменную i и
отображают ее значение. Отображаются значения 4, 5 и 6.
См. также
Классы хранения в C
Спецификаторы классов хранения для объявлений
внутреннего уровня
13.10.2020 • 2 minutes to read • Edit Online
См. также
Классы хранения в C
Описатель класса хранения auto
13.10.2020 • 2 minutes to read • Edit Online
Описатель класса хранения auto объявляет автоматическую переменную, то есть переменную с локальным
временем существования. Переменная auto доступна только в том блоке, в котором она объявлена.
Объявления переменных auto могут содержать инициализаторы, как описано в статье Инициализация.
Поскольку переменные с классом хранения auto не инициализируются автоматически, необходимо явно
инициализировать их при объявлении или присвоить им начальные значения в блоке. Для
неинициализированных переменных auto значения не определены. (Локальная переменная с классом
хранения auto или register инициализируется заново каждый раз, когда она попадает в область
доступности, если для нее указан инициализатор.)
См. также
Ключевое слово auto
Спецификатор класса хранения register
13.10.2020 • 2 minutes to read • Edit Online
См. также
Спецификаторы классов хранения для объявлений внутреннего уровня
Спецификатор класса хранения static
13.10.2020 • 2 minutes to read • Edit Online
Переменная, объявленная на внутреннем уровне с помощью описателя класса хранения static , имеет
глобальное время существования, но доступна только внутри блока, в котором она объявлена. Описатель
static полезно использовать в константных строках, потому что при этом снимается нагрузка частой
инициализации в часто вызываемых функциях.
Примечания
Если переменная с типом static не инициализирована явно, она инициализируется со значением 0 по
умолчанию. Внутри функции static выделяет хранилище и служит определением. Внутренние статические
переменные представляют закрытое постоянное хранилище, видимое только одной функции.
См. также
Классы хранения в C
Storage classes (C++) (Классы хранения (C++))
Спецификатор класса хранения extern
13.10.2020 • 2 minutes to read • Edit Online
Переменная, объявленная с использованием описателя для класса хранения extern , представляет собой
ссылку на переменную с тем же именем, определенную в другом исходном файле. Она используется, чтобы
сделать видимым определение переменной внешнего уровня. Для переменной, объявленной как extern , не
выделено хранилище; по сути, это только имя.
Пример
Этот пример иллюстрирует объявления на внутреннем и внешнем уровнях.
// Source1.c
int i = 1;
// Source2. c
#include <stdio.h>
void func(void);
int main()
{
// Prints 1:
printf_s("%d\n", i);
func();
return;
}
void func(void)
{
// Address of global i assigned to pointer variable:
static int *external_i = &i;
// Prints 16, 1:
printf_s("%d\n%d\n", i, *external_i);
}
В объявлениях функций можно использовать описатель класса хранения static или extern . Функции
всегда имеют глобальное время существования.
Объявления функций на внутреннем уровне имеют то же значение, что и объявления функций на внешнем
уровне. Это означает , что функция видна с момента объявления на протяжении всего времени
существования записи преобразования, даже если она объявлена с локальной областью видимости.
Правила видимости для функций слегка отличаются от правил для переменных следующим.
Функция, объявленная как static , видна только в пределах исходного файла, в котором она
определена. Функции в том же исходном файле могут вызывать функцию static , но функции в
других исходных файлах не могут получить прямой доступ к ней по имени. Можно объявить другую
функцию static с тем же именем в другом исходном файле, не создавая конфликта.
Функции, объявленные как extern , видны во всех исходных файлах программы (если впоследствии
такая функция не будет повторно объявлена как static ). Любая функция может вызывать функцию
extern .
Объявления функций, опускающие описатель класса хранения, по умолчанию являются extern .
Блок , относящийся только к системам Microsoft
См. также
Классы хранения в C
Спецификаторы типов C
13.10.2020 • 4 minutes to read • Edit Online
Синтаксис
type-specifier: void char short int long float double signed unsigned
struct-or-union-specifier enum-specifier typedef-name
Типы signed char , signed int , и signed long int вместе с аналогичными типами
signed short int
unsigned и enum совокупно именуются целочисленными типами. Описатели типов float , double и
long double называются типами с плавающей точкой или плавающей запятой. Любой спецификатор
целочисленного типа или типа с плавающей запятой можно использовать в объявлении переменной или
функции. Если в объявлении отсутствует описатель type-specifier, для него предполагается тип int .
Необязательные ключевые слова signed и unsigned могут указываться перед любым целочисленным
типом или после него, за исключением enum . Также их можно использовать отдельно в качестве
описателей типа, и тогда они трактуются соответственно как signed int и unsigned int . Если ключевое
слово int используется отдельно, оно обрабатывается как signed . Если ключевые слова long и short
используются отдельно, они трактуются как long int и short int .
Типы перечисления считаются базовыми типами. Описатели типов для типов перечисления
рассматриваются в статье Объявления перечислений C.
Ключевое слово void используется для трех целей: задание типа возвращаемого значения функции,
задание списка типов аргументов для функции, не принимающей аргументов, и задание указателя на
неуказанный тип. Тип void можно использовать для объявления функций, не возвращающих никаких
значений, или для объявления указателя на неуказанный тип. В статье Аргументы описано, как
обрабатывается void , если это единственное ключевое слово в скобках после имени функции.
Проверка типов теперь соответствует требованиям ANSI, то есть типы short и int считаются разными
типами. Например, это является переопределением в компиляторе Microsoft C, которое принималось
предыдущими версиями компилятора.
int myfunc();
short myfunc();
int *pi;
short *ps;
Компилятор Microsoft C также выдает предупреждения в случае разного использования знака (типы со
знаком и без знака). Пример:
signed int *pi;
unsigned int *pu
Выражения типа void вычисляются для учета побочных эффектов. Невозможно каким-либо образом
использовать (несуществующее) значение выражения типа void ; также невозможно преобразовать
выражение типа void (с помощью явного или неявного преобразования) в любой тип, кроме void . При
использовании в контексте, в котором требуется выражение void , выражения любого другого типа его
значение игнорируется.
Для обеспечения соответствия спецификации ANSI тип void** не может использоваться как int** . В
качестве указателя на неуказанный тип можно использовать только void * .
С помощью объявлений typedef можно создавать дополнительные описатели типа, как описано в статье
Объявления Typedef. Сведения о размерах для каждого типа см. в статье Хранение базовых типов.
См. также
Объявления и типы
Спецификаторы и эквиваленты типов данных
13.10.2020 • 2 minutes to read • Edit Online
В этой книге в большинстве случаев вместо полных форм описателей типов используются формы,
приведенные в следующей таблице. При этом предполагается, что тип char является знаковым по
умолчанию. Таким образом, если в этой книге указывается тип char , то это означает то же, что и
signed char .
unsigned char —
float —
long double 2 —
При помощи параметра компилятора /J можно указать, что тип char по умолчанию является не
signed char , а unsigned char . При использовании этого параметра описатель char означает то же, что и
unsigned char . Для объявления знакового символьного значения необходимо использовать ключевое слово
signed . Если значение char явным образом объявлено как signed , то параметр /J на него не влияет , и
его расширение до типа int выполняется с расширением знака. Расширение типа char до типа int
выполняется с дополнением нулями.
Квалификаторы типов предоставляют идентификатору одно из двух свойств. Квалификатор типа const
объявляет объект как неизменяемый. Квалификатор типа volatile объявляет элемент , значение которого
можно изменить допустимым образом с помощью средств, недоступных программе, в которой он
находится, таких как выполняемый в данный момент поток.
Квалификаторы типов const и volatile могут использоваться в объявлении только один раз.
Квалификаторы типов могут использоваться с любым описателем типа; однако они не могут находиться
после первой запятой в объявлении нескольких элементов. Например, следующие объявления допустимы.
Квалификаторы типов имеют смысл только при обращении к идентификаторам как к l-значениям в
выражениях. Дополнительные сведения о левосторонних значениях и выражениях см. в статье Выражения
L-Value и R-Value.
Синтаксис
type-qualifier: constvolatile
Ниже представлены допустимые объявления const и volatile .
Если спецификация типа массива включает квалификаторы типов, определяется элемент , а не тип массива.
Если спецификация типа функции включает квалификаторы, поведение не определено. Ни volatile , ни
const не влияют на диапазон значений или арифметические свойства объекта.
Компилятор предполагает , что в любом месте программы к переменной volatile может обратиться
неизвестный процесс, который использует или изменяет ее значение. Следовательно, независимо от
оптимизаций, указанных в командной строке, необходимо создать код для каждого назначения
переменной volatile или ссылки на нее, даже если кажется, что он ничего не делает.
Если volatile используется отдельно, предполагается int . Описатель типа volatile можно
использовать для предоставления надежного доступа к специальным адресам памяти. Используйте
volatile с объектами данных, к которым можно получить доступ или которые можно изменить с
помощью обработчиков сигналов, одновременного выполнения программ или специального
оборудования, например регистров управления MMIO. Можно объявить переменную как volatile на
весь срок ее существования или объявить как volatile только одну ссылку.
Элемент может одновременно быть const и volatile , и тогда его невозможно изменить
допустимым образом в той же программе, но можно изменить в некотором асинхронном процессе.
См. также
Объявления и типы
Деклараторы и объявления переменных
13.10.2020 • 4 minutes to read • Edit Online
В остальной части данного раздела описывается форма и значение объявлений для переменных типов,
включенных в этот список. В частности, в остальных разделах объясняется, как объявить следующие
объекты.
Декларатор — это часть объявления, задающая имя, которое нужно вставить в программу. Он может
включать модификаторы, например * (указатель на), и любые ключевые слова соглашения о вызовах
Майкрософт.
В деклараторе
char — это описатель типа, __declspec(thread) и * — это модификаторы, а var — это имя
идентификатора.
Синтаксис
declarator:
pointeropt direct-declarator
direct-declarator:
identifier
( declarator )
direct-declarator [ constant-expressionopt ]
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-listopt )
pointer:
* type-qualifier-listopt
* type-qualifier-listopt pointer
type-qualifier-list:
type-qualifier
type-qualifier-list type-qualifier
NOTE
См. соответствующий синтаксис для объявления в разделе Обзор объявлений или Краткие сведения о синтаксисе
языка C для получения сведений о синтаксисе, который ссылается на декларатор.
Если декларатор состоит из неизмененного идентификатора, объявляемый элемент имеет базовый тип.
Если звездочка (* ) отображается слева от идентификатора, тип изменяется на тип указателя. Если после
идентификатора следуют квадратные скобки ( [ ] ), тип изменяется на тип массива. Если после
идентификатора следуют скобки, тип меняется на тип функции. Дополнительные сведения об
интерпретации приоритетности в пределах объявлений см. в разделе Интерпретация более сложных
деклараторов.
Каждый декларатор объявляет по крайней мере один идентификатор. Декларатор должен включать
описатель типа, чтобы называться полным объявлением. Описатель типа предоставляет тип элементов
типа массива, тип объекта, к которому относится тип указателя, или тип возвращаемого значения
функции.
Объявления массивов и указателей более подробно обсуждаются далее в этом разделе. В следующем
примере проиллюстрировано несколько простых форм деклараторов.
См. также
Объявления и типы
Простые объявления переменных
13.10.2020 • 2 minutes to read • Edit Online
Объявление обычной переменной, простейшей формы прямого декларатора, указывает имя и тип
переменной. Оно также указывает класс хранения и тип данных переменной.
Классы хранения или типы (или и то, и другое) требуются в объявлениях переменных. Нетипизированные
переменные (например, var; ) создают предупреждения.
Синтаксис
declarator:
pointeropt direct-declarator
direct-declarator:
identifier
identifier:
nondigit
identifier nondigit
identifier digit
В случае арифметического типа, типа структуры, типа объединения, типа перечисления, типа void и типов,
представляемых именами typedef , простые деклараторы можно использовать в объявлении, поскольку
описатель предоставляет всю вводимую информацию. Для типов указателя, массива и функций требуются
более сложные деклараторы.
Чтобы указать несколько переменных в одном объявлении, можно использовать список идентификаторов,
разделенных запятыми ( , ). Все переменные, определенные в объявлении, имеют один и тот же базовый тип.
Пример:
Переменные x и y могут содержать любое значение в наборе, определенном типом int для конкретной
реализации. Простой объект z инициализируется значением 1 и не может быть изменен.
В этом примере обе переменные reply и flag имеют тип unsigned long и содержат целочисленные
значения без знака.
См. также
Деклараторы и объявления переменных
Объявления перечислений C
13.10.2020 • 6 minutes to read • Edit Online
Переменные типа enum можно использовать в выражениях индексации и в качестве операндов всех
арифметических операторов и операторов отношения. Перечисления являются альтернативой директиве
препроцессора #define с тем преимуществом, что можно создать значения, подчиняющиеся обычным
правилам области.
В ANSI C выражения, определяющие значение константы перечислителя, всегда имеют тип int . Таким
образом хранилище, связанное с переменной перечисления, является хранилищем, необходимым для
одного значения int . Константу перечисления или значение перечисляемого типа можно использовать
как целочисленное выражение в любом месте, допустимом в языке C.
Синтаксис
enum-specifier:
enum identifier opt { enumerator-list }
enum identifier
enum identifier
{
enumerator-list
}
объявляет , что identifier является тегом для перечисления, определенного нетерминальным параметром
enumerator-list. enumerator-list определяет содержимое перечислителя. Подробное описание параметра
enumerator-list представлено ниже.
Если объявление тега является видимым, все последующие объявления, в которых используется этот тег,
но отсутствует enumerator-list, обозначают ранее объявленный перечисляемый тип. Тег должен ссылаться
на определенный тип перечисления, и этот тип перечисления должен находиться в текущей области.
Поскольку тип перечисления определен в другом месте, enumerator-list не отображается в этом
объявлении. В объявлениях типов, производных от перечислений, и объявлениях typedef для типов
перечислений можно использовать тег перечисления до определения типа перечисления.
Синтаксис
enumerator-list:
enumerator
enumerator-list , enumerator
enumerator:
enumeration-constant
enumeration-constant = constant-expression
enumeration-constant:
identifier
Каждое значение enumeration-constant в списке enumerator-list именует значение набора перечисления.
По умолчанию первый параметр enumeration-constant связан со значением 0. Следующий параметр
enumeration-constant в списке связывается со значением (enumeration-constant + 1), если явно не указано
другое значение. Имя параметра enumeration-constant эквивалентно его значению.
К тегам перечисления применяются обычные правила области. Они должны отличаться от всех
тегов перечислений, структур или объединений с такой же видимостью.
Примеры
В следующих примерах показаны объявления перечисления.
Значение 0 связано с saturday по умолчанию. Для идентификатора sunday явно задано значение 0.
Оставшимся идентификаторам по умолчанию присваиваются значения от 1 до 5.
Обратите внимание, что имя константы перечисления используется для присвоения значения. Поскольку
тип перечисления DAY был объявлен ранее, необходим только тег перечисления DAY .
Чтобы явно присвоить целочисленное значение переменной перечисляемого типа данных, используйте
следующее приведение типа.
workday = ( enum DAY ) ( day_value - 1 );
или как
if ( match_flag == false )
{
.
. /* statement */
.
}
end_flag = true;
Также можно объявить неименованные типы данных перечислителя. Имя типа данных опускается, но
можно объявлять переменные. Переменная response является переменной определенного типа.
См. также
Перечисления
Объявления структур
13.10.2020 • 8 minutes to read • Edit Online
"Объявление структуры" именует тип и задает последовательность переменных значений ("элементы" или
"поля" структуры), которые могут иметь разные типы. Необязательный идентификатор — тег —
предоставляет имя типа структуры и может использоваться в последующих ссылках на тип структуры.
Переменная этого типа структуры включает определенную этим типом последовательность целиком.
Структуры в языке C аналогичны типам, известным в других языках как "записи".
Синтаксис
спецификатор-структуры-или-объединения:
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
структура-или-объединение:
struct
union
список-объявлений-структуры:
struct-declaration
struct-declaration-list struct-declaration
объявление-структуры:
specifier-qualifier-list struct-declarator-list ;
список-спецификаторов-и-квалификаторов:
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt
список-деклараторов-структуры:
struct-declarator struct-declarator-list , struct-declarator
декларатор-структуры:
declarator
type-specifier declaratoropt : constant-expression
Объявление типа структуры не оставляет места для структуры. Это всего лишь шаблон для последующих
объявлений структурных переменных.
Ранее определенный идентификатор (тег) можно использовать для ссылки на структурный тип,
определенный в другом месте. В этом случае список-объявлений-структур невозможно повторить, пока
определение видно. Объявления указателей на структуры и объекты typedef для типов структуры могут
использовать тег структуры до определения типа структуры. Однако определение структуры необходимо
получить до выполнения каких-либо фактических действий с размером полей. Это неполное определение
типа и тега типов. Для того чтобы это определение стало полным, определение типа должно
отображаться позже в той же области.
Невозможно объявить элемент так, чтобы он имел тип структуры, в которой отображается. Однако
элемент можно объявить как указатель на структурный тип, в котором он отображается, при условии, что
этот структурный тип имеет тег. Это позволяет создавать связанные списки структур.
Доступ к вложенным структурам можно осуществлять так же, как если бы они были объявлены на уровне
области файлов. Например, с данным объявлением
struct a
{
int x;
struct b
{
int y;
} var2;
} var1;
struct a var3;
struct b var4;
Примеры
В следующих примерах показаны объявления структуры.
Структура employee содержит три члена: name , id и class . Член name — это 20-элементный массив, а
id и class — простые элементы с типом int и long соответственно. Идентификатор employee
является идентификатором структуры.
В этом примере определяются три переменных структуры: student , faculty и staff . Каждая структура
имеет такой же список из трех элементов. Эти элементы объявлены как имеющие структурный тип
employee , определенный в предыдущем примере.
struct /* Defines an anonymous struct and a */
{ /* structure variable named complex */
float x, y;
} complex;
Структура complex содержит два элемента с типом float — x и y . Тип структуры не имеет тегов и,
следовательно, является безымянным или анонимным.
Первые два элемента структуры — это переменная char и указатель на значение float . Третий элемент ,
next , объявляется как указатель на определяемый структурный тип ( sample ).
Анонимные структуры могут быть полезны, если именованный тег не требуется. Это происходит в том
случае, если одно объявление определяет все экземпляры структуры. Пример:
struct
{
int x;
int y;
} mystruct;
struct somestruct
{
struct /* Anonymous structure */
{
int x, y;
} point;
int type;
} w;
Компилятор позволяет использовать безразмерный массив или массив нулевого размера в качестве
последнего члена структуры. Это полезно, если размер константного массива различается при
использовании в разных ситуациях. Объявление такой структуры выглядит следующим образом.
Объявления структуры также можно задать без декларатора, если они являются элементами другой
структуры или объединения. Уровень имен полей повышается до уровня внешней структуры. Например,
безыменная структура выглядит следующим образом:
struct s
{
float y;
struct
{
int a, b, c;
};
char str[10];
} *p_s;
.
.
.
p_s->b = 100; /* A reference to a field in the s structure */
См. также
Деклараторы и объявления переменных
Битовые поля в C
13.10.2020 • 4 minutes to read • Edit Online
Представлять собой заданное количество бит , т. е. "битовое поле", могут не только деклараторы для
членов структуры или объединения, но и декларатор структуры. Указание его длины отделяется от
декларатора имени поля двоеточием. Битовое поле интерпретируется как целочисленный тип.
Синтаксис
декларатор-структуры:
declarator
type-specifier declaratoropt : constant-expression
Выражение constant-expression задает ширину поля в битах. type-specifier для declarator должен иметь тип
unsigned int , signed int или int , а значение constant-expression должно быть неотрицательными и
целочисленным. Если указано значение 0, то объявление не содержит declarator . Массивы битовых полей,
указатели на битовые поля, а также функции, возвращающие битовые поля, не допускаются.
Необязательный параметр declarator задает имя битового поля. Битовые поля могут объявляться только в
рамках структуры. Оператор взятия адреса ( & ) не может применяться к компонентам битового поля.
Битовые поля должны иметь достаточную длину, чтобы вмещать в себя битовый шаблон. Например,
следующие два оператора недопустимы.
struct
{
unsigned short icon : 8;
unsigned short color : 4;
unsigned short underline : 1;
unsigned short blink : 1;
} screen[25][80];
Массив содержит 2000 элементов. Каждый элемент представляет собой отдельную структуру с четырьмя
членами, каждый из которых представляет собой битовое поле: icon , color , underline и blink . Размер
каждой структуры равен 2 байтам.
Битовые поля имеют одну и ту же семантику, что и целочисленный тип. Это означает , что битовое поле
используется в выражениях точно так же, как использовалась бы переменная того же базового типа,
независимо от количества битов в битовом поле.
Битовые поля, определенные как int , обрабатываются как signed . Расширение Microsoft к стандарту ANSI
C допускает битовые поля типов char и long (как signed , так и unsigned ). Неименованные битовые поля
с базовым типом long , short или char ( signed или unsigned ) принудительно устанавливают
выравнивание по границе, соответствующей этому типу.
Битовые поля в целом числе назначаются в направлении от младшего разряда к старшему. В приведенном
ниже коде
struct mybitfields
{
unsigned short a : 4;
unsigned short b : 5;
unsigned short c : 7;
} test;
00000001 11110010
cccccccb bbbbaaaa
Поскольку в процессорах семейства 8086 младший байт целочисленных значений размещается перед
старшим байтом, указанное выше целое число 0x01F2 будет храниться в физической памяти как 0xF2 , за
которым следует 0x01 .
См. также
Объявления структур
Хранение и выравнивание структур
13.10.2020 • 3 minutes to read • Edit Online
Структурные элементы сохраняются последовательно, в порядке объявления: первый элемент имеет самый
низкий адрес памяти, а последний — наивысший.
У каждого объекта есть элемент alignment-requirement. Для структур таким требованием является
крупнейший из элементов таких структур. Каждому объекту задается элемент offset, чтобы было верно
следующее выражение:
offset % alignment-requirement == 0
Смежные битовые поля упакованы в тот же одно-, двух- или четырехбайтовый модуль распределения, если
целочисленные типы имеют тот же размер и если следующее битовое поле помещается в текущий блок
распределения, не пересекая границ, установленных общими требованиями выравнивания битовых полей.
Для экономии места или соответствия существующим структурам данных может потребоваться сохранить
структуры более или менее компактно. Параметр компилятора /Zp[n] и #pragma pack управляют упаковкой
данных структуры в память. При использовании параметра /Zp[n], где n — 1, 2, 4, 8 или 16, каждый элемент
структуры после первого хранится в байтовом диапазоне, который представляет собой требование к
выравниванию поля или размер пакета (n) в зависимости от того, что меньше. В виде формулы байтовые
границы можно выразить следующим образом:
где n — это размер пакета, выраженный с параметром /Zp[n], а item — это элемент структуры. Размер
пакета по умолчанию — /Zp8.
Чтобы использовать директиву pragma pack для указания упаковки, отличной от заданной в командной
строке для определенной структуры, разместите директиву pragma pack , где размер пакета — 1, 2, 4, 8 или
16, перед структурой. Для возобновления компоновки в соответствии с инструкциями с командной строки
задайте директиву pragma pack без аргументов.
Битовые поля по умолчанию имеют размер long для компилятора Microsoft C. Элементы структуры
выравниваются по размеру типа или размеру /Zp [n] в зависимости от того что меньше. Размер по
умолчанию — 4.
См. также
Объявления структур
Объявления объединений
13.10.2020 • 4 minutes to read • Edit Online
Объявление объединения определяет набор значений переменных и при необходимости тег, который
именует объединение. Значения переменных называются членами объединения и могут иметь различные
типы. Объединения аналогичны вариантным записям в других языках.
Синтаксис
спецификатор-структуры-или-объединения:
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
структура-или-объединение:
struct
union
список-объявлений-структуры:
struct-declaration
struct-declaration-list struct-declaration
Содержимое объединения определено как
объявление-структуры:
specifier-qualifier-list struct-declarator-list ;
список-спецификаторов-и-квалификаторов:
type-specifier specifier-qualifier-listopt
type-qualifier specifier-qualifier-listopt
список-деклараторов-структуры:
struct-declarator
struct-declarator-list , struct-declarator
Переменная с типом union хранит одно из значений, определенных в этом типе. Объявления структуры и
объединения подчиняются тем же правилам. Объединения также могут иметь битовые поля.
Элементы объединений не могут иметь неполный тип, тип void или тип функции. Поэтому члены могут
быть указателями на объявляемый тип объединения, но не экземпляром объединения.
Объявление типа объединения — это лишь шаблон. Память не резервируется, пока не будет объявлена
переменная.
NOTE
Если объявляется объединение двух типов и сохраняется одно значение, но для доступа к объединению
используется другой тип, результаты будут ненадежными. Например, объявлено объединение float и int .
Сохраняется значение float , но программа позднее использует это значение как int . В таком случае
полученное значение будет зависеть от внутренних хранимых данных для значений float . Целочисленное
значение будет ненадежным.
Примеры
Ниже представлены примеры объединений.
В этом примере определяется переменная объединения с типом sign и объявляется переменная number с
двумя членами: целым числом со знаком svar и целым числом без знака uvar . В результате этого
объявления можно сохранить текущее значение number как целое число со знаком или целое число без
знака. С данным типом объединения связан тег sign .
Массив screen содержит 2000 элементов. Каждый элемент массива представляет собой отдельное
объединение с двумя членами: window1 и screenval . Член window1 является структурой с двумя членами-
битовыми полями: icon и color . Элемент screenval представляет собой int . В любой момент времени
каждый элемент объединения содержит значение int , представленное screenval , либо структуру,
представленную значением window1 .
Вложенные объединения можно объявить анонимно, если они являются членами другой структуры или
объединения. Ниже приводится пример безымянного объединения.
struct str
{
int a, b;
union / * Unnamed union */
{
char c[4];
long l;
float f;
};
char c_array[10];
} my_str;
.
.
.
my_str.l == 0L; /* A reference to a field in the my_str union */
Объединения часто являются вложенными в структуре, содержащей поле, ко