क्या सभी बिट्स को सही पर सेट करने के लिए -1 का उपयोग करना सुरक्षित है?


132

मैंने देखा है कि यह पैटर्न C & C ++ में बहुत अधिक उपयोग किया जाता है।

unsigned int flags = -1;  // all bits are true

क्या इसे पूरा करने का एक अच्छा पोर्टेबल तरीका है? या उपयोग कर रहा है 0xffffffffया ~0बेहतर है?


1
मुझे नहीं मिला, क्या आप समझा सकते हैं?
corazza

8
मुझे लगता है कि क्या कोड का अर्थ स्पष्ट है, सबसे महत्वपूर्ण सवाल है। हालांकि -1यह हमेशा काम करेगा, तथ्य यह है कि एक टिप्पणी की जरूरत है के बाद यह दिखाता है कि यह स्पष्ट कोड नहीं है। यदि चर का मतलब झंडे का संग्रह है, तो इसे पूर्णांक क्यों सौंपें? इसका प्रकार एक पूर्णांक हो सकता है, लेकिन इसका निश्चित रूप से शब्दार्थ पूर्णांक नहीं है। आप इसे बढ़ाने या इसे गुणा करने के लिए कभी नहीं जा रहे हैं। इसलिए मैं 0xffffffffपोर्टेबिलिटी या शुद्धता के लिए नहीं, बल्कि स्पष्टता के लिए उपयोग करूंगा ।
कैम जैक्सन

@CamJackson टिप्पणी नहीं है और कोई भी C कोड लिखने से परिचित हो सकता है कि मूल्यों का प्रतिनिधित्व कैसे किया जाता है।
मील्स रूट

मूल रूप से प्रश्न को C और C ++ के रूप में ठीक से टैग किया गया था। हो सकता है कि भाषाएं उस C ++ में विचलन कर रही हों जिसमें दो के पूरक की आवश्यकता हो। इसने कहा, यह इस तथ्य को नहीं बदलता है जो -1दोनों भाषाओं के लिए एक पोर्टेबल और पिछड़े संगत समाधान बना हुआ है, लेकिन यह अन्य उत्तरों में कुछ तर्क को प्रभावित कर सकता है।
एड्रियन मैक्कार्थी

जवाबों:


154

मैं आपको इसे वैसा ही करने की सलाह देता हूं जैसा आपने दिखाया है, क्योंकि यह सबसे सीधा आगे है। आरंभ में -1जो हमेशा काम करेगा , वास्तविक साइन प्रतिनिधित्व से स्वतंत्र ~होगा , जबकि कभी-कभी आश्चर्यजनक व्यवहार होगा क्योंकि आपके पास सही ऑपरेंड प्रकार होगा। तभी आपको एक unsignedप्रकार का सबसे उच्च मूल्य मिलेगा ।

संभावित आश्चर्य के उदाहरण के लिए, इस पर विचार करें:

unsigned long a = ~0u;

यह जरूरी नहीं कि सभी 1 बिट्स के साथ एक पैटर्न स्टोर करें a। लेकिन यह पहले सभी बिट्स 1 के साथ एक पैटर्न बनाएगा unsigned int, और फिर इसे असाइन करेगा a। क्या होता है जब unsigned longअधिक बिट्स होता है कि सभी 1 नहीं होते हैं।

और इस पर विचार करें, जो गैर-दो के पूरक प्रतिनिधित्व पर विफल हो जाएगा:

unsigned int a = ~0; // Should have done ~0u !

इसका कारण यह है कि ~0सभी बिट्स को उलटना पड़ता है। इन्वर्टिंग कि -1एक दो के पूरक मशीन पर निकलेगा (जो हमारे लिए आवश्यक मूल्य है!), लेकिन किसी अन्य प्रतिनिधित्व पर नहीं निकलेगा -1। एक पूरक मशीन पर, यह शून्य उपज देता है। इस प्रकार, एक पूरक मशीन पर, उपरोक्त aशून्य को प्रारंभ करेगा ।

आपको यह समझना चाहिए कि यह सभी मूल्यों के बारे में है - बिट्स नहीं। चर को एक मूल्य के साथ आरंभीकृत किया जाता है । यदि इनिशियलाइज़र में आप इनिशियलाइज़ेशन के लिए प्रयुक्त वैरिएबल के बिट्स को संशोधित करते हैं, तो उन बिट्स के अनुसार मान उत्पन्न होगा। aउच्चतम संभव मूल्य को इनिशियलाइज़ करने के लिए आपको जो मूल्य चाहिए, वह है -1या UINT_MAX। दूसरे के प्रकार पर निर्भर करेगा a- आप का उपयोग करने की आवश्यकता होगी ULONG_MAXएक के लिए unsigned long। हालांकि, पहला इसके प्रकार पर निर्भर नहीं करेगा, और यह सबसे अधिक मूल्य प्राप्त करने का एक अच्छा तरीका है।

हम इस बारे में बात नहीं कर रहे हैं कि क्या -1सभी बिट्स एक है (यह हमेशा नहीं होता है)। और हम इस बारे में बात नहीं कर रहे हैं कि क्या ~0सभी बिट्स एक (इसके पास हैं)।

लेकिन हम जिस बारे में बात कर रहे हैं, वह है कि इनिशियलाइज्ड flagsवैरिएबल का परिणाम क्या है। और इसके लिए, केवल-1 हर प्रकार और मशीन के साथ काम करेंगे।


9
-1 को सभी में परिवर्तित करने की गारंटी क्यों है? क्या यह मानक की गारंटी है?
२०:११

