क्या आकार (कुछ सूचक) हमेशा चार के बराबर होता है?


227

उदाहरण के लिए: sizeof(char*)रिटर्न 4. के रूप में करता है int*, long long*है, मैं कोशिश की है सब कुछ है कि। क्या इसका कोई अपवाद हैं?


51
इसे नीचे क्यों चिह्नित करें? किसी भी शुरुआत के लिए अच्छा सवाल।
मार्टिन यॉर्क

2
मुझे संदेह है कि एक और सवाल इस में छिपा है: "आकार क्या है?" या हो सकता है "Why is sizeof <any pointer> == 4? 4 के बारे में इतना खास क्या है?"। क्या मैं सही हू?

2
खैर, यह आपके प्लेटफॉर्म पर निर्भर करता है। अधिकांश कार्यान्वयन विशिष्ट प्लेटफ़ॉर्म पर हर तरह के पॉइंटर के लिए एक समान आकार साझा करते हैं।
फोएगॉन

जवाबों:


194

आपको जो गारंटी मिलती है, वह है sizeof(char) == 1। कोई अन्य गारंटी नहीं है, जिसमें कोई गारंटी नहीं है sizeof(int *) == sizeof(double *)

व्यवहार में, पॉइंटर्स 16-बिट सिस्टम पर 2 आकार के होंगे (यदि आप एक को पा सकते हैं), 4 एक 32-बिट सिस्टम पर और 8 एक 64-बिट सिस्टम पर, लेकिन किसी दिए गए पर भरोसा करने में प्राप्त होने वाली कोई भी चीज नहीं है आकार।


96
और 24-बिट सिस्टम पर 3 बाइट्स। हां, मैंने एक पर काम किया है। एम्बेडेड उपकरणों की दुनिया में आपका स्वागत है।
dwj

30
मैंने 16-बिट सिस्टम पर 20-बिट पॉइंटर्स के साथ भी काम किया है। मुझे यह देखना चाहिए कि उस मामले में क्या आकार वापस आता है ...
न्यायाधीश मेग्गार्डन

5
@monjardin: IIRC, 8086 जैसा था। 16 बिट पता और 4 बिट खंड रजिस्टर था। मेरा मानना ​​है कि एक सामान्य "एनईएआर" सूचक 16 बिट्स था और "एफएआर" के रूप में घोषित एक संकेतक अधिक था, शायद 24, हालांकि मुझे यकीन है।
rmeador

18
एक और गारंटी है कि आकार (चार *) == आकार (शून्य *), क्योंकि उनके पास समान अभ्यावेदन (वस्तु [आकार] और मूल्य [उनके मूल्य के लिए प्रासंगिक बिट्स का सेट] प्रतिनिधित्व)
जोहान्स स्काउब - लिट्ल

7
चूंकि प्रश्न अपवादों के लिए पूछता है, इसलिए यह ध्यान दिया जाना चाहिए कि गैर-स्थैतिक सदस्य फ़ंक्शन पॉइंटर्स अक्सर सामान्य पॉइंटर्स के लिए एक अलग आकार होते हैं और प्लेटफ़ॉर्म, प्रकार, आदि से भिन्न होते हैं।
जॉन ५३४२

36

यहां तक ​​कि एक सादे x86 32 बिट प्लेटफॉर्म पर, आप विभिन्न प्रकार के पॉइंटर आकार प्राप्त कर सकते हैं, उदाहरण के लिए इसे आज़माएं:

struct A {};

struct B : virtual public A {};

struct C {};

struct D : public A, public C {};

int main()
{
    cout << "A:" << sizeof(void (A::*)()) << endl;
    cout << "B:" << sizeof(void (B::*)()) << endl;
    cout << "D:" << sizeof(void (D::*)()) << endl;
}

विजुअल C ++ 2008 के तहत, मुझे पॉइंटर्स-टू-मेंबर-फंक्शन के साइज़ के लिए 4, 12 और 8 मिलते हैं।

रेमंड चेन ने यहां इस बारे में बात की ।


