Найти в Дзене
Old Programmer

Программирование на языке C. Преобразование числа в строку и обратно (int, long int, long long, int64_t)

Мой канал Old Programmer, а здесь: Программирование. Тематическое оглавление моего Zen-канала (Old Programmer). А здесь собраны все ссылки, касающиеся языка C/C++. Сегодня статья для начинающих программировать на C. Так что жду вопросов. У меня и раздел такой появился. Посмотрите также И вот это тоже рекомендую, по данной теме Но вопрос то совсем не простой. И я даже не уверен, что мне удастся написать статью, которая сразу все разъяснит тем, кто начинает программировать. Но понимание приходит постепенно с практикой, да и комментарии никто не отменял. О числовых типах int, long int, long long int, int64_t Меня как-то уже упрекнули, что я почему то считаю числа типа int обязательно 32-битовыми. Вообще с этим типом чисел в языке Си не все так просто. Когда все работали в 16-битовых системах, то числа типа int обозначали числа длиной именно два байта. Но потом появились 32-битовые системы. В них по умолчанию int стало обозначать числа в 4 байта. Это было важно для совместимост
Оглавление

Мой канал Old Programmer, а здесь: Программирование. Тематическое оглавление моего Zen-канала (Old Programmer). А здесь собраны все ссылки, касающиеся языка C/C++.

Сегодня статья для начинающих программировать на C. Так что жду вопросов. У меня и раздел такой появился.

  • Язык программирования C для начинающих. Путеводитель по моему каналу Old Programmer

Посмотрите также

  • Язык программирования C. Функция printf. Форматный вывод (спецификаторы и модификаторы)

И вот это тоже рекомендую, по данной теме

  • Об ассемблере. Системы счисления

Но вопрос то совсем не простой. И я даже не уверен, что мне удастся написать статью, которая сразу все разъяснит тем, кто начинает программировать. Но понимание приходит постепенно с практикой, да и комментарии никто не отменял.

programmer's notes

О числовых типах int, long int, long long int, int64_t

Меня как-то уже упрекнули, что я почему то считаю числа типа int обязательно 32-битовыми. Вообще с этим типом чисел в языке Си не все так просто. Когда все работали в 16-битовых системах, то числа типа int обозначали числа длиной именно два байта. Но потом появились 32-битовые системы. В них по умолчанию int стало обозначать числа в 4 байта. Это было важно для совместимости. Старые программы, таким образом, проще было адаптировать для новой платформы. С другой стороны в новых системах можно было писать программы, которые бы адекватно работали и в старых системах после компиляции.

Далее появились 64-битовые системы. Но int остался 32-битовым типом. Однако еще в 32-битовых системах появился тип long int (или просто long), а также long long int (или просто long long), ну и наконец int64_t. Для нынешней 64-битовой платформы они все дают 64-битовый (8-байтовый) тип данных. Это можно увидеть, заглянув в файл stdint.h. Однако надо понимать, что, например, в типе int64_t все таки явно декларируется 64 бита. Выполним последовательность команд

printf("%lu\n", sizeof(long));
printf("%lu\n", sizeof(long long));
printf("%lu\n", sizeof(int64_t));
printf("%lu\n", sizeof(int));

В первых трех случаях получим значение 8 (байтов), в последнем 4. Однако для 32-битовых систем тип long тоже даст 4. Для чего я это рассказываю? А вот для чего. Тип, где явно указан его размер, не может измениться при переходе к другой системе, хотя там его может и не быть. А вот размеры целых типов int, long int, long long int всегда нужно проверять.

О знаковых и беззнаковых числах

Вопрос этот не тривиальный. Даже мне встречались вполне профессиональные программисты, которые этот вопрос не очень знали. Просто не сталкивались с задачами, которые требуют в нем разбираться. А достаточно запомнить одну важную истину: одно и то же двоичное число можно интерпретировать и как число со знаком и как и число беззнаковое. На уровне битов никаких знаков нет. Есть только интерпретация. Например, если число имеет размер 8 битов, то 255 в беззнаковом варианте будет соответствовать -1 в знаковом. 128 в беззнаковом варианте будет соответствовать -128 в знаковом и т.д. (см. рисунок 1)

Рисунок 1
Рисунок 1

Вы легко можете проверить соответствие с помощью функции printf(): printf("%hhd %hhu\n",128,128) и т.п. Аналогично для 16 битовых чисел знаковые числа меняются от -32768 до 32767, а беззнаковые от 0 до 65535. Для 4-х байтовых чисел знаковые от -2147483648 до 2147483647, беззнаковые от 0 до 4294967295. И наконец в случае с с 8-байтовыми числами промежуток знаковых чисел от -9223372036854775808 до 9223372036854775807 и беззнаковые от 0 до 18446744073709551615 (в шестнадцатеричном формате это 0xffffffffffffffff).

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

Преобразование целого числа в строку и обратно

Проще всего преобразовывать число в строку. Для этого существует стандартная функция sprintf(), которая полностью аналогично printf() за исключением того, что она выводит данные не на консоль, а в буфер (первый параметр). Например

char s[100];
int i = 23453;
sprintf(s,"%d",i);

Соответственно число i (знаковое 4-х байтовое) будет преобразовано в строку. Или

char s[100];
unsigned long long i = 0xffffffffffffffff;
sprintf(s,"%llu",i);

В строке s будет содержаться 18446744073709551615.

Для обратного преобразования строки в число есть две функции atoi() для 4-х байтовых чисел и atol() (atoll()) для 8-ми байтовых чисел. Но функции преобразуют только знаковые числа. Это всегда нужно иметь в виду, чтобы не получить неожиданный результат.

Ну, а напоследок приведу пример программы, с двумя функциями, которые переводят строки в число для знаковых и беззнаковых 8-байтовых чисел (см. sp4000.c). Результат выполнения программы

18446744073709551615
18446744073709551615
-1
-9223372036854775808
-9223372036854775808

Объясните как результат выполнения программы.

Замечание 1
В программе sp4000.c представлены две функции для знаковых и беззнаковых чисел. Но мы то знаем, что это только вопрос интерпретации. Так что можно пользоваться только одной функцией stoll(), при необходимости преобразуя типы переменных, понимая при этом, что вы делаете.

Замечание 2
Когда работаешь с языком C всегда хочется написать свою функцию, тем более что и библиотечные функции также чаще всего пишутся на том же языке. Вот люблю я C за это.

Пишите, что бы вы хотели увидеть в новых статьях на моем канале. Будем разбираться. Old Programmer ждет вас.

Подписывайтесь на мой канал и ставьте 'LIKE'.

Фрагмент программы sp4000.c
Фрагмент программы sp4000.c
programmer's notes