Пост

Структура программы на языке Си

Основная точка входа программы

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

1
2
int main(void) { /* ... */ }
int main(int argc, char *argv[]) { /* ... */ }

Дополнительно про main_function

Основной синтаксис программы

Фигурные скобки ‘{}’ обозначают начало и конец блока, где располагается какой-то код и в большинстве случаев они обязательны. Они нужны для того чтобы логически отделить принадлежность группы каких-то инстуркций от других блоков.

Вернемся к программе из вводного урока hello.c:

1
2
3
4
5
6
#include <stdio.h>

int main() {
    printf("hello, world\n");
    return 0;
}

При запуске, выполнение программы начнется с функции main. Все инструкции внутри фигурных скобок,
начиная с ‘{‘ и заканчивая ‘}’ - будут выполнятся последовательно друг за другом:

1) printf("hello, world\n");
2) return 0;

Каждая инструкция в языке Cи ДОЛЖНА заканчивается “;”.
Это настолько важно, что если пропустить ее, компилятор вам об этом сообщит:

1
2
3
4
5
6
7
8
root@fedora-develop:~/C# gcc semi_error.c -o semi_error
semi_error.c: In function ‘main’:
semi_error.c:4:27: error: expected ‘;’ before ‘return’
    4 |     printf("hello, world")
      |                           ^
      |                           ;
    5 |     return 0;
      |     ~~~~~~                 

Сообщит также и о неоткрытой в начале ‘{‘ фигурной скобке:

1
2
3
4
5
6
7
8
9
10
11
semi_error.c: In function ‘main’:
semi_error.c:4:5: error: expected declaration specifiers before ‘printf’
    4 |     printf("hello, world");
      |     ^~~~~~
semi_error.c:5:5: error: expected declaration specifiers before ‘return’
    5 |     return 0;
      |     ^~~~~~
semi_error.c:6:1: error: expected declaration specifiers before ‘}’ token
    6 | }
      | ^
semi_error.c:7: error: expected ‘{’ at end of input

Так и о не закрытой в конце:

1
2
3
4
5
root@fedora-develop:~/C# gcc semi_error.c -o semi_error
semi_error.c: In function ‘main’:
semi_error.c:5:5: error: expected declaration or statement at end of input
    5 |     return 0;
      |     ^~~~~~

Разница между инструкцией и ключевым словом

В языке Си есть такое понятие как минимальная единица синтаксиса программы, ту которую компилятор может распознать и называется это - лексема. Лексемы языка Си включают различные элементы, такие как ключевые слова, операторы, идентификаторы, литералы и так далее.

Ключевые слова

Ключевые слова - это слова, которые зарезервированы в языке и используются компилятором
для распознания каких-то определенных действий.

Например: int, char, if, return, for

Операторы

К операторам относятся арифметические операции, операции сравнения:

Например: +, -, *, /, ==, >, <

Идентификаторы

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

  • myFunction
  • my_var
  • var1

Литералы

Литерал - это строка, число или символ, которое можно описать в программе следующим образом:

  • 123
  • “hello world”
  • ‘fuck’
  • 3.14

WIKI

Разделительные символы

; () {} ,

Комментарии

Комментарии больше относятся к синтаксической конструкции и в языке Си есть два вида комментариев:

Многострочные: /* Это комментарий */
Однострочные: // Это комментарий

Однострочные комментарии появились начиная со стандарта C99. Ранее в языке были только многострочные комментарии, хотя в С++, многострочные комментарии появились в стандарте С++98. Комментарии никак не обрабатываются компилятором и предназначены для программистов

Последовательная обработка программы

1
2
3
4
5
6
#include <stdio.h>

int main() {
    printf("hello, world\n");
    return 0;
}

#include - ключевое слово для препроцессора. Source file inclusion

<stdio.h> - это просто файл с объявлениями функций. Данный файл можно легко найти в Linux:

1
2
3
4
root@fedora-develop:~/C# find / -name 'stdio.h' 2> /dev/null 
/usr/include/c++/13/tr1/stdio.h
/usr/include/bits/stdio.h
/usr/include/stdio.h

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

1
2
3
4
5
root@fedora-develop:~/C# gcc -E -Wp,-v -
#include <...> search starts here:
 /usr/lib/gcc/x86_64-redhat-linux/13/include
 /usr/local/include
 /usr/include

Поведение препроцессора для ключевого слова #include выглядит так:

1) Обработка #include:

  • Когда препроцессор встречает директиву #include, он ищет указанный файл заголовка.

2) Поиск заголовочных файлов:

  • Если указанный файл заголовка заключен в угловые скобки (#include <file.h>), препроцессор
    обычно ищет файл в стандартных системных директориях для заголовочных файлов.

  • Если файл заголовка указан в двойных кавычках (#include "file.h"), препроцессор
    сначала ищет файл в текущем каталоге, а затем включает поиск в стандартных системных директориях.

3) Абсолютные и относительные пути:

  • Если указан абсолютный или относительный путь к файлу, препроцессор использует этот путь для поиска.

int main() {

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

main - это идентификатор но так как это основная точка входа программы
этот идентификатор можно назвать зарезервированным идентификатором.

’()’ и ‘{}’ - это Разделительные символы

printf("hello, world\n"); - функция, которая является частью стандартной библиотеки GNU C Library

Функция printf() - выводит информацию на стандартный поток вывода stdout.
В качестве аргументов, в данном случае, она принимает строку и специальный символ ‘\n’, называемый escape-последовательностью

Например ‘\n’ - переводит вывод данных на левый край новой строки.

return 0; - эта инструкция возвращает значение из функции main, в данном примере она вернет свое значение в операционную систему. В этом можно легко убедиться и продемонстрировать скомпилировав и запустив тестовую программу hello.c:

1
2
3
4
root@fedora-develop:~/C# gcc main.c -o main
root@fedora-develop:~/C# ./main; echo $?
Hello world
0

‘0’ в контексте завершения работы программы означает ее успешное завершение. Мы можем также вернуть любое другое значение:

1
2
3
4
5
#include <stdio.h>
int main(int argc, char* argv[]) {
  printf("Hello world\n");
  return 100;
} 

Проверяем:

1
2
3
4
root@fedora-develop:~/C# gcc main.c -o main
root@fedora-develop:~/C# ./main; echo $?
Hello world
100

Ненулевые значения могут использоваться для указания на различные виды ошибок или проблемы в программе.

Литература

Авторский пост защищен лицензией CC BY 4.0 .

© spybull. Некоторые права защищены.

Использует тему Chirpy для Jekyll

Популярные теги