กฎการแปลงประเภทโดยนัยในตัวดำเนินการ C ++


168

ฉันอยากรู้เรื่องเวลาที่ควรโยน กฎการแปลงประเภทโดยนัยคืออะไรใน C ++ เมื่อทำการเพิ่มทวีคูณเป็นต้นตัวอย่างเช่น

int + float = ?
int * float = ?
float * int = ?
int / float = ?
float / int = ?
int / int = ?
int ^ float = ?

และอื่น ๆ ...

นิพจน์จะได้รับการประเมินว่าเป็นประเภทที่แม่นยำกว่าเสมอหรือไม่ กฎแตกต่างกันสำหรับ Java หรือไม่ โปรดแก้ไขให้ฉันด้วยถ้าฉันตอบคำถามนี้ไม่ถูกต้อง


16
โปรดทราบว่า^XOR
GManNickG

16
@int ^ float = ข้อผิดพลาดในการคอมไพล์ :)
Serge Dundich

คำตอบ:


223

ในตัวดำเนินการ C ++ (สำหรับประเภท POD) มักจะกระทำกับวัตถุประเภทเดียวกัน
ดังนั้นหากพวกเขาไม่เหมือนกันจะได้รับการส่งเสริมให้ตรงกับคนอื่น
ชนิดของผลลัพธ์ของการดำเนินการเหมือนกับตัวถูกดำเนินการ (หลังจากการแปลง)

If either is      long          double the other is promoted to      long          double
If either is                    double the other is promoted to                    double
If either is                    float  the other is promoted to                    float
If either is long long unsigned int    the other is promoted to long long unsigned int
If either is long long          int    the other is promoted to long long          int
If either is long      unsigned int    the other is promoted to long      unsigned int
If either is long               int    the other is promoted to long               int
If either is           unsigned int    the other is promoted to           unsigned int
If either is                    int    the other is promoted to                    int
Both operands are promoted to int

บันทึก. intขนาดต่ำสุดของการดำเนินงานคือ ดังนั้นshort/ charได้รับการส่งเสริมintก่อนที่จะดำเนินการเสร็จสิ้น

ในนิพจน์ของคุณทั้งหมดintจะได้รับการเลื่อนระดับเป็นfloatก่อนดำเนินการ floatผลการดำเนินงานที่เป็น

int + float =>  float + float = float
int * float =>  float * float = float
float * int =>  float * float = float
int / float =>  float / float = float
float / int =>  float / float = float
int / int                     = int
int ^ float =>  <compiler error>

1
"ขนาดขั้นต่ำของการดำเนินการคือ int" - สิ่งนี้จะแปลกมาก (แล้วสถาปัตยกรรมที่รองรับการทำงานแบบ char / short ได้อย่างมีประสิทธิภาพ) นี่เป็นข้อมูลจำเพาะ C ++ หรือไม่
Rafał Dowgird

3
@Rafal: ใช่ int ควรเป็นชนิดจำนวนเต็มที่มีประสิทธิภาพที่สุดสำหรับการดำเนินการบนแพลตฟอร์มเฉพาะ ถ่านต้องเป็น 1 เสมอ แต่ตัวย่อจะมีขนาดเท่ากันได้
Martin York

1
@ Rafał: ใช่มันแปลกมากและอยู่ในมาตรฐาน ในหลายกรณีสถาปัตยกรรมที่คุณอธิบายอาจใช้charประเภทประสิทธิภาพสูงสุด หากค่าของchar + charถูกกำหนดให้ a charคุณก็สามารถทำเลขคณิตในcharและยกตัวอย่างเช่น แต่ถ้าผลที่ได้รับมอบหมายให้แล้วก็มีการทำเลขคณิตในประเภทที่มีขนาดใหญ่พอที่จะได้รับผลที่ถูกต้องเมื่อมันมากกว่าint CHAR_MAX
Steve Jessop

