คงยืนยันใน C


87

วิธีใดที่ดีที่สุดในการบรรลุการยืนยันแบบคงที่ของเวลาคอมไพล์ใน C (ไม่ใช่ C ++) โดยเน้นเฉพาะ GCC

คำตอบ:


91

มาตรฐาน C11 เพิ่ม_Static_assertคำหลัก

สิ่งนี้ถูกนำมาใช้ตั้งแต่ gcc-4.6 :

ช่องแรกต้องเป็นนิพจน์คงที่ ช่องที่สองเป็นลิเทอรัลสตริงคงที่ซึ่งยาวได้ ( _Static_assert(0, L"assertion of doom!"))

ฉันควรทราบว่าสิ่งนี้ถูกนำไปใช้ในเสียงดังรุ่นล่าสุดด้วย


4
[... ดูเหมือนจะใช้งานโดย gcc โดยเสียงดัง ... ]คุณสามารถยืนยันได้มากขึ้นว่า ;-) _Static_assertเป็นส่วนหนึ่งของมาตรฐาน C11 และคอมไพเลอร์ใด ๆ ที่รองรับ C11 ก็จะมี
PP

1
สามารถใช้ในขอบเขตไฟล์ (นอกฟังก์ชันใด ๆ ) ได้หรือไม่? เพราะฉันได้รับerror: expected declaration specifiers or '...' before 'sizeof'สำหรับบรรทัดstatic_assert( sizeof(int) == sizeof(long int), "Error!); (ฉันใช้ C ไม่ใช่ C ++ อยู่แล้ว)
user10607

@ user10607 ฉันแปลกใจที่มันใช้ไม่ได้ .. เดี๋ยวก่อนคุณไม่มีใบเสนอราคาที่ท้ายสตริงข้อผิดพลาดของคุณ ใส่เข้าไปแล้วกลับมา สิ่งนี้ใช้ได้กับฉันใน gcc-4.9: _Static_assert( sizeof(int) == sizeof(long int), "Error!");บน macine ของฉันฉันได้รับข้อผิดพลาด
emsr

ฉันมี gcc 4.8.2 บน Ubuntu คำพูดที่หายไปคือการพิมพ์ความคิดเห็นผิด (ฉันมีรหัส) นี่คือบรรทัดแรกในไฟล์หลังจากมีส่วนหัวสองสามส่วน คอมไพเลอร์ให้ข้อผิดพลาดที่เหมือนกันสองข้อ: error: expected declaration specifiers or '...' before 'sizeof'AND error: expected declaration specifiers or '...' before string constant(เขาอ้างถึง"Error!"สตริง) (เช่น: ฉันกำลังคอมไพล์ด้วย -std = c11 เมื่อใส่การประกาศภายในฟังก์ชันทั้งหมดทำงานได้ดี (ล้มเหลวและประสบความสำเร็จตามที่คาดไว้))
user10607

2
@ user10607 ฉันต้องระบุ -std = gnu11 ในบรรทัดคำสั่งด้วย ฉันแปลกใจจริงๆที่มีความแตกต่างระหว่าง 4.8 และ 4.8 ฉันมีแหล่งข้อมูลเพียงบรรทัดเดียว ฉันยังใช้มาตรฐาน C _Static_assertไม่ได้ static_assertC คุณต้อง `#include <assert.h> เพื่อรับมาโคร static_assert
emsr

93

สิ่งนี้ใช้ได้ในฟังก์ชันและขอบเขตที่ไม่ใช่ฟังก์ชัน (แต่ไม่ใช่ภายในโครงสร้างสหภาพแรงงาน)

  1. หากไม่สามารถจับคู่การยืนยันเวลาคอมไพล์ได้ GCC จะสร้างข้อความที่เกือบเข้าใจได้ sas.c:4: error: size of array ‘static_assertion_this_should_be_true’ is negative

  2. มาโครสามารถหรือควรเปลี่ยนเพื่อสร้างชื่อเฉพาะสำหรับ typedef (เช่นต่อ__LINE__ท้ายstatic_assert_...ชื่อ)

  3. แทนที่จะเป็น ternary สิ่งนี้สามารถใช้ได้เช่นกัน#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[2*(!!(COND))-1]ซึ่งเกิดขึ้นได้กับคอมไพเลอร์เก่า cc65 (สำหรับ 6502 cpu) ที่เป็นสนิม

อัปเดต: เพื่อความสมบูรณ์นี่คือเวอร์ชันที่มี__LINE__

UPDATE2: รหัสเฉพาะ GCC

GCC 4.3 (ฉันเดา) เปิดตัวแอตทริบิวต์ฟังก์ชัน "ข้อผิดพลาด" และ "คำเตือน" ถ้าการเรียกใช้ฟังก์ชันที่มีแอตทริบิวต์นั้นไม่สามารถกำจัดได้ด้วยการกำจัดรหัสตาย (หรือมาตรการอื่น ๆ ) ข้อผิดพลาดหรือคำเตือนจะถูกสร้างขึ้น สามารถใช้เพื่อยืนยันเวลาคอมไพล์ด้วยคำอธิบายความล้มเหลวที่ผู้ใช้กำหนด ยังคงเป็นตัวกำหนดว่าจะใช้ในขอบเขตเนมสเปซได้อย่างไรโดยไม่ต้องใช้ฟังก์ชันดัมมี่:

และนี่คือลักษณะ:


1
ใน Visual Studio เขียนว่า "Negative subscript" ไม่ได้เอ่ยชื่อตัวแปร ...
szx

Nordic Mainframe - ตัวเลือกที่ 3 ในคำตอบของคุณใช้ไม่ได้กับเสียงดัง
Elazar

1
เกี่ยวกับโซลูชันสุดท้าย (GCC 4.3 + - เฉพาะ): สิ่งนี้มีประสิทธิภาพมากเนื่องจากสามารถตรวจสอบอะไรก็ได้ที่เครื่องมือเพิ่มประสิทธิภาพสามารถคิดได้ แต่จะล้มเหลวหากไม่ได้เปิดใช้งานการเพิ่มประสิทธิภาพ อย่างไรก็ตามระดับการเพิ่มประสิทธิภาพขั้นต่ำเปล่า ( -Og) อาจเพียงพอสำหรับการทำงานนี้และไม่ควรรบกวนการดีบัก หนึ่งอาจพิจารณาทำให้การยืนยันแบบคงที่เป็น no-op หรือ runtime assert ถ้า__OPTIMIZE__(และ__GNUC__) ไม่ได้กำหนดไว้
SørenLøvborg

ในข้อมูลโค้ดที่มีเวอร์ชัน LINE (อัปเดต: เพื่อความสมบูรณ์นี่คือเวอร์ชันที่มี `LINE) เมื่อคอมไพล์มีข้อผิดพลาดที่บรรทัด (STATIC_ASSERT (X, static_assertion_at_line _ ## L)) ซึ่งสามารถแก้ไขได้โดยเพิ่มอีกหนึ่งรายการ ระดับดังต่อไปนี้: #define COMPILE_TIME_ASSERT4 (X, L) static_assert (X, # L); # กำหนด COMPILE_TIME_ASSERT3 (X, L) COMPILE_TIME_ASSERT3 (X, "" ยืนยันที่: ## L "");
อาทิตย์

ฉันใช้สิ่งที่คล้ายกับ__LINE__เวอร์ชันใน gcc 4.1.1 ... ด้วยความรำคาญเป็นครั้งคราวเมื่อสองส่วนหัวที่แตกต่างกันมีหนึ่งในบรรทัดที่มีหมายเลขเดียวกัน!
MM

10

cl

ฉันรู้ว่าคำถามกล่าวถึง gcc อย่างชัดเจน แต่เพื่อความสมบูรณ์นี่คือการปรับแต่งสำหรับคอมไพเลอร์ของ Microsoft

การใช้อาร์เรย์ที่มีขนาดติดลบ typedef ไม่ได้ชักชวนให้clคายข้อผิดพลาดที่เหมาะสม มันบอกว่าerror C2118: negative subscript. บิตฟิลด์ที่มีความกว้างเป็นศูนย์จะมีราคาที่ดีกว่าในแง่นี้ เนื่องจากสิ่งนี้เกี่ยวข้องกับการพิมพ์โครงสร้างเราจึงจำเป็นต้องใช้ชื่อประเภทที่ไม่ซ้ำกัน __LINE__อย่าตัดมัสตาร์ด - เป็นไปได้ที่จะมีCOMPILE_TIME_ASSERT()บรรทัดเดียวกันในส่วนหัวและไฟล์ต้นฉบับและคอมไพล์ของคุณจะแตก __COUNTER__มาช่วย (และอยู่ใน gcc ตั้งแต่ 4.3)

ตอนนี้

ภายใต้clให้:

ข้อผิดพลาด C2149: 'static_assertion_failed_use_another_compiler_luke': ฟิลด์บิตที่มีชื่อต้องไม่มีความกว้างเป็นศูนย์

Gcc ยังให้ข้อความที่เข้าใจได้:

ข้อผิดพลาด: ความกว้างเป็นศูนย์สำหรับบิตฟิลด์ 'static_assertion_failed_use_another_compiler_luke'


4

จากWikipedia :


15
จะดีกว่าถ้าคุณเชื่อมโยงกับแหล่งที่มาที่แท้จริง: jaggersoft.com/pubs/CVu11_3.html
Matt Joiner

มันใช้ไม่ได้ใน gcc 4.6 - มันระบุว่า "case label ไม่ได้ลดเป็นค่าคงที่จำนวนเต็ม" มันมีประเด็น
Liosan

ตอนนี้คุณทั้งคู่อาจจะย้ายไปแล้ว แต่ฉันก็เขียนของตัวเอง (ดูคำตอบของฉัน ) ฉันใช้ลิงค์ของคุณ @MattJoiner เพื่อช่วยฉัน
Hashbrown

และถ้าคุณสามารถรบกวนได้โปรดแจ้งให้เราทราบว่ามันเหมาะกับคุณหรือไม่ @Liosan ฉันเพิ่งเริ่มเจาะลึก C ++ ดังนั้นฉันจึงมางานปาร์ตี้
ช้า

สำหรับ Visual C ++ นั้นมีstatic_assertในตัวตั้งแต่เวอร์ชัน 2010 และทำงานได้ทั้งในโหมด c ++ และ c อย่างไรก็ตามมันไม่มี c99 _Static_assert ในตัว
ddbug

3

ฉันไม่แนะนำให้ใช้วิธีแก้ปัญหาโดยใช้typedef:

typedefไม่รับประกันว่าการประกาศอาร์เรย์ด้วยคีย์เวิร์ดจะได้รับการประเมินในเวลาคอมไพล์ ตัวอย่างเช่นโค้ดต่อไปนี้ในขอบเขตบล็อกจะคอมไพล์:

ฉันอยากจะแนะนำสิ่งนี้แทน (บน C99):

เนื่องจากstaticคีย์เวิร์ดอาร์เรย์จะถูกกำหนดในเวลาคอมไพล์ โปรดทราบว่าการยืนยันนี้จะใช้ได้เฉพาะกับCONDที่ได้รับการประเมินในเวลาคอมไพล์ มันจะใช้ไม่ได้ (กล่าวคือคอมไพล์จะล้มเหลว) ด้วยเงื่อนไขที่อิงตามค่าในหน่วยความจำเช่นค่าที่กำหนดให้กับตัวแปร


4
แม้ว่าจะได้ผล แต่ก็ยังเพิ่มความต้องการหน่วยความจำของคุณด้วย
sherrellbc

1
ข้อผิดพลาด: กำหนด 'static_assertion_INVALID_CHAR_SIZE' แต่ไม่ได้ใช้ [-Werror = unused-variable]
Alex

2

หากใช้มาโคร STATIC_ASSERT () ด้วย__LINE__จะเป็นไปได้ที่จะหลีกเลี่ยงการขัดแย้งหมายเลขบรรทัดระหว่างรายการในไฟล์. c กับรายการอื่นในไฟล์ส่วนหัวโดยรวม__INCLUDE_LEVEL__.

ตัวอย่างเช่น :


1

วิธีคลาสสิกคือการใช้อาร์เรย์:

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

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


การรวมสิ่งนี้ไว้ใน#define STATIC_ASSERT()มาโครประเภททั่วไปและให้ตัวอย่างทั่วไปมากขึ้นและเอาต์พุตคอมไพเลอร์ตัวอย่างจากตัวอย่างทั่วไปของคุณโดยใช้STATIC_ASSERT()จะช่วยให้คุณได้รับคะแนนโหวตมากขึ้นและทำให้เทคนิคนี้มีความหมายมากขึ้นฉันคิดว่า
Gabriel Staples

ฉันไม่เห็นด้วย คอมไพเลอร์เห็นมาโครความคิดและให้ข้อความที่สับสนมากขึ้น
Paolo.Bolzoni

1

จาก Perl โดยเฉพาะperl.hบรรทัด 3455 ( <assert.h>รวมไว้ล่วงหน้า):

หากstatic_assertมี (จาก<assert.h>) จะใช้ มิฉะนั้นหากเงื่อนไขเป็นเท็จระบบจะประกาศบิตฟิลด์ที่มีขนาดลบซึ่งทำให้การคอมไพล์ล้มเหลว

STMT_START/ STMT_ENDกำลังขยายมาโครเป็นdo/ while (0)ตามลำดับ


1

เพราะ:

  1. _Static_assert() ตอนนี้ถูกกำหนดเป็น gcc สำหรับ C ทุกเวอร์ชันและ
  2. static_assert() ถูกกำหนดไว้ใน C ++ 11 และใหม่กว่า

แมโครอย่างง่ายต่อไปนี้STATIC_ASSERT()จึงใช้ได้ใน:

  1. C ++:
    1. C ++ 11 ( g++ -std=c++11) หรือใหม่กว่า
  2. ค:
    1. gcc -std=c90
    2. gcc -std=c99
    3. gcc -std=c11
    4. gcc (ไม่ระบุมาตรฐาน)

กำหนดSTATIC_ASSERTดังต่อไปนี้:

ตอนนี้ใช้มัน:

ตัวอย่าง:

ทดสอบใน Ubuntu โดยใช้ gcc 4.8.4:

ตัวอย่างที่ 1:gccผลลัพธ์ที่ดี(เช่นSTATIC_ASSERT()รหัสทำงาน แต่เงื่อนไขเป็นเท็จทำให้เกิดการยืนยันเวลาคอมไพล์):

$ gcc -Wall -o static_assert static_assert.c && ./static_assert
static_assert.c: ในฟังก์ชัน 'main'
static_assert.c: 78: 38: ข้อผิดพลาด: การยืนยันแบบคงที่ล้มเหลว: "(1> 2) ล้มเหลว"
# กำหนด STATIC_ASSERT (test_for_true ) _Static_assert ((test_for_true), "(" #test_for_true ") ล้มเหลว")
^
static_assert.c: 88: 5: หมายเหตุ: ในการขยายมาโคร 'STATIC_ASSERT'
STATIC_ASSERT (1> 2);
^

ตัวอย่างที่ 2:g++ -std=c++11ผลลัพธ์ที่ดี(เช่นSTATIC_ASSERT()รหัสทำงาน แต่เงื่อนไขเป็นเท็จทำให้เกิดการยืนยันเวลาคอมไพล์):

$ g ++ -Wall -std = c ++ 11 -o static_assert static_assert.c && ./static_assert
static_assert.c: ในฟังก์ชัน 'int main ()'
static_assert.c: 74: 32: ข้อผิดพลาด: การยืนยันแบบคงที่ล้มเหลว: (1> 2) ล้มเหลว
#define _Static_assert static_assert / * static_assertเป็นส่วนหนึ่งของ C ++ 11 หรือใหม่กว่า * /
^
static_assert.c: 78: 38: หมายเหตุ: ในการขยายมาโคร '_Static_assert'
# กำหนด STATIC_ASSERT (test_for_true) _Static_assert ((test_for_true), "(" #test_for_true ") ล้มเหลว")
^
static_assert.c: 88: 5: หมายเหตุ: ในการขยายมาโคร 'STATIC_ASSERT'
STATIC_ASSERT (1> 2);
^

ตัวอย่างที่ 3: เอาต์พุต C ++ ที่ล้มเหลว (เช่น: รหัสยืนยันทำงานไม่ถูกต้องเลยเนื่องจากใช้ C ++ เวอร์ชันก่อน C ++ 11):

$ g ++ -Wall -o static_assert static_assert.c && ./static_assert
static_assert.c: 88: 5: Warning: identifier 'static_assert' เป็นคีย์เวิร์ดใน C ++ 11 [-Wc ++ 0x-compat]
STATIC_ASSERT (1> 2 );
^
static_assert.c: ในฟังก์ชัน 'int main ()'
static_assert.c: 78: 99: ข้อผิดพลาด: 'static_assert' ไม่ได้รับการประกาศในขอบเขตนี้
#define STATIC_ASSERT (test_for_true) _Static_assert ((test_for_true), "(" #test_for_true " ) ล้มเหลว ")
^
static_assert.c: 88: 5: หมายเหตุ: ในการขยายมาโคร 'STATIC_ASSERT'
STATIC_ASSERT (1> 2);
^

ผลการทดสอบฉบับเต็มที่นี่:

ที่เกี่ยวข้อง:

  1. ใช้ static_assert เพื่อตรวจสอบประเภทที่ส่งไปยังมาโคร [คำตอบของฉันเอง]
    1. https://en.cppreference.com/w/cpp/types/is_same
    2. https://en.cppreference.com/w/cpp/language/decltype
  2. ใช้ static_assert เพื่อตรวจสอบประเภทที่ส่งไปยังมาโคร
  3. วิธีใช้การยืนยันแบบคงที่ใน C เพื่อตรวจสอบประเภทของพารามิเตอร์ที่ส่งผ่านไปยังมาโคร

1
ทำไมต้องซับซ้อนเมื่อมีstatic_assertมาโครassert.h?
Goodbye SE

@KamiKaze ฉันแปลกใจกับคำถามของคุณเพราะดูเหมือนว่าคุณอาจไม่ได้อ่านคำตอบของฉันจริงๆ? บรรทัดที่ 2 ของคำตอบของฉันบอกทุกอย่าง: "static_assert () ถูกกำหนดใน C ++ 11 และใหม่กว่า" ดังนั้นจึงstatic_assert()ไม่มีใน C ดูที่นี่ด้วย: en.cppreference.com/w/cpp/language/static_assert -static_assertมีรายการอยู่ "(ตั้งแต่ C ++ 11)" ความงามของคำตอบของฉันคือมันใช้งานได้ใน C90 ของ gcc และใหม่กว่ารวมถึง C ++ 11 และใหม่กว่าแทนที่จะเป็นใน C ++ 11 และใหม่กว่าเช่นstatic_assert(). นอกจากนี้คำตอบของฉันซับซ้อนอะไรบ้าง มันเป็นเพียงคู่#defines
Gabriel Staples

static_assertถูกกำหนดไว้ใน C ตั้งแต่ C11 _Static_assertมันเป็นแมโครที่จะขยาย en.cppreference.com/w/c/error/static_assert นอกจากนี้และตรงกันข้ามกับคำตอบของคุณ_Static_assertไม่มีใน c99 และ c90 ใน gcc (เฉพาะใน gnu99 และ gnu90) เป็นไปตามมาตรฐาน โดยพื้นฐานแล้วคุณทำงานพิเศษมากมายซึ่งจะก่อให้เกิดประโยชน์ก็ต่อเมื่อคอมไพล์ด้วย gnu90 และ gnu99 และทำให้ usecase เล็กลงอย่างไม่มีนัยสำคัญ
Goodbye SE

> "_Static_assert ไม่มีใน c99 และ c90 ใน gcc (เฉพาะใน gnu99 และ gnu90)" ฉันเข้าใจว่าคุณหมายถึงอะไร เป็นนามสกุล gcc ดังนั้นคุณจึงถูกต้อง > "โดยทั่วไปคุณทำงานพิเศษจำนวนมาก" ฉันไม่เห็นด้วย; คำจำกัดความที่เรียบง่ายอย่างยิ่ง 2 ข้อคือไม่ได้หมายความว่า "งานพิเศษ" ที่พูดฉันเข้าใจว่าตอนนี้คุณหมายถึงอะไร ฉันยังคงคิดว่าสิ่งที่ฉันทำมีประโยชน์และเพิ่มคุณค่าให้กับองค์ความรู้และคำตอบที่นำเสนอที่นี่ดังนั้นฉันจึงไม่คิดว่ามันจะเหมาะกับการโหวตลด นอกจากนี้ความผิดพลาดของฉันในการพูดว่า "C90 และใหม่กว่า" แทนที่จะเป็น "gcc C90 และใหม่กว่า" หรือ "g90 และใหม่กว่า" นั้นอยู่ในความคิดเห็นของฉันด้านบนเท่านั้นไม่ใช่ในคำตอบของฉัน
Gabriel Staples

เนื่องจากเป็นความผิดจริงการโหวตลดจึงเป็นสิ่งที่ชอบธรรม หากคุณแก้ไขข้อความที่ไม่ถูกต้องฉันจะตรวจสอบคำตอบอีกครั้งและอาจเพิกถอนการลงคะแนนของฉัน การเพิ่มโค้ดดังกล่าวหากไม่จำเป็น (ดังนั้นหากคุณไม่ได้ทำงานกับ gnu90 และ gnu99) จะไม่เป็นประโยชน์สำหรับความชัดเจนและเพิ่มความยุ่งเหยิงมากขึ้น ถ้าคุณมี usecase มันอาจจะคุ้มค่า แต่ฉันสงสัยเกี่ยวกับความหายากของกรณีการใช้งานที่ต้องใช้ความสามารถในการเข้ากันได้ gnu99 / 90 และ c ++ 11
Goodbye SE

0

สำหรับผู้ที่คุณต้องการบางสิ่งที่เรียบง่ายและพกพาได้ แต่ไม่สามารถเข้าถึงคุณสมบัติ C ++ 11 ได้ฉันได้เขียนสิ่งนี้ไว้
ใช้STATIC_ASSERTตามปกติ (คุณสามารถเขียนสองครั้งในฟังก์ชันเดียวกันได้หากต้องการ) และใช้GLOBAL_STATIC_ASSERTภายนอกฟังก์ชันโดยใช้วลีเฉพาะเป็นพารามิเตอร์แรก


คำอธิบาย:
ขั้นแรกให้ตรวจสอบว่าคุณมีคำยืนยันจริงหรือไม่ซึ่งคุณต้องการใช้อย่างแน่นอนหากมีอยู่
ถ้าคุณไม่ยืนยันโดยการรับไอซ์ของคุณpredและหารด้วยตัวมันเอง สิ่งนี้ทำสองสิ่ง
หากเป็นศูนย์, id est, การยืนยันล้มเหลวจะทำให้เกิดข้อผิดพลาดหารด้วยศูนย์ (เลขคณิตถูกบังคับเนื่องจากพยายามประกาศอาร์เรย์)
ถ้าไม่ใช่ศูนย์จะทำให้ขนาดอาร์เรย์เป็น1ปกติ ดังนั้นหากการยืนยันผ่านไปคุณจะไม่ต้องการให้มันล้มเหลวอีกต่อไปเพราะเพรดิเคตของคุณถูกประเมินเป็น-1(ไม่ถูกต้อง) หรือเป็น232442(เสียพื้นที่มาก IDK หากจะปรับให้เหมาะสม)
สำหรับหมายความว่าคุณสามารถเขียนได้หลายครั้ง นอกจากนี้ยังหล่อให้STATIC_ASSERTมันถูกห่อด้วยเครื่องหมายวงเล็บทำให้เป็นบล็อกซึ่งกำหนดขอบเขตของตัวแปรassert
voidซึ่งเป็นวิธีที่ทราบกันดีในการกำจัดunused variableคำเตือน
สำหรับGLOBAL_STATIC_ASSERTแทนที่จะอยู่ในบล็อกโค้ดจะสร้างเนมสเปซ อนุญาตให้ใช้เนมสเปซภายนอกฟังก์ชันได้ uniqueระบุเป็นสิ่งจำเป็นที่จะหยุดคำจำกัดความขัดแย้งใด ๆ ถ้าคุณใช้คนนี้มากกว่าหนึ่งครั้ง


ทำงานให้ฉันใน GCC และ VS'12 C ++


2
ไม่มีเนมสเปซใน C.
martinkunev

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

0

วิธีนี้ใช้ได้กับชุดตัวเลือก "ลบสิ่งที่ไม่ได้ใช้" ฉันอาจใช้ฟังก์ชันส่วนกลางหนึ่งฟังก์ชันเพื่อตรวจสอบพารามิเตอร์ส่วนกลาง


1
ถ้ามันใช้งานได้ทั้งหมดมันจะทำในแหล่งที่มาของไฟล์ปฏิบัติการเท่านั้น
Coder

0

สิ่งนี้ใช้ได้กับ gcc เก่า ๆ ขออภัยที่ฉันลืมว่าเป็นเวอร์ชันอะไร:

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