4
सदस्य कार्यों के संकेत एक वास्तविक दर्द हैं। यह दुर्भाग्यपूर्ण है कि सभी कंपाइलर इसे डिजिटल मार्स C ++ कंपाइलर की तरह नहीं देते हैं, जो सभी मामलों में 4 पर वापस आते हैं।
dalle

gcc 4.72 सभी 8 प्रिंट करें ... क्या यह c ++ मानक में अपरिभाषित है?
Gob00st

2
@ Gob00st: केवल एक चीज जो परिभाषित है वह है चार। 1. अन्य प्रकार हो सकते हैं जो भी आकार उस कंपाइलर के लिए प्रासंगिक हो। इन सूचक प्रकारों के बीच संगतता की कोई आवश्यकता नहीं है।
ग्रहण

ठीक है धन्यवाद। फिर कोई आश्चर्य नहीं कि जीसीसी और वीसी का अलग-अलग कार्यान्वयन है।
23:00 पर Gob00st

5
@ ग्रहण हाँ वहाँ है: char <= short <= int <= long <= long long
कोल जॉनसन

30

पहले से ही पोस्ट की गई सूची के लिए एक और अपवाद। 32-बिट प्लेटफ़ॉर्म पर, पॉइंटर्स 6 ले सकते हैं, 4 नहीं , बाइट्स:

#include <stdio.h>
#include <stdlib.h>

int main() {
    char far* ptr; // note that this is a far pointer
    printf( "%d\n", sizeof( ptr));
    return EXIT_SUCCESS;
}

यदि आप इस कार्यक्रम को ओपन वाटकॉम के साथ संकलित करते हैं और इसे चलाते हैं, तो आपको 6 मिलेंगे, क्योंकि दूर के संकेत जो इसमें 32-बिट ऑफसेट और 16-बिट खंड मानों का समर्थन करते हैं


5
खंड नहीं, बल्कि चयनकर्ता - यह मेमोरी एड्रेस का हिस्सा नहीं है, लेकिन LDT या GDT में एक इंडेक्स प्रविष्टि और कुछ एक्सेस फ़्लैग हैं
Roee Shenberg

1
X86 में सेगमेंट और ऑफ़सेट क्यों हैं जबकि पता स्थान समतल है?
फुल्विक

@ LưuV LnhPhúc क्योंकि यह निकट बिंदुओं के बहुत ही सामान्य मामले के लिए स्थान बचाता है, जिसे छोटा किया जा सकता है।
क्रिस्टोफर क्रेतुज़िग

1
@ChristopherCreutzig का अर्थ है कि खंडों का उपयोग PAE की तरह पता स्थान के विस्तार के लिए किया जाता है?
फुलकव

@ LưuV LnhPhúc यह एक लंबा समय हो गया है कि मैंने कुछ 32 बिट पर असेंबली की है। मेरे द्वारा याद किया जाने वाला हिस्सा यह है कि आप अपने पास मौजूद कोड की ओर इशारा करते हुए पॉइंटर्स के लिए जगह बचा सकते हैं। इसके अलावा, सभी 32 बिट आर्किटेक्चर नहीं - निश्चित रूप से सभी x86 पर आधारित नहीं हैं - एक फ्लैट मेमोरी मॉडल का उपयोग करें। देखें, जैसे, tenouk.com/Bufferoverflowc/Bufferoverflow1a.html इसके बारे में कुछ और चर्चा के लिए, हालाँकि, जैसा कि मैंने कहा, यह कुछ समय रहा है और मैं किसी भी चीज़ के लिए वाउच नहीं कर सकता।
क्रिस्टोफर क्रेतुज़िग

24

यदि आप 64-बिट मशीन के लिए संकलन कर रहे हैं, तो यह 8 हो सकता है।


2
जबकि यह आमतौर पर मामला है, यह जरूरी नहीं कि सच है। उदाहरण के लिए, यदि आप 64-बिट मशीन पर संकलित कर रहे हैं, जहां शब्द का आकार 64-बिट है, तो आकार-प्रकार (चार *) संभवतः 1 होगा। ग्रहण में और भी सामान्य मशीनों में और अधिक विदेशी सूचक प्रकारों का उल्लेख नहीं करना dmityugov लिखते हैं।
काज ड्रैगन

