2009-09-11 4 views
7

एक अभ्यास के रूप में, मैं एक मैक्रो लिखना चाहता हूं जो मुझे बताता है कि एक पूर्णांक चर पर हस्ताक्षर किए गए हैं या नहीं। यह वही है जो मेरे पास अब तक है और मुझे परिणाम मिलने की उम्मीद है यदि मैं इसे char variable पर gcc -fsigned-char या -funsigned-char के साथ आज़माता हूं।मैं कैसे बता सकता हूं कि एक सी पूर्णांक चर पर हस्ताक्षर किए गए हैं या नहीं?

#define ISVARSIGNED(V) (V = -1, (V < 0) ? 1 : 0) 

क्या यह पोर्टेबल है? परिवर्तनीय के मूल्य को नष्ट किए बिना ऐसा करने का कोई तरीका है?

+0

यह एक उत्सुक समस्या है, लेकिन मैं इस जानकारी के लिए आपके इच्छित उपयोग के बारे में और अधिक चिंतित हूं है। साझा करने का कोई मौका? –

+0

यही कारण है कि सी ++ में आरटीटीआई है। :) –

+2

@jeffamaphone: वास्तव में, यह वह जगह है जहां टेम्पलेट सी ++ में चमकते हैं। – sbi

उत्तर

4
#define ISVARSIGNED(V) ((V)<0 || (-V)<0 || (V-1)<0) 

वी के मूल्य में परिवर्तन नहीं करता है तीसरे टेस्ट मामले संभालती है जहां वी == 0.

मेरी संकलक (जीसीसी/cygwin) इस int और long लेकिन char के लिए नहीं लिए काम करता है पर या short

#define ISVARSIGNED(V) ((V)-1<0 || -(V)-1<0) 

भी दो परीक्षणों में नौकरी करता है।

+0

सबसे अच्छा मैंने अभी तक देखा है। पोर्टेबल, मानक-अनुरूप, सटीक, जहां तक ​​मैं देख सकता हूं। –

+1

हस्ताक्षरित/हस्ताक्षरित शॉर्ट और चार के बीच अंतर नहीं करता है। < == > अभिव्यक्ति का मूल्यांकन करते समय उन प्रकारों को int में प्रचारित किया जाता है। – mob

+0

यदि आप इसे 'शॉर्ट' और 'char' के लिए काम करना चाहते हैं तो आप इसे उपयोग करने से पहले चर को' char' पर डाल सकते हैं। यह अधिकतर अतिप्रवाह मुद्दों को संभालना चाहिए। मुझे लगता है ... –

5
#define ISVARSIGNED(V) ((-(V) < 0) != ((V) < 0)) 

चर के मूल्य को नष्ट किए बिना। लेकिन 0 मानों के लिए काम नहीं करता है।

के बारे में क्या:

#define ISVARSIGNED(V) (((V)-(V)-1) < 0) 
+3

द्वारा विशेषज्ञ सी प्रोग्रामिंग पुस्तक से एक अभ्यास है # ISFARSIGNED (V) ((-V <0)! = (वी <0)) – plinth

+0

हाँ मुझे सी और पीडी नहीं होना चाहिए वह अनावश्यक सामान ;-) – ypnos

+0

@ प्लिंथ, आप 'वी' के आस-पास "अतिरिक्त" माता-पिता भूल गए हैं जो इसे पागल मैक्रो विस्तार से सुरक्षित बनाते हैं – rmeador

5

आप जीसीसी उपयोग कर रहे हैं आप typeof कीवर्ड का उपयोग कर सकते मूल्य अधिलेखित नहीं करने के लिए:

#define ISVARSIGNED(V) ({ typeof (V) _V = -1; _V < 0 ? 1 : 0 }) 

यह एक अस्थायी चर बनाता है, _V, है V के समान प्रकार।

पोर्टेबिलिटी के लिए, मुझे नहीं पता। यह दो की तारीफ मशीन पर काम करेगा (ए.के.ए. सबकुछ जो भी आपका कोड कभी भी सभी संभावनाओं पर चलता है), और मेरा मानना ​​है कि यह किसी की तारीफ और साइन-एंड-परिमाण मशीनों पर भी काम करेगा। एक साइड नोट के रूप में, यदि आप typeof का उपयोग करते हैं, तो आप इसे सुरक्षित बनाने के लिए -1 से typeof (V) डालना चाहेंगे (यानी चेतावनियां ट्रिगर करने की संभावना कम हो)।

+0

सी ++ में, यह मानक द्वारा काम करने की गारंटी है, पूर्णांक प्रतिनिधित्व के बावजूद (एन बिट्स के लिए, मान 2^एन -1) है। मेरे पास सी मानक आसान नहीं है (उनमें से कोई भी)। –

