__attribute__((unused)),__attribute__((format(scanf,m,n)))

__attribute__ unused

One of the easiest attributes to use, this marks a variable as intentionally being possibly unused. Not only does this quiet the compiler from issuing an unused-variable warning, it tells the human the same thing: this is intentional.

Of course, it's a good idea to actually remove variables that you're not using, this is not always possible. A common case of the unused int argc parameter to main() is one, as are variables sometimes excluded by conditional compilation.

int main(int argc, char **argv)
{
   /* code that uses argv, but not argc */
}
$ gcc -W test.c
test.c:1: warning: unused parameter 'argc'

The __attribute__ is added just after the variable name, and though it can appear unwieldy, it's a style you can get used to:

int main(int argc __attribute__((unused)), char **argv)
{ ...

Additional uses shown, each with a comment showing the compiler warning it might have generated. Here we assume the code is being compiled without the DEBUG macro being defined, which excludes the actual use of mypid.

/* warning: 'someFunction' declared 'static' but never defined */
static int someFunction() __attribute__((unused));

int main(int argc __attribute__((unused)), char **argv)
{
/* warning: unused variable 'mypid' */
int	mypid __attribute__((unused)) = getpid();

#ifdef DEBUG
	printf("My PID = %d\n", mypid);
#endif

	return 0;
}

__attribute__ format

This __attribute__ allows assigning printf-like or scanf-like characteristics to the declared function, and this enables the compiler to check the format string against the parameters provided throughout the code. This is exceptionally helpful in tracking down hard-to-find bugs.

There are two flavors:

  • __attribute__((format(printf,m,n)))
  • __attribute__((format(scanf,m,n)))

but in practice we use the first one much more often.

The (m) is the number of the "format string" parameter, and (n) is the number of the first variadic parameter. To see some examples:

/* like printf() but to standard error only */
extern void eprintf(const char *format, ...)
	__attribute__((format(printf, 1, 2)));  /* 1=format 2=params */

/* printf only if debugging is at the desired level */
extern void dprintf(int dlevel, const char *format, ...)
	__attribute__((format(printf, 2, 3)));  /* 2=format 3=params */

With the functions so declared, the compiler will examine the argument lists

$ cat test.c
1  extern void eprintf(const char *format, ...)
2               __attribute__((format(printf, 1, 2)));
3
4  void foo()
5  {
6      eprintf("s=%s\n", 5);             /* error on this line */
7
8      eprintf("n=%d,%d,%d\n", 1, 2);    /* error on this line */
9  }

$ cc -Wall -c test.c
test.c: In function `foo':
test.c:6: warning: format argument is not a pointer (arg 2)
test.c:8: warning: too few arguments for format

Note that the "standard" library functions - printf and the like - are already understood by the compiler by default.

__attribute__ noreturn

This attribute tells the compiler that the function won't ever return, and this can be used to suppress errors about code paths not being reached. The C library functions abort() and exit() are both declared with this attribute:

extern void exit(int)   __attribute__((noreturn));
extern void abort(void) __attribute__((noreturn));

Once tagged this way, the compiler can keep track of paths through the code and suppress errors that won't ever happen due to the flow of control never returning after the function call.

In this example, two nearly-identical C source files refer to an "exitnow()" function that never returns, but without the __attribute__ tag, the compiler issues a warning. The compiler is correct here, because it has no way of knowing that control doesn't return.

$ cat test1.c
extern void exitnow();

int foo(int n)
{
        if ( n > 0 )
	{
                exitnow();
		/* control never reaches this point */
	}
        else
                return 0;
}

$ cc -c -Wall test1.c
test1.c: In function `foo':
test1.c:9: warning: this function may return with or without a value

But when we add __attribute__, the compiler suppresses the spurious warning:

$ cat test2.c
extern void exitnow() __attribute__((noreturn));

int foo(int n)
{
        if ( n > 0 )
                exitnow();
        else
                return 0;
}

$ cc -c -Wall test2.c
no warnings!
发布了591 篇原创文章 · 获赞 285 · 访问量 49万+

猜你喜欢

转载自blog.csdn.net/Rong_Toa/article/details/104334875