@KazDragon sizeof(char*)==1,? क्या आपको यकीन है? क्या आपका मतलब नहीं है size(char)==1?
एरॉन मैकडैड

3
@AaronMcDaid का वास्तव में आकार आकार (चार *) था। sizeof (char) हमेशा 1. होता है, लेकिन यदि आपका मशीन शब्द 64-बिट्स है, और आपके विकास का वातावरण इस तरह से कार्यान्वित किया जाता है कि CHAR_BITS = 64, तो यह संभव है कि एक संकेतक चार और चार के रूप में एक ही स्थान पर फिट बैठता है और इसलिए यह भी 1.
कज़ ड्रैगन ड्रैगन


1
@KazDragon मैं निर्माण कर रहा हूं (बहुत धीरे-धीरे, जब मैं नहीं बोल रहा हूं) 16-बिट शब्दों के साथ एक मशीन और कोई बाइट एड्रेसिंग नहीं। हालांकि यह C को वैसे भी नहीं चला सकता है।
user253751

17

तकनीकी रूप से, सी मानक केवल उस आकार (चर) == 1 की गारंटी देता है, और बाकी कार्यान्वयन पर निर्भर है। लेकिन आधुनिक x86 आर्किटेक्चर (जैसे इंटेल / एएमडी चिप्स) पर यह काफी अनुमानित है।

आपने शायद 16-बिट, 32-बिट, 64-बिट आदि के रूप में वर्णित प्रोसेसर सुना है, इसका आमतौर पर मतलब है कि प्रोसेसर पूर्णांक के साथ एन-बिट्स का उपयोग करता है। चूँकि पॉइंटर्स मेमोरी एड्रेस को स्टोर करते हैं, और मेमोरी एड्रेस पूर्णांक होते हैं, यह प्रभावी रूप से आपको बताता है कि कितने बिट्स पॉइंटर्स के लिए उपयोग किए जाने वाले हैं। साइज़ोफ़ आमतौर पर बाइट्स में मापा जाता है, इसलिए 32-बिट प्रोसेसर के लिए संकलित कोड 4 (32 बिट / 8 बिट प्रति बाइट) के लिए पॉइंटर्स का आकार रिपोर्ट करेगा, और 64-बिट प्रोसेसर के लिए कोड 8 के पॉइंटर्स के आकार की रिपोर्ट करेगा (64 बिट / 8 बिट प्रति बाइट)। यह वह जगह है जहां 32-बिट प्रोसेसर के लिए 4 जीबी रैम की सीमा आती है - यदि प्रत्येक मेमोरी एड्रेस एक बाइट से मेल खाती है, तो अधिक मेमोरी को संबोधित करने के लिए आपको 32-बिट से बड़े पूर्णांकों की आवश्यकता होती है।


"आपने शायद 16-बिट, 32-बिट, 64-बिट, आदि के रूप में वर्णित प्रोसेसर सुना है। इसका आमतौर पर मतलब है कि प्रोसेसर पूर्णांक के लिए एन-बिट्स का उपयोग करता है।" -> मैं 64-बिट मशीन लगा रहा हूँ, लेकिन sizeof (int) 4 बाइट्स है। यदि आपका कथन सत्य है, तो यह कैसे संभव हो सकता है ?!
संगीथ सरवनराज

6
@SangeethSaravanaraj: 32-बिट कोड के साथ पश्चगामी संगतता के लिए, उन्होंने इरादा किया है कि 4 बाइट्स जारी रहें और आपको 'लॉन्ग' निर्दिष्ट करके 8 बाइट प्रकार का उपयोग करने के लिए ऑप्ट-इन करना होगा। लंबा वास्तव में x86-64 पर मूल शब्द आकार है। इसे देखने का एक तरीका यह है कि आम तौर पर कंपाइलर आपकी संरचना को शब्द संरेखित करने के लिए पैड करेंगे (हालाँकि वहाँ आर्किटेक्चर हो सकते हैं जहाँ शब्द आकार और संरेखण असंबद्ध हैं), इसलिए यदि आप इसमें एक इंट (32-बिट) के साथ एक संरचना बनाते हैं, तो और उस पर कॉल आकार (), यदि आप वापस 8 प्राप्त करते हैं, तो आप जानते हैं कि यह उन्हें 64-बिट शब्द आकार में पैड कर रहा है।
जोसेफ गार्विन

