The attribute is an extension of gcc and does not belong to standard C language.
Using attributes can modify the properties of variables, functions, or data types, and there are many attributes, some of which are indeed very useful.
I found a few attributes that can modify functions for your reference.
If you want a function to execute before the main function, you can use the constructor attribute, which means construction.
If you want a function to execute after the main function, you can use the destructor attribute, which has a meaning similar to destruction.
Some online introductions use these two attributes to simulate C++ constructors and destructors. To be honest, this is far from the constructors and destructors in C++. However, it can still be used for some initialization and cleanup operations in the program.
The second one is nonnull.
When writing functions, we often perform parameter checks to prevent the passed parameters from being null pointers, which could lead to exceptions in the program.
Using the nonnull attribute allows the compiler to check. If the passed parameter is NULL, a warning will be prompted during compilation, which is very user-friendly.
The third one is deprecated.
If you want to deprecate a function, for example, not to use it in future versions of the project, you can use the deprecated attribute. By adding this attribute, if you still use this function, a warning will be prompted during compilation.
For example, the common gets function, if it is suddenly removed from the standard library, it would not be friendly to older programs, so it can only be reminded.
The fourth one is noreturn.
For functions that do not return, you can use the noreturn attribute. Note that a return value of void type and a function that does not return are two different things; such code will prompt a warning during compilation.
If you add an infinite loop or exit within the function, such a function is considered not to return.
The fifth one is weak, used to define weak functions.
For example, if a weak function is defined in one file, another file can completely redefine it, and the compiler will automatically link to the newly defined user function.
The weak attribute appears frequently on STM32, such as interrupt functions, etc.
There are many attributes extended by gcc; opening the gcc documentation, I roughly estimated that there might be around a hundred.
Perhaps C language also found these attributes useful, as the latest C23 standard has also introduced the concept of attributes, but the usage is quite peculiar, using two nested square brackets, and currently, the supported attributes are also relatively few.
The compiler has always been ahead of the standards; perhaps in some future C language standard, more gcc attributes will be added to C language.