문자열을 드문 정수 유형으로 포괄적으로 변환하는 방법은 무엇입니까?
문제
배경 : 예를 들어 사용하고 싶다면 scanf()
문자열을 표준 정수 유형으로 변환하려면 uint16_t
, 나는 사용할 것이다 SCNu16
~에서 <inttypes.h>
, 이와 같이:
#include <stdio.h>
#include <inttypes.h>
uint16_t x;
char *xs = "17";
sscanf(xs, "%" SCNu16, &x);
그러나 더 드문 정수 유형과 같은 것입니다 pid_t
그런 것이 없다. 일반 정수 유형 만 지원합니다 <inttypes.h>
. 다른 방식으로 변환, 휴대로 printf()
ㅏ pid_t
, 나는 그것을 캐스팅 할 수있다 intmax_t
그리고 사용 PRIdMAX
, 이와 같이:
#include <stdio.h>
#include <inttypes.h>
#include <sys/types.h>
pid_t x = 17;
printf("%" PRIdMAX, (intmax_t)x);
그러나 휴대 할 수있는 방법이없는 것 같습니다. scanf()
a pid_t
. 그래서 이것은 내 질문입니다.이 작업을 수행하는 방법은 무엇입니까?
#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! /*
나는 생각했다 scanf()
in intmax_t
그런 다음 값이 안에 있는지 확인합니다 pid_t
캐스팅 전의 제한 pid_t
, 그러나 최대 또는 최소 값을 얻는 방법은없는 것 같습니다. pid_t
.
해결책
사용하는 강력하고 휴대용 솔루션이 하나 있습니다. strtoimax()
오버플로를 확인하십시오.
즉, 나는 구문 분석합니다 intmax_t
, 오류를 확인하십시오 strtoimax()
, 그리고 또한 그것이 "적합"지 확인합니다. pid_t
캐스트하고 원본과 비교함으로써 intmax_t
값.
#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;
...
}
사용할 수 없습니다 scanf()
, 왜냐하면 (내가 의견에서 말했듯이) scanf()
오버플로를 감지하지 않습니다. 그러나 나는 strtoll()
-관련 함수는 intmax_t
; strtoimax()
하다!
또한 다른 것을 사용하는 것도 효과가 없습니다. strtoimax()
정수 유형의 크기를 모르는 경우 (pid_t
,이 경우).
다른 팁
그것은 당신이 얼마나 휴대가되고 싶은지 정확히 달려 있습니다. Posix는 그렇게 말합니다 pid_t
프로세스 ID 및 프로세스 그룹 ID를 저장하는 데 사용되는 서명 된 정수 유형입니다. 실제로, 당신은 안전을 가정 할 수 있습니다 long
충분히 큽니다. 실패, 당신 intmax_t
충분히 커야합니다 (따라서 유효한 모든 것을 받아 들일 것입니다. pid_t
); 문제는 그 유형이 합법적이지 않은 값을 받아 들일 수 있다는 것입니다. pid_t
. 당신은 바위와 어려운 곳 사이에 갇혀 있습니다.
나는 사용할 것이다 long
그리고 100 년의 소프트웨어 고고학자가 512 비트 값을 pid_t
.
POSIX 1003.1-2008 이제 웹에서 사용할 수 있습니다 (3872 페이지, PDF 및 HTML). 등록해야합니다 (무료). 나는 그것을 얻었다 열린 그룹 서점.
내가 보는 것은 서명 된 정수 유형이어야한다는 것입니다. 분명히, 모든 유효한 서명 된 정수 값이 적합합니다 intmax_t
. 정보를 찾을 수 없습니다 <inttypes.h>
또는 <unistd.h>
이는 PID_T_MAX 또는 PID_T_MIN 또는 다른 값을 나타냅니다 (그러나 오늘 저녁에만 액세스 할 수 있었으므로 찾지 못한 곳에 숨어있을 수 있습니다). Otoh, 나는 나의 원래 의견을지지한다 - 나는 32 비트 값이 실용적으로 적절하다고 생각하며, 나는 long
어쨌든 8 비트 기계에서 64 비트가 될 것입니다. 나는 '적절한 특권'프로세스가 너무 큰 값을 읽고 유형의 불일치로 인해 잘못된 프로세스에 신호를 보냈다고 생각합니다. 나는 그것에 대해 걱정할 것이라고 확신하지 않습니다.
... OOOH! ... P400 아래 <sys/types.h>
구현은 blksize_t, pid_t, size_t, ssize_t 및 suseconds_t의 너비가 길이의 너비보다 크지 않은 하나 이상의 프로그래밍 환경을 지원해야합니다.
당신이 정말로 걱정한다면 당신은 할 수 있습니다 _assert(sizeof(pid_t) <= long)
또는 '%'물건에 대해 선택한 유형.
설명 된 바와 같이 이 답변, 사양이 말합니다 signed int
. 'int'가 변경되면 정의에 따라 '%u'가 변경됩니다.