Author: Little Friend bird

A, the Attribute

Attributes are a feature of GNU C. So what is this thing for iOS?

  • This is a compiler instruction that can declare properties for objects or functions in order for the compiler to do more error checking and optimizations.
  • Function Attribute, Variable Attribute and Type Attribute can be set.

Instructions in Swift documentation:

Attributes provide more information about a declaration or type. There are two kinds of attributes in Swift, those that apply to declarations and those that apply to types.

Property provides more information about the declaration or type. There are two types of attributes in Swift, one for declarations and one for types.

Reference: the Attributes

Two, use method

Here is a list of how to use it and what the general scenario is.

1, memory alignment, depth optimization

// Aligned adjusts the number of bits per line in memory alignment
// If the value is less than 4, the compiler automatically optimizes to 4
// The maximum value can be 8
struct stu{
    char sex;
    int length;
    char name[2];
    char value[16];
}__attribute__((aligned(16)));

struct stu my_stu;

NSLog(@"%lu".sizeof(my_stu));
NSLog(@"%p %p,%p,%p", &my_stu,&my_stu.length,&my_stu.name,&my_stu.value);
NSLog(@"Hello, World!");
Copy the code

2. Enforce inlining

Reduce function calls, but note that recursive methods cannot be inlined.

// If __attribute__((always_inline)) is used
// Assembler will reduce callq methods
__attribute__((always_inline)) void inlineFunction(a){
    int a = 10; a+= 10;
}

void testInline(a){
    inlineFunction(a); }testInline(a);Copy the code

For both of these, you can always trust the compiler, except when it deceives you. Then try to optimize it again.

3, standard reminder

Remind others not to do this by warning or reporting an error!

/* OC can be used with #param mark-xxxx swift with # mark-xxxxx */
// Add this to an overridden method in the parent class, and the compiler will remind the subclass to call [super] in the overridden method.
__attribute__((objc_requires_spuer))



//deprecated(gnu::deprecated)
// Deprecated API
// The first argument is the deprecated message, and the second is the function suggested to replace it
void func(void) __attribute__((deprecated("message"."replacement")));



// Diagnose_if adds conditions that need to be met in function calls, and alerts or alerts are issued at compile time
// No runtime warnings are issued.
int  tabs(int a)
__attribute__((diagnose_if(a >= 0."Redundant abs call"."warning")));

int must_abs(int a)
__attribute__((diagnose_if(a >= 0."Redundant abs call"."error")));

int val = tabs(1);    //warning
int val2 = must_abs(1);//error
int val3 = tabs(val);//nothing
int val4 = must_abs(val);//nothing


//enable_if, which is the opposite of diagnose_if
void func(int a)__attribute__((enable_if(a>0 && a<120."I am xx"))) {
    NSLog(@"11:%d",a);
}

func(1000); Matching function for call to 'func'
Copy the code

4. Grammar conversion

// Convert struct and union to NSValue
// __attribute__((objc_boxable))
// Then you can use NSValue syntactic sugar.
struct __attribute__((objc_boxable)) _people {
    int year;
    NSString *name;
};

union __attribute__((objc_boxable)) _student {
    int class;
};

typedef struct __attribute__((objc_boxable)) _people people;
people p;
NSValue *boxed = @(p);
Copy the code

5. Black Magic

For details about what you want to do, see the following example.

// constructor/destructor, which can be called before and after main
// Constructor is called a little later than the load method
// Destructor will call before the exit function.
// Their call priority can be adjusted. The next parameter is the priority
// __attribute_((constructor(101))) [0-100] is reserved by the system
// Constructor can be used to do very bad things because the load method has already been loaded and memory already contains information about the loaded class.
__attribute__((constructor))
void funca(a){
    print("beforeMain");
}

__attribute__((destructor))
void funcb(a){
    print(@"beforeExit");
}

/* The rest is up to the imagination, 😂 */
Copy the code

When the scope of the listening variable ends, the specified function is called.

// Used on an object to call a specified function when the scope of the variable ends
// Call time is earlier than dealloc
// End of scope includes: return, goto, break, exception
// Make sure the incoming type is the same
__attribute__((cleanup(func)))

void func(__strong NSString **value){
    NSLog(*value);
}

