ตัวอย่างเช่น
sizeof(char*)
ผลตอบแทน 4. ไม่int*
, long long*
ทุกอย่างที่ฉันได้พยายาม มีข้อยกเว้นสำหรับสิ่งนี้หรือไม่?
ตัวอย่างเช่น
sizeof(char*)
ผลตอบแทน 4. ไม่int*
, long long*
ทุกอย่างที่ฉันได้พยายาม มีข้อยกเว้นสำหรับสิ่งนี้หรือไม่?
คำตอบ:
sizeof(char) == 1
การรับประกันที่คุณได้รับก็คือ ไม่มีการค้ำประกันอื่น ๆ sizeof(int *) == sizeof(double *)
รวมทั้งการรับประกันว่าไม่มี
ในทางปฏิบัติพอยน์เตอร์จะมีขนาด 2 ในระบบ 16 บิต (หากคุณสามารถหาได้) 4 ในระบบ 32 บิตและ 8 ในระบบ 64 บิต แต่ไม่มีสิ่งใดที่จะได้รับจากการพึ่งพา ขนาด.
แม้บนแพลตฟอร์ม 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;
}
ภายใต้ Visual C ++ 2008 ฉันได้รับ 4, 12 และ 8 สำหรับขนาดของพอยน์เตอร์กับสมาชิกฟังก์ชัน
เป็นข้อยกเว้นอีกประการสำหรับรายการที่โพสต์แล้ว บนแพลตฟอร์ม 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;
}
หากคุณคอมไพล์โปรแกรมนี้ด้วย Open Watcom และเรียกใช้คุณจะได้รับ 6 เนื่องจากตัวชี้ไกลที่รองรับประกอบด้วยค่าออฟเซ็ต 32 บิตและ 16 บิต
หากคุณกำลังรวบรวมสำหรับเครื่อง 64 บิตอาจเป็น 8
sizeof(char*)==1
? คุณแน่ใจไหม? คุณไม่หมายถึงsize(char)==1
เหรอ
ในทางเทคนิคแล้วมาตรฐาน C รับประกันได้เพียงว่า sizeof (char) == 1 และส่วนที่เหลือนั้นขึ้นอยู่กับการใช้งาน แต่สำหรับสถาปัตยกรรม x86 ที่ทันสมัย (เช่นชิป Intel / AMD) สามารถคาดการณ์ได้ค่อนข้าง
คุณอาจเคยได้ยินตัวประมวลผลที่อธิบายว่าเป็น 16 บิต, 32- บิต, 64- บิตเป็นต้นซึ่งมักจะหมายความว่าโปรเซสเซอร์ใช้ N-bits สำหรับจำนวนเต็ม เนื่องจากพอยน์เตอร์เก็บที่อยู่หน่วยความจำและที่อยู่หน่วยความจำเป็นจำนวนเต็มสิ่งนี้จะบอกคุณได้อย่างมีประสิทธิภาพว่าจะใช้บิตจำนวนเท่าใดสำหรับพอยน์เตอร์ sizeof มักจะวัดเป็นไบต์ดังนั้นโค้ดที่คอมไพล์แล้วสำหรับตัวประมวลผลแบบ 32 บิตจะรายงานขนาดตัวชี้เป็น 4 (32 บิต / 8 บิตต่อไบต์) และรหัสสำหรับตัวประมวลผลแบบ 64 บิตจะรายงานขนาดตัวชี้เป็น 8 (64 บิต / 8 บิตต่อไบต์) นี่เป็นที่ที่ข้อ จำกัด ของ RAM 4GB สำหรับโปรเซสเซอร์ 32 บิตมาจาก - หากที่อยู่หน่วยความจำแต่ละอันสอดคล้องกับไบต์เพื่อระบุหน่วยความจำเพิ่มเติมคุณต้องมีจำนวนเต็มมากกว่า 32 บิต
ขนาดของตัวชี้โดยทั่วไปขึ้นอยู่กับสถาปัตยกรรมของระบบที่มีการใช้งาน ตัวอย่างเช่นขนาดของตัวชี้ใน 32 บิตคือ 4 ไบต์ (32 บิต) และ 8 ไบต์ (64 บิต) ในเครื่อง 64 บิต บิตประเภทในเครื่องนั้นไม่มีอะไรนอกจากที่อยู่หน่วยความจำที่สามารถมีได้ เครื่อง 32 บิตสามารถมี2^32
พื้นที่ที่อยู่และเครื่อง 64 บิตสามารถมี2^64
พื้นที่ที่อยู่ได้ไม่เกิน ดังนั้นตัวชี้ (ตัวแปรที่ชี้ไปยังตำแหน่งหน่วยความจำ) ควรจะสามารถชี้ไปยังที่อยู่หน่วยความจำใด ๆ ( 2^32 for 32 bit and 2^64 for 64 bit
) ที่เครื่องเก็บ
ด้วยเหตุนี้เราจึงเห็นขนาดของตัวชี้เป็น 4 ไบต์ในเครื่อง 32 บิตและ 8 ไบต์ในเครื่อง 64 บิต
นอกเหนือจากความแตกต่าง 16/32/64 บิตแม้กระทั่งสิ่งอื่น ๆ สามารถเกิดขึ้นได้
มีเครื่องที่ sizeof (int *) จะเป็นหนึ่งค่าอาจเป็น 4 แต่ที่ sizeof (char *) มีขนาดใหญ่กว่า เครื่องที่ใช้คำพูดแทนไบต์ต้องมีการเพิ่ม "พอยน์เตอร์อักขระ" เพื่อระบุส่วนของคำที่คุณต้องการเพื่อนำมาตรฐาน C / C ++ มาใช้อย่างถูกต้อง
นี่เป็นสิ่งที่ผิดปกติอย่างมากเนื่องจากผู้ออกแบบฮาร์ดแวร์ได้เรียนรู้คุณค่าของความสามารถในการระบุแอดเดรสไบต์
void*
และchar*
ได้รับการจัดการในซอฟต์แวร์และมีส่วนเสริมด้วยการชดเชยแบบ 3 บิตภายในคำ - แต่เนื่องจากไม่มีที่อยู่ 64- บิตที่อยู่จริงการชดเชยจะถูกเก็บไว้ในลำดับสูง 3 บิตของ 64 บิต คำ. ดังนั้นchar*
และint*
มีขนาดเท่ากัน แต่มีการนำเสนอภายในที่แตกต่างกันและรหัสที่ถือว่าพอยน์เตอร์นั้น "จริง" เพียงจำนวนเต็มอาจล้มเหลวได้ไม่ดี
พอยน์เตอร์ 8 บิตและ 16 บิตถูกใช้ในไมโครคอนโทรลเลอร์รายละเอียดต่ำที่สุด นั่นหมายถึงทุกเครื่องซักผ้าไมโครตู้เย็นทีวีเก่าและแม้แต่รถยนต์
คุณสามารถพูดได้ว่าสิ่งเหล่านี้ไม่มีส่วนเกี่ยวข้องกับการเขียนโปรแกรมในโลกแห่งความเป็นจริง แต่นี่คือตัวอย่างหนึ่งในโลกแห่งความจริง: Arduino ที่มี RAM 1-2-4k (ขึ้นอยู่กับชิป) ที่มีตัวชี้ 2 ไบต์
มันล่าสุดราคาถูกเข้าถึงได้สำหรับทุกคนและคุ้มค่ากับการเข้ารหัส
นอกเหนือจากสิ่งที่ผู้คนพูดเกี่ยวกับระบบ 64 บิต (หรืออะไรก็ตาม) แล้วยังมีตัวชี้ชนิดอื่นนอกเหนือจากตัวชี้ไปยังวัตถุ
ตัวชี้ไปยังสมาชิกอาจมีขนาดเกือบทุกขนาดขึ้นอยู่กับวิธีการใช้งานโดยคอมไพเลอร์ของคุณ: พวกเขาไม่จำเป็นต้องมีขนาดเท่ากันทั้งหมด ลองตัวชี้ไปยังสมาชิกของคลาส POD จากนั้นตัวชี้ไปยังสมาชิกที่สืบทอดมาจากคลาสพื้นฐานของคลาสที่มีหลายเบส สนุกจัง
จากสิ่งที่ฉันจำได้มันขึ้นอยู่กับขนาดของที่อยู่หน่วยความจำ ดังนั้นในระบบที่มีรูปแบบที่อยู่แบบ 32 บิตขนาดของมันจะคืนค่า 4 เนื่องจากเป็น 4 ไบต์
sizeof (unsigned int) == sizeof (signed int)
ข้อกำหนดนี้พบได้ใน 3.9.1 / 3 "สำหรับแต่ละมาตรฐานลงนามจำนวนเต็มชนิดมีอยู่เหมือนกัน ( แต่แตกต่างกัน) มาตรฐานชนิดจำนวนเต็มไม่ได้ลงนาม: unsigned char
, unsigned short int
, unsigned int
, unsigned long int
และunsigned long long int
, แต่ละซึ่งตรงกับจำนวนเดียวกันของการจัดเก็บและมีความต้องการการจัดตำแหน่งเช่นเดียวกับที่สอดคล้องกันลงนามจำนวนเต็มชนิด "
โดยทั่วไป sizeof (อะไรที่สวยมาก) จะเปลี่ยนเมื่อคุณรวบรวมบนแพลตฟอร์มที่แตกต่างกัน บนแพลตฟอร์ม 32 บิตพอยน์เตอร์จะมีขนาดเท่ากันเสมอ บนแพลตฟอร์มอื่น ๆ (64 บิตเป็นตัวอย่างที่ชัดเจน) สิ่งนี้สามารถเปลี่ยนแปลงได้
ไม่ขนาดของตัวชี้อาจแตกต่างกันไปขึ้นอยู่กับสถาปัตยกรรม มีข้อยกเว้นมากมาย
ขนาดของตัวชี้และ int คือ 2 ไบต์ในคอมไพเลอร์ Turbo C บนเครื่อง windows 32 บิต
ขนาดของพอยเตอร์จึงเป็นคอมไพเลอร์เฉพาะ แต่โดยทั่วไปคอมไพเลอร์ส่วนใหญ่จะถูกนำไปใช้เพื่อสนับสนุนตัวแปรตัวชี้ 4 ไบต์ใน 32 บิตและตัวแปรตัวชี้ 8 ไบต์ในเครื่อง 64 บิต)
ขนาดของตัวชี้จึงไม่เหมือนกันในทุกเครื่อง
สาเหตุขนาดของตัวชี้ของคุณคือ 4 ไบต์เนื่องจากคุณกำลังรวบรวมสำหรับสถาปัตยกรรมแบบ 32 บิต FryGuy ชี้ให้เห็นว่าในสถาปัตยกรรม 64 บิตคุณจะเห็น 8
ในWin64 (Cygwin GCC 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
ตัวชี้เป็นเพียงคอนเทนเนอร์สำหรับที่อยู่ บนเครื่อง 32 บิตช่วงที่อยู่ของคุณคือ 32 บิตดังนั้นตัวชี้จะเป็น 4 ไบต์เสมอ บนเครื่อง 64 บิตคุณมีช่วงที่อยู่ 64 บิตตัวชี้จะเป็น 8 ไบต์
เพื่อความสมบูรณ์และความสนใจทางประวัติศาสตร์ในโลก 64 บิตมีการจัดทำแพลตฟอร์มที่แตกต่างกันตามขนาดของประเภทยาวและยาวชื่อ LLP64 และ LP64 ส่วนใหญ่อยู่ระหว่างระบบ Unix-type และ Windows มาตรฐานเก่าที่ชื่อว่า ILP64 ได้สร้าง int = 64-bit
Microsoft ดูแลรักษา LLP64 โดยที่ longlong = 64 bit wide แต่ long อยู่ที่ 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