2
ฉันแค่ต้องการเน้นความจริงที่ว่าint ได้รับการเลื่อนตำแหน่งเป็น int ที่ไม่ได้ลงชื่อ !!! ฉันต่อสู้กับข้อบกพร่องมาหลายวันแล้วเพราะฉันรู้สึกว่าทั้งสองจะได้รับการเลื่อนขั้นเป็นระยะเวลานาน ๆ เพื่อที่ผลลัพธ์เชิงลบที่เป็นไปได้จะไม่ทำให้เกิดอันเดอร์โฟล์ / ปิดล้อม
nitsas

10
ตัวอย่างของปัญหา " int ได้รับการเลื่อนตำแหน่งเป็น unsigned int ": ((int) 4) - ((unsigned int) 5)จะส่งผล4294967295ให้ 32 บิต int และ 32 บิตที่ไม่ได้ลงชื่อ
nitsas

33

ดำเนินการทางคณิตศาสตร์ที่เกี่ยวข้องกับผลในการfloatfloat

int + float = float
int * float = float
float * int = float
int / float = float
float / int = float
int / int = int

สำหรับคำตอบรายละเอียดเพิ่มเติม ดูสิ่งที่ส่วน§5 / 9 จากมาตรฐาน C ++ พูดว่า

ตัวดำเนินการไบนารีจำนวนมากที่คาดว่าตัวถูกดำเนินการทางคณิตศาสตร์หรือชนิดการแจงนับทำให้เกิดการแปลงและประเภทผลลัพธ์ที่ได้ในลักษณะเดียวกัน จุดประสงค์คือให้ผลลัพธ์ประเภททั่วไป ซึ่งเป็นประเภทของผลลัพธ์ด้วย

รูปแบบนี้เรียกว่าการแปลงทางคณิตศาสตร์ตามปกติซึ่งกำหนดไว้ดังนี้:

- ถ้าตัวถูกดำเนินการตัวใดตัวหนึ่งเป็นชนิด long double ตัวอื่นจะถูกแปลงเป็น long double

- มิฉะนั้นถ้าตัวถูกดำเนินการตัวใดตัวหนึ่งเป็นสองเท่าตัวที่เหลือจะถูกแปลงเป็นสองเท่า

- มิฉะนั้นถ้าตัวถูกดำเนินการใดตัวหนึ่งเป็นแบบลอยตัวอีกตัวจะถูกแปลงเป็นแบบลอย

- มิฉะนั้นการโปรโมตแบบรวม (4.5) จะต้องดำเนินการกับตัวถูกดำเนินการทั้งสอง 4.5

- จากนั้นถ้าตัวถูกดำเนินการตัวใดตัวหนึ่งถูกไม่ได้ลงนามแบบยาวอีกตัวจะถูกแปลงเป็นแบบยาวที่ไม่ได้ลงชื่อ

- มิฉะนั้นถ้าหนึ่งตัวถูกดำเนินการเป็น int ยาวและ int ไม่ได้ลงนามอื่นแล้วถ้า int ยาวสามารถเป็นตัวแทนของค่าทั้งหมดของ int ไม่ได้ลงนาม int int ไม่ได้ลงนามจะถูกแปลงเป็น int ยาว; มิฉะนั้นตัวถูกดำเนินการทั้งสองจะถูกแปลงเป็น int long ที่ไม่ได้ลงชื่อ

- มิฉะนั้นถ้าตัวถูกดำเนินการตัวใดตัวหนึ่งยาวตัวอื่นจะถูกแปลงเป็นแบบยาว

- มิฉะนั้นถ้าตัวถูกดำเนินการตัวใดตัวหนึ่งไม่ได้ลงนามอีกตัวจะถูกแปลงเป็นตัวตนที่ไม่ได้ลงนาม

[หมายเหตุ: มิฉะนั้นกรณีที่เหลือเพียงอย่างเดียวคือตัวถูกดำเนินการทั้งสองเป็น int]


3
... ตราบชนิดอื่น ๆ คือค่ามิได้double long double
CB Bailey

1
@Charles: ถูกต้อง ฉันอ้างส่วนที่เกี่ยวข้องจากมาตรฐานเพื่อชี้แจงเพิ่มเติม
Nawaz

