Размер типа данных char в C в формате% s или% c? - PullRequest
0 голосов
/ 22 февраля 2020

На inte rnet я обнаружил, что информация о char в C программировании ниже:

Datatype        Size        Range           Format

char            1 byte     −128 to 127        %c

signed char     1 byte     −128 to 127        %c

unsigned char   1 byte        0 to 255        %c

Но я знаю, что есть формат% s char (тип данных), он используется для работы со строкой. Мой вопрос: Есть ли разница в размере и диапазоне этих двух форматов? Спасибо всем!

Ответы [ 5 ]

3 голосов
/ 22 февраля 2020

Строки в C определяются как массив символов, который содержит последовательность символов, оканчивающихся нулевым символом '\ 0'.

Например, строковый литерал "Hello" имеет тип char[6] (учитывайте завершающий нулевой символ). Таким образом, оператор sizeof( "Hello" ) возвращает значение 6.

Спецификатор преобразования %s предназначен для вывода строк и ожидает указатель на первый символ строки. Размер строки ограничен только ресурсами используемой системы и не может быть больше максимального значения, хранимого в типе size_t.

Спецификатор преобразования Th %c предназначен для вывода скалярного объекта. типа char. Объекты типа char имеют размер, равный 1 (sizeof(char ) равен 1). Имейте в виду, что в C символьные литералы имеют тип int. Так, например, sizeof ('A') дает 4 (если размер объекта типа int равен 4).

Вот демонстрационная программа

#include <stdio.h>

int main(void) 
{
    printf( "sizeof( \"Hello\" ) = %zu\n", sizeof( "Hello" ) );

    char c = 'A';

    printf( "sizeof( char ) = %zu, sizeof( 'A' ) = %zu\n", sizeof( c ), sizeof( 'A' ) );

    return 0;
}

Ее вывод is

sizeof( "Hello" ) = 6
sizeof( char ) = 1, sizeof( 'A' ) = 4

Обратите внимание, что диапазон значений типа char зависит от параметров компилятора, а тип char может вести себя как тип signed char или unsigned char. Поэтому правильнее было бы написать

char            1 byte     −128 to 127        %c
or
char            1 byte     0 to 255           %c

из стандарта C (5.2.4.2.1 Размеры целочисленных типов)

2 Если значение объекта типа char рассматривается как целое число со знаком при использовании в выражении, значение CHAR_MIN должно быть таким же, как у SCHAR_MIN, а значение CHAR_MAX должно быть таким же, как и у SCHAR_MAX. В противном случае значение CHAR_MIN должно быть равно 0, а значение CHAR_MAX должно быть таким же, как и значение UCHAR_MAX. Значение UCHAR_MAX должно быть равно 2CHAR_BIT - 1.

3 голосов
/ 22 февраля 2020

A char представляет собой один символ / букву, например, напечатанный с помощью "%c" и, например, 'X'.
То, что напечатано с помощью "%s", представляет собой строку из многих символов с нулевым символом в конце и может быть задана как например "foobar". Обратите внимание на различные кавычки.
( Кстати, распространенная ошибка при работе с ними и попытке их хранения - нехватка места для конечного нуля. Обычно требуется еще больше, чем очевидно. )

Сравнить https://en.cppreference.com/w/cpp/io/c/fprintf

«Диапазон» того, на что обычно ссылается %s, определить очень сложно. Это могут быть книги.

То, что напечатано %s, иногда описывается как "C псевдострока", но тип данных как таковой отсутствует.

1 голос
/ 22 февраля 2020

В C нет строкового типа, но стандартная библиотека C определяет строки для символьных массивов с нулевым символом в конце §7.1.1p1 стандарта C11 Draft

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

Таблица, показанная OP, верна, что char, signed char и unsigned char все шириной 1 байт. Диапазоны минимальных значений указаны для типов в Стандарте, но без диапазонов абсолютных значений; хотя диапазоны значений в таблице являются общими, они не гарантируются. В частности, нередко char является типом без знака с диапазоном значений от 0 до 255. Обратите внимание, что для типов со знаком char стандарт требует только минимального диапазона от -127 до 127. Даже байты должны иметь минимальная 8 битная ширина, но точно 8 бит не указана. Фактические детали - это детали реализации.

%c и %s используются в форматированных операциях ввода / вывода; они не имеют прямого отношения к типам, а используются для описания функций, которые следует ожидать типам. Для функций семейства fprintf() спецификатор преобразования %c указывает функции ожидать целочисленный аргумент, который будет преобразован в значение unsigned char и напечатан как символ. Обратите внимание, что кодировка символов не обязательно должна быть ASCII (это еще одна деталь реализации), но это наиболее распространенная в наши дни.