9
रूपांतरण जो होता है, वह बार-बार ULONG_MAX से एक अधिक जोड़ता है, जब तक कि वह सीमा में नहीं होता है (C TC2.3 में 6.3.1.3)। C ++ में यह समान है, बस इसे औपचारिक रूप देने का एक और तरीका है (modulo 2 ^ n)। यह सब गणितीय संबंधों के लिए आता है।
जोहान्स शहाब -

6
@ मुख्य भूमिका: कास्टिंग -1 निश्चित रूप से अधिकतम अहस्ताक्षरित मूल्यों को प्राप्त करने का एक अच्छा तरीका है, लेकिन यह वास्तव में वर्णनात्मक नहीं है; यही कारण है कि _MAX स्थिरांक मौजूद हैं (SIZE_MAX को C99 में जोड़ा गया था); दी गई, सी ++ संस्करण numeric_limits<size_t>::max()थोड़ा लंबा-घुमावदार है, लेकिन इतना कास्ट है ...
क्रिस्टोफ़

11
"हम इस बारे में बात नहीं कर रहे हैं कि क्या -1 में सभी बिट्स हैं (यह हमेशा नहीं होता है)। और हम इस बारे में बात नहीं कर रहे हैं कि ~ 0 में सभी बिट्स हैं (यह निश्चित रूप से है)।" - वात ??? मैंने सोचा था कि पूरे बिंदु को सभी बिट्स को सेट करना था 1. कि झंडे कैसे काम करते हैं..कोई ?? आप बिट्स को देखो । मूल्य के बारे में कौन परवाह करता है?
एमपीएन

14
@ मर्क प्रश्नकर्ता परवाह करता है। वह पूछता है "क्या सभी बिट्स को सच करने के लिए -1 का उपयोग करना सुरक्षित है"। यह इस बारे में नहीं पूछता है कि बिट्स किसका -1प्रतिनिधित्व करता है, और न ही यह पूछता है कि बिट्स क्या ~0है। हम मूल्यों की परवाह नहीं कर सकते हैं, लेकिन संकलक करता है। हम इस तथ्य को नजरअंदाज नहीं कर सकते हैं कि परिचालन मूल्यों के साथ और साथ काम करता है। मूल्य के ~0नहीं हो सकता है -1, लेकिन यह मूल्य आप की जरूरत है। मेरा उत्तर और @ डिंगो का सारांश देखें।
जोहान्स शहाब -

49
  • unsigned int flags = -1; पोर्टेबल है।
  • unsigned int flags = ~0; पोर्टेबल नहीं है क्योंकि यह एक दो-पूरक प्रतिनिधित्व पर निर्भर करता है।
  • unsigned int flags = 0xffffffff; यह पोर्टेबल नहीं है क्योंकि यह 32-बिट इनट्स मानता है।

यदि आप C मानक द्वारा गारंटीकृत तरीके से सभी बिट्स सेट करना चाहते हैं, तो पहले वाले का उपयोग करें।


10
~ 0 (यानी किसी का पूरक ऑपरेटर) दो के पूरक प्रतिनिधित्व पर कैसे निर्भर करता है?
ड्रू हॉल

11
आपके पास यह पीछे है। इसकी सेटिंग झंडे -1 से है जो एक टोमस पूरक प्रतिनिधित्व पर निर्भर करता है। एक साइन + परिमाण प्रतिनिधित्व माइनस में केवल दो बिट्स सेट होते हैं: साइन बिट और परिमाण के कम से कम महत्वपूर्ण बिट।
स्टीफन सी। स्टील

15
C मानक के लिए यह आवश्यक है कि शून्य का int मान उसके साइन बिट और सभी मान बिट्स शून्य हो। किसी के पूरक के बाद, वे सभी बिट एक हैं। सभी बिट्स सेट के साथ एक इंट के मान हैं: साइन-एंड-परिमाण: INT_MIN एक का पूरक: -0 दो का पूरक: -1 इसलिए बयान "अहस्ताक्षरित int झंडे = ~ 0;" जो भी ऊपर दिए गए मान को प्लेटफ़ॉर्म के पूर्णांक प्रतिनिधित्व से मेल खाता है। लेकिन दो के पूरक का '-1' एकमात्र है जो सभी झंडे बिट्स को एक में सेट कर देगा।
डिंगो

9
@ स्टीफन: प्रतिनिधित्व पर सहमत हुए। लेकिन जब एक मान को एक अहस्ताक्षरित int को सौंपा जाता है, तो अहस्ताक्षरित को मान का आंतरिक प्रतिनिधित्व (दो के पूरक प्रणाली को छोड़कर जहां वह आमतौर पर काम करता है) को अपनाकर अपना मूल्य नहीं प्राप्त करता है। अहस्ताक्षरित int को निर्दिष्ट सभी मान modulo (UINT_MAX + 1) हैं, इसलिए -1 को असाइन करना आंतरिक प्रतिनिधित्व से कोई फर्क नहीं पड़ता।
डिंगो

20
@ मर्क: आप दो कार्यों को भ्रमित कर रहे हैं। निश्चित रूप से सभी बिट सेट के साथ ~0एक intमूल्य देता है। लेकिन जरूरी नहीं कि हस्ताक्षरित बिट पैटर्न के समान बिट पैटर्न वाले अहस्ताक्षरित परिणाम में ए intको असाइन किया जाए । केवल एक 2 के पूरक प्रतिनिधित्व के साथ यह हमेशा मामला होता है। 1s के पूरक या संकेत-परिमाण प्रतिनिधित्व पर, एक भिन्न बिट पैटर्न में परिणामों के लिए एक नकारात्मक मूल्य प्रदान करना । ऐसा इसलिए है क्योंकि C ++ मानक परिभाषित हस्ताक्षरित -> अहस्ताक्षरित रूपांतरण modulo- समान मान होना चाहिए, समान बिट्स के साथ मान नहीं। unsigned intintunsigned int
स्टीव जेसप

