37

I just now learned about the __unused flag that can be used when compiling with GCC and the more I learn about it, the more questions I have...

Why does this compile without warning/error? It seems strange that I specifically tell the compiler I won't be using a variable, then when I use it, things proceed as normal.

- (void)viewDidLoad
{
    [super viewDidLoad];

    [self foo:0];
}

- (void)foo:(NSInteger)__unused myInt
{
    myInt++;
    NSLog(@"myInt: %d", myInt);  // Logs '1'
}

Also, what is the difference between the following two method signatures?

- (void)foo:(NSInteger)__unused myInt;

- (void)foo:(NSInteger)myInt __unused;
Cœur
  • 37,241
  • 25
  • 195
  • 267
MikeS
  • 3,891
  • 6
  • 35
  • 51
  • 1
    They are equivalent and you can also write `- (void)foo:(__unused NSInteger)myInt;` and `- (void)foo:(NSInteger __unused)myInt;`. – Cœur Apr 25 '16 at 03:09

2 Answers2

82

The __unused macro (which is in fact expanded to the __attribute__((unused)) GCC attribute) only tells the compiler "don't warn me if I don't use this variable".

unused: This attribute, attached to a variable, means that the variable is meant to be possibly unused. GCC does not produce a warning for this variable. (Source: gnu.gcc.org doc)

So this GCC attribute is to avoid a warning when you don't use a variable, and NOT to trigger one when you use the variable you claimed unused.


As regard to putting the attribute before or after the variable name in your last example, both are accepted and equivalent in your case: the compiler is just lenient about that placement for compatibility purposes (quite as you can also write both const int i or int const i)

For compatibility with existing code written for compiler versions that did not implement attributes on nested declarators, some laxity is allowed in the placing of attributes (Source: gnu.gcc.org doc)

AliSoftware
  • 32,623
  • 6
  • 82
  • 77
12

As of Xcode 7.3.1, there is currently no difference between:

- (void)foo:(NSInteger)__unused myInt;// [syntax 1]
- (void)foo:(NSInteger __unused)myInt;// [syntax 2]
- (void)foo:(__unused NSInteger)myInt;// [syntax 3]

But the following doesn't work:

- (void)foo:(NSInteger)myInt __unused;// [doesn't work]

For usage on this, Apple recommends first syntax. (information was partially taken from this answer)

But there is difference between:

__unused NSString *foo, *bar;  // [case a] attribute applies to foo and bar
NSString *foo __unused, *bar;  // [case b] attribute applies to foo only

NSString * __unused foo, *bar; // [case c] attribute applies to foo only
NSString __unused *foo, *bar;  // [case d] attribute applies to foo and bar
CFStringRef __unused foo, bar; // [case e] attribute applies to foo and bar

If we want __unused to apply to all, syntax [a] is my personal best as it leaves no ambiguity.

If we want __unused to apply to one, syntax [b] is my personal best as it leaves no ambiguity.

The latter three solutions are acceptable but confusing in my opinion. (information was partially taken from this answer)


And while we're talking about the order of keywords, kind reminder:

const NSString *foo = bar;  // BAD: foo is NOT const
NSString const *foo = bar;  // BAD: foo is NOT const
NSString *const foo = bar;  // GOOD: foo is const
Cœur
  • 37,241
  • 25
  • 195
  • 267