int main(a) {
    // This will output Hello world
    NSString *str __attribute__((cleanup(func))) = @"hello world";
    return 0;
}
Copy the code
  • The example of the @onExit macro in ReactiveCocoa, as well as in SDWebImage, looks a lot like defer in Swift.
// the pointer to void(^*block)(void)
static inline void blockCleanUp(__strong void(^*block)(void)) {
    (*block)();
}

/ / define onExit
#define onExit __strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^

// The usage mode
onExit {
    NSLog(@"I output last!");
}
Copy the code

6, confusion reinforcement

This can be used for compilation hardening, but it may affect some dynamic calls, so be careful.

// Can be used on interface and protocol to change the class name or protocol name to the specified name at compile time
__attribute__((objc_runtime_name("xxx")))
Copy the code

7, declare function does not return

  • Indicates that the function is not returned to the caller after completion of execution. The exit() function is an example of a _Noreturn function that does not proceed once exit() is called.
  • Unlike void, void returns the caller at the end of execution, except that it does not provide a return value.
_Noreturn void func(int a ){
    print(a)
}
Copy the code
  • An example from AFNetworking,__attribute__((noreturn))Similar to the Swift function that returns a value of type Never.
// Start an NSRunLoop when generating separate network NSthreads to ensure that the separated threads continue to execute for the life of the application.
+ (void) __attribute__((noreturn)) networkRequestThreadEntryPoint:(id)__unused object {
    do{ @autoreleasepool { [[NSRunLoop currentRunLoop] run]; }}while (YES);
}
Copy the code

8. Judgment check

//__has_attribute is used to check whether an attribute exists
#if __has_feature(attribute_ns_returns_retained)
    #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
#else
    #define NS_RETURNS_RETAINED
#endif
Copy the code

9. Forbid derivative subclasses

// If you add a subclass to a class, the class cannot add a subclass. If you add a subclass, the compiler will fail.
__attribute__((objc_subclassing_restricted))
@interface Person: NSObject
Copy the code

New clang features

1. New deprecation declaration

Added more parameters:

  • introducedFor the first time to define
  • deprecatedDeprecated version
  • obsoletedAbandoned version
  • unavailableThe platform is invalid
  • message=string-literalHints in deprecated or deprecated versions
  • replacement=string-literalSubstitution of this API
void func(void) __attribute__((availability(macos,introduced=10.4,deprecated=10.6,obsoleted=10.7)));
// Does this argument list feel like @#available()?
Copy the code

2, C override a C++ function

// Override a C++ function in C. Function overloading in C is introduced using reloadable properties.
__attribute__((overloadable)))

#include <math.h>

float __attribute__((overloadable)) tgsin(float x) { 
    return sinf(x); 
}

double __attribute__((overloadable)) tgsin(double x) { 
    return sin(x); 
}

long double __attribute__((overloadable)) tgsin(long double x) { 
    return sinl(x); 
}
Copy the code

Allocate pointer space ahead of time

Optimizes the big guy special.

// alloc_size needs to be used with __builtin_object_size
// alloc_size can take at most two parameters, which specify the number of parameters in the function
// Depending on the size of the value we pass in, what is retrieved from __builtin_object_size
// If there are two arguments, then it is the result of multiplying the sizes of the two arguments.
// The size of the pointer is bound

void *my_malloc(int a) __attribute__((alloc_size(1)));
void *my_callocd(int a, int b, int m) __attribute__((alloc_size(1.3)));
void *my_malloc(int a) {
    return NULL;
}
void *my_callocd(int a, int b, int m){
    return NULL;
}

void *const p = my_malloc(100);
NSLog(@"%d", __builtin_object_size(p,1));

void *const a = my_callocd(20.3.5);
NSLog(@"%d", __builtin_object_size(a,2));
Copy the code

Four, summary

There are many, many uses of Attribute that are not listed because there are too many.

Think of it as a little study note on the front end of the compiler. The compiler, one of the three romances of computing, is not easily conquered.

Three romances of the computer

  • Compilation principle
  • The operating system
  • graphics

Welcome to join us in the comments section

Stay with us for more updates on iOS and industry technology

Five, the reference

  1. Attributes — The Swift Programming Language (Swift 5.5)
  2. The Attribute usage 1
  3. The Attribute usage 2
  4. The Attribute description
  5. GCC Documentation
  6. CPP documentation
  7. The use of the cleanup
  8. The specification of noreturn
  9. Fantastic macro magic in ReactiveCocoa