วิธีการระงับคำเตือน“ พารามิเตอร์ที่ไม่ได้ใช้” ใน C?


210

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

Bool NullFunc(const struct timespec *when, const char *who)
{
   return TRUE;
}

ใน C ++ ฉันสามารถใส่/*...*/ความคิดเห็นรอบพารามิเตอร์ แต่ไม่ได้อยู่ใน C error: parameter name omittedแน่นอนที่มันทำให้ฉันข้อผิดพลาด



4
@CiroSantilli คำถามนี้มี upvotes มากกว่าจะเป็นการดีกว่าถ้าจะทำเครื่องหมายคำถามอื่นว่าซ้ำซ้อน
sashoalm


-Wno-unused-parameterมันแค่ดังเกินไปและไม่ค่อยจับแมลง เมื่อ-Wshadowมีการใช้
Trass3r

คำตอบ:


297

ฉันมักจะเขียนมาโครเช่นนี้

#define UNUSED(x) (void)(x)

คุณสามารถใช้แมโครนี้สำหรับพารามิเตอร์ที่ไม่ได้ใช้ทั้งหมดของคุณ (โปรดทราบว่าสิ่งนี้ใช้ได้กับคอมไพเลอร์ใด ๆ )

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

void f(int x) {
    UNUSED(x);
    ...
}

45
ฉันเพิ่งใช้ (เป็นโมฆะ) x โดยตรง
ศ. Falken

6
ในขณะที่นี่เป็นวิธีเดียวที่พกพาได้ AFAIK ความน่ารำคาญใจของสิ่งนี้คือมันอาจทำให้เข้าใจผิดหากคุณใช้ตัวแปรในภายหลังและลืม ro ลบบรรทัดที่ไม่ได้ใช้ นี่คือสาเหตุที่ GCC ไม่ได้ใช้ดี
ideasman42

6
@CookSchelling: อา แต่คุณไม่ควรใช้มันอย่างนั้น void f(int x) {UNUSED(x);}ทำอะไรเช่นนี้:
งาน

9
@Alcott เพราะ (ในกรณีของฉัน) ฟังก์ชั่นอาจเป็นหนึ่งในหลาย ๆ อันที่จะต้องมีลายเซ็นเหมือนกันเพราะมันถูกอ้างถึงโดยตัวชี้ฟังก์ชั่น
josch

17
ฉันกำลังใช้#define UNUSED(...) (void)(__VA_ARGS__)ซึ่งทำให้ฉันสามารถใช้สิ่งนี้กับตัวแปรหลายตัว
Matthew Mitchell

110

ใน GCC คุณสามารถฉลากพารามิเตอร์ที่มีแอตทริบิวต์unused

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

ในทางปฏิบัติสิ่งนี้สามารถทำได้โดยการใส่__attribute__ ((unused))ก่อนพารามิเตอร์ ตัวอย่างเช่น:

void foo(workerid_t workerId) { }

กลายเป็น

void foo(__attribute__((unused)) workerid_t workerId) { }

24
สำหรับมือใหม่ใด ๆ เช่นฉันนี่หมายถึง__attribute__ ((unused))การโต้แย้งต่อหน้า
josch

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

นอกจากนี้ทราบว่า__attribute__((unused))เป็นส่วนขยายของ GCC เป็นกรรมสิทธิ์ มันรองรับคอมไพเลอร์อื่น ๆ แต่ฉันคิดว่ามันจะไม่ทำงานกับ MSVC มันไม่ได้เป็นส่วนหนึ่งของมาตรฐานคอมไพเลอร์โดยตรงดังนั้นนี่จึงไม่สามารถพกพาได้เหมือนกับตัวเลือกอื่น ๆ
โซอี้

58

คุณสามารถใช้แอตทริบิวต์ที่ไม่ได้ใช้ของ gcc / clang ได้ แต่ฉันใช้แมโครเหล่านี้ในส่วนหัวเพื่อหลีกเลี่ยงการมีแอตทริบิวต์เฉพาะ gcc ทั่วทุกแหล่งที่มาการมี__attribute__อยู่ทุกที่นั้นค่อนข้าง verbose / น่าเกลียด

#ifdef __GNUC__
#  define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
#else
#  define UNUSED(x) UNUSED_ ## x
#endif

#ifdef __GNUC__
#  define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x
#else
#  define UNUSED_FUNCTION(x) UNUSED_ ## x
#endif

จากนั้นคุณสามารถทำ ...

void foo(int UNUSED(bar)) { ... }

ฉันชอบสิ่งนี้เพราะคุณได้รับข้อผิดพลาดหากคุณลองใช้barในรหัสใดก็ได้เพื่อให้คุณไม่สามารถทิ้งคุณลักษณะไว้โดยไม่ได้ตั้งใจ

