In the ARM C/C++ Language Implementation Guide (p 99), NOINIT is listed as a pragma directive. In the previous code that I'm working with, __no_init was defined as an intrinsic function (IAR compiler for MSP430). I understand that intrinsic functions are sets of assembly code that are convenient to not have to attempt to translate to C, but what I don't understand is how an intrinsic function is different than a #pragma, and why #pragma NOINIT could be the intrinsic __no_init in a different compiler. What specifically makes #pragma directives and intrinsic functions different?
(I speak generally, and hedge a bit because languages do differ...)
Keywords are usually recognized by the grammar of the language. This is a fundamental level of recognition. (Without keywords, parsing would be more difficult; error messages in the face of minor syntax errors much harder to deliver, etc...)
Keywords are usually fully reserved, which means (generally), for example, that you cannot declare a variable of the same identifier as a keyword, no matter the scope or context. E.g., we (generally) cannot name variables as
while since keywords tend to be reserved for the language and not the user.
By contrast, functions are just declarations that obey the scoping rules. So, the identifiers allowed for user-defined variables in one scope can be reused with different meanings (for different variables) in different contexts aka different scopes.
Depending on the language, of course, intrinsic functions are just built-in function declarations entered into the global scope and that happen to precede your code. Intrinsic functions don't alter the grammar of the language. As ordinary declarations (albeit built-in), you can (theoretically) reuse these identifier in another scope for a different purpose. So, if you have an intrinsic function named
__atomicIncrement, for example, you ought to be able to redeclare that same identifier with a different meaning in an inner scope, just as local variable declarations can typically reuse identifiers used in global declarations (modulo specific language and/or compiler behaviors).
__no_init in the IAR compilers is being treated like a keyword, not a function (intrinsic or otherwise). It is similar to the
volatile keyword, which modifies the the variable in that declaration.
volatile affects the code generation but in more ways that merely invoking intrinsic functions could, because the compilers not only use alternate code sequences to read and write the
volatiles (which could potentially be accomplished with intrinsic functions if you used them at each access of the variable) but also change (i.e. restrict) their optimization strategies for code neighboring them (i.e. the more ordinary code that precedes and succeeds a volatile access).)
So, in one compiler a pragma is used and in another a keyword, both to accomplish the modification of the declaration (and both as extensions, though the keyword version actually extends the language grammar whereas the pragma version fits within existing language grammar). In this case, neither involves an intrinsic function.