25

सच कहूँ तो मुझे लगता है कि सभी fff अधिक पठनीय है। जैसा कि टिप्पणी है कि इसका एंटीपैटर, अगर आप वास्तव में परवाह करते हैं कि सभी बिट्स सेट / क्लियर हो गए हैं, तो मैं तर्क दूंगा कि आप शायद ऐसी स्थिति में हैं जहां आप वैसे भी चर के आकार के बारे में परवाह करते हैं, जो बढ़ावा देने जैसी किसी चीज के लिए कहेंगे :: uint16_t, आदि।


ऐसे कई मामले हैं जिनमें आप इतना ध्यान नहीं रखते हैं, लेकिन वे दुर्लभ हैं। उदाहरण के लिए एल्गोरिथ्म जो एन बिट्स के डेटासेट पर काम करते हैं, जो इसे आकार के टुकड़े (अहस्ताक्षरित) में तोड़कर * CHAR_BIT बिट्स प्रत्येक।
MSalters

2
+1। भले ही डेटाटाइप का आकार # F के # से बड़ा हो (यानी, आपने सभी बिट्स को सही पर सेट नहीं किया है), चूंकि आप स्पष्ट रूप से मान सेट कर रहे हैं, आप कम से कम इस बात से अवगत हैं कि कौन से बिट्स "सुरक्षित हैं" का उपयोग करने के लिए "..
21

17

एक तरीका है जो वर्णित समस्याओं से बचा जाता है बस करना है:

unsigned int flags = 0;
flags = ~flags;

पोर्टेबल और बात करने के लिए।


2
लेकिन फिर आप के flagsरूप में घोषित करने की क्षमता खो देते हैं const
डेविड स्टोन

1
@DavidStoneunsigned int const flags = ~0u;

@Zoidberg '- जो दो के पूरक के अलावा अन्य प्रणालियों पर काम करने में विफल रहता है। उदाहरण के लिए, एक साइन-परिमाण प्रणाली पर, ~0एक पूर्णांक होता है जिसमें सभी बिट्स 1 पर सेट होते हैं, लेकिन जब आप तब वेरिएबल intको असाइन करते unsignedहैं flags, तो आप एक पूर्णांक -2**31(32-बिट int) से मान रूपांतरण करते हैं (-2**31 % 2**32) == 2**31, जो पूर्णांक है सभी बिट्स के साथ लेकिन 1 पर सेट
डेविड स्टोन 1

यह भी एक कारण है कि यह उत्तर खतरनाक है। ऐसा लगता है जैसे @Zoidberg '- का जवाब समान होगा, लेकिन यह वास्तव में नहीं है। हालाँकि, कोड को पढ़ने वाले व्यक्ति के रूप में, मुझे यह समझने के लिए सोचना होगा कि आपने इसे शुरू करने के लिए दो कदम क्यों उठाए, और संभवतः इसे एक ही चरण में बदलने के लिए लुभाया जाए।
डेविड स्टोन

2
आह हाँ, मैंने uआपके उत्तर में प्रत्यय नहीं देखा । यह निश्चित रूप से काम करेगा, लेकिन अभी भी unsignedदो बार आपके द्वारा उपयोग किए जाने वाले डेटा प्रकार ( और कोई बड़ा) को निर्दिष्ट करने की समस्या नहीं है, जिससे त्रुटियां हो सकती हैं। त्रुटि दिखाने के लिए सबसे अधिक संभावना है अगर असाइनमेंट और प्रारंभिक चर घोषणा अलग हैं, हालांकि।
डेविड स्टोन

13

मुझे यकीन नहीं है कि झंडे के लिए एक अहस्ताक्षरित int का उपयोग करना C ++ में पहले स्थान पर एक अच्छा विचार है। बिटसेट और लाइक के बारे में क्या?

std::numeric_limit<unsigned int>::max()बेहतर है क्योंकि 0xffffffffमानता है कि अहस्ताक्षरित int एक 32-बिट पूर्णांक है।


मुझे इसके मानक की वजह से यह पसंद है, लेकिन यह बहुत चिंताजनक है और यह आपको दो बार टाइप करता है। ~ 0 का उपयोग करना संभवतः सुरक्षित है क्योंकि 0 किसी भी पूर्णांक प्रकार का हो सकता है। (हालांकि मुझे पता है कि यह बहुत सी की बदबू आ रही है)
मैके

तथ्य यह है कि वर्डी को एक लाभ के रूप में देखा जा सकता है। लेकिन मुझे ~ 0 भी पसंद है।
एडुआर्ड ए।

2
आप मानक UINT_MAX मैक्रो के साथ शब्दशीलता को कम कर सकते हैं, क्योंकि आप वैसे भी अहस्ताक्षरित प्रकार को हार्डकोड कर रहे हैं।

2
@ मैके आप C ++ 11 में टाइप करने से बच सकते हैं autoauto const flags = std::numeric_limit<unsigned>::max()
डेविड स्टोन

11
unsigned int flags = -1;  // all bits are true

"क्या यह पूरा करने के लिए एक अच्छा [,] पोर्टेबल तरीका है?"

पोर्टेबल? जी हां

अच्छा? इस थ्रेड पर दिखाए गए सभी भ्रम के सबूत के रूप में, बहस योग्य । पर्याप्त स्पष्ट होने के नाते कि आपके साथी प्रोग्रामर कोड को समझ सकते हैं भ्रम के बिना अच्छे कोड के लिए हमारे द्वारा मापे गए आयामों में से एक होना चाहिए।

