Программы
Функции и типы в первом приближении

Функции и типы в первом приближении

Назад, к "первой утилите".

0 программистов ругал сердитый шeф,

Потом уволил одного, и стало их FF.

– Юрий Нестеренко, "0A программистов"

Сейчас мы немного рассмотрим теорию, чтобы заполнить пространство под вопросом о false – будет много букв – сложнее случайно увидеть "ответ".

Но эта теория тут не просто так: наша функция main – хоть и необычная, но функция. Опять же, мы объявили саму функцию main как функцию, возвращающую int – тип данных. Очень хитрый тип данных.

Немного о функциях

Итак, в общем виде функцию можно описать следующим шаблоном:

<возвращаемый тип> <имя функции>(<тип1> <арг1>, <тип1> <арг2>, ...) {
    <тело функции>
}

Функция имеет свою локальную область видимости – переменные, определённые внутри неё недоступны снаружи. По факту они создаются на стеке и после выхода из функции стек откатится к состоянию до попадания в функцию – данные станут недоступны (разве что не найдётся какой-то обходной путь – хак).

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

Возврат значений производится, как и во многих языках с помошью return.

Стоит заметить, что в отличии от всяких Go и Python, мы не можем вернуть сразу несколько значений. Это ограничение, естественно, можно обойти, но оно же во многом определило, как создаются API многих функций. Так, на будущее.

Что такое int?

Вернёмся к нашему "хитрому" типу данных. Типы данных во многих существующих языках – набор функций и ограничений на хранимую в переменной информацию. В Си же это размер байт, выделенных на переменную (этакое ограничение) + его представление (удобство, "синтаксический сахар" для работы с байтами).

В чём же хитрость?

Начнём с того, что int – знаковое целое – то есть туда можно положить целое число: хоть отрицательное, хоть положительное. Но не очень большое.

Размер int зависит то платформы. Посмотреть размер типа или переменной можно функцией sizeof:

    int main() {
        return sizeof(int);
    }

Собираем:

    clang int_size.c -o ./int_size

Запускаем:

falseecho $?
    4

– видим, что в нашем случае int занимает 4 байта.

А что, если мы туда положим что-то большее?

    int main(void) {
        int num = 0xffffffff;
        return num + 12;
    }

Переполнение:

echo $?
    11

На самом деле 0xffffffff – не самый большой int, самый большой – 0x7FFFFFFF из-за устройства представления байтов знаковым целым числом. В диапозоне [8000000, 0xffffffff] - отрицательные числа.

То есть первый бит – бит знака. Так что, если вы выйдите за самое большое число int, вы внезапно получите самое маленькое число... Вот такой он, хитрый int!

Однако, 0xffffffff прекрасно справляется с демонстрацией переполнения 0xffffffff + 12 = 11.

Ответ на загадку

Так что, если взять 0xffffffff и прибавить к нему 1... И вернуть это... В общем, это явно не было нулём, но стало! Более того: код возврата вообще ограничен беззнаковым байтом, так что каждое число, кратное 256 – также окажется истиной! И да, это уже вопросы к самому коду.

Также может быть вам интересно:

Первая реальная утилита

Вы когда-нибудь писали код командной строки? А из чего она состоит? А поковыряемся чутка!

Читать »

Почему мы начали не с "Hello World"?

Часто начинают именно с "Hello world", но для нас это не подходит

Читать »
Фото Python: Встроенные типы данных (list, set, dict, etc)

Python: Встроенные типы данных (list, set, dict, etc)

В Python есть множество встроенных типов данных. Их использование значительно упрощает жизнь и ускоряет разработку программных продуктов.

Фото Python: типы данных, переменные, логическое ветвление и циклы

Python: типы данных, переменные, логическое ветвление и циклы

Первая часть заметок о Python. О базовых типах, переменных, ветвлении и циклах.

Фото Как сделать свою middleware в Django (с примерами)

Как сделать свою middleware в Django (с примерами)

Middleware или "промежуточное программное обеспечение" - элегантный способ установить общие правила обработки запросов и ответов приложения. Давайте напишем парочку middleware, чтобы понять, как они работают.

Фото Как настроить отправку почты из Django

Как настроить отправку почты из Django

Письма об ошибках, отчёты на почту, восстановление паролей - всё это полезно при работе с сайтом. Django предоставляет удобный способ это сделать с минимумом настроек!

Фото Добавляем постраничную пагинацию на Django сайт

Добавляем постраничную пагинацию на Django сайт

На сайтах часто встречаются многостраничные объекты: список товаров, список заметок и т.д. Поэтому важно уметь добавить навигацию по страницам на Django-проекте.

Фото Новый оператор match-case в Python

Новый оператор match-case в Python

В новой версии Python (3.10) появится новый оператор. Новый оператор сопоставления по шаблону (match-case).

Фото Нет слов, одни... однострочники

Нет слов, одни... однострочники

На днях вышел пост со списком полезных однострочников для JavaScript программистов. Памятуя Perl-овую молодость, заглянул туда.

Фото Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

Добавляем переменные в контекст Django шаблонов (свой контекст-процессор)

В Django вы можете передавать данные в шаблоны посредством контекстов. Контекст передаётся из контроллера (view в терминах Django), однако, если одни и те же данные нужны в разных местах, лучше сделать свой контекст-процессор.