tags:

views:

1672

answers:

10
+3  Q: 

const static

const static int foo = 42;

I saw this in some code here at StackOverflow and I could'nt figure out what it does. Then I saw some confused answeres at other forums. My best guess is that it's used in C to hide the constant foo from other modules. Is this correct? If so, why would anyone use it in a C++ context where you can just make it private?

+3  A: 

It's missing an 'int'. It should be:

const static int foo = 42;

In C and C++, it declares an integer constant with local file scope of value 42.

Why 42? If you don't already know (and it's hard to believe you don't), it's a refernce to the Answer to Life, the Universe, and Everything.

Kevin
Yes, thanks. I editet the question
c0m4
I do know about thhgttg :-)
c0m4
Thanks... now everytime... for the rest of my life...when I see 42, I will always thing about this. haha
JTA
This is proof-positive that the universe was created by being with 13 fingers (the question and answer actually match in base 13).
paxdiablo
Its the mice. 3 toes on each foot, plus a tail gives you base 13.
KeithB
You don't actually need the 'int' in a declaration, though it's definitely good taste to write it out. C always assumes 'int' types by default. Try it!
ephemient
+17  A: 

It has uses in both C and C++.

As you guessed, the "static" part limits it's scope to that file. It also provides for static initialization. "const" just tells the compiler to not let anybody modify it. This variable is either put in the data or bss segment depending on the architecture, and might be in memory marked read-only.

All that is how C treats these variables ( or how C++ treats namespace variables ). In C++, a member marked static is shared by all instances of a given class. Whether it's private or not doesn't affect the fact that one variable is shared by multiple instances. Having 'const' on there will warn you if any code would try to modify that.

If it was strictly private, then each instance of the class would get it's own version ( optimizer notwithstanding)

Chris Arguin
The original example is talking about a "private variable". Therefore, this is a mebmer and static has *no* affect on the linkage. You should remove "the static part limits it's scope to that file".
Richard Corden
The "special section" is known as the data segment, which it shares with all the other global variables, such as explicit "strings" and global arrays. This is opposing to the code segment.
spoulson
@Richard - what makes you think it's a member of a class? There's nothing in the question that says it is. *If* it's a member of a class, then you're right, but if it's just a variable declared at global scope, then Chris is right.
Graeme Perrow
The original poster mentioned private as a possible better solution, but not as the original problem.
Chris Arguin
@Graeme, OK so it's not "definitely" a member - however, this answer is making statements which only apply to namespace members and those statements are wrong for members variables. Given the amount of votes that error may confuse someone not very familiar with the language - it should be fixed.
Richard Corden
@Richard, I concur, and updated it based on your concerns. I'm a C programmer, and wasn't thinking about the meaning in Object scope.
Chris Arguin
+1  A: 

Yes, it hides a variable in a module from other modules. In C++, I use it when I don't want/need to change a .h file that will trigger an unnecessary rebuild of other files. Also, I put the static first:

static const int foo = 42;

Also, depending on its use, the compiler won't even allocate storage for it and simply "inline" the value where it's used. Without the static, the compiler can't assume it's not being used elsewhere and can't inline.

Jim Buck
+1  A: 

This ia s global constant visible/accessible only in the compilation module (.cpp file). BTW using static for this purpose is deprecated. Better use an anonymous namespace and an enum:

namespace
{
  enum
  {
     foo = 42
  };
}
Roskoto
this would force the compiler to not treat foo as a constant and as such hinders optimization.
Nils Pipenbrinck
enums values are always constant so I don't see how this will hinder any optimizations
Roskoto
ah - true.. my error. thought you've used a simple int-variable.
Nils Pipenbrinck
Roskoto, I'm not clear what benefit the `enum` has in this context. Care to elaborate? Such `enums` are usually only used to prevent the compiler from allocating any space for the value (though modern compilers don't need this `enum` hack for it) and to prevent the creation of pointers to the value.
Konrad Rudolph
Konrad, What exactly problem you see in using an enum in this case? Enums are used when you need constant ints which is exactly the case.
Roskoto
How is using static in this way 'deprecated'? I would definitely prefer the example in the question over doing it with an enum. Also, this way only works for integer values.
jonner
Roskoto
Doh - otherway round...deprecated for objects, not functions.
Richard Corden
Roskoto, it's not a problem exactly, it just doesn't semantically match what I'm trying to do. I'm not creating an enumeration, i'm creating a single named constant. Also, I can't use the same method for floats, so I'd rather be consistent and just use `static const` in both cases.
jonner
the static has nothing to do with the const thing. You can always have: namespace{ const float foo = 42.0;}
Roskoto
You asked about the problem with enum, not static. In any case, an anonymous namespace is not exactly equivalent to static. It makes the name inaccessible to other translation units, but I believe a variable in an anonymous namespace still has external linkage.
jonner
Of course they are not equivalent that's why static is deprecated in favor of anonymous namespaces. And yes they have external linkage but with a random name assigned from the compiler so you can never guess or match it incidentally.
Roskoto
A: 