इसके अलावा, यह विधि संकलक चेतावनी के लिए प्रवण है । अपने संकलक को अपंग किए बिना चेतावनी को समाप्त करने के लिए, आपको एक स्पष्ट कलाकार की आवश्यकता होगी। उदाहरण के लिए,

unsigned int flags = static_cast<unsigned int>(-1);

स्पष्ट कलाकारों के लिए आवश्यक है कि आप लक्ष्य प्रकार पर ध्यान दें। यदि आप लक्ष्य प्रकार पर ध्यान दे रहे हैं, तो आप स्वाभाविक रूप से अन्य दृष्टिकोणों के नुकसान से बचेंगे।

मेरी सलाह होगी कि लक्ष्य प्रकार पर ध्यान दें और सुनिश्चित करें कि कोई निहित रूपांतरण नहीं हैं। उदाहरण के लिए:

unsigned int flags1 = UINT_MAX;
unsigned int flags2 = ~static_cast<unsigned int>(0);
unsigned long flags3 = ULONG_MAX;
unsigned long flags4 = ~static_cast<unsigned long>(0);

आपके साथी प्रोग्रामर के लिए सभी सही और अधिक स्पष्ट हैं

और C ++ 11 के साथ : हम autoइनमें से किसी को भी सरल बनाने के लिए उपयोग कर सकते हैं :

auto flags1 = UINT_MAX;
auto flags2 = ~static_cast<unsigned int>(0);
auto flags3 = ULONG_MAX;
auto flags4 = ~static_cast<unsigned long>(0);

मैं केवल सही से बेहतर और स्पष्ट मानता हूं।


10

किसी भी अहस्ताक्षरित प्रकार में परिवर्तित करना मानक द्वारा सभी में परिणाम की गारंटी है~0Uआम तौर पर इसका उपयोग आमतौर पर बुरा होता है क्योंकि 0टाइप होता है unsigned intऔर जब तक आप स्पष्ट रूप से कुछ नहीं लिखते, तब तक एक बड़े अहस्ताक्षरित प्रकार के सभी बिट्स नहीं भरेंगे ~0ULL। समझदार प्रणालियों पर, ~0समान होना चाहिए -1, लेकिन चूंकि मानक लोगों को पूरक और हस्ताक्षर / परिमाण प्रतिनिधित्व की अनुमति देता है, कड़ाई से यह पोर्टेबल नहीं है।

निश्चित रूप से यह लिखना हमेशा ठीक होता है कि 0xffffffffक्या आप जानते हैं कि आपको 32 बिट्स की आवश्यकता है, लेकिन -1 का यह फायदा है कि यह किसी भी संदर्भ में काम करेगा, भले ही आपको आकार का पता न हो, जैसे कि मैक्रोज़, जो कई प्रकारों पर काम करते हैं , या यदि प्रकार का आकार कार्यान्वयन द्वारा भिन्न होता है। यदि आप प्रकार जानते हैं, तो सभी को प्राप्त करने का एक और सुरक्षित तरीका सीमा मैक्रोज़ है UINT_MAX,ULONG_MAX , ULLONG_MAX, आदि

व्यक्तिगत रूप से मैं हमेशा -1 का उपयोग करता हूं। यह हमेशा काम करता है और आपको इसके बारे में सोचने की जरूरत नहीं है।


एफडब्ल्यूआईडब्ल्यू, अगर मेरा मतलब है "सभी 1 बिट्स" मैं उपयोग करता हूं ~(type)0(ठीक है, typeपाठ्यक्रम के अधिकार में भरें )। कास्टिंग शून्य अभी भी एक शून्य में परिणाम करता है, इसलिए यह स्पष्ट है, और लक्ष्य प्रकार में सभी बिट्स की उपेक्षा करना बहुत स्पष्ट रूप से परिभाषित है। ऐसा नहीं है कि अक्सर मैं वास्तव में उस ऑपरेशन को चाहता हूं; YMMV।
डोनल फैलो

6
@ डोनल: आप बस गलत हैं। सी निर्दिष्ट करता है कि, जब एक मान को एक अहस्ताक्षरित प्रकार में फिट नहीं किया जाता है, तो मानों को कम किया जाता है modulo 2 ^ n जहां n गंतव्य स्थानों में बिट्स की संख्या है। यह हस्ताक्षरित मूल्यों और बड़े अहस्ताक्षरित प्रकारों पर लागू होता है। इसका टोट्स सप्लीमेंट से कोई लेना-देना नहीं है।
R .. गिटहब स्टॉप हेल्पिंग ICE

2
वे इसे वही लागू करते हैं , जो तुच्छ है; आप बस एक हस्ताक्षरित या एक negनिर्देश के बजाय एक अहस्ताक्षरित घटाव opcode का उपयोग करें। जिन मशीनों में फर्जी हस्ताक्षर किए गए अंकगणित व्यवहार हैं, उनमें अलग-अलग हस्ताक्षरित / अहस्ताक्षरित अंकगणित हैं। बेशक एक अच्छा संकलक हमेशा हस्ताक्षर किए गए मूल्यों के लिए भी हमेशा हस्ताक्षर किए गए ऑपकोड की उपेक्षा करेगा और इस तरह मुफ्त में दो-पूरक प्राप्त करेगा।
आर .. गिटहब स्टॉप हेल्पिंग ICE

1
@ आर .: var = ~(0*var)मामला varएक अहस्ताक्षरित प्रकार की तुलना में संकीर्ण होने के लिए विफल होगा int। शायद var = ~(0U*var)? (व्यक्तिगत रूप से मैं अभी भी पसंद करता हूं -1, हालांकि)।
कैफे डेस

