Функции и указатели в C++
В языке С++ присутствует возможность использовать функции, то есть логичекские структурные единицы кода, которые позволяют сделать код более читаемым и разделить функционал.
myFunction.cpp
Синтаксис функций можно описать следующим образом:
тип_возвращаемого_значения название_функции(аргументы_функции) . код функции . >
Пример функции, возвращающей наибольшее число из двух:
int max(int x, int y) if (x > y) return x; else return y; >
Вызов функции выглядит следующим образом:
int a = 150; int b = 980; int c = max(a, b) // Функция вернет значение 980
Указатели
Попробуем реализовать функцию, которая принимает 3 integer переменных, сравнивает 2 из них и результат сравнения(наибольшее из чисел) записывает в третий аргумент.
madMax.cpp
Кажется логичным сделать подобную реализацию этой функции:
void max(int x, int y, int c) if (x > y) c = x; else c = y; >
Однако, мы можем убедиться в том, что следующий код, использующий нашу функцию сработает некорректно.
int a = 150; int b = 980; int c = 0; max(a, b, c) std::cout c; // Печатает 0 а не 980.
Что произошло? Все дело в том, что при вызове функции в ее аргументы были переданы всего лишь значения переменных a, b, c, которые равнялись соответственно 150, 980 и 0. Поэтому внутри функции были созданы переменные x, y, c в которых хранились эти значения, но эти переменные лежат совсем по другим адресам в оперативной памяти. Соответственно, изменение значений переменных внутри функций приводит к тому, что они изменяются не по тем адресам, в которых лежат переменные вызывающей стороны.
Указатели — это один из способов, позволяющих решить данную проблему. Идея заключается в том, чтобы передавать не значение переменной, а ее адрес в оперативной памяти, по которму можно определить и изменить значение.
Тогда с учетом этого, функция max() должна быть модифицирована следующим образом:
void max(int x, int y, int* c) if (x > y) *c = x; else *c = y; >
Где int* — это тип аргумента, означающий адрес на переменную типа integer. Оператр * позволяет обратиться по адресу данной переменной и считать или записать значение.
Как же теперь вызывать эту функцию?
int a = 150; int b = 980; int c = 0; max(a, b, &c) std::cout c; // Печатает 980
Теперь все заработало. Оператор & позволяет узнать адрес переменной и, например, как здесь, передать его в функцию, для того, чтобы та могла записать по нему новое значение.
Сайт построен с использованием Pelican. За основу оформления взята тема от Smashing Magazine. Исходные тексты программ, приведённые на этом сайте, распространяются под лицензией GPLv3, все остальные материалы сайта распространяются под лицензией CC-BY-SA.
Использование INT_MAX и INT_MIN в C/C++
В этой статье мы рассмотрим использование INT_MAX и INT_MIN в C/C++.
На самом деле это полезные макросы, которые представляют максимальное и минимальное целочисленные значения.
Давайте посмотрим на это, используя несколько примеров.
Использование INT_MAX и INT_MIN
INT_MAX — это макрос, представляющий максимальное целочисленное значение. Точно так же INT_MIN представляет минимальное целочисленное значение.
#include INT_MAX INT_MIN
Обратите внимание, что любая целочисленная переменная должна находиться между INT_MIN и INT_MAX. Обычно целые числа хранятся в виде 4 байтов (32 бита). Это означает, что почти на всех машинах максимальное целочисленное значение будет 2^(31) — 1=+2147483647. Минимальное целочисленное значение будет -(2^31)=-2147483648. Давайте проверим это для нашей машины.
#include #include int main()
Maximum Integer Value: 2147483647 Minimum Integer Value: -2147483648
Действительно, мы получаем то, что предсказываем. Давайте теперь возьмем другой пример, чтобы правильно предсказать любое целочисленное переполнение или потерю значимости.
#include #include int main() < int value = 0; while (value >= 0) < // Check for overflow if (value == INT_MAX) < printf("value = %d. Possible overflow!\n", value); >value ++; > printf("Now, value = %d\n", value); value = 0; while (value value --; > printf("Now, value = %d\n", value); return 0; >
value = 2147483647. Possible overflow! Now, value = -2147483648 value = -2147483648. Possible underflow! Now, value = 2147483647
Хотя это занимает несколько секунд, это действительно делает то, что мы ожидаем. Целое число переполнится до INT_MIN и переполнится до INT_MAX . Это полезно для обнаружения таких скачков значений.
Зачем нужны эти макросы?
- Чтобы избавить вас от необходимости запоминать фактические значения.
- Используйте единые шаблоны программирования на всех компьютерах
- Очень удобно использовать
Надеюсь, эти причины могут убедить вас использовать макросы такого рода всякий раз, когда вы создаете свою собственную библиотеку C/C++.
Заключение
В этой статье мы узнали об использовании макросов INT_MAX и INT_MIN в C/C++.
Для получения аналогичного контента просмотрите наш раздел учебника по программированию на C.
Рекомендации
- страница cplusplus.com на climits
min(x,y)
Макрос max() возвращает наибольшее из двух значений, а макрос min() возвращает наименьшее из двух значений. Макросы max() и min() возвращают тот же тип результата, что и их аргументы. Оба аргумента макросов должны иметь один и тот же тип.
Следующая программа иллюстрирует использование макросов max ( ) и min ( ) :
#include
#include
int main ( void )
{
printf ( «max of 10, 20 is %d \n » , max ( 10 , 20 ) ) ;
printf ( «min of 10, 20 is %d \n » , min ( 10 , 20 ) ) ;
return 0 ;
}
C++: Целочисленные типы
Целые числа представляют собой бесконечное множество, и в конечном объеме памяти компьютера нельзя представить их все. Таким образом язык может представить только подмножество целых чисел. Отсюда следует определение типа, тип данных — это возможное множество значений.
Разнообразные целочисленные типы в С++ отличаются друг от друга объемом памяти, выделяемым для хранения целого значения. Чем больше объем памяти, тем шире диапазон предоставляемых целочисленных значений.
В С++ базовыми целочисленными типами, в порядке увелечения ширины, являются: char , short , int , long и long long . Каждый из этих типов имеет версии со знаком и без знака. Таким образом, на выбор предоставляется десять целочисленных типов. Давайте познакомимся с ними поближе:
- short — имеет ширину не менее 16 бит и хранит диапазон чисел от — 32768 до 32767
- int — имеет гарантированную ширину, как минимум такую же как short и диапазон чисел от -2 147 483 648 до 2 147 483 647
- long — имеет ширину не менее 32 бит и хранит диапазон чисел от -2 147 483 648 до 2 147 483 647
- long long — имеет ширину не менее 64 бит и хранит диапазон чисел от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
Посмотреть ширину типа в вашей системе можно с помощью оператора sizeof() , а диапазоны с помощью символических констант, подключив заголовочный файл стандартной библиотеки climits .
#include #include int main()
Integer range: from-2147483648 to 2147483647 Int type: 4 byte
Стоит сказать, что минимальную ширину типа гарантирует язык, а максимальная зависит от архитектуры процессора.
Каждый из вышеприведённых типов может быть беззнаковым, то есть хранить только неотрицательные числа. За счет этого можно увеличить значение, которое может хранить переменная. Например, если short представляет диапазон от -32 768 до 32 767, то unsigned short от 0 до 65 532:
#include #include int main()
Int max: 4294967295 Int type: 4 byte
Видно, что верхняя граница увеличилась в два раза, нижняя будет смещена к нулю, но на количестве выделенной памяти это не сказалось. Такое поведение связано с тем, что для хранения отрицательных чисел используется дополнительный бит.
Что будет если в беззнаковую переменную сохранить отрицательное число или выйти за пределы диапазона знаковой переменной:
#include #include #define ZERO 0 // определим символьную константу со значением 0 int main() < int int_number < INT_MAX >; // 2147483647 unsigned u_int_number < ZERO >; // 0 std::cout
new value int_number: -2147483648 new value u_int_number: 4294967295
Произошла потеря значимости, то есть в обоих случаях мы получили числа другой границы диапазона и компилятор на это не указал. За этим надо следить особенно если вы работаете с большими числами.
Из всего вышесказанного возникает вопрос: Зачем такой богатый набор типов данных? Допустим, что вы пишете программу для контроллера микроволновой печи и вам известно, что данные которыми будет оперировать программа — это положительные числа, значение которых не превышает 32 000. Естественно ваш выбор падет на unsigned short и если у вас большой массив данных, можно существенно сэкономить память.
В остальных случаях, тип int имеет наиболее естественный размер целого числа для целевого компьютера. Под естественным размером подразумевается целочисленная форма, которую компьютер может обработать наиболее эффективным образом.
Задание
Допишите консольную утилиту, которая принимает в качестве аргумента количество секунд и преобразует их в количество дней. Выведите результат на экран. Этап получения аргумента и преобразование его в число уже написан, вам надо дописать логику преобразования секунд в дни.
86400 seconds = 1 days
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.