Làm thế nào để triệt tiêu các cảnh báo không sử dụng của Cảnh báo trong C?


210

Ví dụ:

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

Trong C ++ tôi đã có thể đưa ra một /*...*/nhận xét xung quanh các tham số. Nhưng tất nhiên không phải ở C, nơi nó cho tôi lỗi error: parameter name omitted.



4
@CiroSantilli Câu hỏi này có nhiều upvote hơn, tốt hơn là đánh dấu câu hỏi khác là trùng lặp.
sashoalm


-Wno-unused-parameter, nó quá ồn ào và hiếm khi bắt lỗi đặc biệt. khi -Wshadowđược sử dụng
Trass3r

Câu trả lời:


297

Tôi thường viết một macro như thế này:

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

Bạn có thể sử dụng macro này cho tất cả các tham số không sử dụng của bạn. (Lưu ý rằng điều này hoạt động trên bất kỳ trình biên dịch.)

Ví dụ:

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

45
Tôi chỉ sử dụng (void) x trực tiếp
Giáo sư Falken

6
Mặc dù đây là cách di động duy nhất AFAIK, nhưng điều khó chịu với điều này là nó có thể gây hiểu lầm nếu bạn sử dụng biến sau đó và quên ro xóa dòng không sử dụng. đây là lý do tại sao không sử dụng GCC là tốt đẹp.
ideaman42

6
@CookSchelling: Ah nhưng bạn không nên sử dụng nó như thế. Làm một cái gì đó như thế này : void f(int x) {UNUSED(x);}.
Công việc

9
@Alcott vì (như trong trường hợp của tôi), hàm có thể là một trong số nhiều chữ ký phải có cùng chữ ký vì chúng được tham chiếu bởi một con trỏ hàm.
josch

17
Tôi đang sử dụng #define UNUSED(...) (void)(__VA_ARGS__)cho phép tôi áp dụng điều này cho nhiều biến.
Matthew Mitchell

110

Trong gcc, bạn có thể gắn nhãn tham số với unusedthuộc tính .

Thuộc tính này, được gắn vào một biến, có nghĩa là biến đó có nghĩa là có thể không được sử dụng. GCC sẽ không đưa ra cảnh báo cho biến này.

Trong thực tế điều này được thực hiện bằng cách đặt __attribute__ ((unused))ngay trước tham số. Ví dụ:

void foo(workerid_t workerId) { }

trở thành

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

24
Đối với bất kỳ người mới như tôi, điều này có nghĩa là đặt __attribute__ ((unused))trước đối số.
josch

2
@josch Tôi nghĩ bạn hoàn toàn chính xác, nhưng tài liệu dường như ngụ ý rằng nó nên được đặt sau tham số. Cả hai tùy chọn có thể được hỗ trợ mà không có vấn đề.
Antonio

Cũng lưu ý rằng đó __attribute__((unused))một phần mở rộng GCC độc quyền . Nó được hỗ trợ bởi một số trình biên dịch khác, nhưng tôi cho rằng điều này sẽ không hoạt động với MSVC. Tuy nhiên, đây không phải là một phần của tiêu chuẩn trình biên dịch, vì vậy đây không phải là khả năng di động như một số tùy chọn khác
Zoe

58

Bạn có thể sử dụng thuộc tính không sử dụng của gcc / clang, tuy nhiên tôi sử dụng các macro này trong một tiêu đề để tránh có các thuộc tính cụ thể của gcc trên toàn bộ nguồn, cũng có __attribute__ở mọi nơi là hơi dài dòng / xấu xí.

#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

Sau đó, bạn có thể làm ...

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

Tôi thích điều này bởi vì bạn gặp lỗi nếu bạn thử sử dụng barmã ở bất cứ đâu để bạn không thể bỏ qua thuộc tính.

và cho các chức năng ...

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

Lưu ý 1):
Theo như tôi biết, MSVC không có tương đương __attribute__((__unused__)).

Lưu ý 2):
Các UNUSEDmacro sẽ không làm việc cho các đối số có chứa dấu ngoặc đơn,
vì vậy nếu bạn có một cuộc tranh cãi như float (*coords)[3] bạn không thể làm,
float UNUSED((*coords)[3])hoặc float (*UNUSED(coords))[3], Đây là Nhược điểm duy nhất để UNUSEDtôi tìm thấy vĩ mô cho đến nay, trong những trường hợp này tôi rơi trở lại đến(void)coords;


Hoặc có thể chỉ #define __attribute__(x)dành cho môi trường không phải GCC (AFAIK không ai trong số __attribute__đó được MSVC hỗ trợ)?
Franklin Yu

Điều đó có thể hoạt động, nhưng các thuật ngữ tiền tố dunder được dành riêng cho trình biên dịch vì vậy tôi muốn tránh điều này.
ideaman42

Đối với gcc của tôi, ít nhất là đặt trình xác định thuộc tính trước khi mã định danh dường như hoạt động đúng với funcs, vars và tham số, do đó, có thể sử dụng mã định danh #define POSSIBLY_UNUSED (định danh) __ ((không sử dụng )) cho cả ba
Britton Kerin

Khi đặt nó sau khi tôi nhận được warning: unused parameter ‘foo’ [-Wunused-parameter](gcc 7.3.0)
ideaman42

19

Với gcc với thuộc tính không sử dụng:

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

16

Thấy rằng điều này được đánh dấu là gcc, bạn có thể sử dụng chuyển đổi dòng lệnh Wno-unused-parameter.