1
यह जवाब जोहान्स शाउब के मुकाबले बहुत स्पष्ट है। हालांकि, बिना कलाकारों के एक अनिर्दिष्ट प्रकार के एक नकारात्मक शाब्दिक पूर्णांक को निर्दिष्ट करने से आमतौर पर संकलक चेतावनी होती है। चेतावनी को दबाने के लिए एक कलाकार की आवश्यकता होती है, जिसका मतलब है कि लक्ष्य प्रकार पर ध्यान देना है, इसलिए आप UINT_MAX या ULONG_MAX का उपयोग कर सकते हैं और मानक में एक छोटे से विस्तार पर भरोसा करने के बजाय स्पष्ट रूप से अपने साथी प्रोग्रामर के कई स्पष्ट रूप से भ्रमित करते हैं ।
एड्रियन मैक्कार्थी

5

जब तक आपके पास #include <limits.h>आपके एक शामिल हैं, तब तक आपको बस उपयोग करना चाहिए

unsigned int flags = UINT_MAX;

यदि आप लंबे समय के बिट्स चाहते हैं, तो आप उपयोग कर सकते हैं

unsigned long flags = ULONG_MAX;

इन मानों की गारंटी है कि परिणाम के सभी मूल्य बिट्स 1 पर सेट किए गए हैं, इस बात की परवाह किए बिना कि हस्ताक्षर किए गए पूर्णांक कैसे लागू किए जाते हैं।


1
आपके द्वारा सुझाए गए स्थिरांक वास्तव में सीमा में परिभाषित किए गए हैं ।h - stdint.h में अतिरिक्त पूर्णांक प्रकार (निश्चित आकार के पूर्णांक, intptr_t, ...) के लिए सीमाएँ शामिल हैं
क्रिस्टोफ़

5

हाँ। जैसा कि अन्य उत्तरों में बताया गया है,-1 है, सबसे पोर्टेबल है; हालाँकि, यह बहुत अर्थपूर्ण नहीं है और संकलक की चेतावनी को ट्रिगर करता है।

इन मुद्दों को हल करने के लिए, इस सरल सहायक की कोशिश करें:

static const struct All1s
{
    template<typename UnsignedType>
    inline operator UnsignedType(void) const
    {
        static_assert(std::is_unsigned<UnsignedType>::value, "This is designed only for unsigned types");
        return static_cast<UnsignedType>(-1);
    }
} ALL_BITS_TRUE;

उपयोग:

unsigned a = ALL_BITS_TRUE;
uint8_t  b = ALL_BITS_TRUE;
uint16_t c = ALL_BITS_TRUE;
uint32_t d = ALL_BITS_TRUE;
uint64_t e = ALL_BITS_TRUE;

3
एक सी प्रोग्रामर के रूप में, इस तरह का कोड मुझे रात में बुरे सपने देता है।
jforberg

और क्या होता है जब आप इस संदर्भ में उपयोग करते हैं जैसे ALL_BITS_TRUE ^ aकि aएक हस्ताक्षरित पूर्णांक कहां है? प्रकार हस्ताक्षरित पूर्णांक रहता है और बिट-पैटर्न (ऑब्जेक्ट प्रतिनिधित्व) लक्ष्य 2 के पूरक होने या न होने पर निर्भर करता है।
पीटर कॉर्ड्स

नहीं, ALL_BITS_TRUE ^ aएक संकलित त्रुटि देता है क्योंकि ALL_BITS_TRUEअस्पष्ट है। uint32_t(ALL_BITS_TRUE) ^ aहालाँकि, इसका उपयोग किया जा सकता है । आप इसे अपने आप cpp.sh पर आज़मा सकते हैं :) आजकल मैं एक सुनिश्चित करने static_assert(std::is_unsigned<UnsignedType>::value, "This is designed only for unsigned types");के operatorलिए जोड़ूंगा कि उपयोगकर्ता उपयोग करने की कोशिश न करें int(ALL_BITS_TRUE)। मैं जवाब अपडेट कर दूंगा।
डायमंड पायथन

3

मैं -1 काम नहीं करूंगा। यह बल्कि गैर-सहज (मेरे लिए कम से कम) है। हस्ताक्षरित डेटा को एक अहस्ताक्षरित चर पर असाइन करना बस चीजों के प्राकृतिक आदेश का उल्लंघन लगता है।

आपकी स्थिति में, मैं हमेशा उपयोग करता हूं 0xFFFF । (पाठ्यक्रम के चर आकार के लिए Fs की सही संख्या का उपयोग करें।)

[BTW, मैं बहुत मुश्किल से वास्तविक दुनिया कोड में किया -1 चाल को देखते हैं।]

साथ ही, यदि आप वास्तव में एक vairable में अलग-अलग बिट्स के बारे में परवाह है, यह अच्छा विचार निश्चित-चौड़ाई का उपयोग शुरू किया जाएगा uint8_t, uint16_t, uint32_tप्रकार के।


2

इंटेल के IA-32 प्रोसेसर पर 0xFFFFFFFF को 64-बिट रजिस्टर में लिखना और अपेक्षित परिणाम प्राप्त करना ठीक है। ऐसा इसलिए है क्योंकि IA32e (IA32 के लिए 64-बिट एक्सटेंशन) केवल 32-बिट तुरंत का समर्थन करता है। 64-बिट निर्देशों में 32-बिट तत्काल 64-बिट्स पर हस्ताक्षर-विस्तारित हैं

निम्नलिखित अवैध है:

mov rax, 0ffffffffffffffffh

निम्नलिखित RAX में 64 1s डालता है:

mov rax, 0ffffffffh

पूर्णता के लिए, निम्नलिखित RAX (उर्फ EAX) के निचले हिस्से में 32 1s डालता है:

mov eax, 0ffffffffh