@SangeethSaravanaraj: ध्यान दें कि सैद्धांतिक रूप से सीपीयू का मूल शब्द आकार और कंपाइलर 'int' जो तय करता है, वह मनमाने ढंग से अलग हो सकता है, यह सिर्फ 'int' के लिए कन्वेंशन है, जो पहले 686-64 के आसपास मूल शब्द के आकार में आता था, जहां यह पीछे के कम्पीटर्स को कम करने के लिए लंबा है।
जोसफ गार्विन

स्पष्टीकरण के लिए धन्यवाद! :)
संगीथ सरवनराज

7

पॉइंटर का आकार मूल रूप से उस सिस्टम की वास्तुकला पर निर्भर करता है जिसमें इसे लागू किया गया है। उदाहरण के लिए 32 बिट में एक पॉइंटर का आकार 4 बाइट्स (32 बिट) और 8 बिट्स (64 बिट) 64 बिट मशीनों में होता है। एक मशीन में बिट प्रकार स्मृति पते के अलावा कुछ भी नहीं है, कि यह हो सकता है। 32 बिट मशीनों में 2^32एड्रेस स्पेस हो सकता है और 64 बिट मशीनों में 2^64एड्रेस स्पेस हो सकता है। तो एक पॉइंटर (वैरिएबल जो एक मेमोरी लोकेशन की ओर इशारा करता है) किसी भी मेमोरी एड्रेस ( 2^32 for 32 bit and 2^64 for 64 bit) को इंगित करने में सक्षम होना चाहिए जो एक मशीन रखती है।

इस कारण से हम एक पॉइंटर का आकार 32 बिट मशीन में 4 बाइट और 64 बिट मशीन में 8 बाइट देखते हैं।


6

16/32/64 बिट अंतर के अलावा और भी अजीब चीजें हो सकती हैं।

ऐसी मशीनें आ गई हैं जहां आकार (इंट *) का एक मूल्य होगा, शायद 4 लेकिन जहां आकार (चार *) बड़ा है। मशीनें जो स्वाभाविक रूप से बाइट्स के बजाय शब्दों को संबोधित करती हैं, उन्हें वर्ण / बिंदु को निर्दिष्ट करने के लिए "संवर्द्धन" करना होता है कि आप वास्तव में C / C ++ मानक को ठीक से लागू करने के लिए किस शब्द का भाग चाहते हैं।

यह अब बहुत ही असामान्य है क्योंकि हार्डवेयर डिज़ाइनर ने बाइट एड्रेस की योग्यता को जान लिया है।


4
क्रे वेक्टर मशीनों के लिए सी कंपाइलर, जैसे कि T90, कुछ ऐसा ही करते हैं। हार्डवेयर पते 8 बाइट्स हैं, और 8-बाइट शब्दों को इंगित करते हैं। void*और char*सॉफ्टवेयर में संभाला जाता है, और शब्द के भीतर 3-बिट ऑफसेट के साथ संवर्धित होता है - लेकिन चूंकि वास्तव में 64-बिट पता स्थान नहीं है, इसलिए ऑफसेट को 64-बिट के उच्च-क्रम 3 बिट्स में संग्रहीत किया जाता है शब्द। इसलिए char*और int*समान आकार हैं, लेकिन अलग-अलग आंतरिक प्रतिनिधित्व हैं - और कोड जो मानता है कि संकेत "वास्तव में" हैं केवल पूर्णांक बुरी तरह से विफल हो सकते हैं।
कीथ थॉम्पसन

5

