March 13th, 2020

13 глава Лафоре, обязательность main, С++

В 13-й главе учебника Лафоре в разделе «Межфайловое взаимодействие» много мелких кусков кода, иллюстрирующих текст учебника, но они не оформлены в какие-то небольшие примеры, как это было в предыдущих главах. Это, мне кажется, недостаток. Возможно, не хватало места, ведь бумажный учебник к тому моменту, видимо, уже получался слишком толстым. Я решил немного покрутить эти куски кода в компиляторе.

Этот код не выполняет какой-либо работы, так как он нужен лишь для иллюстрации правил объявления и определения программных элементов (переменных, функций, классов). Но нужно помнить, что определение функции main обязательно (в многофайловой программе — в одном из файлов), иначе компилятор (у меня — компилятор среды «Visual Studio Community 2017») выдаст ошибку компоновки:
error LNK2001: неразрешенный внешний символ "_main"
которая автоматически влечет за собой другую ошибку компоновки:
fatal error LNK1120: неразрешенных внешних элементов: 1

Одного объявления функции main тоже недостаточно:
int main();
необходимо определение этой функции (наличие тела функции), хотя бы так:
int main() {}

Тут нужно заметить, что инструкция return для функции main по стандарту не является обязательной. Ее отсутствие эквивалентно return 0;. Подробнее об этом можно прочитать тут:
https://en.cppreference.com/w/cpp/language/main_function

С++: объявление и определение переменной

Продолжение, начало тут: 13 глава Лафоре, обязательность main, С++.

Объявлением (по-английски «declaration») переменной называется указание ее типа и имени. Определение (по-английски «definition») переменной — это выделение под нее необходимой памяти.

int someVar;              // не только объявление, но и определение
cout << &someVar << endl; // выведем на экран для проверки адрес переменной
Этот код у меня работает без ошибок (компилятор среды «Visual Studio Community 2017»).

Почему? Казалось бы, я только объявил переменную. Однако, компилятор еще и выделил под эту переменную память, то есть произошло и определение этой переменной. Большинство объявлений переменных является одновременно и определениями.

Интересно, что если переменная глобальная (то есть определена вне тела какой-либо функции и не является членом класса или структуры), то при ее определении она еще считается и инициализированной нулем. Для локальной переменной это не так. Например:
#include <iostream>
using namespace std;

int someVar1;                 // глобальная переменная

int main()
{
    int someVar2;             // локальная переменная

    cout << someVar1 << endl; // выведет на экран число 0
    cout << someVar2 << endl; // ошибка компиляции
}
Текст ошибки будет следующий:
error C4700: использована неинициализированная локальная переменная "someVar2"

Это, видимо, не совсем ошибка, а, скорее, предупреждение. Его можно обойти. Например, так (следующий код у меня собирается без ошибок и работает):
#include <iostream>
using namespace std;

int someVar1;                  // глобальная переменная

int main()
{
    int someVar2;              // локальная переменная

    cout << someVar1 << endl;  // выведет на экран число 0
    cout << &someVar2 << endl;
    cout << someVar2 << endl;  // выведет на экран какое-то значение
}

Но какой в этом смысл? Хорошей практикой в программировании считается всегда инициализировать переменные перед их использованием. Это точно уменьшит число ошибок.