ดังนั้นจำนวนเต็มสามารถแปลงเป็นแบบลอยโดยไม่ทำให้ข้อมูลสูญหายได้หรือไม่? (เช่นโดยการยกกำลังเลขชี้กำลังและใช้ทุกอย่างสำหรับแมนทิสซา)
Marco A.

1
คำตอบนี้ล้าสมัย แนะนำการปรับปรุง โดยเฉพาะอย่างยิ่งlong longและunsigned longไม่ได้อยู่ที่นี่
chux - Reinstate Monica

@MarcoA 32- บิตfloatไม่มีบิตเพียงพอในแมนทิสซา (24 บิตสำหรับIEEE-754 ) สำหรับ 32- บิตintดังนั้นอาจมีข้อมูลสูญหาย 64- บิตdoubleควรจะไม่เป็นไร
Mark Ransom

17

เนื่องจากคำตอบอื่น ๆ ไม่ได้พูดเกี่ยวกับกฎใน C ++ 11 นี่คือกฎข้อหนึ่ง จากมาตรฐาน C ++ 11 (ฉบับร่าง n3337) §5 / 9 (เน้นความแตกต่าง):

รูปแบบนี้เรียกว่าการแปลงทางคณิตศาสตร์ตามปกติซึ่งกำหนดไว้ดังนี้:

- หากตัวถูกดำเนินการเป็นประเภทการแจงนับจะไม่มีการแปลง ถ้าตัวถูกดำเนินการอื่นไม่มีชนิดเดียวกันนิพจน์นั้นไม่ถูกต้อง

- ถ้าตัวถูกดำเนินการตัวใดตัวหนึ่งเป็นชนิด long double ตัวอื่นจะถูกแปลงเป็น long double

- มิฉะนั้นถ้าตัวถูกดำเนินการตัวใดตัวหนึ่งเป็นสองเท่าตัวที่เหลือจะถูกแปลงเป็นสองเท่า

- มิฉะนั้นถ้าตัวถูกดำเนินการใดตัวหนึ่งเป็นแบบลอยตัวอีกตัวจะถูกแปลงเป็นแบบลอย

- มิฉะนั้นโปรโมชั่นรวมจะต้องดำเนินการในตัวถูกดำเนินการทั้งสอง จากนั้นจะใช้กฎต่อไปนี้กับตัวถูกดำเนินการที่ได้รับการส่งเสริม:

- หากตัวถูกดำเนินการทั้งสองมีประเภทเดียวกันไม่จำเป็นต้องทำการแปลงใด ๆ เพิ่มเติม

- มิฉะนั้นหากตัวถูกดำเนินการทั้งสองมีประเภทจำนวนเต็มลงนามหรือทั้งคู่มีประเภทจำนวนเต็มไม่ได้ลงนามตัวถูกดำเนินการที่มีประเภทของอันดับการแปลงจำนวนเต็มน้อยกว่าจะถูกแปลงเป็นประเภทของตัวถูกดำเนินการที่มีอันดับมากขึ้น

- มิฉะนั้นหากตัวถูกดำเนินการที่มีประเภทจำนวนเต็มไม่ได้ลงนามมีอันดับมากกว่าหรือเท่ากับอันดับของประเภทตัวถูกดำเนินการอื่นตัวถูกดำเนินการที่มีประเภทจำนวนเต็มลงนามจะถูกแปลงเป็นประเภทของตัวถูกดำเนินการด้วยชนิดจำนวนเต็มไม่ได้ลงนาม

- มิฉะนั้นหากประเภทของตัวถูกดำเนินการที่มีประเภทจำนวนเต็มที่ลงนามสามารถเป็นตัวแทนของค่าทั้งหมดของประเภทของตัวถูกดำเนินการที่มีประเภทจำนวนเต็มไม่ได้ลงนามตัวถูกดำเนินการกับประเภทจำนวนเต็มไม่ได้ลงนามจะถูกแปลงเป็นชนิดของตัวถูกดำเนินการ