8 लो और 16 बिट पॉइंटर्स का उपयोग अधिकांश लो प्रोफाइल माइक्रोकंट्रोलर में किया जाता है। इसका मतलब है कि हर वॉशिंग मशीन, माइक्रो, फ्रिज, पुराने टीवी और यहां तक ​​कि कार भी।

आप कह सकते हैं कि इनका वास्तविक विश्व प्रोग्रामिंग से कोई लेना-देना नहीं है। लेकिन यहां एक वास्तविक दुनिया उदाहरण है: 2 बाइट पॉइंटर्स के साथ 1-2-4k ram (चिप पर निर्भर करता है) के साथ Arduino।

यह हाल ही में सस्ता, सभी के लिए सुलभ है और इसके लिए कोडिंग के लायक है।


4

64-बिट (या जो भी) सिस्टम के बारे में लोगों ने क्या कहा है, इसके अलावा, पॉइंटर-टू-ऑब्जेक्ट की तुलना में अन्य प्रकार के पॉइंटर हैं।

एक पॉइंटर-टू-मेंबर लगभग किसी भी आकार का हो सकता है, यह इस बात पर निर्भर करता है कि वे आपके कंपाइलर द्वारा कैसे लागू किए गए हैं: वे जरूरी नहीं कि सभी समान आकार के भी हों। POD वर्ग के एक पॉइंटर-टू-मेंबर को आज़माएँ, और उसके बाद एक पॉइंटर-टू-मेंबर को एक वर्ग के आधार वर्गों में से कई बेस के साथ विरासत में मिला। क्या मजाक है।


3

मुझे जो याद आता है, वह एक मेमोरी एड्रेस के आकार पर आधारित है। इसलिए 32-बिट एड्रेस स्कीम वाले सिस्टम पर, साइज़ 4 वापस आएगा, क्योंकि यह 4 बाइट्स है।


4
ऐसी कोई आवश्यकता नहीं है। ऐसी कोई आवश्यकता भी नहीं है कि sizeof (अहस्ताक्षरित int) == sizeof (हस्ताक्षरित int)। एक पॉइंटर को एक इंट का आकार हमेशा परिभाषा से, साइज़ोफ़ (int *), एक चार साइज़ोफ़ (चार *) आदि द्वारा किया जाएगा। किसी अन्य धारणा पर भरोसा करना पोर्टेबिलिटी के लिए एक बुरा विचार है।
Mihai Limbășan

आह, मैं अब देखता हूं। जानकारी के लिए धन्यवाद।
विल मैक

1
2 अभी भी वापस आ सकता है, अगर CHAR_BIT 16 है। आकार () चार्ट की संख्या में गिना जाता है, ऑक्टेट नहीं।
MSalters 13

5
@ मिहाई: सी ++ में sizeof (unsigned int) == sizeof (signed int), यह आवश्यकता 3.9.1 / 3 में पाई जाती है। "मानक प्रकार पूर्णांक हस्ताक्षर किए में से प्रत्येक के लिए, वहाँ एक इसी (लेकिन अलग) मानक अहस्ताक्षरित पूर्णांक प्रकार मौजूद है: unsigned char, unsigned short int, unsigned int, unsigned long int, और unsigned long long int, जिनमें से प्रत्येक भंडारण की एक ही राशि पर है और के रूप में प्रकार पूर्णांक हस्ताक्षर किए वाली संबंधित एक ही संरेखण आवश्यकताएं होती हैं "
बेन वायगेट

3

जब आप विभिन्न प्लेटफार्मों पर संकलन करते हैं, सामान्य तौर पर, साइज़ोफ़ (बहुत कुछ भी) बदल जाएगा। 32 बिट प्लेटफ़ॉर्म पर, पॉइंटर्स हमेशा एक ही आकार के होते हैं। अन्य प्लेटफार्मों पर (64 बिट स्पष्ट उदाहरण होने के नाते) यह बदल सकता है।


3

नहीं, आर्किटेक्चर के आधार पर एक पॉइंटर का आकार भिन्न हो सकता है। कई अपवाद हैं।


3

विंडोज़ 32 बिट मशीन पर टर्बो सी संकलक में सूचक और इंट का आकार 2 बाइट्स है।

