long long ใน C / C ++


84

ฉันกำลังลองใช้รหัสนี้ในคอมไพเลอร์ C ++ ของ GNU และไม่เข้าใจพฤติกรรมของมัน:

#include <stdio.h>;

int main()
{
    int  num1 = 1000000000;
    long num2 = 1000000000;
    long long num3;
    //num3 = 100000000000;
    long long num4 = ~0;

    printf("%u %u %u", sizeof(num1), sizeof(num2), sizeof(num3));
    printf("%d %ld %lld %llu", num1, num2, num3, num4);
    return 0;
}

เมื่อฉันยกเลิกการแสดงความคิดเห็นในบรรทัดที่แสดงความคิดเห็นรหัสจะไม่รวบรวมและให้ข้อผิดพลาด:

ข้อผิดพลาด: ค่าคงที่จำนวนเต็มใหญ่เกินไปสำหรับประเภทยาว

แต่ถ้ารหัสถูกคอมไพล์ตามที่เป็นอยู่และถูกเรียกใช้งานโค้ดจะสร้างค่าที่มากกว่า 10000000000

ทำไม?


8
อาจจะสายเกินไปในตอนนี้ แต่สำหรับผู้อ่านในอนาคตผมขอแนะนำให้คุณใช้และการใช้งาน<stdint.h> uint64_tเพื่อแสดงค่า 64 บิตprintf( "%" PRIu64 "\n", val);
กระตือรือร้น

@enthusiasticgeek <stdint.h>รวมuint64_t a = 0xffffffffffffff; printf( "%" PRIu64 "\n",a ); : error: expected ‘)’ before ‘PRIu64’ printf( "%" PRIu64 "\n",a ); :: warning: spurious trailing ‘%’ in format [-Wformat=] printf( "%" PRIu64 "\n",a );
Herdsman

คำตอบ:


148

ตัวอักษร 100000000000 แต่งหน้าคงจำนวนเต็มอักษร intแต่ค่าที่มีขนาดใหญ่เกินไปสำหรับประเภท คุณต้องใช้คำต่อท้ายเพื่อเปลี่ยนประเภทของลิเทอรัลเช่น

long long num3 = 100000000000LL;

ปัจจัยที่ทำให้ตัวอักษรลงในประเภทLL long longC ไม่ "ฉลาด" พอที่จะสรุปสิ่งนี้จากประเภททางด้านซ้ายประเภทนี้เป็นคุณสมบัติของตัวอักษรไม่ใช่บริบทที่จะใช้


47
กลับเมื่อคำตอบนี้ถูกเขียนขึ้นมันอาจจะเป็นที่ถูกต้อง แต่ตอนนี้ c ++ มาตรฐานกล่าวว่าประเภทของตัวอักษรจำนวนเต็มไม่มีคำต่อท้ายเป็นครั้งแรกของint, long intและlong long intที่คุ้มค่าสามารถแสดง [C ++ §2.14.2 / 2] ดังนั้นตอนนี้จึงไม่จำเป็นต้องเพิ่มคำต่อท้าย 'LL' ลงในลิเทอรัลจำนวนเต็มที่ใหญ่เกินไปสำหรับประเภทอื่น
bames53

8
สาเหตุที่เป็นปัญหามาก่อนไม่ใช่เพราะ C ++ ไม่ 'ฉลาด' พอที่จะกำหนดประเภทตัวอักษรจากประเภทของตัวแปรที่กำหนดให้มันเป็นเพราะส่วนขยายของคอมไพเลอร์ไม่ได้ใช้จำนวนเต็มขยาย พิมพ์เพื่อให้สามารถใช้งานได้ดีกับภาษามาตรฐาน ตอนนี้ C ++ มีกฎที่ว่าประเภทจำนวนเต็มขยายใด ๆ จะรวมเข้ากับมาตรฐานได้ดีขึ้น: open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf
bames53

4
@unwind ฉันคิดว่าคำตอบควรได้รับการแก้ไขตามคำแนะนำเหล่านี้
Antonio

26

ลอง:

num3 = 100000000000LL;

และ BTW ใน C ++ นี่คือส่วนขยายของคอมไพเลอร์มาตรฐานไม่ได้กำหนด long long ซึ่งเป็นส่วนหนึ่งของ C99