และสำหรับฟังก์ชั่น ...

static void UNUSED_FUNCTION(foo)(int bar) { ... }

หมายเหตุ 1):
เท่าที่ผมรู้ว่า MSVC __attribute__((__unused__))ไม่ได้เทียบเท่ากับ

หมายเหตุ 2):แมโครจะไม่ทำงานสำหรับข้อโต้แย้งที่มีวงเล็บดังนั้นหากคุณมีข้อโต้แย้งเช่น คุณไม่สามารถทำหรือนี่เป็นเพียงข้อเสียกับฉันแมโครพบเพื่อให้ห่างไกลในกรณีเหล่านี้ผมถอยกลับ ถึง
UNUSED
float (*coords)[3]
float UNUSED((*coords)[3])float (*UNUSED(coords))[3]UNUSED(void)coords;


หรืออาจเป็นเพียง#define __attribute__(x)สำหรับสภาพแวดล้อมที่ไม่ใช่ GCC (AFAIK ไม่มี__attribute__MSVC สนับสนุนอยู่บ้าง)
Franklin Yu

ที่สามารถทำงานได้ แต่คำนำหน้า dunder ถูกสงวนไว้สำหรับคอมไพเลอร์ดังนั้นฉันค่อนข้างจะหลีกเลี่ยง
ideasman42

สำหรับ gcc ของฉันอย่างน้อยการวางตัวระบุคุณลักษณะไว้ก่อนที่ตัวระบุจะทำงานได้ดีกับ funcs, vars และพารามิเตอร์ดังนั้นบางอย่างเช่น #define POSSIBLY_UNUSED (ตัวระบุ) แอตทริบิวต์ตัวระบุ__ ((__ ไม่ได้ใช้ )) สามารถใช้ตัวระบุทั้งสาม
Britton Kerin

เมื่อวางไว้หลังจากที่ฉันได้รับwarning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
ideasman42


16

เห็นว่าเรื่องนี้ถูกทำเครื่องหมายเป็น gcc Wno-unused-parameterคุณสามารถใช้สวิตช์บรรทัดคำสั่ง

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

gcc -Wno-unused-parameter test.c

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


7

วิธีเฉพาะ gcc / g ++ เพื่อยับยั้งการเตือนพารามิเตอร์ที่ไม่ได้ใช้สำหรับบล็อกของซอร์สโค้ดคือล้อมรอบด้วยคำสั่ง pragma ต่อไปนี้:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
<code with unused parameters here>
#pragma GCC diagnostic pop

Clang สนับสนุน pragmas สำหรับการวินิจฉัยเหล่านี้เช่นกันclang.llvm.org/docs/…
eush77

4

การติดป้ายกำกับแอตทริบิวต์เป็นวิธีที่เหมาะสมที่สุด MACRO ทำให้เกิดความสับสนในบางครั้ง และโดยการใช้ void (x) เรากำลังเพิ่มโอเวอร์เฮดในการประมวลผล

หากไม่ได้ใช้อาร์กิวเมนต์อินพุตให้ใช้

void foo(int __attribute__((unused))key)
{
}

หากไม่ได้ใช้ตัวแปรที่กำหนดไว้ภายในฟังก์ชั่น

void foo(int key)
{
   int hash = 0;
   int bkt __attribute__((unused)) = 0;

   api_call(x, hash, bkt);
}

หลังจากนี้ใช้ตัวแปรแฮชสำหรับตรรกะของคุณ แต่ไม่ต้องการ bkt กำหนด bkt เป็นไม่ได้ใช้มิฉะนั้นคอมไพเลอร์ say'bkt set bt ไม่ได้ใช้

หมายเหตุ: นี่เป็นเพียงการระงับคำเตือนไม่ใช่เพื่อการปรับให้เหมาะสม


1
คุณไม่ต้องเพิ่มโอเวอร์เฮดในการประมวลผลโดยใช้void(x)คอมไพเลอร์จะปรับมันให้เหมาะสม
Majora320

4

ฉันมีปัญหาเดียวกัน ฉันใช้ห้องสมุดส่วนที่สาม เมื่อฉันรวบรวมไลบรารีนี้คอมไพเลอร์ (gcc / clang) จะบ่นเกี่ยวกับตัวแปรที่ไม่ได้ใช้

แบบนี้

