Bagaimana cara menekan peringatan "parameter yang tidak digunakan" di C?

210

Misalnya:

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

Di C ++ saya bisa memberikan /*...*/komentar di sekitar parameter. Tetapi tidak dalam C tentu saja, di mana itu memberi saya kesalahan error: parameter name omitted.

nixgadget
sumber
kemungkinan duplikat dari Apa cara terbaik untuk menekan "Peringatan variabel x yang tidak digunakan"
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
4
@CiroSantilli Pertanyaan ini memiliki lebih banyak suara, akan lebih baik untuk menandai pertanyaan lain sebagai duplikat.
sashoalm
1
Lihat juga versi C ++ dari pertanyaan ini
Shafik Yaghmour
-Wno-unused-parameter, itu terlalu berisik dan jarang menangkap bug esp. kapan -Wshadowdigunakan
Trass3r

Jawaban:

297

Saya biasanya menulis makro seperti ini:

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

Anda dapat menggunakan makro ini untuk semua parameter yang tidak digunakan. (Perhatikan bahwa ini bekerja pada kompiler apa pun.)

Sebagai contoh:

void f(int x) {
    UNUSED(x);
    ...
}
Pekerjaan
sumber
45
Saya hanya menggunakan (void) x langsung
Prof. Falken
6
sementara ini adalah satu-satunya cara AFAIK portabel, gangguan dengan ini adalah dapat menyesatkan jika Anda menggunakan variabel nanti dan lupa untuk menghapus garis yang tidak digunakan. inilah mengapa GCC yang tidak digunakan itu bagus.
ideasman42
6
@CookSchelling: Ah tapi Anda tidak boleh menggunakannya seperti itu. Melakukan sesuatu seperti ini: void f(int x) {UNUSED(x);}.
Pekerjaan
9
@Alcott karena (seperti dalam kasus saya) fungsi mungkin salah satu dari banyak yang harus memiliki tanda tangan yang sama karena mereka dirujuk oleh pointer fungsi.
josch
17
Saya menggunakan #define UNUSED(...) (void)(__VA_ARGS__)yang memungkinkan saya untuk menerapkan ini ke beberapa variabel.
Matthew Mitchell
110

Di gcc, Anda dapat memberi label parameter dengan unusedatribut .

Atribut ini, melekat pada variabel, berarti bahwa variabel dimaksudkan untuk menjadi mungkin tidak terpakai. GCC tidak akan menghasilkan peringatan untuk variabel ini.

Dalam praktiknya ini dilakukan dengan meletakkan __attribute__ ((unused))tepat sebelum parameter. Sebagai contoh:

void foo(workerid_t workerId) { }

menjadi

void foo(__attribute__((unused)) workerid_t workerId) { }
Aliran
sumber
24
Untuk pemula seperti saya, ini berarti menempatkan __attribute__ ((unused))di depan argumen.
josch
2
@ josch Saya pikir Anda benar-benar benar, tetapi dokumentasi tampaknya menyiratkan bahwa itu harus diletakkan setelah parameter. Kedua opsi mungkin didukung tanpa masalah.
Antonio
Perhatikan juga bahwa itu __attribute__((unused))adalah ekstensi GCC eksklusif . Ini didukung oleh beberapa kompiler lain, tetapi saya berasumsi ini tidak akan bekerja dengan MSVC. Ini bukan langsung bagian dari standar kompiler, jadi ini tidak portabel seperti beberapa opsi lain
Zoe
58

Anda dapat menggunakan atribut gcc / clang yang tidak digunakan, namun saya menggunakan makro ini di header untuk menghindari memiliki atribut spesifik gcc di seluruh sumber, juga memiliki di __attribute__mana - mana sedikit verbose / jelek.

#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

Maka kamu bisa melakukan ...

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

Saya lebih suka ini karena Anda mendapatkan kesalahan jika Anda mencoba menggunakan barkode di mana saja sehingga Anda tidak dapat meninggalkan atribut secara tidak sengaja.

dan untuk fungsi ...

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

Catatan 1):
Sejauh yang saya tahu, MSVC tidak memiliki yang setara dengan __attribute__((__unused__)).

Catatan 2):
The UNUSEDmakro tidak akan bekerja untuk argumen yang mengandung kurung,
jadi jika Anda memiliki argumen seperti float (*coords)[3] Anda tidak dapat melakukan,
float UNUSED((*coords)[3])atau float (*UNUSED(coords))[3], ini adalah satu-satunya downside ke UNUSEDmakro saya menemukan sejauh ini, dalam kasus ini saya jatuh kembali untuk(void)coords;

gagasanman42
sumber
Atau mungkin hanya #define __attribute__(x)untuk lingkungan non-GCC (AFAIK tidak ada __attribute__yang didukung oleh MSVC)?
Franklin Yu
Itu bisa bekerja, tetapi istilah awalan dunder dicadangkan untuk kompiler jadi saya lebih suka menghindari ini.
ideasman42
Untuk gcc saya, paling tidak menempatkan penspesifikasi atribut sebelum pengenal tampaknya berfungsi dengan benar untuk funcs, vars, dan parameter, jadi sesuatu seperti #define POSSIBLY_UNUSED (pengidentifikasi) atribut pengidentifikasi __ ((__tidak digunakan )) dapat digunakan untuk ketiga
Britton Kerin
Ketika meletakkannya setelah saya dapatkan warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
ideasman42
19

Dengan gcc dengan atribut yang tidak digunakan:

int foo (__attribute__((unused)) int bar) {
    return 0;
}
Teddy
sumber
16

Melihat ini ditandai sebagai gcc, Anda dapat menggunakan sakelar baris perintah Wno-unused-parameter.

Sebagai contoh:

gcc -Wno-unused-parameter test.c

Tentu saja ini mempengaruhi keseluruhan file (dan mungkin memproyeksikan tergantung di mana Anda mengatur sakelar) tetapi Anda tidak perlu mengubah kode apa pun.

Paul Hutchinson
sumber
7

Cara khusus gcc / g ++ untuk menekan peringatan parameter yang tidak digunakan untuk blok kode sumber adalah melampirkannya dengan pernyataan pragma berikut:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
<code with unused parameters here>
#pragma GCC diagnostic pop
Tenang
sumber
Clang juga mendukung pragma diagnostik ini clang.llvm.org/docs/…
eush77
4

Memberi label pada atribut adalah cara yang ideal. MACRO terkadang menyebabkan kebingungan. dan dengan menggunakan void (x), kami menambahkan overhead dalam pemrosesan.

Jika tidak menggunakan argumen input, gunakan

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

Jika tidak menggunakan variabel yang ditentukan di dalam fungsi

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

   api_call(x, hash, bkt);
}

Sekarang nanti gunakan variabel hash untuk logika Anda tetapi tidak perlu bkt. mendefinisikan bkt sebagai tidak digunakan, jika tidak kompiler mengatakan 'set bt tidak digunakan ".

CATATAN: Ini hanya untuk menekan peringatan bukan untuk optimisasi.

pengguna2452561
sumber
1
Anda tidak menambahkan overhead dalam pemrosesan dengan menggunakan void(x), kompiler akan mengoptimalkannya.
Majora320
4

Saya mendapat masalah yang sama. Saya menggunakan perpustakaan bagian ketiga. Ketika saya mengkompilasi perpustakaan ini, kompiler (gcc / dentang) akan mengeluh tentang variabel yang tidak digunakan.

Seperti ini

test.cpp: 29:11: peringatan: set variabel 'magic' tetapi tidak digunakan [-Wunused-but-set-variable] sihir pendek [] = {

test.cpp: 84: 17: peringatan: variabel yang tidak digunakan 'before_write' [-Wunused-variable] int64_t before_write = Utas :: currentTimeMillis ();

Jadi solusinya cukup jelas. Menambahkan -Wno-unusedsebagai gcc / dentang CFLAG akan menekan semua peringatan "tidak digunakan", bahkan jika Anda telah -Wallmenetapkannya.

Dengan cara ini, Anda TIDAK PERLU mengubah kode apa pun.

landerlyoung
sumber
1
Ini bagus jika Anda benar-benar ingin mengabaikan semua peringatan yang tidak digunakan, tapi itu hampir tidak pernah terjadi. Ini biasanya hanya contoh spesifik yang ingin Anda abaikan.
Dan Bechard
1

Dalam MSVC untuk menekan peringatan tertentu sudah cukup untuk menentukan nomor itu untuk dikompilasi sebagai / wd #. CMakeLists.txt saya berisi blok seperti itu:

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 ()

Sekarang saya tidak bisa mengatakan apa sebenarnya / wd4512 / wd4702 / wd4100 / wd4510 / wd4355 / wd4127 artinya, karena saya tidak memperhatikan MSVC selama tiga tahun, tetapi mereka menekan peringatan superpedantic yang tidak mempengaruhi hasil.

Bwana Sang Guru
sumber
0

Saya telah melihat gaya ini digunakan:

if (when || who || format || data || len);
Iustin
sumber
14
Hm Saya tidak bisa mengatakan saya suka ini, karena ini mengasumsikan semua parameter yang terlibat dapat dikonversi menjadi bool.
Suma
1
Ini sebenarnya bukan konvensi yang bagus, meskipun kompiler hampir pasti akan mengoptimalkannya, tidak terlalu jelas apa yang terjadi dan dapat membingungkan pemeriksa sumber statis. lebih baik gunakan salah satu saran lain di sini IMHO.
ideasman42
1
Saya tidak percaya saya masih mendapatkan balasan untuk ini. Pertanyaannya menyatakan bahwa itu untuk C. Ya, dalam bahasa lain ini tidak akan berhasil.
Iustin
2
Saya tidak akan menggunakannya kecuali +1 untuk faktor kebaruan.
mgalgs
2
memeriksa kebenaran variabel dapat memberikan peringatan, untuk struct. misalnya. struct { int a; } b = {1}; if (b);GCC memperingatkan used struct type value where scalar is required,.
ideasman42
-1

Sebagai catatan, saya suka jawaban Ayub di atas tapi saya ingin tahu tentang solusi hanya menggunakan nama variabel dengan sendirinya dalam pernyataan "tidak melakukan apa-apa":

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

Tentu, ini memiliki kekurangan; misalnya, tanpa catatan "tidak digunakan" itu terlihat seperti kesalahan daripada garis kode yang disengaja.

Keuntungannya adalah bahwa tidak ada DEFINE yang diperlukan dan itu menghilangkan peringatan.

Apakah ada perbedaan kinerja, optimasi, atau lainnya?

Person Person II
sumber
2
Saya juga menggunakan ini dengan MSVC, tetapi GCC memunculkan peringatan "pernyataan tanpa efek". Jadi, solusi Ayub adalah jalan yang harus ditempuh.
Dmitrii Semikin
Pendekatan ini masih menghasilkan peringatan di
XCode