Making it private would still mean it appears in the header. I tend to use "the weakest" way that works. See this classic article by Scott Meyers: http://www.ddj.com/cpp/184401197 (it's about functions, but can be applied here as well).

yrp
+1  A: 

In C++,

static const int foo = 42;

is the preferred way to define & use constants. I.e. use this rather than

#define foo 42

because it doesn't subvert the type-safety system.

ceretullis
+5  A: 

That line of code can actually appear in several different contexts and alghough it behaves approximately the same, there are small differences.

Namespace Scope

// foo.h
static const int i = 0;

'i' will be visible in every translation unit that includes the header. However, unless you actually use the address of the object (for example. '&i'), I'm pretty sure that the compiler will treat 'i' simply as a type safe 0. Where two more more translation units take the '&i' then the address will be different for each translation unit.

// foo.cc
static const int i = 0;

'i' has internal linkage, and so cannot be referred to from outside of this translation unit. However, again unless you use its address it will most likely be treated as a type-safe 0.

One thing worth pointing out, is that the following declaration:

const int i1 = 0;

is exactly the same as static const int i = 0. A variable in a namespace declared with const and not explicitly declared with extern is implicitly static. If you think about this, it was the intention of the C++ committee to allow const variables to be declared in header files without always needing the static keyword to avoid breaking the ODR.

Class Scope

class A {
public:
  static const int i = 0;
};

In the above example, the standard explicitly specifies that 'i' does not need to be defined if its address is not required. In other words if you only use 'i' as a type-safe 0 then the compiler will not define it. One difference between the class and namespace versions is that the address of 'i' (if used in two ore more translation units) will be the same for the class member. Where the address is used, you must have a definition for it:

// a.h
class A {
public:
  static const int i = 0;
};

// a.cc
#include "a.h"
const int A::i;            // Definition so that we can take the address
Richard Corden
+1  A: 

It's a small space optimization.

When you say

const int foo = 42;

You're not defining a constant, but creating a read-only variable. The compiler is smart enough to use 42 whenever it sees foo, but it will also allocate space in the initialized data area for it. This is done because, as defined, foo has external linkage. Another compilation unit can say:

extern const int foo;

To get access to its value. That's not a good practice since that compilation unit has no idea what the value of foo is. It just knows it's a const int and has to reload the value from memory whenever it is used.

Now, by declaring that it is static:

static const int foo = 42;

The compiler can do its usual optimization, but it can also say "hey, nobody outside this compilation unit can see foo and I know it's always 42 so there is no need to allocate any space for it."

Ferruccio
+3  A: 

A lot of people gave the basic answer but nobody pointed out that const defaults to static (and some gave wrong information). See the C++98 standard section 3.5.3.

First some background:

Translation unit: A source file after the pre-compiler (recursively) included all its include files.

Static linkage: A symbol is only available within its translation unit.

External linkage: A symbol is available from other translation units.

At namespace level

static const int sci = 0; // sci is explicitly static
const int ci = 1;         // ci is implicitly static
extern const int eci = 2; // eci is explicitly extern
extern int ei = 3;        // ei is explicitly extern
int i = 4;                // i is implicitly extern
static int si = 5;        // si is explicitly static

At function level

static means the value is maintained between function calls (again if it's const the static is redundant).
The semantics of function static variables is similar to global variables in that they reside in the program's data-segment (and not the stack or the heap), see this question for more details about static variables' lifetime.

At class level

static means the value is shared between all instances of the class and const means it doesn't change (and can be initialized inline) this is the only case in which neither the static nor the const are redundant.

Motti
+1  A: 

To all the great answers, I want to add a small detail:

If You write plugins (e.g. DLLs or .so libraries to be loaded by a CAD system), then static is a life saver that avoids name collisions like this one:

  1. The CAD system loads a plugin A, which has a "const int foo = 42;" in it.
  2. The system loads a plugin B, which has "const int foo = 23;" in it.
  3. As a result, plugin B will use the value 42 for foo, because the plugin loader will realize, that there is already a "foo" with external linkage.

Even worse: Step 3 may behave differently depending on compiler optimization, plugin load mechanism, etc.

I had this issue once with two helper functions (same name, different behaviour) in two plugins. Declaring them static solved the problem.

Black