ฉันจะเขียนลิเทอรัลสั้น ๆ ใน C ++ ได้อย่างไร


120

คำถามพื้นฐานมาก: ฉันจะเขียนshortตัวอักษรใน C ++ ได้อย่างไร

ฉันรู้สิ่งต่อไปนี้:

  • 2 เป็น int
  • 2U เป็น unsigned int
  • 2L คือ long
  • 2LL คือ long long
  • 2.0f คือ float
  • 2.0 คือ double
  • '\2'คือchar.

แต่ฉันจะเขียนshortตัวอักษรได้อย่างไร? ฉันลองแล้ว2Sแต่นั่นทำให้คอมไพเลอร์เตือน


10
ฉันเดาว่าตัวอักษรสั้น ๆ ไม่ได้รับการสนับสนุนเพียงอย่างเดียวเนื่องจากสิ่งที่น้อยกว่า int จะถูก "เลื่อนระดับ" เป็น int ในระหว่างการประเมิน int มีขนาดที่เป็นธรรมชาติที่สุด เรียกว่าการส่งเสริมจำนวนเต็มใน C ++
user534498

คำตอบ:


82
((short)2)

ใช่มันไม่ได้เป็นเพียงตัวอักษรสั้น ๆ แต่เป็น casted-int มากกว่า แต่พฤติกรรมก็เหมือนกันและฉันคิดว่าไม่มีวิธีโดยตรงในการทำเช่นนั้น

นั่นคือสิ่งที่ฉันทำเพราะฉันไม่พบอะไรเลย ฉันเดาว่าคอมไพเลอร์จะฉลาดพอที่จะรวบรวมสิ่งนี้ราวกับว่ามันเป็นลิเทอรัลสั้น ๆ (นั่นคือมันจะไม่จัดสรร int จริง ๆ แล้วจึงร่ายทุกครั้ง)

ต่อไปนี้แสดงให้เห็นว่าคุณควรกังวลกับเรื่องนี้มากแค่ไหน:

a = 2L;
b = 2.0;
c = (short)2;
d = '\2';

คอมไพล์ -> ถอด ->

movl    $2, _a
movl    $2, _b
movl    $2, _c
movl    $2, _d

นั่นคือสิ่งที่ฉันทำเพราะฉันไม่พบอะไรเลย ฉันเดาว่าคอมไพเลอร์จะฉลาดพอที่จะรวบรวมสิ่งนี้ราวกับว่ามันเป็นลิเทอรัลสั้น ๆ (นั่นคือมันจะไม่จัดสรร int จริง ๆ แล้วจึงร่ายทุกครั้ง)
กีบ

"นักแสดง" คือไม่ได้ทำอะไรเลยจริงๆ ไม่มีคำสั่งแอสเซมเบลอร์ "cast" เมื่อเรากำลังพูดถึง C หรือ C ++ (.NET MSIL เป็นคนละเรื่อง) ที่นั่นบนโลหะทั้งหมดเป็นเพียงเลขฐานสอง
Isak Savo

9
ประเภทของ a, b, c และ d ข้างต้นคืออะไร?
Ates Goral

2
@Ates Goral: ints ทั้งหมด การเปลี่ยนเป็น short หรือ char น่าจะเปลี่ยนคำสั่งเป็น movw หรือ movb ทั่วทั้งกระดาน

2
นั่นไม่ใช่ตัวอักษรสั้น ๆ เมื่อคุณใช้ว่านักแสดงและรวบรวมกับ GCC และตัวเลือก -Wconversion short foo = 1; foo += (short)2;ที่คุณยังคงได้รับการวินิจฉัยสำหรับคอมไพเลอร์คำสั่ง แต่ไม่สามารถหลีกเลี่ยงได้เนื่องจากการส่งเสริมจำนวนเต็ม
ฮาร์เปอร์

51

C ++ 11 ช่วยให้คุณใกล้เคียงกับสิ่งที่คุณต้องการ (ค้นหา "ตัวอักษรที่ผู้ใช้กำหนด" เพื่อเรียนรู้เพิ่มเติม)

#include <cstdint>