- มิฉะนั้นตัวถูกดำเนินการทั้งสองจะถูกแปลงเป็นประเภทจำนวนเต็มไม่ได้ลงนามที่สอดคล้องกับประเภทของตัวถูกดำเนินการด้วยประเภทจำนวนเต็มลงนาม

ดูที่นี่สำหรับรายการที่มีการปรับปรุงบ่อยครั้ง


1
กฎเหล่านี้เหมือนกันในทุกรุ่นของ C ++ ยกเว้นสำหรับการกำหนดขอบเขตที่เพิ่มในหลักสูตร C ++ 11
MM

6

คำตอบนี้ถูกกำกับโดยส่วนใหญ่ที่ความคิดเห็นที่ทำโดย @ RafałDowgird:

"ขนาดขั้นต่ำของการดำเนินการคือ int" - นี่จะแปลกมาก (แล้วสถาปัตยกรรมที่รองรับการทำงานแบบ char / short ได้อย่างมีประสิทธิภาพ) นี่เป็นข้อมูลจำเพาะของ C ++ หรือไม่

โปรดทราบว่ามาตรฐาน C ++ มีกฎ "as-if" ที่สำคัญทั้งหมด ดูหัวข้อ 1.8: การทำงานของโปรแกรม:

3) บทบัญญัตินี้บางครั้งเรียกว่ากฎ "ราวกับถ้า" เนื่องจากการดำเนินการมีอิสระที่จะเพิกเฉยต่อข้อกำหนดใด ๆ ของมาตรฐานตราบใดที่ผลที่ได้คือว่าข้อกำหนดได้รับการปฏิบัติตามเท่าที่สามารถพิจารณาได้จากที่สังเกตได้ พฤติกรรมของโปรแกรม

คอมไพเลอร์ไม่สามารถตั้งค่าintให้เป็น 8 intบิตในขนาดถึงแม้ว่ามันจะเป็นคนที่เร็วที่สุดตั้งแต่เอกสารมาตรฐานขั้นต่ำ

ดังนั้นในกรณีของคอมพิวเตอร์เชิงทฤษฎีที่มีการดำเนินการ 8 บิตที่รวดเร็วเป็นพิเศษการเลื่อนตำแหน่งโดยนัยintสำหรับคณิตศาสตร์อาจมีความสำคัญ อย่างไรก็ตามสำหรับการดำเนินการหลาย ๆ อย่างคุณไม่สามารถบอกได้ว่าคอมไพเลอร์ได้ทำการดำเนินการในความแม่นยำของ a intและจากนั้นแปลงเป็น a charเพื่อเก็บไว้ในตัวแปรของคุณหรือไม่

ตัวอย่างเช่นให้พิจารณาunsigned char = unsigned char + unsigned char + unsigned charว่าการเพิ่มใดจะล้น (ลองสมมติว่ามีค่า 200 สำหรับแต่ละรายการ) หากคุณได้รับการเลื่อนตำแหน่งintคุณจะได้รับ 600 ซึ่งจะถูกโยนลงไปโดยปริยายunsigned charซึ่งจะปิด modulo 256 ดังนั้นจึงให้ผลลัพธ์สุดท้ายที่ 88 หากคุณไม่ได้ทำโปรโมชันดังกล่าวคุณจะต้องห่อระหว่างแรก สองส่วนเพิ่มเติมซึ่งจะช่วยลดปัญหาจาก200 + 200 + 200ถึง144 + 200ซึ่งก็คือ 344 ซึ่งจะลดลงเป็น 88 ในคำอื่น ๆ โปรแกรมไม่ทราบความแตกต่างดังนั้นคอมไพเลอร์มีอิสระที่จะละเว้นอาณัติเพื่อดำเนินการกลางในintกรณีที่ตัวถูกดำเนินการมี intการจัดอันดับที่ต่ำกว่า

นี่เป็นความจริงโดยทั่วไปของการบวกการลบและการคูณ มันไม่เป็นความจริงโดยทั่วไปสำหรับการหารหรือโมดูลัส


4