Ví dụ:

gcc -Wno-unused-parameter test.c

Tất nhiên, điều này ảnh hưởng đến toàn bộ tệp (và có thể dự án tùy thuộc vào nơi bạn đặt công tắc) nhưng bạn không phải thay đổi bất kỳ mã nào.


7

Một cách cụ thể của gcc / g ++ để triệt tiêu cảnh báo tham số không sử dụng cho một khối mã nguồn là kèm theo nó với các câu lệnh pragma sau:

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

Clang cũng hỗ trợ các pragma
eush77

4

Dán nhãn thuộc tính là cách lý tưởng. MACRO đôi khi dẫn đến sự nhầm lẫn. và bằng cách sử dụng void (x), chúng tôi sẽ thêm một chi phí xử lý.

Nếu không sử dụng đối số đầu vào, hãy sử dụng

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

Nếu không sử dụng biến được định nghĩa bên trong hàm

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

   api_call(x, hash, bkt);
}

Bây giờ sau đó sử dụng biến băm cho logic của bạn nhưng không cần bkt. định nghĩa bkt là không sử dụng, nếu không trình biên dịch nói 'bkt đặt bt không được sử dụng ".

LƯU Ý: Đây chỉ là để loại bỏ cảnh báo không phải để tối ưu hóa.


1
Bạn không thêm bất kỳ chi phí nào trong quá trình xử lý bằng cách sử dụng void(x), trình biên dịch sẽ tối ưu hóa nó.
Majora320

4

Tôi đã có cùng một vấn đề. Tôi đã sử dụng một thư viện phần thứ ba. Khi tôi biên dịch thư viện này, trình biên dịch (gcc / clang) sẽ phàn nàn về các biến không sử dụng.

Như thế này

test.cpp: 29: 11: cảnh báo: biến 'ma thuật' được đặt nhưng không được sử dụng [-Wunuse-but-set-biến] ma thuật ngắn [] = {

test.cpp: 84: 17: cảnh báo: biến không được sử dụng 'before_write' [-Wunuse-biến] int64_t before_write = Thread :: currentTimeMillis ();

Vì vậy, giải pháp là khá rõ ràng. Thêm -Wno-unuseddưới dạng gcc / clang CFLAG sẽ loại bỏ tất cả các cảnh báo "không sử dụng", thậm chí nghĩ rằng bạn đã -Wallđặt.

Theo cách này, bạn KHÔNG CẦN thay đổi bất kỳ mã nào.


1
Điều này tốt nếu bạn thực sự muốn bỏ qua tất cả các cảnh báo không sử dụng, nhưng điều đó gần như không bao giờ xảy ra. Nó thường chỉ là những trường hợp cụ thể mà bạn muốn bỏ qua.
Dan Bechard

1

Trong MSVC để loại bỏ một cảnh báo cụ thể, đủ để chỉ định số của nó cho trình biên dịch là / wd #. CMakeLists.txt của tôi chứa khối như vậy:

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

Bây giờ tôi không thể nói chính xác / wd4512 / wd4702 / wd4100 / wd4510 / wd4355 / wd4127 nghĩa là gì, bởi vì tôi không chú ý đến MSVC trong ba năm, nhưng chúng ngăn chặn các cảnh báo siêu lớn không ảnh hưởng đến kết quả.


0

Tôi đã thấy phong cách này đang được sử dụng:

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

14
Hừm. Tôi không thể nói rằng tôi thích điều này, vì điều này giả sử tất cả các tham số có thể được chuyển đổi thành một bool.
Suma

1
Đây thực sự không phải là một quy ước tốt, mặc dù trình biên dịch gần như chắc chắn sẽ tối ưu hóa nó, nhưng nó không thực sự rõ ràng những gì đang xảy ra và có thể gây nhầm lẫn cho trình kiểm tra nguồn tĩnh. sử dụng tốt hơn một trong những gợi ý khác ở đây IMHO.
ideaman42

1
Tôi không thể tin rằng tôi vẫn nhận được trả lời cho điều này. Câu hỏi nói rằng nó dành cho C. Có, trong một ngôn ngữ khác, nó sẽ không hoạt động.
Iustin 17/03/13

2
Tôi sẽ không sử dụng nó nhưng +1 cho yếu tố mới lạ.
mgasms

2
kiểm tra sự thật của các biến có thể đưa ra cảnh báo, cho các cấu trúc. ví dụ. struct { int a; } b = {1}; if (b);GCC cảnh báo used struct type value where scalar is required,.
ideaman42

-1

Đối với hồ sơ, tôi thích câu trả lời của Gióp ở trên nhưng tôi tò mò về một giải pháp chỉ sử dụng tên biến trong chính câu lệnh "không làm gì":

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

Chắc chắn, điều này có nhược điểm; ví dụ, không có ghi chú "không sử dụng", nó trông giống như một lỗi thay vì một dòng mã có chủ ý.

Lợi ích là không cần DEFINE và nó được loại bỏ cảnh báo.

Có bất kỳ hiệu suất, tối ưu hóa, hoặc sự khác biệt khác?


2
Tôi đã sử dụng điều này với MSVC, nhưng GCC đưa ra cảnh báo "tuyên bố không có hiệu lực". Vì vậy, giải pháp của công việc là con đường để đi.
Dmitrii Semikin

Cách tiếp cận này vẫn tạo cảnh báo trong XCode
MOK9
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.