11
ตอนนี้ C ++ 11 กำหนด long long แล้ว
Mohamed El-Nakib

4

ขึ้นอยู่กับโหมดที่คุณกำลังรวบรวม long long ไม่ได้เป็นส่วนหนึ่งของมาตรฐาน C ++ แต่รองรับเฉพาะ (โดยปกติ) เป็นส่วนขยาย สิ่งนี้มีผลต่อประเภทของตัวอักษร ลิเทอรัลจำนวนเต็มทศนิยมที่ไม่มีคำต่อท้ายจะเป็นประเภท int เสมอถ้า int ใหญ่พอจะแทนจำนวนได้ หากตัวเลขมีขนาดใหญ่เกินไปเป็นเวลานานผลลัพธ์จะถูกกำหนดให้ใช้งานได้ (อาจเป็นเพียง int long จำนวนหนึ่งที่ถูกตัดทอนเพื่อความเข้ากันได้แบบย้อนหลัง) ในกรณีนี้คุณต้องใช้คำต่อท้าย LL อย่างชัดเจนเพื่อเปิดใช้งานส่วนขยายแบบยาว (ในคอมไพเลอร์ส่วนใหญ่)

C ++ เวอร์ชันถัดไปจะรองรับอย่างเป็นทางการในระยะยาวโดยที่คุณไม่ต้องการคำต่อท้ายใด ๆ เว้นแต่คุณจะต้องการบังคับให้ประเภทของตัวอักษรมีความยาวอย่างน้อยที่สุด หากไม่สามารถแสดงตัวเลขได้ในระยะยาวคอมไพเลอร์จะพยายามใช้ long long โดยอัตโนมัติแม้ว่าจะไม่มีคำต่อท้าย LL ผมเชื่อว่านี่เป็นพฤติกรรมของ C99 เช่นกัน


1

รหัสของคุณรวบรวมที่นี่ได้ดี (แม้ว่าบรรทัดนั้นจะไม่มีการใส่ความคิดเห็นก็ต้องเปลี่ยนเป็นไฟล์

num3 = 100000000000000000000;

เพื่อเริ่มรับคำเตือน


คอมไพเลอร์อะไร ใน C ++ ลิเทอรัลจำนวนเต็มเป็น int หรือ long ที่มีขนาดเล็กที่สุดใน C99 จะเป็น int ที่เล็กที่สุดยาวและยาว ดังนั้นเมื่อใช้ C ++ เป็นส่วนขยายที่ไม่ได้มาตรฐานบางทีคอมไพเลอร์ของคุณอาจใช้กฎ C99 สำหรับตัวอักษรด้วย
Steve Jessop

gcc เวอร์ชัน 4.3.2 (Debian 4.3.2-1.1) บนระบบลินุกซ์ 64 บิต
Omry Yadan

@SteveJessop อาจจะช้าไปหน่อย แต่ความยาวไม่จำเป็นต้องเป็น 64 บิต เกือบตลอดเวลา แต่คุณไม่มีหลักประกันว่าจะมีอยู่ทุกหนทุกแห่ง การรับประกันเพียงอย่างเดียวที่คุณมีคืออย่างน้อยก็ใหญ่เท่ากับ int ซึ่งอย่างน้อยก็ใหญ่เท่ากับ int สั้น ๆ ซึ่งอย่างน้อยก็ใหญ่พอ ๆ กับถ่าน สุดท้าย char ถูกกำหนดให้ใหญ่พอที่จะแสดงทุกอักขระในชุดอักขระพื้นฐานของการนำไปใช้งาน (โดยทั่วไปคือ 8 บิต)
pauluss86

@ pauluss86: ฉันไม่ได้พูดถึงการค้ำประกัน Omry บอกว่าเขาใช้ gcc 4.3.2 บนระบบ Debian 64 บิต ฉันสังเกตว่าสิ่งนี้อธิบายถึงสิ่งที่เขาเห็นตั้งแต่ (ฉันบังเอิญรู้ว่าเป็นเรื่องของความรู้ทั่วไป) gcc ได้รับการกำหนดค่าโดยค่าเริ่มต้นในระบบดังกล่าวให้ใช้ 64 บิตlongตาม LP64 ABI ของ OS นั้น
Steve Jessop

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