Pergunta

Alguns antecedentes: Se eu quisesse usar para, por exemplo, scanf() para converter uma string em um tipo inteiro padrão, como uint16_t, eu usaria SCNu16 de <inttypes.h>, como este:

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

Mas um tipo inteiro mais incomum como pid_t não tem qualquer coisa semelhante, apenas os tipos inteiros normais são apoiados por <inttypes.h>. Para converter o outro lado, para printf() portably um pid_t, posso lançá-lo aos intmax_t e uso PRIdMAX, como este:

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

No entanto, não parece ser uma maneira de scanf() portably em um pid_t. Portanto, esta é a minha pergunta: Como fazer isso portably

#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! /*

pensei em scanf()ing a um intmax_t e depois verificar que o valor está dentro dos limites do pid_t antes de lançar a pid_t, mas não parece ser uma maneira de obter o valor máximo ou mínimo para pid_t.

Foi útil?

Solução

Há uma solução robusta e portátil, que é usar strtoimax() e verificar se há excessos.

Isto é, eu analisar um intmax_t, verifique se há um erro de strtoimax(), e depois também ver se "encaixa" em um pid_t por convertê-lo e compará-lo com o valor intmax_t originais.

#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;
  ...
}

Não é possível usar scanf(), porque, (como eu disse em um comentário) scanf() não irá detectar excessos . Mas eu estava errado em dizer que nenhuma das funções strtoll() relacionada leva uma intmax_t; strtoimax() faz!

Ele também não vai funcionar para o uso de qualquer outra coisa do que strtoimax() se você não sabe o tamanho de seu tipo inteiro (pid_t, neste caso).

Outras dicas

Depende exatamente como portátil que você quer ser. POSIX diz que pid_t é um tipo inteiro assinado usado para IDs processo de armazenamento e IDs de grupo processo. Na prática, você poderia assumir com segurança que long é grande o suficiente. Na falta deste, o seu intmax_t deve ser grande o suficiente (para que ele irá aceitar qualquer pid_t válido); O problema é que esse tipo poderia aceitar valores que não são legítimos em pid_t. Você está preso entre uma rocha e um lugar duro.

Gostaria de usar long e não se preocupar muito sobre isso, exceto para um comentário em algum lugar obscuro que um arqueólogo software de 100 anos, portanto, vai encontrar e observar dá uma razão para que a CPU de 256 bits está se deteriorando a um impasse quando entregou um 512 valor bit como um pid_t.

POSIX 1.003,1-2008 já está disponível na web (todo 3872 páginas do mesmo, em PDF e HTML). Você tem que registrar (gratuito). Eu tenho a ele a partir do Open grupo Livraria .

Tudo o que vejo lá é que ele deve ser um tipo inteiro assinado. Claramente, todos os valores inteiros assinados válidos caber em intmax_t. Não consigo encontrar qualquer informação em <inttypes.h> ou <unistd.h> que indica PID_T_MAX ou PID_T_MIN ou outros valores (mas eu tenho apenas esta noite tem acesso a ele, para que ele pudesse ser escondido onde eu não olhei para ele). OTOH, eu mantenho a minha comentário original - Eu acredito que valores de 32 bits são pragmaticamente adequada, e eu usaria long qualquer maneira, o que seria de 64 bits em máquinas de 8 bits. Suponho que cerca a pior coisa que poderia acontecer é que um processo de 'apropriadamente privilegiada' ler um valor que era muito grande, e enviou um sinal para o processo errado devido a uma incompatibilidade de tipos. Eu não estou convencido de que eu estaria preocupado com isso.

... oooh! ... P400 sob <sys/types.h>

A implementação deve apoiar um ou mais programação ambientes em que as larguras de blksize_t, pid_t, size_t, ssize_t e suseconds_t não são maiores do que a largura do tipo long.

Se você está realmente em causa pode _assert(sizeof(pid_t) <= long) ou qualquer que seja o tipo que você escolher para o seu material '%'.

Como explicado na esta resposta , a especificação diz signed int. Se as mudanças 'int', o '% U' por alterações de definição com ele.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top