2009-01-13 14 views
10

कुछ पृष्ठभूमि: यदि मैं के लिए,, 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> द्वारा समर्थित हैं। अन्य तरीके से बदलने के लिए, करने के लिए portably एक pid_tprintf(), मैं इसे intmax_t पर कास्ट कर सकते और PRIdMAX उपयोग करते हैं, इस तरह:

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

हालांकि, वहाँ के लिए portably scanf() एक 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! /* 

मैं एक intmax_t को ing और उसके बाद यह जांच करना कि मूल्य pid_t को कास्टिंग से पहले pid_t की सीमा के भीतर है scanf() के बारे में सोचा है, लेकिन वहाँ एक रास्ता अधिकतम या pid_t के लिए न्यूनतम मूल्यों को प्राप्त करने के लिए प्रतीत नहीं होता ।

उत्तर

8

वहाँ एक मजबूत और पोर्टेबल समाधान, strtoimax() का उपयोग करें और अतिप्रवाह के लिए जाँच करने के लिए है जो है।

है कि, मैं एक intmax_t पार्स, strtoimax() से एक त्रुटि के लिए जाँच करें, और तब भी देखें कि क्या वह यह कास्टिंग और मूल intmax_t मूल्य से तुलना करके "फिट" एक pid_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() करता है!

यह भी जब तक आप अपने पूर्णांक प्रकार के आकार का पता (pid_t, इस मामले में) strtoimax() से कुछ और उपयोग करने के लिए काम नहीं करेगा।

3

यह इस बात पर निर्भर करता है कि आप कितने पोर्टेबल बनना चाहते हैं। POSIX का कहना है कि pid_t एक हस्ताक्षरित पूर्णांक प्रकार है जो प्रक्रिया आईडी और प्रक्रिया समूह आईडी को संग्रहीत करने के लिए उपयोग किया जाता है। अभ्यास में, आप सुरक्षा के साथ मान सकते हैं कि long काफी बड़ा है। यह विफल होने पर, आपका intmax_t काफी बड़ा होना चाहिए (इसलिए यह किसी मान्य pid_t को स्वीकार करेगा); समस्या यह है कि वह प्रकार उन मानों को स्वीकार कर सकता है जो pid_t में वैध नहीं हैं। आप एक चट्टान और एक कठिन जगह के बीच फंस गए हैं।

मैं long का उपयोग करूंगा और इसके बारे में चिंता न करें कि कहीं भी एक अस्पष्ट टिप्पणी को छोड़कर 100 साल के सॉफ़्टवेयर पुरातत्त्ववेत्ता को पता चल जाएगा और देखेगा कि 256-बिट CPU एक हद तक क्यों रुक रहा है pid_t के रूप में 512-बिट मान।

POSIX 1003.1-2008 अब वेब पर उपलब्ध है (इसके सभी 3872 पृष्ठ, पीडीएफ और एचटीएमएल में)। आपको पंजीकरण करना होगा (फ्री)। मुझे Open Group Bookstore से मिल गया।

जो कुछ मैं वहां देखता हूं वह यह है कि यह एक हस्ताक्षरित पूर्णांक प्रकार होना चाहिए। स्पष्ट रूप से, सभी वैध हस्ताक्षरित पूर्णांक मान intmax_t में फिट होते हैं। मुझे <inttypes.h> या <unistd.h> में कोई जानकारी नहीं मिलती जो PID_T_MAX या PID_T_MIN या अन्य ऐसे मानों को इंगित करती है (लेकिन मुझे केवल इस शाम को इसका उपयोग मिल गया है, इसलिए यह छुपाया जा सकता है जहां मैंने इसकी तलाश नहीं की है)। ओटीओएच, मैं अपनी मूल टिप्पणी से खड़ा हूं - मेरा मानना ​​है कि 32-बिट मान व्यावहारिक रूप से पर्याप्त हैं, और मैं long का उपयोग करता हूं, जो 8-बिट मशीनों पर 64-बिट होगा। मुझे लगता है कि लगभग सबसे बुरी चीज जो हो सकती है वह यह है कि 'उचित विशेषाधिकार' प्रक्रिया एक ऐसे मूल्य को पढ़ती है जो बहुत बड़ी थी, और प्रकारों के मेल के कारण गलत प्रक्रिया को संकेत भेज दिया गया। मुझे विश्वास नहीं है कि मैं इसके बारे में चिंतित हूं।

... ओह! ... <sys/types.h>

कार्यान्वयन के अंतर्गत P400 एक या अधिक प्रोग्रामिंग परिवेशों का समर्थन करेगा, जिसमें चौड़ाई blksize_t, pid_t, size_t, ssize_t, और suseconds_t की से अधिक नहीं कर रहे हैं लंबी चौड़ाई की चौड़ाई।

+1

मैंने सुना है कि अगले POSIX मानक केवल एक intmax_t में फिट करने के लिए इसे की आवश्यकता होगी, इसलिए का उपयोग कर लंबे समय से बाहर है। मैंने वास्तव में जो किया वह जीएनयू सी लाइब्रेरी के दस्तावेज़ों पर निर्भर था कि pid_t हमेशा int होगा, और टिप्पणी कर रहा है। कोड वैसे भी अन्य glibc- विशिष्ट सामान का उपयोग करता है, इसलिए यह एक वास्तविक समस्या नहीं है। – Teddy

+0

मुझे एक गैर-पोर्टेबल धारणा (कोड में जो पहले स्थान पर पोर्टेबल नहीं था) का उपयोग करके पहले से ही "व्यावहारिक रूप से पर्याप्त" समाधान प्राप्त हुआ है। जो कुछ मैं चाहता था वह वास्तव में पोर्टेबल समाधान था, अगर ऐसी चीज वास्तव में मौजूद है। – Teddy

0

यदि आप वास्तव में चिंतित हैं तो आप _assert(sizeof(pid_t) <= long) या जो भी प्रकार आप अपनी '%' सामग्री के लिए चुन सकते हैं।

जैसा कि this answer में बताया गया है, spec signed int कहता है। यदि 'int' में परिवर्तन होता है, तो परिभाषा के अनुसार आपका '% u' इसके साथ बदल जाता है।

+2

आकार वास्तव में एक प्रकार के संभावित मूल्यों के साथ खुद को चिंता नहीं करता है, केवल बाइट्स में भंडारण आवश्यकताओं। तो आपका कोड वास्तव में गारंटी नहीं देता है कि आप क्या सोचते हैं। इसके अलावा, spec "हस्ताक्षरित पूर्णांक प्रकार" कहता है, "हस्ताक्षरित int" नहीं। बड़ा अंतर। – Teddy

संबंधित मुद्दे

 संबंधित मुद्दे