+0

मुझे न तो, लेकिन मुझे विकिपीडिया (सभी चीजों का स्रोत सत्य: पी) पर पढ़ना याद है कि सी मानक मैंने सूचीबद्ध तीन प्रस्तुतियों को अनुमति देता है। ऐसा नहीं है कि कोई भी अब उनका उपयोग करता है ... –

-1

हस्ताक्षरित/हस्ताक्षरित गणित की एक विशिष्ट विशेषता यह है कि जब आप एक हस्ताक्षरित संख्या को सही स्थानांतरित करते हैं, तो सबसे महत्वपूर्ण बिट की प्रतिलिपि बनाई जाती है। जब आप एक अहस्ताक्षरित संख्या बदलाव, नए बिट्स 0.

#define HIGH_BIT(n) ((n) & (1 << sizeof(n) * CHAR_BITS - 1)) 
#define IS_SIGNED(n) (HIGH_BIT(n) ? HIGH_BIT(n >> 1) != 0 : HIGH_BIT(~n >> 1) != 0 

तो बुनियादी तौर पर, इस मैक्रो निर्धारित करने के लिए एक नंबर के उच्च बिट सेट कर दिया जाता है कि क्या एक सशर्त अभिव्यक्ति का उपयोग करता है। यदि ऐसा नहीं है, तो मैक्रो इसे संख्या को अस्वीकार कर थोड़ा सा सेट करता है। हम अंकगणित अस्वीकृति नहीं कर सकते क्योंकि -0 == 0. हम फिर 1 बिट तक सही स्थानांतरित करते हैं और परीक्षण करते हैं कि साइन एक्सटेंशन हुआ है या नहीं।

यह 2 के पूरक अंकगणितीय मानता है, लेकिन यह आमतौर पर एक सुरक्षित धारणा है।

+0

क्या आपके पास बिट बदलावों के व्यवहार पर इन धारणाओं का स्रोत है? –

+0

सी 99 मानक (धारा 6.5.7) का कहना है कि एक हस्ताक्षरित, नकारात्मक मूल्य का सही बदलाव परिभाषित किया गया है। मेरी व्याख्या यह है कि 2 की पूरक मशीन पर एक साइन एक्सटेंशन होगा। चूंकि सी 2 के पूरक आर्किटेक्चर के लिए विशिष्ट नहीं है, इसलिए वे बाहर नहीं आएंगे और यह नहीं कहेंगे। –

+0

आप जादू '8' के बजाय' CHAR_BITS' का उपयोग कर अधिक पीसी होंगे। (हाँ, मुझे पता है, हम में से केवल कुछ ही मशीनों पर काम नहीं कर रहे हैं जहां एक बाइट 8 बिट है। फिर भी।) – sbi

1

इस सरल समाधान का कोई साइड इफेक्ट नहीं है, जिसमें केवल एक बार वी (जो मैक्रो में महत्वपूर्ण है) का जिक्र करने के लाभ शामिल हैं। हम जीसीसी एक्सटेंशन "typeof" का उपयोग वी के प्रकार के प्राप्त करने के लिए, और फिर डाली -1 इस प्रकार हैं:

#define IS_SIGNED_TYPE(v) ((typeof(v))-1 <= 0) 

यह < = (जब सक्षम) सिर्फ < कुछ मामलों के लिए संकलक चेतावनी से बचने के लिए के बजाय है।

0

पृथ्वी पर क्यों आपको मैक्रो होने की आवश्यकता है?टेम्पलेट्स इस के लिए महान हैं:

template <typename T> 
bool is_signed(T) { 
    static_assert(std::numeric_limits<T>::is_specialized, "Specialize std::numeric_limits<T>"); 
    return std::numeric_limits<T>::is_signed; 
} 

कौन सा सभी मौलिक अभिन्न प्रकार के लिए बाहर के बॉक्स काम करेंगे। यह पॉइंटर्स पर संकलन-समय पर भी असफल हो जाएगा, जो संस्करण केवल घटाव और तुलना का उपयोग नहीं करेगा।

संपादित: ओह, प्रश्न की आवश्यकता सी फिर भी, टेम्पलेट्स अच्छा तरीका है: पी

0

सभी "यह नकारात्मक" उत्तर देने के लिए एक अलग दृष्टिकोण:

#define ISVARSIGNED(V) (~(V^V)<0) 

इस तरह वी के विभिन्न मूल्यों के लिए विशेष मामलों की आवश्यकता नहीं है, क्योंकि ∀ वी ∈ ℤ, वी^वी = 0.

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