और वास्तव में मेरे पास कार्यक्रम विफल हो गए हैं जब मैं 0xffffffff को 64-बिट चर में लिखना चाहता था और मुझे इसके बजाय 0xffffffffffffff मिला। सी में यह होगा:

uint64_t x;
x = UINT64_C(0xffffffff)
printf("x is %"PRIx64"\n", x);

परिणाम है:

x is 0xffffffffffffffff

मैंने इसे सभी उत्तरों के लिए एक टिप्पणी के रूप में पोस्ट करने के लिए सोचा था जिसमें कहा गया था कि 0xFFFFFFFF 32 बिट्स को मानता है, लेकिन इतने सारे लोगों ने उत्तर दिया कि मुझे लगा कि मैं इसे एक अलग उत्तर के रूप में जोड़ दूंगा।


1
बधाई हो, आपको एक कंपाइलर बग मिला है!
टीसी

क्या इसे बग के रूप में कहीं भी प्रलेखित किया गया है?
नाथन फेलमैन

1
यह मानते हुए कि यह UINT64_C(0xffffffff)किसी चीज का विस्तार है 0xffffffffuLL, यह निश्चित रूप से एक कंपाइलर बग है। सी मानक बड़े पैमाने पर मूल्यों पर चर्चा करता है , जो प्रतिनिधित्व 0xffffffff4294967295 (36893488147419103231 नहीं) है, और दृष्टि में पूर्णांक प्रकारों पर हस्ताक्षर करने के लिए कोई रूपांतरण नहीं हैं।
टीसी

2

मुद्दों के बहुत स्पष्ट स्पष्टीकरण के लिए लिटब का जवाब देखें।

मेरी असहमति यह है कि, बहुत सख्ती से बोलना, किसी भी मामले की कोई गारंटी नहीं है। मैं किसी भी वास्तुकला के बारे में नहीं जानता, जो सभी बिट्स के सेट के रूप में 'बिट्स की संख्या के दो से कम शक्ति' के एक अहस्ताक्षरित मूल्य का प्रतिनिधित्व नहीं करता है, लेकिन यहां मानक वास्तव में क्या कहते हैं (3.9.1 / 7 प्लस) नोट 44):

अभिन्न प्रकार के अभ्यावेदन शुद्ध द्विआधारी संख्या प्रणाली के उपयोग से मूल्यों को परिभाषित करेंगे। [नोट ४४:] बाइनरी अंक ० और १ का उपयोग करने वाले पूर्णांकों के लिए एक स्थितीय प्रतिनिधित्व, जिसमें क्रमिक बिट्स द्वारा दर्शाए गए मान योगात्मक हैं, १ से शुरू होते हैं, और २ की क्रमिक अभिन्न शक्ति से गुणा किए जाते हैं, शायद बिट के लिए छोड़कर। सर्वोच्च स्थान।

यह बिट्स में से एक के लिए कुछ भी होने की संभावना छोड़ देता है।


सामान्य तौर पर, हम पैडिंग बिट्स के मूल्य के बारे में निश्चित नहीं हो सकते हैं। और अगर हम चाहते हैं, तो हम खतरे में पड़ सकते हैं क्योंकि हम उनके लिए एक जाल प्रतिनिधित्व उत्पन्न कर सकते हैं (और यह संकेत बढ़ा सकता है)। हालाँकि, std के लिए अहस्ताक्षरित चार की आवश्यकता होती है, जिसमें कोई पेडिंग बिट्स नहीं है, और c ++ मानक में 4.7 / 2 में कहा गया है कि एक पूर्णांक को एक अहस्ताक्षरित प्रकार में परिवर्तित करना, जिसके परिणामस्वरूप अहस्ताक्षरित चर का मान स्रोत पूर्णांक मान के लिए सबसे छोटा मान है, (modulo 2 ^ n, n == अहस्ताक्षरित प्रकार में बिट्स)। तब (-1) == ((2 ^ एन) -1) (मॉड 2 ^ एन)। 2 ^ n-1 में सभी बिट्स शुद्ध बाइनरी नंबरिंग सिस्टम में सेट किए गए हैं।
जोहान्स शाउब -

