दिलचस्प पोस्ट
ओएस स्तरीय सिस्टम जानकारी प्राप्त करें क्यों घातक त्रुटि "LNK1104: 'C: \ Program.obj' फ़ाइल नहीं खोल सकता '' जब मैं विजुअल स्टूडियो में एक सी ++ प्रोजेक्ट संकलित करता हूं? SQLite डेटाबेस बनाम कच्चे संसाधन परीक्षण के लिए समीकरण यदि कोई बिंदु एक वृत्त के अंदर है अपूर्णांक रखने के लिए स्ट्रिंग को दशमलव में कनवर्ट करें आईपी ​​एड्रेस का इस्तेमाल करते हुए टोमकेट तक नहीं पहुंच सकते .net UrlEncode – लोअरकेस समस्या स्ट्रिंग के लिए हैश फ़ंक्शन Google Apps स्क्रिप्ट में अधिकतम निष्पादन समय बढ़ गया एक एमएस-एसक्यूएल डाटाबेस के अंदर किसी भी तालिका के किसी भी कॉलम में एक मान की खोज कैसे करें? लॉग बेस (2) सी / सी ++ में लिखने के लिए कैसे SQLAlchemy: फ्लश () और प्रतिबद्ध () के बीच अंतर क्या है? ऐप सेवा पर संगीतकार कैसे स्थापित करें? पुनरावर्तक में पुनरावर्तक माडल से पैरामीटर पास करें

जीसीसी ने शिफ्ट ओवरफ्लो छोड़ दिया

मैक पर जीसीसी संस्करण 4.2.1 (ऐप्पल इंक का निर्माण 5664) का उपयोग करते हुए निम्नलिखित छोटे प्रोग्राम बहुत अजीब है I

#include <stdio.h> int main(){ int x = 1 << 32; int y = 32; int z = 1 << y; printf("x:%d, z: %d\n", x, z); } 

परिणाम x:0, z: 1
कोई भी विचार क्यों एक्स और जेड के मूल्य अलग हैं?
बहुत बहुत धन्यवाद।

Solutions Collecting From Web of "जीसीसी ने शिफ्ट ओवरफ्लो छोड़ दिया"

संक्षिप्त जवाब: इंटेल प्रोसेसर मास्क को 5 बिट (अधिकतम 31) में बदलाव की गणना है। दूसरे शब्दों में, वास्तव में किया गया बदलाव (32 | 31) = 0 बिट्स (कोई परिवर्तन नहीं) है

एक ही परिणाम एक लिनक्स 32-बिट पीसी पर जीसीसी का उपयोग कर रहा है।

मैंने इस कार्यक्रम का एक छोटा संस्करण इकट्ठा किया क्योंकि मुझे आश्चर्य था कि 32 बिट की एक बायीं तरफ नॉन-शून्य मूल्य का परिणाम क्यों होना चाहिए:

 int main(){ int y = 32; unsigned int z = 1 << y; unsigned int k = 1; k <<= y; printf("z: %u, k: %u\n", z, k); } 

.. gcc -Wall -o as -S deleteme.c सी। कमांड का gcc -Wall -o as -S deleteme.c (मेरी टिप्पणियां हैं)

 main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx subl $36, %esp movl $32, -16(%ebp) ; y = 32 movl -16(%ebp), %ecx ; 32 in CX register movl $1, %eax ; AX = 1 sall %cl, %eax ; AX <<= 32(32) movl %eax, -12(%ebp) ; z = AX movl $1, -8(%ebp) ; k = 1 movl -16(%ebp), %ecx ; CX = y = 32 sall %cl, -8(%ebp) ; k <<= CX(32) movl -8(%ebp), %eax ; AX = k movl %eax, 8(%esp) movl -12(%ebp), %eax movl %eax, 4(%esp) movl $.LC0, (%esp) call printf addl $36, %esp popl %ecx popl %ebp leal -4(%ecx), %esp ret 

ठीक है, इसका क्या अर्थ है? यह निर्देश है कि मुझे पहेलियाँ:

 sall %cl, -8(%ebp) ; k <<= CX(32) 

स्पष्ट रूप से 32 बिट्स द्वारा छोड़ा गया स्थानांतरित किया जा रहा है।

आप मुझे मिल गया है – यह sall अनुदेश का उपयोग कर रहा है जो एक अंकगणितीय बदलाव है । मुझे नहीं पता है कि शुरुआती पोजीशन में फिर से दिखने में 32 परिणामों के द्वारा इसे घूमने क्यों नहीं। मेरा प्रारंभिक अनुमान यह होगा कि प्रोसेसर एक घड़ी चक्र में इस अनुदेश को अनुकूलित करने के लिए अनुकूलित है – जिसका अर्थ है कि 31 से अधिक समय तक किसी भी बदलाव को ध्यान नहीं दिया जाएगा। लेकिन मैं इसका जवाब खोजने के लिए उत्सुक हूं क्योंकि मुझे उम्मीद है कि घुमाए जाने के परिणामस्वरूप सभी प्रकार के बिट्स को डेटा प्रकार के बाएं छोर से गिरना चाहिए।