तो सूचक का आकार संकलक विशिष्ट है। लेकिन आम तौर पर अधिकांश कंपाइलरों को 32 बिट में 4 बाइट पॉइंटर वैरिएबल और 64 बिट मशीन में 8 बाइट पॉइंटर वैरिएबल को सपोर्ट करने के लिए लागू किया जाता है)।

इसलिए सभी मशीनों में सूचक का आकार समान नहीं है।


2

आपके पॉइंटर का आकार 4 बाइट्स है, क्योंकि आप 32-बिट आर्किटेक्चर के लिए संकलन कर रहे हैं। जैसा कि फ्रायजी ने बताया, 64-बिट आर्किटेक्चर पर आप 8 देखेंगे।


2

में Win64 (Cygwin जीसीसी 5.4) , आइए नीचे देखते हैं:

सबसे पहले, निम्नलिखित संरचना का परीक्षण करें:

struct list_node{
    int a;
    list_node* prev;
    list_node* next;
};

struct test_struc{
    char a, b;
};

परीक्षण कोड नीचे है:

std::cout<<"sizeof(int):            "<<sizeof(int)<<std::endl;
std::cout<<"sizeof(int*):           "<<sizeof(int*)<<std::endl;
std::cout<<std::endl;

std::cout<<"sizeof(double):         "<<sizeof(double)<<std::endl;
std::cout<<"sizeof(double*):        "<<sizeof(double*)<<std::endl;
std::cout<<std::endl;

std::cout<<"sizeof(list_node):      "<<sizeof(list_node)<<std::endl;
std::cout<<"sizeof(list_node*):     "<<sizeof(list_node*)<<std::endl;
std::cout<<std::endl;

std::cout<<"sizeof(test_struc):     "<<sizeof(test_struc)<<std::endl;
std::cout<<"sizeof(test_struc*):    "<<sizeof(test_struc*)<<std::endl;    

उत्पादन नीचे है:

sizeof(int):            4
sizeof(int*):           8

sizeof(double):         8
sizeof(double*):        8

sizeof(list_node):      24
sizeof(list_node*):     8

sizeof(test_struc):     2
sizeof(test_struc*):    8

आप देख सकते हैं कि 64-बिट में sizeof(pointer)है 8


1

एक सूचक एक पते के लिए सिर्फ एक कंटेनर है। 32 बिट मशीन पर, आपकी पता सीमा 32 बिट्स होती है, इसलिए एक पॉइंटर हमेशा 4 बाइट्स का होगा। 64 बिट मशीन पर आपके पास 64 बिट्स की एक पता सीमा होती है, एक पॉइंटर 8 बाइट्स होगा।


1
32-बिट बाइट्स के साथ 32-बिट मशीन पर, साइज़ोफ़ (चार *) हो सकता है 1.
रॉबर्ट गैंबल

"... 32-बिट बाइट्स के साथ"। मुझे नहीं पता था कि ऐसी चीजें अस्तित्व में थीं ... फैंसी।
एड एस।

1
एक 32 बिट बतख पर, साइज़ोफ (चार *) पीआई रिटर्न करता है
एड्रियानो वरोली पियाज़ा

0

पूर्णता और ऐतिहासिक अभिरुचि के लिए, 64 बिट की दुनिया में, मुख्य रूप से यूनिक्स-टाइप सिस्टम और विंडोज के बीच, एलएलपी 64 और एलपी 64 नामक लंबे और लंबे लंबे प्रकारों के आकार पर अलग-अलग मंच सम्मेलन थे। ILP64 नाम का एक पुराना मानक भी int = 64-बिट चौड़ा बना।

Microsoft ने LLP64 को लंबे समय तक = 64 बिट चौड़ा बनाए रखा, लेकिन आसान पोर्टिंग के लिए लंबे समय तक 32 पर बना रहा।

Type           ILP64   LP64   LLP64
char              8      8       8
short            16     16      16
int              64     32      32
long             64     64      32
long long        64     64      64
pointer          64     64      64

स्रोत: https://stackoverflow.com/a/384672/48026

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.