What does it mean if you put more that one static modifier before a variable? - objective-c

I was just fooling around in Xcode and I discovered that the following statement compiles and it doesn't even raise a warning let alone an error:
static static static int static long static var[5];
What's up with that? Does this make it super-DUPER static? :)
All joking aside, why does the compiler permit repeating the static modifier? Is there actually a reason to allow people to do this or were the people who wrote the compiler too lazy to make this raise an error?

I'm not an Objective-C developer, but does the language allow for an arbitrary ordering of modifiers (e.g. static volatile extern)? If so, then it's probably a benign bug in the compiler that after reading a modifier ("static" in this case) returns to a state where it accepts any modifier terminal again, and will do until it encounters the variable's type. Continual static declarations wouldn't contradict any prior modifiers so it wouldn't raise any errors; so based on this I would expect volatile volatile volatile int x; to also work.

For C 2011, The following applies:
Section 6.7.1 Paragraph 2
At most, one storage-class specifier may be given in the declaration specifiers in a declaration, except that _Thread_local may appear with static or extern.
And storage class specifiers are defined as:
storage-class-specifier:
typedef
extern
static
_Thread_local
auto
register
So for C 2011, that should be illegal.
As to Objective C, I have no idea where to find a language specification, so I can't help you there.

Related

Why declare a C function as static inline?