मुझे http://faydoc.tripod.com/cpu/sal.htm का एक लिंक मिला है जो बताता है कि शिफ्ट की संख्या (सीएल रजिस्टर में) को 5 बीट्स के साथ मुखौटा है I इसका मतलब यह है कि यदि आपने 32 बीट्स की तरफ बदलाव की कोशिश की तो वास्तविक बदलाव किया जाएगा शून्य बिट्स (यानी कोई परिवर्तन नहीं)। जवाब है!

यदि आपकी ints 32 बिट या छोटी है, तो व्यवहार अनिर्धारित है … और अपरिभाषित व्यवहार को समझाया नहीं जा सकता

स्टैंडर्ड कहते हैं:

6.5.7 / 3 […] यदि सही ऑपरेंड का मान नकारात्मक है या प्रचारित बाएं ऑपरेंड की चौड़ाई के बराबर या उसके बराबर है, तो व्यवहार अनिर्धारित है।


आप अपने पूर्ण चौड़ाई बिट आकार की जांच कर सकते हैं, उदाहरण के लिए:

 #include <limits.h> #include <stdio.h> int main(void) { printf("bits in an int: %d\n", CHAR_BIT * (int)sizeof (int)); return 0; } 

और आप अपनी पूर्ण चौड़ाई (पैडिंग बिट्स) देख सकते हैं, उदाहरण के लिए:

 #include <limits.h> #include <stdio.h> int main(void) { int width = 0; int tmp = INT_MAX; while (tmp) { tmp >>= 1; width++; } printf("width of an int: %d\n", width + 1 /* for the sign bit */); return 0; } 

मानक 6.2.6.2/2: हस्ताक्षरित पूर्णांक प्रकारों के लिए, ऑब्जेक्ट के प्रतिनिधित्व के बिट्स को तीन समूहों में विभाजित किया जाएगा: मूल्य बिट्स, पैडिंग बिट्स और साइन बिट। कोई पैडिंग बिट्स की आवश्यकता नहीं है; ठीक एक साइन बिट हो जाएगा

C99 मानक का कहना है कि परिपथ के बिट्स (या अधिक) की चौड़ाई में एक संख्या को स्थानांतरित करने का नतीजा अपरिभाषित है। क्यूं कर?

अच्छी तरह से यह एक विशेष आर्किटेक्चर के लिए सबसे कुशल कोड बनाने के लिए कंपाइलर्स को अनुमति देता है। उदाहरण के लिए, i386 शिफ्ट अनुदेश बिट्स की संख्या के लिए एक 5 बिट विस्तृत फ़ील्ड का इस्तेमाल करता है ताकि 32 बिट ऑपरेंड को स्थानांतरित किया जा सके। सीएमएक्स मानक से कंपाइलर को बदलाव की गिनती के निचले पांच बिट्स लेना पड़ता है और उन्हें क्षेत्र में डाल दिया जाता है। स्पष्ट रूप से इसका मतलब है कि 32 बिट (बाइनरी में = 100000) की एक शिफ्ट इसलिए 0 की पारी के समान है और परिणाम इसलिए बाएं ऑपरेंड के रूप में अपरिवर्तित हो जाएगा।

एक अलग सीपीयू वास्तुकला एक व्यापक बिट फ़ील्ड का प्रयोग कर सकता है, 32 बिट्स कहें। कंपाइलर अभी भी फ़ील्ड में सीधे बदलाव की गिनती डाल सकता है लेकिन इस बार परिणाम 0 हो जाएगा क्योंकि 32 बिट्स की एक शिफ्ट सभी बिट्स को बाएं ऑपरेंड से बदल देगी।

अगर सीएएम ने इन कार्यों में से एक या अन्य को सही के रूप में परिभाषित किया है, तो इंटेल के लिए कंपाइलर को बदलाव की गिनती के लिए विशेष जांच करना पड़ता है जो कि बहुत बड़ी है या गैर i386 के लिए कंपाइलर को शिफ्ट गेट को मुखौटा बनाना है

कारण क्यों

  int x = 1 << 32; 

तथा

  int z = 1 << y; 

विभिन्न परिणाम दें क्योंकि पहली गणना एक स्थिर अभिव्यक्ति है और संकलक द्वारा पूरी तरह से किया जाता है। संकलक को 64 बिट अंकगणितीय का उपयोग करके निरंतर अभिव्यक्ति की गणना करनी चाहिए। दूसरी अभिव्यक्ति की गणना कंपाइलर द्वारा उत्पन्न कोड द्वारा की जाती है। चूंकि दोनों वाई और जेड के प्रकार int , कोड 32 बिट विस्तृत ints का उपयोग कर गणना करता है (इंटेल i386 और x86_64 दोनों पर एप्पल पर जीसीसी के साथ 32 बिट्स है)।

मेरे मन में "int x = y << 32;" समझ नहीं है अगर sizeof (int) == 4

लेकिन मेरे साथ एक समान समस्या थी:

लंबे y = … लंबे x = y << 32;

जहां मुझे एक चेतावनी मिली "चेतावनी: बायीं तरफ संख्या> = चौड़ाई प्रकार" हालांकि सवाल में लक्ष्य पर आकार (लंबे) 8 था 8। इसके बजाए मैंने चेतावनी से छुटकारा दिलाया:

लंबे x = (y << 16) << 16;

और यह काम करने के लिए लग रहा था

64 बिट वास्तुकला पर कोई चेतावनी नहीं थी एक 32 बिट वास्तुकला पर वहाँ था।