หากคุณยกเว้นประเภทที่ไม่ได้ลงนามจะมีลำดับชั้นที่จัดลำดับไว้ดังนี้: char ที่ลงนามแล้ว, สั้น, int, ยาว, ยาว, ยาว, ลอย, สองเท่า, ยาวสองเท่า ก่อนอื่นสิ่งที่มาก่อน int ในด้านบนจะถูกแปลงเป็น int จากนั้นในการดำเนินการแบบไบนารีประเภทอันดับที่ต่ำกว่าจะถูกแปลงเป็นสูงกว่าและผลลัพธ์จะเป็นประเภทที่สูงกว่า (คุณจะทราบว่าจากลำดับชั้นเมื่อใดก็ตามที่เกี่ยวข้องกับจุดลอยตัวและประเภทอินทิกรัลประเภทอินทิกรัลจะถูกแปลงเป็นประเภทจุดลอย)

สิ่งที่ไม่ได้ลงนามทำให้ซับซ้อนขึ้นเล็กน้อย: มันทำให้การจัดอันดับแย่ลงและส่วนต่าง ๆ ของการจัดอันดับกลายเป็นการนำไปปฏิบัติ ด้วยเหตุนี้จึงเป็นการดีที่สุดที่จะไม่ผสมการลงชื่อและไม่ได้ลงชื่อในนิพจน์เดียวกัน (ผู้เชี่ยวชาญ C ++ ส่วนใหญ่ดูเหมือนจะหลีกเลี่ยงการไม่ได้ลงชื่อเว้นแต่การดำเนินการระดับบิตจะเกี่ยวข้องนั่นคืออย่างน้อยสิ่งที่ Stroustrup แนะนำ)


3
Stroustrup สามารถแนะนำสิ่งที่เขาชอบ แต่การใช้เครื่องหมายintสำหรับจำนวนที่ไม่จำเป็นต้องเป็นเชิงลบก็คือของเสียที่สมบูรณ์ในช่วง 50% ของช่วงที่มีอยู่ทั้งหมด ฉันไม่ใช่ Stroustrup แต่ฉันใช้เป็นunsignedค่าเริ่มต้นและsignedเมื่อฉันมีเหตุผลเท่านั้น
underscore_d