test.cpp: 29: 11: คำเตือน: ชุดตัวแปร 'magic' แต่ไม่ได้ใช้ [-Wunused-but-set-variable] short magic [] = {

test.cpp: 84: 17: คำเตือน: ตัวแปรที่ไม่ได้ใช้ 'before_write' [-Wunused-variable] int64_t before_write = หัวข้อ :: currentTimeMillis ();

ดังนั้นการแก้ปัญหาค่อนข้างชัดเจน การเพิ่ม-Wno-unusedเป็น gcc / clang CFLAG จะหยุดการเตือน "ไม่ได้ใช้" ทั้งหมดแม้จะคิดว่าคุณได้-Wallตั้งไว้แล้ว

ด้วยวิธีนี้คุณไม่จำเป็นต้องเปลี่ยนรหัสใด ๆ


1
นี่เป็นเรื่องปกติถ้าคุณต้องการเพิกเฉยต่อคำเตือนที่ไม่ได้ใช้ทั้งหมด แต่ก็ไม่เป็นเช่นนั้น โดยปกติจะเป็นเพียงกรณีเฉพาะที่คุณต้องการเพิกเฉย
Dan Bechard

1

ใน MSVC เพื่อยับยั้งการเตือนเฉพาะมันก็เพียงพอที่จะระบุจำนวนมันเพื่อคอมไพเลอร์เป็น / wd # CMakeLists.txt ของฉันมีบล็อกดังกล่าว:

If (MSVC)
    Set (CMAKE_EXE_LINKER_FLAGS "$ {CMAKE_EXE_LINKER_FLAGS} / NODEFAULTLIB: LIBCMT")
    Add_definitions (/W4 /wd4512 /wd4702 /wd4100 /wd4510 /wd4355 /wd4127)
    Add_definitions (/D_CRT_SECURE_NO_WARNINGS)
Elseif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC)
    Add_definitions (-Wall -W -pedantic)
Else ()
    Message ("Unknown compiler")
Endif ()

ตอนนี้ฉันไม่สามารถพูดในสิ่งที่แน่นอน / wd4512 / wd4702 / wd4100 / wd4510 / wd4355 / wd4127 หมายความว่าเพราะฉันไม่ได้สนใจ MSVC เป็นเวลาสามปี แต่พวกเขาหยุดยั้งคำเตือนที่ยิ่งใหญ่


0

ฉันเคยเห็นรูปแบบนี้ถูกใช้:

if (when || who || format || data || len);

14
ฮึ่ม ฉันไม่สามารถพูดได้ว่าฉันชอบสิ่งนี้เพราะถือว่าพารามิเตอร์ทั้งหมดที่เกี่ยวข้องสามารถแปลงเป็นบูลได้
Suma

1
นี่ไม่ใช่การประชุมที่ดีจริงๆแม้ว่าคอมไพเลอร์จะปรับให้เหมาะสม แต่ก็ไม่ชัดเจนว่าเกิดอะไรขึ้นและอาจสร้างความสับสนให้กับตัวตรวจสอบแหล่งที่มาแบบคงที่ ดีกว่าใช้หนึ่งในคำแนะนำอื่น ๆ ที่นี่ IMHO
ideasman42

1
ฉันไม่อยากจะเชื่อเลยว่าฉันยังคงได้รับคำตอบจากสิ่งนี้ คำถามดังกล่าวระบุว่ามีไว้สำหรับซีใช่ในภาษาอื่นไม่สามารถใช้งานได้
Iustin

2
ฉันจะไม่ใช้มัน แต่ +1 สำหรับปัจจัยแปลกใหม่
mgalgs

2
การตรวจสอบความจริงของตัวแปรสามารถให้คำเตือนสำหรับ structs เช่น. struct { int a; } b = {1}; if (b);GCC เตือน, used struct type value where scalar is required.
ideasman42

-1

สำหรับบันทึกฉันชอบคำตอบของ Job ด้านบน แต่ฉันอยากรู้เกี่ยวกับวิธีแก้ปัญหาโดยใช้ชื่อตัวแปรด้วยตัวเองในคำสั่ง "do-nothing":

void foo(int x) {
    x; /* unused */
    ...
}

แน่นอนว่านี่มีข้อเสีย; ตัวอย่างเช่นหากไม่มีโน้ต "ที่ไม่ได้ใช้" จะดูเหมือนว่าเป็นข้อผิดพลาดแทนที่จะเป็นโค้ดที่มีเจตนา

ประโยชน์คือไม่จำเป็นต้องกำหนด DEFINE และกำจัดคำเตือน

มีประสิทธิภาพการเพิ่มประสิทธิภาพหรือความแตกต่างอื่น ๆ หรือไม่?


2
ฉันใช้สิ่งนี้กับ MSVC แต่ GCC แจ้งเตือนคำสั่ง "ไม่มีผล" ดังนั้นทางออกของ Job จึงเป็นไปได้
Dmitrii Semikin

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