Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is static const different from extern const?

In my iOS/Objective C projects, I often have a constants.h file with my API keys and such. Until today, I've been declaring my constants as static const like so:

static NSString * const kAPIKey = @"wembvkejrvb43789gvbiu2bvfake";

This works fine, but with the unfortunate downside that I can only create constants for primitives and NSString literals, essentially. Other objects, such as UIColor objects, cannot be stored in this constant as they cannot be initialized with a static literal syntax (my understanding, citation required).

After reading some C++ docs, I understand a few things:

  • The static is unnecessary, as const are implicitly static.
  • Calling NSString * const x is actually declaring a constant and immutable value in x. I cannot change the value, but may be able to change what x points to.
  • This const has internal linkage, meaning the the value is defined right away (presumable at compile time).

Are these conclusions correct?

How does an extern const differ? I assume they are externally linked (thus the extern keyword). Are they defined at run time? Can I create some sort of dynamic extern const that can be set with a value returned by a class method?

For example, I would like to create a globally-scoped constant that contains a UIColor value. I would like to construct this color value using the [UIColor colorWithRed:green:blue:alpha:] class method. This clearly doesn't work with the internally linked constants I've been using (I'm assuming because it happens at compile-time) - but is it possible using an external constant, possibly set up in the +initialize method?

Any elaboration on the details of this behavior would be immensely helpful.

like image 444
chris stamper Avatar asked Dec 11 '14 00:12

chris stamper


3 Answers

On your specific programming question, how to create a compile-time defined color object: you can't, because, apart from the handful for which the language supplies literal syntax, objects are created at runtime.

But you can still do it elegantly at runtime, without any addition to global scope, the same way the sdk does...

@interface UIColor (RainbowAddition)

+ (UIColor *)chartruseColor;

@end

@implementation UIColor (RainbowAddition)

+ (UIColor *)chartruseColor {
    // bonus: this is really chartruse... according to the internet
    return [self colorWithRed:0.5 green:1.0 blue:0.0 alpha:1.0];
}

@end

http://cloford.com/resources/colours/500col.htm

like image 32
danh Avatar answered Sep 27 '22 22:09

danh


The static is unnecessary, as const are implicitly static.

No, that's not true.

static when used at file scope (i.e. outside any method or function) means that the variable is visible only within that file.

extern means that the variable is defined in some other file.

const means that the variable cannot be modified.

Consider strings. Often, you'll have an implementation file (name ends in .m) that defines some constant string pointer:

NSString *const SomeString = @"some string";

You might want to use that same constant from other files. If so, you could add a declaration to the header (name ends in .h) file that explains to the compiler that the variable is defined elsewhere:

extern NSString *const SomeString;

and that would let you use SomeString in any file that imports the header file. On the other hand, you might decide that you definitely do not want the constant used outside the implementation file. In that case, you could declare it static (in the implementation file again):

static NSString *const SomeString = @"some string";

and that would prevent its use from outside the file.

Calling NSString * const x is actually declaring a constant and immutable value in x. I cannot change the value, but may be able to change what x points to.

Right, it declares the pointer x to be constant -- you can't change it. You also can't change the value that it points to if it's actually a NSString because an instance NSString isn't mutable.

This const has internal linkage, meaning the the value is defined right away (presumable at compile time).

I'll take the 5th on that -- I'm not sure exactly how the compiler deals with constant strings. I think it's safe to use that as a mental model, though; the string will in any case be defined before your code ever gets to use it.

like image 166
Caleb Avatar answered Sep 27 '22 21:09

Caleb


Objective-C is a pure extension of C, C++ is not.

At global scope:

  • in C (and Objective-C) writing const is equivalent to extern const (external linkage);
  • in C++ writing const is equivalent to static const (internal linkage).

Both in C (and Objective-C) and C++, to create a global-scoped const you can define it, just one time, in one source file like extern const TYPE identifier = VALUE; and declare it (typically in an header file) like: extern const TYPE identifier; (read it: I defined this const elsewhere at global linkage level).

like image 25
Isidoro Ghezzi Avatar answered Sep 27 '22 21:09

Isidoro Ghezzi