Как переносить строку в необычный целочисленный тип?

StackOverflow https://stackoverflow.com/questions/437802

Вопрос

Немного предыстории: если бы я хотел использовать, например, scanf() для преобразования строки в стандартный целочисленный тип, например uint16_t, я & # 8217; буду использовать SCNu16 из <inttypes.h> вот так:

#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);

Но более необычный целочисленный тип, такой как pid_t, не имеет ничего подобного; printf() поддерживает только нормальные целочисленные типы. Чтобы преобразовать другой способ в переносимое intmax_t a PRIdMAX, я могу привести его к <=> и использовать <=>, например:

#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
pid_t x = 17;
printf("%" PRIdMAX, (intmax_t)x);

Тем не менее, похоже, что не существует способа переноса <=> в <=>. Так что это мой вопрос: как это сделать переносимо?

#include <stdio.h>
#include <sys/types.h>
pid_t x;
char *xs = 17;
sscanf(xs, "%u", &x);  /* Not portable! pid_t might not be int! /*

Я подумал о <=> переходе к <=>, а затем проверял, что значение находится в пределах <=> & # 8217; s ограничен до приведения к <=>, но, похоже, не существует способа чтобы получить максимальные или минимальные значения для <=>.

Это было полезно?

Решение

Существует одно надежное и переносимое решение, которое заключается в использовании strtoimax() и проверке на переполнение.

То есть я анализирую intmax_t, проверяю наличие ошибки в pid_t, а затем также проверяю, подходит ли она " соответствует " в scanf() путем его приведения и сравнения с исходным значением strtoll().

#include <inttypes.h>
#include <stdio.h>
#include <iso646.h>
#include <sys/types.h>
char *xs = "17";            /* The string to convert */
intmax_t xmax;
char *tmp;
pid_t x;                    /* Target variable */

errno = 0;
xmax = strtoimax(xs, &tmp, 10);
if(errno != 0 or tmp == xs or *tmp != '\0'
   or xmax != (pid_t)xmax){
  fprintf(stderr, "Bad PID!\n");
} else {
  x = (pid_t)xmax;
  ...
}

Невозможно использовать <=>, потому что (как я сказал в комментарии) <=> не будет обнаруживать переполнения . Но я ошибся, сказав, что ни одна из функций, связанных с <=>, не принимает <=>; <=> делает!

Также не будет возможно использовать что-либо кроме <=>, если вы не знаете размер целочисленного типа (в данном случае <=>).

Другие советы

Это зависит от того, насколько портативным вы хотите быть. POSIX говорит, что pid_t - это целочисленный тип со знаком, используемый для хранения идентификаторов процессов и идентификаторов групп процессов. На практике вы можете с уверенностью предположить, что long достаточно велико. В противном случае ваш intmax_t должен быть достаточно большим (поэтому он будет принимать любые действительные <inttypes.h>); проблема в том, что этот тип может принимать значения, которые не являются допустимыми в <unistd.h>. Вы застряли между камнем и наковальней.

Я бы использовал <sys/types.h> и не очень беспокоился об этом, за исключением неясного комментария где-то, который 100-летний археолог найдет и наблюдает, и объясняет причину, по которой 256-битный процессор останавливается при передаче 512-битное значение как <=>.

POSIX 1003.1-2008 теперь доступен в Интернете (все 3872 страницы этого, в PDF и HTML). Вы должны зарегистрироваться (бесплатно). Я узнал об этом из книжного магазина Open Group .

Я вижу только то, что это должен быть целочисленный тип со знаком. Понятно, что все допустимые целочисленные значения со знаком вписываются в <=>. Я не могу найти в <=> или <=> никакой информации, указывающей на PID_T_MAX или PID_T_MIN или другие подобные значения (но я только сегодня вечером получил к ней доступ, поэтому она может быть скрыта там, где я ее не искал) , OTOH, я поддерживаю мой оригинальный комментарий - я считаю, что 32-битные значения прагматически адекватны, и я все равно буду использовать <=>, что будет 64-битным на 8-битных машинах. Я предполагаю, что примерно худшее, что может случиться, это то, что процесс с соответствующими привилегиями считывает слишком большое значение и посылает сигнал неправильному процессу из-за несоответствия типов. Я не уверен, что буду беспокоиться об этом.

... оооо! ... p400 в разделе <=>

  

Реализация должна поддерживать одну или несколько сред программирования, в которых ширина   blksize_t, pid_t, size_t, ssize_t и suseconds_t не больше ширины типа long.

Если вы действительно обеспокоены, вы можете _assert(sizeof(pid_t) <= long) или любой другой тип, который вы выберете для своей вещи '%'.

Как описано в этот ответ , в спецификации сказано signed int. Если «int» меняется, ваш «% u» по определению меняется вместе с ним.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top