Цель данной статьи осветить некоторые тонкие моменты компиляции c++ приложения компилятором Visual Studio. Все примеры будут компилироваться из командной строки (bat файлами) это позволит лучше понять происходящее. В примерах я использую Visual Studio Express 2012 for Windows Desktop.
Рассмотрим следующий простой пример консольного приложения Windows в котором печатаются все параметры, передаваемые через командную строку, и переменные окружения (envp — это указатель на массив, содержащий переменные окружения с их значениями, разделенные знаком равенства (=)):
#include #include int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) < _tprintf(TEXT(«argc = %dn»), argc); for(int i = 0; i < argc; ++i) < _tprintf(TEXT(«argv[%d] = «%s»n»), i, argv[i]); >int n = 0; while(envp[n] != NULL) < _tprintf(TEXT(«envp[%d] = «%s»n»), n, envp[n]); n++; >return 0; >
.bat файл, компилирующий этот пример, имеет вид:
set «vc_path=C:Program FilesMicrosoft Visual Studio 11.0VC» call «%vc_path%vcvarsall.bat» x86 set «bin=bin» set «src=src» set «progname=simple» «%vc_path%bincl.exe» /c /ZI /nologo /W3 /Od /Oy- /D «WIN32» /D «_DEBUG» /D «_WINDOWS» /D «_UNICODE» /D «UNICODE» ^ /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fo»%bin%%progname%.obj» ^ /Fd»%bin%%progname%.pdb» /Gd /TP /analyze- /errorReport:prompt %src%%progname%.cpp «%vc_path%binlink.exe» /ERRORREPORT:PROMPT /OUT:»%bin%%progname%.exe» /INCREMENTAL /NOLOGO kernel32.lib user32.lib ^ gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib ^ odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:»level=’asInvoker’ uiAccess=’false'» ^ /manifest:embed /DEBUG /PDB:»%bin%%progname%.pdb» /TLBID:1 /DYNAMICBASE /NXCOMPAT ^ /IMPLIB:»%bin%%progname%.lib» /MACHINE:X86 %bin%%progname%.obj pause
При этом предполагается следующее расположение файлов
Как создать проект на языке си в Microsoft Visual Studio?
Во всех Windows-приложениях должна быть входная функция, за реализацию которой отвечаете вы. Существует две такие функции:
int WINAPI _tWinMain( HINSTANCE hInstanceExe, HINSTANCE, PTSTR pszCmdLine, int nCmdShow); int _tmain( int argc, TCHAR *argv[], TCHAR *envp[]);
_tWinMain и _tmain это в действительности макросы, которые раскрываются как WinMain или wWinMain для _tWinMain и main или wmain для _tmain в зависимости от того используется Unicode или нет.
На самом деле входная функция операционной системой не вызывается. Вместо этого происходит обращение к стартовой функции из библиотеки C/C++, заданной во время компоновки параметром -entry: командной строки. Она инициализирует библиотеку С/С++, чтобы можно было вызывать такие функции, как malloc и free, а также обеспечивает корректное создание любых объявленных вами глобальных и статических С++-объектов до того, как начинается выполнение вашего кода. В следующей таблице показано, в каких случаях реализуются те или иные входные функции.
Типы приложений и соответствующие им входные функции
Тип приложения | Входная функция | Стартовая функция, встраиваемая в исполняемый файл |
GUI-приложение, работающее с ANSI-символами и строками | _tWinMain (WinMain) | WinMainCRTStartup |
GUI-приложение, работающее с Unicode-символами и строками | _tWinMain (wWinMain) | wWinMainCRTStartup |
CUI-приложение, работающее с ANSI-символами и строками | _tmain (main) | mainCRTStartup |
CUI-приложение, работающее с Unicode-символами и строками | _tmain (wmain) | wmainCRTStartup |
Компоновщик отвечает за выбор подходящей стартовой функции из библиотеки С/С++ при компоновке исполняемого файла. Если задан ключ /SUBSYSTEM:WINDOWS, компоновщик ищет в коде функцию WinMain или wWinMain. Если этих функций нет, компоновщик сообщает об ошибке «unresolved external symbol». В противном случае компоновщик выбирает WinMainCRTStartup или wWinMainCRTStartup, соответственно.
Аналогичным образом, если задан ключ /SUBSYSTEM:CONSOLE, компоновщик ищет в коде функцию main или wmain и выбирает соответственно mainCRTStartup или wmainCRTStartup; если в коде нет ни main, ни wmain, сообщается о той же ошибке – «unresolved external symbol».
Но не многие знают, что в проекте можно вообще не указывать ключ /SUBSYSTEM компоновщика. Если вы так и сделаете, компоновщик будет сам определять подсистему для вашего приложения. При компоновке он проверит, какая из четырех функций ( WinMain, wWinMain, main или wmain ) присутствует в вашем коде, и на основании этого выбирет подсистему и стартовую функцию из библиотеки С/С++.
Теперь несколько замечаний по .bat файлу и ключам компилятора и компоновщика
При создании .bat файла нужно четко следить за тем, чтобы создаваемый текстовый файл имел формат завершения строки в стиле Windows или Unix, но не Mac, иначе bat файл просто не будет запускаться.
Для нормальной работы компилятора перед вызовом cl.exe или link.exe необходимо вызвать call “%vc_path%vcvarsall.bat” x86. Этот bat файл инициализирует переменные окружения INCLUDE, LIB, LIBPATH, PATH и некоторые другие необходимые для работы cl.exe и link.exe. Например, в моем случае было
set «INCLUDE=C:Program FilesMicrosoft Visual Studio 11.0VCINCLUDE;C:Program FilesWindows Kits8.0includeshared;C:Program FilesWindows Kits8.0includeum;C:Program FilesWindows Kits8.0includewinrt;» set «LIB=C:Program FilesMicrosoft Visual Studio 11.0VCLIB;C:Program FilesWindows Kits8.0libwin8umx86;» set «LIBPATH=C:WindowsMicrosoft.NETFrameworkv4.0.30319;C:WindowsMicrosoft.NETFrameworkv3.5;C:Program FilesMicrosoft Visual Studio 11.0VCLIB;C:Program FilesWindows Kits8.0ReferencesCommonConfigurationNeutral;C:Program FilesMicrosoft SDKsWindowsv8.0ExtensionSDKsMicrosoft.VCLibs11.0ReferencesCommonConfigurationneutral;»
При вызове cl.exe использовались следующие ключи:
- /с – компиляция без связывания
- /ZI – компилятор включает отладочную информацию в базу данных приложения (только для x86)
- /nologo – подавляет отображение информации о компиляторе
- /W3 – устанавливает уровень предупреждений компилятора на 3 уровень
- /Od – отключает оптимизацию (так как /Od предотвращает перемещение кода, установка этого ключа облегчает процесс отладки)
- /Oy – предотвращает создание указателей фрейма в стеке вызова, /Oy- отключает такое поведение (только для x86)
- /D “_DEBUG” – определяется при компиляции с ключами /LDd, /MDd и /MTd
- /D “_WINDOWS” – определяет, что целевая OS – Windows
- /D “UNICODE” – указывает компилятору на необходимость использовать в приложении версии Win API функций для работы с Unicode
Например, вот фрагмент из WinUser.h:
#ifdef UNICODE #define CreateWindowEx CreateWindowExW #else #define CreateWindowEx CreateWindowExA #endif
#ifdef _UNICODE #define _tcslen wcslen #else #define _tcslen strlen #endif
- инициализацию локальных переменных ненулевыми значениями. Это позволяет идентифицировать баги, которые не проявляются в отладочной сборке. Больщая вероятность, что переменная в стеке будет оставаться нулевой в отладочной сборке нежели в рилизной сборке, так как компилятор оптимизирует стек переменных в рилиной сборке. Будучи однажды использованной память отведенная под стек не обнуляется компилятором. По этому, последующие не инициализированные переменные в стеке будут содержать значения оставшееся от предыдущего использования этой области памяти.
- Проверка выхода за границы локальных переменных, таких как массивы. /RTCs не определяет выход за границы при обращении к памяти явившейся результатом выравнивания компилятором положения структуры в памяти. Такое может произойти при использовании выравнивания (С++ ), /Zp или pack или, если вы распологаете элементы структуры в таком порядке, который вынуждает компилятор вставлять отступы.
- Проверка указателя стека, что позволяет определить разрушение указателя стека. Разрушение указателя стека может произойти при несоответствии типов вызова. Например, используя указатель на функцию, вы можите вызвать функцию из DLL, которая экспортируется как __stdcall, но вы определили указатель на функцию как __cdecl.
Замечание:
стековый фрейм (функции) – область памяти, выделяемая всякий раз, когда вызывается функция, предназначается для временного хранения аргументов и локальных переменных функции.
/RTCu – заставляет компилятор выдавать предупреждения, когда переменная используется без инициализации. Например, команда, которая генерирует предупреждение (4-го уровня) С4701 может также генерировать ошибку времени выполнения при установленном ключе /RTCu. Любые команды, которые генерируют предупреждения компилятора (уровня 1 и 4) С4700, будут также генерировать ошибку времени выполнения при установленном ключе /RTCu.
Тем не менее, рассмотрим следующий фрагмент кода:
int a, *b, c; if ( 1 ) < b = >c = a; // No run-time error with /RTCu
Если переменная могла быть проинициализирована, установка ключа /RTCu не приведет к предупреждению времени исполнения. В сущности, вы можете проинициализировать переменную, выполняя операцию взятия ее адреса. В последнем фрагменте кода оператор http://www.sternkn.com/compiler-visual-studio-beginning/» target=»_blank»]www.sternkn.com[/mask_link]
Как писать на C в Visual Studio 2017?
Как установить язык C в Visual Studio 2017?
Нужен именно C, а не C++ или C#. При установке просто нет обычного C.
- Вопрос задан более трёх лет назад
- 8471 просмотр
Комментировать
Решения вопроса 0
Ответы на вопрос 2
А что делать,если в настройках все изменила, но после сборки выдает такую ошибку?
Ответ написан более трёх лет назад
Нравится 1 2 комментария
Привет!
Могу дать парочку советов о том, как писать в VS на си. (испытал уже на себе).
1) Создаете пустой проект (не файл , а именно проект)
2) Справа в обозревателе решений в папку *Исходные файлы* (Source files) создаете файл срр нажатием правой кнопки мыши.
3) пишите в самом начале код #define _CRT_SECURE_NO_WARNINGS ( отключит оповещения об *небезопасном* использовании printf, scanf и тп.)
4) обязательно подключайте библиотеку stdio.h
5) вместо привычной задержки консоли getch() используйте _getche()
На скриншоте видно, что вы создали ConsoleAplication, поэтому у вас ошибка.
Попробуйте создать проект и посмотрите на изменения.
Источник: qna.habr.com
Основы программирования в Visual Studio
Разработка программного обеспечения, в наши дни, стала гораздо более простым и быстрым процессом, чем 25-30 лет назад. Современные пользователи имеют открытый доступ к мощным средам разработки и удобным языкам программирования, которые на порядок облегчают создание ПО. Сегодня, для написания своей собственной программы, вам достаточно иметь подходящий инструмент и знания, как им пользоваться, и мы с удовольствием поделимся с вами и тем и другим.
Уроки Visual Studio
Представляем вашему вниманию мини-курс по разработке программного обеспечения в среде Visual Studio компании Microsoft. Представленные видеоуроки познакомят вас с основами программирования и научат создавать программы на языке C++. Курс состоит из 16-ти уроков, общей продолжительностью 5 часов 55 минут. За это время вы поймете саму суть строения программ и навсегда ликвидируете свою компьютерную безграмотность.
Первый взгляд на Visual Studio. Разбор интерфейса и настроек среды.
Скачать бесплатную версию Visual Studio можете на нашем сайте — 4creates.com/programm.
В данном уроке вы узнаете, что такое интегрированные среды разработки, поймете общий принцип строения программ, научитесь различать диалекты языка и создадите свою первую программу.
Знакомство с языком C++ и его структурой. Базовые знания о данных, функциях и переменных.
Что такое венгерская нотация. Правила ввода переменных и синтаксисов. Блоки цифровой информации и манипуляторы signed / unsigned.
Продолжаем изучение манипуляторов signed / unsigned и разбираем типы с плавающей точкой.
Из данного видео вы узнаете, что такое тип char и typedef, а также познакомитесь с литералами, энумерациями и непечатными символами.
Основы унарных и бинарных операторов. Изучение функции определение типов, статичного кастинга и побитовых операций.
Урок затронет несколько важных мелочей. Вы узнаете, что такое приоритет операторов, пространство имен и продолжительность хранения, а также познакомитесь с логическими конструкциями и символическими константами.
Учимся использовать операторы сравнения, вложенные и логические конструкции, безусловные переходы и переключатели.
Как и где применяются циклы типов for и while. Смотрим и повторяем.
Обзор массивов (одномерных и многомерных) и знакомство со строками в стиле C.
В данном уроке вы познакомитесь с клеточным автоматом Джона Конвея, и научитесь применять его на практике.
Описание косвенной передачи данных, адресов и указателей (в т.ч. на тип char).
На этом занятии речь пойдет о константах, указателях и многомерных массивах.
Обзор ссылок сторонних выражений, а также динамических массивов и переменных.
Предназначение функций в языке C++. Способы передачи аргументов по указателям и ссылкам.
Откройте свой разум для новых знаний и обучение превратиться в непринужденный и увлекательный процесс. Желаем вам всех благ и успехов в любых начинаниях!
Скачать все уроки одним архивом
Похожие материалы
Создаем рисованные презентации в Sparkol (Видеокурс) Обучающий курс по программе Sparkol Videoscribe. Пошаговые видеоуроки познакомят вас с многочисленными возможностями редактора и научат создавать живые презентации, рисуемые рукой.
Вводный курс по КОМПАС-3D Два набора видеоуроков по работе с программой. Один ориентирован на освоение и пошаговое изучение базовых функций, другой – непосредственно на изучение моделирования на конкретных примерах. Также в курсе детально разбирается работа с инструментами и функционалом.
Уроки MAGIX Music Maker Сжатый обучающий курс в видео формате. Наглядно продемонстрирует новичкам основной инструментарий программы и научит создавать музыкальные треки высокого качества.
Больше статей Полезные программы Больше программ
Visual Studio 2013 Создание программ, Интегрированные среды разработки, Визуальные среды разработки
Visual Studio Code Создание программ, Интегрированные среды разработки, Визуальные среды разработки
Microsoft Visual Studio 2019 Создание программ, Интегрированные среды разработки, Визуальные среды разработки
Pascal ABC Создание программ, Интегрированные среды разработки
Источник: 4creates.com