I came across an example for a C-function declared as:
static inline CGPoint SOCGPointAdd(const CGPoint a, const CGPoint b) {
return CGPointMake(a.x + b.x, a.y + b.y);
}
Until now, I declared utility C-functions in .h files and implemented them in .m files, just like this:
CGPoint SOCGPointAdd(const CGPoint a, const CGPoint b) {
return CGPointMake(a.x + b.x, a.y + b.y);
}
I can use this function "inline" anywhere I want and it should also be "static" because it's not associated with any object, like an Objective-c method. What is the point / advantage of specifying "static" and "inline"?
inline does not mean you can use the function “inline” (it is normal to use functions inside other functions; you do not need inline for that); it encourages the compiler to build the function into the code where it is used (generally with the goal of improving execution speed).
static means the function name is not externally linked. If the function were not declared static, the compiler is required to make it externally visible, so that it can be linked with other object modules. To do this, the compiler must include a separate non-inline instance of the function. By declaring the function static, you are permitting all instances of it to be inlined in the current module, possibly leaving no separate instance.
static inline is usually used with small functions that are better done in the calling routine than by using a call mechanism, simply because they are so short and fast that actually doing them is better than calling a separate copy. E.g.:
static inline double square(double x) { return x*x; }
If the storage class is extern, the identifier has external linkage and the inline definition also provides the external definition. If the storage class is static, the identifier has internal linkage and the inline definition is invisible in other translation units.
By declaring a function inline, you can direct the compiler to integrate that function's code into the code for its callers (to replace the complete code of that function directly into the place from where it was called). This makes execution faster by eliminating the function-call overhead. That's why inline functions should be very short.
In C, inline means that it is an inline definition. It doesn't have internal linkage, it has no linkage. It never reaches the linker, which means that if the compiler doesn't use that inline definition to inline every single reference to the function in the compilation unit, then there will be a local linker error if a symbol with the same name (C uses unmangled identifiers) with external linkage is not exported by another translation unit in the compilation. The actual inlining of references to the function by the compiler is exclusively controlled by the optimisation flag or __attribute__((always_inline))
There is no difference between static inline and static, both do not inline the function, and provide the function in the assembly output on -O0 as an internal linkage symbol to the linker, and both inline and optimise out the inclusion of the function in the assembly output on -O1. static inline does have one quirk in that you can use a non-static inline prototype before it, except this prototype is ignored and isn't used as a forward declaration (but using a non-static prototype before a static function is an error).
inline (GCC <5.0, which used -std=gnu90 / gnu89 as default) / extern inline (GCC 5.0 onwards, which uses -std=gnu11): This is a compiler only inline definition. Externally visible function emittance (in the assembly output for use of the assembler and linker) for this inline definition does not occur. If all references to the function in the file are not actually inlined by the compiler (and inlining occurs on higher optimisation levels or if you use __attribute__((always_inline)) inline float func()), then there will be a local linker error if the compiler does not emit the external definition to the linker (and if a symbol with the same name with external linkage is not exported by another translation unit). This allows for an inline definition and an out-of-line function of the same symbol to be defined separately, one with inline and the other out-of-line, but not in the same translation unit as the compiler will confuse them, and an out of line definitition will be treated as a redefinition error. Inline definitions are only ever visible to the compiler and each translation unit can have their own. Inline definitions cannot be exported to other files because inline definitions do not reach the linking stage. In order to achieve this at compile-time, the inline definition can be in a header file and included in each translation unit. This means that the use of inline is a compiler directive and extern/static refer to the out-of-line version produced for the linker. If the function is not defined in the translation unit, it cannot be inlined because it's left to the linker. If the function is defined but not inline, then the compiler will use this version if it decides to inline
extern inline (GCC <5.0) / inline (GCC >5.0): an externally visible function is emitted for this inline definition regardless of whether it is inlined or not meaning this specifier can only be used in one of the translation units. This is intuitively the opposite of 'extern'
static inline: locally visible out-of-line function is emitted by the compiler to the assembly output with a local directive for the assembler for this compiler inline definition, but may be optimised out on higher optimisation levels if all the functions are able to be inlined; it will never allow a linker error to result. It behaves identically to static because the compiler will inline the static definition on higher optimisation levels just like static inline.
An inline function that isn't static shouldn't contain non-const static storage duration variables or access static file-scope variables, this will produce a compiler warning. This is because the inline and out-of-line versions of the function will have distinct static variables if the out-of-line version is provided from a different translation unit. The compiler may inline some functions, not emit a local symbol to be linked to those references, and leave the linkage to the linker which might find an external function symbol, which is assumed to be the same function as it has the same identifier. So it reminds the programmer that it should logically be const because modifying and reading the static will result in undefined behaviour; if the compiler inlines this function reference, it will read a fresh static value in the function rather than the one written to in a previous call to the function, where that previous reference to the function was one that wasn't inlined, hence the variable that was written to in the previous call would have been one provided by a different translation unit. In this instance, it results in a copy local to each translation unit and a global copy and it is undefined as to which copy is being accessed. Making it const ensures that all the copies are identical and will never change with respect to each other, making the behaviour defined and known.
Using an inline / extern inline prototype before/after a non-inline definition means that the prototype is ignored.
Using an inline prototype before an inline definition is how to prototype an inline function without side effects, declaring an inline prototype after the inline definition changes nothing unless the storage specifier changes.
Using an extern inline / extern / regular prototype before/after an inline definition is identical to an extern inline definition; it is a hint that provides an external out-of-line definition of the function, using the inline definition.
Using extern inline / inline on a prototype without a definition in the file but it is referenced in the file results in inline being ignored an then it behaves as a regular prototype (extern / regular, which are identical)
Using a static inline / static on a prototype without a definition in the file but it is referenced in the file results in correct linkage and correct type usage but a compiler warning saying that the function with internal linkage has not been defined (so it uses an external definition)
Using a regular / extern / extern inline prototype before a static inline or static definition is a 'static declaration of 'func' follows non-static declaration' error; using it after does nothing and they are ignored. Using a static or static inline prototype before/after a static inline definition is allowed. Using an inline prototype before a static inline definition is ignored and will not act as a forward declaration. This is the only way in which static inline differs from static as a regular prototype before a static definition results in an error, but this does not.
Using a static inline prototype before a regular / extern / static / static inline / extern inline definition results in static inline overriding the specifiers and acts as correctly as a forward declaration.
__attribute__((always_inline)) always inlines the function symbol in the translation unit, and uses this definition. The attribute can only be used on definitions. The storage / inline specifiers are unaffected by this and can be used with it.
Inline functions are for defining in header files.Small functions are defined in header files.
It should be static so that it can acess only static members.

Alternative syntax to __block?