inline std::uint16_t operator "" _u(unsigned long long value)
{
    return static_cast<std::uint16_t>(value);
}

void func(std::uint32_t value); // 1
void func(std::uint16_t value); // 2

func(0x1234U); // calls 1
func(0x1234_u); // calls 2

// also
inline std::int16_t operator "" _s(unsigned long long value)
{
    return static_cast<std::int16_t>(value);
}

6
shortร่างกายไม่สามารถเป็นstd::uintอะไรได้เนื่องจากเป็นประเภทที่มีลายเซ็น และไม่จำเป็นต้องเป็น 16 บิตหรือประเภทเดียวกับstd::int16_t... ซึ่งตัวเองไม่จำเป็นต้องมีอยู่ในการนำไปใช้งานที่กำหนดหากแพลตฟอร์มไม่สามารถจัดหาประเภทความกว้างที่แน่นอนได้ แนวคิดหลักของคำตอบนี้เป็นสิ่งที่ดี แต่มันถูกลดค่าลงโดยแทนเจนต์ที่อธิบายไม่ได้เป็นประเภทที่ไม่เกี่ยวข้องซึ่ง OP ไม่ได้ถามถึง
underscore_d

หมายเหตุตัวอักษรที่ผู้ใช้กำหนดไม่ได้รับการสนับสนุนใน Visual Studio จนถึง VS2015: msdn.microsoft.com/en-us/library/hh567368(v=vs.140).aspx
parsley72

ฉันไม่รู้ว่าฉันควรจะรักหรือเกลียดมัน แต่นี่เป็นชิ้นส่วนสุดท้ายของระบบประเภทจำนวนเต็มแรงจริงๆใน C ++ ที่ฉันกำลังทำอยู่มันวิเศษมาก
Sahsahae

echoing @underscore_d ฉันจะเพิ่มคะแนน แต่หลังจากแก้ไขshortเป็น aked โดย OP
v.oddou

28

แม้แต่นักเขียนของมาตรฐาน C99 ก็ถูกจับได้ด้วยสิ่งนี้ นี่คือตัวอย่างจากการstdint.hใช้งานโดเมนสาธารณะของ Danny Smith :

/* 7.18.4.1  Macros for minimum-width integer constants

    Accoding to Douglas Gwyn <gwyn@arl.mil>:
    "This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC
    9899:1999 as initially published, the expansion was required
    to be an integer constant of precisely matching type, which
    is impossible to accomplish for the shorter types on most
    platforms, because C99 provides no standard way to designate
    an integer constant with width less than that of type int.
    TC1 changed this to require just an integer constant
    *expression* with *promoted* type."
*/

18

หากคุณใช้ Microsoft Visual C ++ จะมีคำต่อท้ายตามตัวอักษรสำหรับจำนวนเต็มทุกประเภท:

auto var1 = 10i8;  // char
auto var2 = 10ui8; // unsigned char

auto var3 = 10i16;  // short
auto var4 = 10ui16; // unsigned short

auto var5 = 10i32;  // int
auto var6 = 10ui32; // unsigned int

auto var7 = 10i64;  // long long
auto var8 = 10ui64; // unsigned long long

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


1
เมื่อคุณติดตามหนึ่งในส่วนต่อท้ายคุณจะเห็นว่าเช่น""ui8ถูกกำหนดให้เป็น'\000'ซึ่งโดยพื้นฐาน'\0'แล้ว
Nikita

10

คุณยังสามารถใช้ไวยากรณ์ตัวสร้างหลอก

short(2)

ฉันคิดว่ามันน่าอ่านกว่าการแคสติ้ง


4
เรียกว่า "functional cast expression" ฉันชอบมันมากเช่นกันโดยเฉพาะอย่างยิ่งเมื่อเขียนโปรแกรมด้วย Windows API
klaus triendl

6

เท่าที่ฉันรู้คุณไม่มีไม่มีคำต่อท้ายแบบนี้ คอมไพเลอร์ส่วนใหญ่จะเตือนหากลิเทอรัลจำนวนเต็มมีขนาดใหญ่เกินไปที่จะพอดีกับตัวแปรใด ๆ ที่คุณพยายามจัดเก็บไว้

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