Спецификатор преобразования %s сообщает функциям fprintf() ожидать указатель на первый элемент массива символов. Если подходящая точность не указана (например, %5s для печати не более 5 символов), массив должен быть строкой (то есть заканчиваться нулем).

Для функций семейства fscanf() директива %c говорит функции сканировать один или несколько символов на входе (т. е. больше, чем один, когда указана ширина поля, например, %3c), и ожидать указатель на массив символов, достаточно большой для хранения результатов. Для простого scanf("%c", &some_char) максимальное количество символов для сканирования составляет 1, а some_char просто должно быть char, например, определенным как char some_char;. Но для чего-то вроде scanf("%5c", five_chars), five_chars должен быть массивом, способным хранить 5 char с, например, определенным как char five_chars[5];.

Директива %s действует аналогично для функций fscanf(), но без указания максимальной ширины поля fscanf() будет пытаться сопоставить и сохранить символы до тех пор, пока во входных данных не встретятся пробелы. Функция ожидает указатель на массив символов, способный содержать все совпадающие символы (плюс нулевой терминатор), и по этой причине вы всегда должны указывать максимальную ширину поля, чтобы избежать потенциального переполнения буфера. Также обратите внимание, что директива %s всегда приводит к тому, что терминатор \0 записывается после сканирования последнего символа. Таким образом, когда хранилище объявлено как char storage[100];, правильно использовать scanf("%99s", storage);. Это говорит scanf() о соответствии не более 99 символов на входе перед записью окончательного \0, избегая записи после конца массива storage[] в случае большого ввода.

Более подробная информация о fprintf() и fscanf(). Обратите внимание, что fscanf(), в частности, является сложной функцией, которую сложно использовать правильно.

1 голос
/ 22 февраля 2020

%c используется для печати отдельных символьных значений и ожидает, что соответствующий аргумент будет иметь тип char:

char c = 'A';
printf( "%c\n", c );

%s используется для печати строк , которые являются последовательностями символьных значений, включая терминатор с нулевым значением, и ожидают, что его соответствующий аргумент будет иметь тип char * (указатель на char), который является адресом первого символа строки:

char s[] = "hello"; // equivalent to {'h', 'e', 'l', 'l', 'o', 0}
printf( “%s\n”, s ); // equivalent to passing &s[0]

За исключением случаев, когда он является операндом операторов sizeof или унарных & или представляет собой строковый литерал, используемый для инициализации массива символов в объявлении, выражение типа "массив N-элементов T" будет преобразован ("распад") в выражение типа "указатель на T", а значением выражения будет адрес первого элемента массива. Поэтому, когда мы передаем выражение s в printf, на самом деле передается адрес s[0], а не содержимое самого массива. Это в основном эквивалентно записи

* 1 028 *
0 голосов
/ 22 февраля 2020

%s и %c не являются форматами или типами. Они называются «преобразования или формат спецификаторы », используемые для правильного форматирования в отношении одного из типов символов или строки, используемые функциями семейств printf() и scanf(). Таким образом, они не имеют "размера" или "диапазона" сами по себе.


Есть ли разница в размере и диапазоне этих двух форматов?

В C строка сама по себе не является типом. Строка - это непрерывная последовательность символьных объектов.

«Размер» строки определяется в исходном коде или во время работы программы ( массивы переменной длины ); нет общего фиксированного размера для строки.

Строка не имеет ничего общего с «диапазоном», так как она имеет символьный или целочисленный тип.

Вы пытаетесь спросить, предоставляют ли все эти символы вместе (может) больший диапазон. Ответ просто нет.

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

char a;      

a имеет размер 1 байт и диапазон от -128 до 127 или от 0 до 255 (зависит от реализации и платформы, но на большинстве современных систем он будет иметь диапазон от -128 до 127 ).

char b[4];

b имеет размер 4 байта в этом случае, но диапазон его значений не от -2 147 483 648 до 2 147 483 647 (2³² = 4 294 967 296 хранимых значений (обратите внимание, один бит для представления знака) )). Он состоит только из 4 char объектов, каждый из которых имеет 1 байт, выделенный в памяти, и может хранить / представлять значения от -128 до 127/0 до 255.

Если вы хотите использовать более широкий диапазон для одного символа используйте тип широких символов wchar_t.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...