यदि हम वास्तव में सभी बिट्स को एक अहस्ताक्षरित प्रकार के ऑब्जेक्ट प्रतिनिधित्व में रखना चाहते हैं, तो हमें परेशान होने की आवश्यकता होगी। लेकिन हम इसके अलावा एक ट्रैप प्रतिनिधित्व उत्पन्न कर सकते हैं :( वैसे भी, एक कार्यान्वयन शायद उनके अहस्ताक्षरित पूर्णांक से थोड़ा दूर फेंकने का कोई कारण नहीं है, इसलिए यह इसका उपयोग अपने मूल्यों को संग्रहीत करने के लिए करेगा। लेकिन आपको बहुत अच्छा बिंदु मिला है - कुछ भी नहीं है। कुछ मूर्खतापूर्ण बकवास बिट्स होने से एक व्याख्या, मुझे लगता है (चार / हस्ताक्षरित चार / बिना हस्ताक्षर किए चार के अलावा, जो उन लोगों के पास नहीं होनी चाहिए)। +1 बेशक:
जोहान्स स्काउब -

अंत में, मुझे लगता है कि मानक स्पष्ट हो सकता है कि यह 4.7 / 2 में किस प्रतिनिधित्व को दर्शाता है। यदि यह ऑब्जेक्ट प्रतिनिधित्व को संदर्भित करता है, तो अब पैडिंग बिट्स के लिए कोई जगह नहीं है (मैंने लोगों को इस तरह बहस करते देखा है जो मुझे कुछ भी गलत नहीं दिखता है)। लेकिन मुझे लगता है कि यह मूल्य प्रतिनिधित्व के बारे में बात करता है (क्योंकि 4.7 / 2 में सब कुछ वैसे भी मूल्यों के बारे में है - और फिर पैडिंग बिट्स मूल्य बिट्स के बगल में घोंसला कर सकते हैं।
जोहान्स स्कैब -

1
मानक स्पष्ट रूप से लगता है '2 के पूरक, 1 के पूरक और हस्ताक्षरित परिमाण' मन में प्रतिनिधित्व करते हैं, लेकिन कुछ भी शासन नहीं करना चाहते हैं। अभ्यावेदन को फँसाने के बारे में भी दिलचस्प बात। जहां तक ​​मैं बता सकता हूं, मैंने जो बिट उद्धृत किया है वह 'शुद्ध द्विआधारी अंकन प्रणाली' की परिभाषा है जहां तक ​​मानक का संबंध है - अंत में 'बिट को छोड़कर' वास्तव में मेरा एकमात्र संदेह है कि क्या कास्टिंग -1 की गारंटी है काम।
जेम्स हॉपकिन

2

यद्यपि 0xFFFF(या0xFFFFFFFF , आदि) पढ़ने में आसान हो सकता है, यह कोड में पोर्टेबिलिटी को तोड़ सकता है जो अन्यथा पोर्टेबल होगा। उदाहरण के लिए, एक लाइब्रेरी रुटीन की गणना करने के लिए कि डेटा संरचना में कितने आइटमों में कुछ बिट्स सेट हैं (कॉलर द्वारा निर्दिष्ट सटीक बिट्स)। दिनचर्या पूरी तरह से अज्ञेय हो सकती है जैसा कि बिट्स का प्रतिनिधित्व करते हैं, लेकिन अभी भी एक "सभी बिट्स सेट" स्थिर होना चाहिए। इस तरह के मामले में, -1 हेक्स स्थिरांक से काफी बेहतर होगा क्योंकि यह किसी भी बिट आकार के साथ काम करेगा।

दूसरी संभावना, यदि typedefबिटमास्क के लिए एक मूल्य का उपयोग किया जाता है , तो ~ (bitMaskType) 0 का उपयोग करना होगा; अगर बिटमास्क केवल 16-बिट प्रकार का होता है, तो उस अभिव्यक्ति में केवल 16 बिट्स होंगे (भले ही 'int' अन्यथा 32 बिट्स होंगे) लेकिन चूंकि 16 बिट्स की आवश्यकता होगी, इसलिए सभी चीजें ठीक होनी चाहिए, बशर्ते कि वह ठीक हो। वास्तव में टाइपकास्ट में उपयुक्त प्रकार का उपयोग करता है।

संयोग से, प्रपत्र की अभिव्यक्तियों में longvar &= ~[hex_constant]एक गंदा गोटा है यदि हेक्स स्थिरांक फिट करने के लिए बहुत बड़ा है int, लेकिन एक में फिट होगा unsigned int। यदि एक int16 बिट्स है, तो longvar &= ~0x4000;या longvar &= ~0x10000; एक बिट को साफ करेगा longvar, लेकिन longvar &= ~0x8000;15 बिट और उससे ऊपर के सभी बिट्स को साफ कर देगा। वे मान जो फिट होते हैं intउनमें एक प्रकार से लागू किया गया पूरक ऑपरेटर होगा int, लेकिन परिणाम longऊपरी बिट्स को सेट करते हुए साइन इन किया जाएगा । मान जो बहुत बड़े unsigned intहैं वे प्रकार के लिए लागू किए गए पूरक ऑपरेटर होंगे long। मान, जो उन आकारों के बीच हैं, हालांकि, टाइप करने के लिए पूरक ऑपरेटर को लागू करेंगेunsigned int , जो तब longसाइन एक्सटेंशन के बिना टाइप में परिवर्तित हो जाएगा ।


1

व्यावहारिक रूप से: हाँ

सैद्धांतिक रूप से: नहीं।

-1 = 0xFFFFFFFF (या आपके प्लेटफ़ॉर्म पर कोई भी आकार) केवल दो पूरक अंकगणित के साथ सच है। व्यवहार में, यह काम करेगा, लेकिन वहाँ विरासत मशीनें (आईबीएम मेनफ्रेम, आदि) हैं, जहां आपको दो के पूरक प्रतिनिधित्व के बजाय वास्तविक साइन बिट मिला है। आपका प्रस्तावित ~ 0 समाधान हर जगह काम करना चाहिए।


6
मैंने भी कहा। लेकिन तब मुझे एहसास हुआ कि मैं गलत था, क्योंकि -1 पर हस्ताक्षर किए गए मूल्य मानों की परवाह किए बिना, हमेशा रूपांतरण नियमों के तहत अहस्ताक्षरित max_value में परिवर्तित हो जाते हैं। कम से कम, यह सी ++ में करता है, मेरे पास हाथ करने के लिए सी मानक नहीं है।
स्टीव जेसोप

6
एक अस्पष्टता है। -1 0xFFFFFFFF नहीं है। लेकिन -1 0xFFFFFFFF है यदि एक अहस्ताक्षरित int (32 बिट वाले) में परिवर्तित किया गया है। यही बात इस चर्चा को इतना कठिन बना रही है। कई लोगों के मन में बहुत अलग चीजें होती हैं जब वे उन बिट स्ट्रिंग्स के बारे में बात करते हैं।
जोहान्स शहाब -

1

जैसा कि दूसरों ने उल्लेख किया है, -1 पूर्णांक बनाने का सही तरीका है, जो कि 1. बिट सेट के साथ एक अहस्ताक्षरित प्रकार में बदल जाएगा। हालांकि, C ++ में सबसे महत्वपूर्ण बात सही प्रकार का उपयोग करना है। इसलिए, आपकी समस्या का सही उत्तर (जिसमें आपके द्वारा पूछे गए प्रश्न का उत्तर शामिल है) यह है:

std::bitset<32> const flags(-1);

इसमें हमेशा आपके द्वारा आवश्यक बिट्स की सटीक मात्रा शामिल होगी। यह std::bitsetअन्य उत्तरों में उल्लिखित समान कारणों के लिए 1 के साथ सेट किए गए सभी बिट्स के साथ निर्माण करता है।


0

यह निश्चित रूप से सुरक्षित है, क्योंकि -1 में हमेशा सभी उपलब्ध बिट्स सेट होंगे, लेकिन मुझे ~ 0 बेहतर पसंद है। -1 सिर्फ एक के लिए बहुत मतलब नहीं है unsigned int0xFF... अच्छा नहीं है क्योंकि यह प्रकार की चौड़ाई पर निर्भर करता है।


4
"IxFF ... यह अच्छा नहीं है क्योंकि यह उस प्रकार की चौड़ाई पर निर्भर करता है" जो जाने का एकमात्र एकमात्र तरीका है, मुझे लगता है। आप स्पष्ट रूप से परिभाषित करने वाले हैं कि आपके कार्यक्रम में प्रत्येक ध्वज / बिट का क्या अर्थ है। इसलिए, यदि आप परिभाषित करते हैं कि आप झंडे को संग्रहीत करने के लिए सबसे कम 32 बिट्स का उपयोग कर रहे हैं, तो आपको उन 32 बिट्स का उपयोग करने के लिए खुद को प्रतिबंधित करना चाहिए, चाहे इंट का वास्तविक आकार 32 या 64 हो।
जुआन पाब्लो कैलिफ़ोर्नो

0

मैं कहता हूँ:

int x;
memset(&x, 0xFF, sizeof(int));

यह आपको हमेशा वांछित परिणाम देगा।


4
9-बिट वर्णों वाले सिस्टम पर नहीं!
टीसी

0

इस तथ्य पर उत्तोलन करना कि सभी बिट्स को एक अहस्ताक्षरित प्रकार के लिए असाइन करना, दिए गए प्रकार के लिए अधिकतम संभव मान लेने के बराबर है,
और प्रश्न के दायरे को सभी अहस्ताक्षरित पूर्णांक प्रकारों में विस्तारित करना है :

C और C ++ दोनों के लिए किसी भी अहस्ताक्षरित पूर्णांक प्रकार (अहस्ताक्षरित int, uint8_t, uint16_t, आदि) के लिए कार्य करना।

C ++ के विकल्प के रूप में, आप या तो:

  1. शामिल करें <limits>और उपयोग करेंstd::numeric_limits< your_type >::max()
  2. एक कस्टम टेम्प्लेटेड फंक्शन लिखें (यह कुछ पवित्रता जांचने की भी अनुमति देगा, अर्थात यदि गंतव्य प्रकार वास्तव में एक अहस्ताक्षरित प्रकार है)

उद्देश्य अधिक स्पष्टता जोड़ सकता है, क्योंकि असाइन करने के -1लिए हमेशा कुछ व्याख्यात्मक टिप्पणी की आवश्यकता होगी।


0

प्रकार को दोहराने से बचने के लिए अर्थ को और अधिक स्पष्ट और अभी तक बनाने का एक तरीका:

const auto flags = static_cast<unsigned int>(-1);

-6

हाँ दर्शाया गया प्रतिनिधित्व बहुत सही है जैसे कि हम इसे दूसरे तरीके से करते हैं जैसे कि यू को एक ऑपरेटर को सभी बिट्स को उलटने की आवश्यकता होगी लेकिन इस मामले में तर्क काफी सीधा है अगर हम मशीन में पूर्णांक के आकार पर विचार करें

उदाहरण के लिए, अधिकांश मशीनों में एक पूर्णांक 2 बाइट्स = 16 बिट्स होता है, जो अधिकतम मूल्य 2 है 16 ^ = 65535 2 ^ 16 = 65536

0% 65536 = 0 -1% 65536 = 65535 जो 1111 पर निर्भर करता है ............. 1 और सभी बिट्स 1 पर सेट होते हैं (यदि हम अवशेष वर्गों को मॉड 65536 मानते हैं) तो यह बहुत है सीधे आगे।

मेरा अनुमान

यदि आप इस धारणा पर विचार नहीं करते हैं तो यह अहस्ताक्षरित किलों के लिए पूरी तरह से भोजन है और यह वास्तव में काम करता है

बस निम्नलिखित कार्यक्रम के टुकड़े की जाँच करें

मुख्य प्रवेश बिंदु() {

unsigned int a=2;

cout<<(unsigned int)pow(double(a),double(sizeof(a)*8));

unsigned int b=-1;

cout<<"\n"<<b;

getchar();

return 0;

}

4 = बाइट पूर्णांक पर b = 4294967295 व्हिच का उत्तर -1% 2 ^ 32 है

इसलिए यह अहस्ताक्षरित पूर्णांकों के लिए पूरी तरह से मान्य है

किसी भी विसंगतियों के मामले में प्रतिवेदन रिपोर्ट


9
दो टिप्पणियाँ: सबसे पहले, आप "सबसे" मशीनों पर पूर्णांक के आकार के बारे में गलत हैं। दूसरी बात, उर txt iz बहुत मुश्किल से २ पढ़ी जाती है २ उर हमें समरथ भाषा के योग के रूप में देती है। हमें प्लेन अंग्रेजी
कोनराड रुडोल्फ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.