1
นั่นคือทั้งหมดที่ดีและดี underscore_d จนถึงวันที่คุณต้องลบ ปัญหาหลักที่มีตัวเลขที่ไม่ได้ลงนามใน C ++ คือเมื่อคุณทำการลบพวกเขายังคงไม่ได้ลงนาม สมมติว่าคุณเขียนฟังก์ชันเพื่อดูว่า std :: vector นั้นเป็นไปตามลำดับหรือไม่ คุณอาจเขียนbool in_order(vector<T> vec) { for ( int i = 0; i < size() - 1; ++i) { if (vec[i + 1] < vec[i]) return false; } return true;แล้วคุณจะรำคาญที่พบว่ามันเกิดปัญหากับเวกเตอร์เปล่าเพราะขนาด () - 1 คืน 18446744073709551615
jorgbrown

3

ฉันวิธีการแก้ไปปัญหาได้ WA (คำตอบที่ผิด) แล้วฉันเปลี่ยนไปอย่างใดอย่างหนึ่งintไปlong long intและให้AC (ยอมรับ) ก่อนหน้านี้ฉันพยายามทำlong long int += int * intและหลังจากฉันแก้ไขให้long long int += long long int * intแล้ว Googling ฉันมาด้วย

1. การแปลงเลขคณิต

เงื่อนไขสำหรับการแปลงประเภท:

เงื่อนไขพบ ---> การแปลง

  • ทั้งสองตัวถูกดำเนินการเป็นประเภทคู่ยาว ---> ถูกดำเนินการอื่น ๆ จะถูกแปลงเป็นพิมพ์คู่ยาว

  • ก่อนหน้านี้สภาพไม่ได้พบกันและทั้งตัวถูกดำเนินการเป็นประเภทคู่ ---> ถูกดำเนินการอื่น ๆ จะถูกแปลงเป็นพิมพ์คู่

  • เงื่อนไขก่อนหน้านี้ไม่ได้พบกันและทั้งตัวถูกดำเนินการเป็นประเภทลอย ---> ถูกดำเนินการอื่น ๆ จะถูกแปลงเป็นพิมพ์ลอย

  • ไม่ตรงตามเงื่อนไขก่อนหน้า (ไม่มีตัวถูกดำเนินการใด ๆ ที่เป็นประเภทลอยตัว) ---> โปรโมชั่นหนึ่งจะดำเนินการในตัวถูกดำเนินการดังต่อไปนี้:

    • หากทั้งสองตัวถูกดำเนินการเป็นชนิดที่ไม่มีการลงชื่อยาวที่ถูกดำเนินการอื่น ๆ ที่จะถูกแปลงเป็นชนิดที่ไม่มีการลงชื่อยาว
    • หากก่อนหน้านี้สภาพไม่ได้พบกันและถ้าทั้งสองตัวถูกดำเนินการเป็นชนิดยาวและอื่น ๆ ประเภทint ไม่ได้ลงนามทั้งสองตัวถูกดำเนินการจะถูกแปลงเป็นชนิดที่ไม่มีการลงชื่อยาว
    • หากก่อนหน้านี้สองเงื่อนไขจะไม่ได้พบและถ้าทั้งสองตัวถูกดำเนินการเป็นชนิดยาว , t เขาถูกดำเนินการอื่น ๆ ที่จะถูกแปลงเป็นพิมพ์ยาว
    • หากก่อนหน้านี้สามเงื่อนไขจะไม่ได้พบและถ้าทั้งสองตัวถูกดำเนินการเป็นชนิดint ไม่ได้ลงนามที่ถูกดำเนินการอื่น ๆ ที่จะถูกแปลงเป็นพิมพ์int ไม่ได้ลงนาม
    • ถ้าไม่มีเงื่อนไขก่อนหน้านี้จะได้พบกับทั้งสองตัวถูกดำเนินการจะถูกแปลงเป็นพิมพ์int

2. กฎการแปลงจำนวนเต็ม

  • โปรโมชันจำนวนเต็ม:

ประเภทจำนวนเต็มน้อยกว่า int จะได้รับการส่งเสริมเมื่อมีการดำเนินการกับพวกเขา หากค่าทั้งหมดของชนิดดั้งเดิมสามารถแสดงเป็น int ค่าของชนิดที่เล็กกว่าจะถูกแปลงเป็น int มิฉะนั้นจะถูกแปลงเป็น int ที่ไม่ได้ลงชื่อ การส่งเสริมการขายจำนวนเต็มถูกนำไปใช้เป็นส่วนหนึ่งของการแปลงเลขคณิตปกติไปยังนิพจน์อาร์กิวเมนต์บางรายการ ตัวถูกดำเนินการของตัวดำเนินการ unary +, -, และ ~; และตัวถูกดำเนินการของผู้ประกอบการกะ

  • อันดับการแปลงจำนวนเต็ม:

    • เลขจำนวนเต็มสองชนิดที่ไม่มีลายเซ็นจะต้องมีลำดับเหมือนกันแม้ว่าจะมีการแสดงที่เหมือนกันก็ตาม
    • อันดับของประเภทจำนวนเต็มที่ลงนามจะต้องมากกว่าอันดับของประเภทจำนวนเต็มที่ลงนามใด ๆ ที่มีความแม่นยำน้อยกว่า
    • ยศlong long intจะยิ่งกว่าการจัดอันดับของlong intผู้ซึ่งจะเป็นมากกว่ายศintซึ่งจะยิ่งกว่ายศซึ่งจะยิ่งกว่าการจัดอันดับของshort intsigned char
    • อันดับของประเภทจำนวนเต็มใด ๆ ที่ไม่ได้ลงนามจะเท่ากับอันดับของประเภทจำนวนเต็มที่ลงนามที่สอดคล้องกันถ้ามี
    • อันดับของประเภทเลขจำนวนเต็มมาตรฐานใด ๆ จะต้องมากกว่าอันดับของประเภทจำนวนเต็มแบบขยายใด ๆ ที่มีความกว้างเท่ากัน
    • ยศcharเท่ากับยศและsigned charunsigned char
    • อันดับของประเภทเลขจำนวนเต็มแบบขยายที่สัมพันธ์กับชนิดจำนวนเต็มแบบขยายที่ถูกเซ็นอีกครั้งที่มีความแม่นยำเดียวกันนี้จะถูกกำหนดตามการนำไปใช้ แต่ยังคงอยู่ภายใต้กฎอื่น ๆ สำหรับการพิจารณาอันดับการแปลงจำนวนเต็ม
    • สำหรับประเภทจำนวนเต็ม T1, T2 และ T3 ทั้งหมดหาก T1 มีอันดับมากกว่า T2 และ T2 มีอันดับมากกว่า T3 แล้ว T1 จะมีอันดับมากกว่า T3
  • การแปลงเลขคณิตปกติ:

    • หากตัวถูกดำเนินการทั้งสองมีประเภทเดียวกันไม่จำเป็นต้องทำการแปลงใด ๆ เพิ่มเติม
    • หากตัวถูกดำเนินการทั้งสองเป็นประเภทจำนวนเต็มเดียวกัน (ลงนามหรือไม่ได้ลงนาม) ตัวถูกดำเนินการที่มีประเภทของอันดับการแปลงจำนวนเต็มน้อยกว่านั้นจะถูกแปลงเป็นประเภทของตัวถูกดำเนินการที่มีอันดับมากกว่า
    • หากตัวถูกดำเนินการที่มีประเภทจำนวนเต็มไม่ได้ลงนามมีอันดับมากกว่าหรือเท่ากับอันดับของประเภทของตัวถูกดำเนินการอื่นตัวถูกดำเนินการที่มีประเภทจำนวนเต็มลงนามจะถูกแปลงเป็นประเภทของตัวถูกดำเนินการด้วยชนิดจำนวนเต็มไม่ได้ลงนาม
    • หากชนิดของตัวถูกดำเนินการที่มีประเภทจำนวนเต็มที่ลงนามสามารถแสดงค่าทั้งหมดของประเภทของตัวถูกดำเนินการด้วยประเภทจำนวนเต็มที่ไม่ได้ลงนามตัวถูกดำเนินการที่มีประเภทจำนวนเต็มไม่ได้ลงนามจะถูกแปลงเป็นประเภทของตัวถูกดำเนินการ
    • มิฉะนั้นตัวถูกดำเนินการทั้งสองจะถูกแปลงเป็นประเภทจำนวนเต็มไม่ได้ลงนามที่สอดคล้องกับประเภทของตัวถูกดำเนินการด้วยประเภทจำนวนเต็มลงนาม การดำเนินการเฉพาะสามารถเพิ่มหรือแก้ไขความหมายของการดำเนินการทางคณิตศาสตร์ตามปกติ

1

บทที่ 4 ทั้งหมดพูดถึงการแปลง แต่ฉันคิดว่าคุณควรสนใจสิ่งเหล่านี้เป็นส่วนใหญ่:

4.5 การส่งเสริมการขายแบบรวม [conv.prom]
rvalue ประเภท char, ถ่านที่ลงนาม, ถ่านที่ไม่ได้ลงนาม, int สั้นหรือไม่ได้ลงนาม int สามารถแปลงเป็นค่า rvalue ประเภท int ถ้า int สามารถเป็นตัวแทนของค่าทั้งหมดของแหล่งที่มา other-
ฉลาด rvalue แหล่งที่สามารถแปลงเป็น rvalue ชนิด int ไม่ได้ลงนาม
ค่า rvalue ของประเภท wchar_t (3.9.1) หรือประเภทการแจงนับ (7.2) สามารถแปลงเป็น rvalue ของชนิดแรก
ในประเภทต่อไปนี้ที่สามารถเป็นตัวแทนของค่าทั้งหมดของประเภทพื้นฐาน: int, unsigned int,
long หรือ unsigned ยาว.
rvalue สำหรับบิตบิตหนึ่ง (9.6) สามารถแปลงเป็น rvalue ของประเภท int ถ้า int สามารถเป็นตัวแทน
ของค่าทั้งหมดของบิตฟิลด์; มิฉะนั้นสามารถแปลงเป็น int ที่ไม่ได้ลงชื่อหาก int ที่ไม่ได้ลงนามสามารถแสดง
ส่งค่าทั้งหมดของบิตฟิลด์อีกครั้ง หากบิตฟิลด์มีขนาดใหญ่ขึ้นจะไม่มีการส่งเสริมการขายแบบรวม หาก
บิตฟิลด์มีประเภทที่ระบุมันจะถือว่าเป็นค่าอื่น ๆ ของประเภทนั้นเพื่อวัตถุประสงค์ในการส่งเสริมการขาย
rvalue ประเภทบูลสามารถแปลงเป็น rvalue ชนิด int โดยมีเท็จกลายเป็นศูนย์และเป็นความจริง
กลายเป็นหนึ่ง
การแปลงเหล่านี้เรียกว่าการส่งเสริมการขายแบบรวม

4.6 การเลื่อนจุดลอยตัว [conv.fpprom]
rvalue ของชนิดลอยสามารถแปลงเป็น rvalue ของ type double ค่าไม่เปลี่ยนแปลง
การแปลงนี้เรียกว่าการเลื่อนจุดลอย

ดังนั้นการแปลงทั้งหมดที่เกี่ยวข้องกับการลอย - ผลที่ได้คือการลอย

เฉพาะอันเดียวที่เกี่ยวข้องกับทั้ง int - ผลลัพธ์คือ int: int / int = int


1

ประเภทของนิพจน์เมื่อไม่ใช่ทั้งสองส่วนเป็นประเภทเดียวกันจะถูกแปลงเป็นขนาดที่ใหญ่ที่สุดของทั้งสอง ปัญหาที่นี่คือการเข้าใจว่าอันไหนใหญ่กว่าอีกอันหนึ่ง (มันไม่มีส่วนเกี่ยวข้องกับขนาดเป็นไบต์)

ในนิพจน์ที่เกี่ยวข้องกับจำนวนจริงและจำนวนเต็มจำนวนเต็มจะถูกเลื่อนเป็นจำนวนจริง ตัวอย่างเช่นใน int + float ประเภทของนิพจน์คือ float

ความแตกต่างอื่น ๆ เกี่ยวข้องกับความสามารถของประเภท ตัวอย่างเช่นการแสดงออกที่เกี่ยวข้องกับ int และ int ยาวจะเป็นผลมาจากการพิมพ์ int ยาว


2
นี่ไม่เป็นความจริง. บนแพลตฟอร์มพฤษภาคม a longคือ "ใหญ่กว่า" floatแต่ชนิดของlong+ floatคืออะไร
CB Bailey

1
-1: คุณหมายถึงอะไรที่ยิ่งใหญ่ที่สุด ? ทุ่นลอยใหญ่กว่า int หรือไม่? หรือในทางกลับกัน ?
Paul R

2
ขอบคุณสำหรับความคิดเห็นของคุณ ใช่ขนาดเป็นไบต์ที่นี่ไม่น่าสนใจเลย เมื่อมันปรากฏออกมาการใส่ตัวเอนที่ใหญ่ที่สุดอย่างเห็นได้ชัดนั้นไม่เพียงพอที่จะอธิบายคำตอบได้ อย่างไรก็ตามมันไม่สมเหตุสมผลที่จะอธิบายอย่างลึกซึ้งยิ่งขึ้นเนื่องจากขณะนี้มีคำตอบอื่น ๆ
Baltasarq

-2

ข้อแม้!

การแปลงเกิดขึ้นจากซ้ายไปขวา

ลองสิ่งนี้:

int i = 3, j = 2;
double k = 33;
cout << k * j / i << endl; // prints 22
cout << j / i * k << endl; // prints 0

9
นั่นไม่ใช่เพราะการแปลง แต่เป็นเพราะความสำคัญของโอเปอเรเตอร์ j + i * kจะส่งผลให้ 101
gartenriese
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.