I have question on the syntax of __block variables. I know you can use __block on a variable in scope so it's not read-only inside the block. However in one spot in the apple docs, I saw an alternative:
"Variables in the defining scope are read-only by default when used in a block. If you need to change the value of such a variable, you can use a special syntax:
int count = 0;
float cumulativeValue = 0.0;
UpdateElements( a, N, ^(float element){
|count, cumulativeValue|
float value = factor * element;
++count;
cumulativeValue += value;
return value;
} );
In this example, count and cumulativeValue are modified inside the block, so they are included in comma-separated list of shared variables at the beginning of the block scope.
This syntax seems much cleaner and I assume you could then modify variables you did not declare but are still in scope. However, I haven't seen this anywhere else and the xCode compiler does not like my basic block. Is this legitimate syntax?
Wow. Haven't seen that syntax in a long time.
That was one of the various syntactic structures explored during the development of blocks. It was eventually rejected because it was too imprecise in declaring intent and the resulting behavior would have been confusing.
Consider a scope with three blocks, two of which declare a variable as readwrite via |a|. There would be no way of knowing from the int a = 5; declaration at the top of the scope that the variable's value is readwrite in some of the block's scope.
As well, it would make the compiler implementation significantly more difficult. The tradition in C is that a variables storage type is fixed at the time of declaration. Supporting this syntax would have broken that expectation.
Thus, it was decided to use a storage type modifier akin to volatile or static. __block was used primarily because the __ prefix greatly reduces the amount of code that would break by adding a bare keyword.
Thanks for asking this. Bug filed and that documentation will be fixed and/or removed eventually.
The | | syntax was inspired by Smalltalk, as was, of course, the term "block".
As bbum points out, marking the decl site is more honest w.r.t. non-block usage and far more in line with C when modeled, as it ended up, as a new (C) object "duration".
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1451.pdf

In Objective-C ARC, what are "BPTRs declared within extern "BCPL" blocks"?

In the Clang documentation for ARC, it says:
ARC applies to Objective-C pointer types, block pointer types, and
[beginning Apple 8.0, LLVM 3.8] BPTRs declared within extern "BCPL"
blocks.
What are these "BPTRs declared within extern "BCPL" blocks"?
It's a small in-joke.
C++ has the ability to mark identifiers with C linkage, which usually just means no name mangling of functions with the same name but different parameter signature, since C, until recently, had no concept of overloading1.
The way you specify that linkage is by surrounding the identifiers with:
extern "C" {
whatever ...
}
Now, BCPL is a language that pre-dates even C (it actually forms part of the C lineage) and its "linkage" (for want of a better word) was simply a table of addresses known as the global vector.
The author of that document you reference was simply being humorous, CLang doesn't actually provide extern "BCPL" things. You'll also notice that the current version of LLVM is 3.2 with 3.3 not due until June this year. Another indication that the author was having us on, with the LLVM 3.8 comment.
Since the intent of that sentence was simply to show how annotations (within []) work, the rest of the text was largely irrelevant.
1 With the introduction of type-generic expressions in C11, it now it has overloading of a sort, though done at compile time rather than run time.
This line is obviously taken randomly from an unknown context just to demonstrate revision markers like [beginning Apple 8.0, LLVM 3.8], and BPTRs and BCPL do not mean anything specific. Generally, BPTR means something like byte pointer.

Scope of enum itself in Objective-C?

Consider the following code:
enum TableSections {
kSection1 = 0,
kSection2 = 1,
};
What is the scope of the identifier TableSections? If this code is in an implementation file, is TableSections only defined within that compilation unit, defined globally, or something else?
And is the answer specific to Objective-C (llvm, clang, etc.?) or general for all C99 or some larger set?
Enums are C, so we're not talking about anything Objective-C specific.
Enums aren't involved in linkage. They're merely symbolic constants. They're defined wherever they're visible/accessible. If that's a compilation unit, then the enum is usable only from within that compilation unit of course (but not because it's static, local or anything else - simply because the compiler needs to see the source (textual definition) in order to be able to expand the enum members.

What is the use of extern in declaring constants?

can please tell me what is the use of extern variable when declaring the constant variables in different file.
The extern keywords forces the compiler to treat the statement as a declaration rather than a definition. In other words, extern prevents the compiler from reserving space for the variable. Thus, only the compilation unit which does not use extern provides a definition, while the others merely use the declaration, which is in keeping with the "one definition rule"; if each compilation unit were to reserve space independently for the same variable, it would result in a violation of the "one definition rule". Note that extern literally means that "the definition is provided externally (by a different compilation unit)".
Just like C, extern keyword means that the symbol is defined in another object file that will be linked to this one in compilation phase.