В Bash, пуленепробиваемый способ, который будет работать, даже если ваша переменная содержит символы новой строки:
IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
Посмотрите:
$ in= Хитрость для этого заключается в использовании опция -d
для read
(разделитель) с пустым разделителем, так что read
вынужден читать все, что ему дано. И мы наполняем read
точно содержимым переменной in
, без завершающей строки, благодаря printf
. Обратите внимание, что мы также помещаем разделитель в printf
, чтобы строка, переданная в read
, имела конечный разделитель. Без этого read
обрезал бы потенциальные конечные пустые поля:
$ in='one;two;three;' # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'
сохраняется конечное пустое поле.
Обновление для Bash≥4.4
Начиная с Bash 4.4, встроенный модуль mapfile
(он же readarray
) поддерживает опцию -d
для указания разделителя. Отсюда другой канонический путь:
mapfile -d ';' -t array < <(printf '%s;' "$in")
one;two three;*;there is\na newline\nin this field'
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two three" [2]="*" [3]="there is
a newline
in this field")'
Хитрость для этого заключается в использовании опция -d
для read
(разделитель) с пустым разделителем, так что read
вынужден читать все, что ему дано. И мы наполняем read
точно содержимым переменной in
, без завершающей строки, благодаря printf
. Обратите внимание, что мы также помещаем разделитель в printf
, чтобы строка, переданная в read
, имела конечный разделитель. Без этого read
обрезал бы потенциальные конечные пустые поля:
$ in='one;two;three;' # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'
сохраняется конечное пустое поле.
Начиная с Bash 4.4, встроенный модуль mapfile
(он же readarray
) поддерживает опцию -d
для указания разделителя. Отсюда другой канонический путь:
mapfile -d ';' -t array < <(printf '%s;' "$in")
Обоснование C, кажется, подразумевает, что
был получен из заголовок с таким же названием встречается в нескольких существующих 64-битных системах.
но в остальной части текста не говорится об этих макросах, и я не помню, чтобы они существовали в то время.
Что Следующее - просто предположение, но основанное на опыте работы комитетов по стандартизации.
Одним из преимуществ макросов C99 перед стандартизацией дополнительных спецификаторов формата для printf (обратите внимание, что C99 также добавил некоторые из них) является то, что они предоставляют
и
, когда у вас уже есть реализация, поддерживающая требуемые функции специфическим для реализации способом, это просто запись двух файлов с адекватным typedef и макросами. Это снижает затраты на приведение существующей реализации в соответствие, снижает риск нарушения существующих программ, в которых используются особенности существующих особенностей реализации (стандартный способ не мешает), и облегчает перенос совместимых программ в реализацию, у которых их нет. заголовки (они могут быть предоставлены программой). Кроме того, если конкретные способы реализации уже варьировались в то время, это не
Correct, this is how the C99 standard says you should use them. If you want truly portablt code that is 100% standards-conformant to the letter, you should always print an int
using "%d"
and an int32_t
using "%"PRId32
.
Most people won't bother, though, since there are very few cases where failure to do so would matter. Unless you're porting your code to Win16 or DOS, you can assume that sizeof(int32_t) <= sizeof(int)
, so it's harmless to accidentally printf an int32_t
as an int
. Likewise, a long long
is pretty much universally 64 bits (although it is not guaranteed to be so), so printing an int64_t
as a long long
(e.g. with a %llx
specifier) is safe as well.
The types int_fast32_t
, int_least32_t
, et al are hardly ever used, so you can imagine that their corresponding format specifiers are used even more rarely.
Я могу только догадываться, почему. Мне нравится ответ AProgrammer выше, но упускается один аспект: что вы собираетесь добавить в printf в качестве модификатора формата? Уже существует два различных способа использования чисел в строке формата printf (ширина и точность). Было бы неплохо добавить третий вид числа, чтобы сказать, сколько бит точности в аргументе, но где вы собираетесь его поставить, чтобы не запутать людей? К сожалению, одним из недостатков C является то, что printf не предназначен для расширения.
Макросы ужасны, но когда вам нужно написать код, переносимый на 32-битные и 64-битные платформы, они просто находка. Определенно спас мой бекон.
Я думаю, что ответ на ваш вопрос почему либо