c/c++ inline, const and static
§ Quick Facts
order of specifiers doesn’t matter
i.e. const static and static const are the same thing. But static should
come first (convention).
static is a storage specifier, defines the visibility of a thing, affects where and how it is stored.
- inside a function,
staticmarks variables that are preserved and visible to the function across function calls. - outside a function,
staticmeans only visible to the current source file. (can’t be linked even if declaredexternin other units. It modifies the symbol’sBindattribute in the symbol table.
const is a type qualifier. It says this thing won’t change, attemps to modify it triggers compiler error1.
- outside functions,
constvariable (i.e. globals) only take compile-time-constant initializer - inside a function,
constvariable can be modified at runtime once, e.g. static constmeans (indefinitely2) this variable goes to.rodata, it takes compile-time constant.int foo(){ const counter = bar(); // this is ok static const b = bar(); // this is error counter++; // this is error }
c++ static class member
Inside a class definition, the keyword static declares members that are not
bound to class instances3. That is, visible to (i.e. shared by) all
class instances.
c++ static class member function3
- Static member functions are not associated with any object. When called, they have no this pointer.
- Static member functions cannot be virtual, const, volatile, or ref-qualified.
- The address of a static member function may be stored in a regular pointer to function, but not in a pointer to member function . example:
// definition
class X {
static int n;
static void f();
};
// static is only needed on the declarition
int X::n = 7;
void X::f() {/*whatever*/}
int X::n = 1;
c++ const member functions: denoted with const after a function
declartion. It can not modify a data member of the class.
class X {
int data;
public:
int f() const;
int g();
};
int X::f() {
return data++; // errr
}
int X::g() {
return data++; // ok
}
int main() {
X foo;
const X bar;
foo.f(); // ok
foo.g(); // ok
bar.f(); // ok
bar.g(); // error: only const functions
// can be called on a constant class instance
}
c++ const static members: fuck me.
function that returns const thing
this is pointless because return values are rvalues
const int f() {/*return whatever*/}
this can be helpful, e.g. you have bunch of constant globals and wants to get their pointer via some functions. (and you can’t modify the backing data via the returned pointer)
const int *f(){/*whatever*/}
pointer to const and const pointer
const in funciton parameter list: use it only on pointer (pass by reference parameters).
// can not modify data via its pointer
int f(const int *data);
int f(const int *data) {
(*data) += 1; // error
}
// const is meaningless on a passed-by-value parameter
// same as returning a const value
int g(const int input);
who is const.
int this = 1;
int that = 42;
const int *foo = &this; // foo is a pointer to constant int
(*foo) += 1; // illegal, the pointed data is const
foo = &that; // legal, the pointer itself is not const
int * const bar = &this; // bar is a constant pointer to int
(*bar) += 1; // legal
bar = &that; // illegal
recall: const would modify the type
// char and const char are different types
// so are their pointers
char **foo;
const char **bar;
foo = bar; // illegal
bar = foo; // illegal
other stuffs
inlinedoes what it says but not a guaranteeconstexpris evaluated during compile time and used as literals- literals are things that are known at compile time and stored in read-only sections, if necessary.
static_assertassertion of a constexpr during compile timevolatilemeans this thing could have side effect, do not apply optimizations to it.
§ What’s inside (WIP)
§§ static (variable) inside functions
static variables are visible across function calls
#include <stdio.h>
void f(){
static int counter = 0;
printf("%d\n", counter);
counter ++;
}
void g(){
static int counter = 42;
printf("%d\n", counter);
counter ++;
}
int main() {
f(); // 0
f(); // 1
g(); // 42
g(); // 43
return 0;
}
what’s inside
$ gcc -g -o test test.c
$ readelf -s test
value Size Type Bind Vis Ndx Name
2: 0000000000004020 4 OBJECT LOCAL DEFAULT 25 counter.1
3: 0000000000004018 4 OBJECT LOCAL DEFAULT 24 counter.0
$ readelf -S test
[SNIP]
[24] .data PROGBITS 0000000000004008 00003008
0000000000000014 0000000000000000 WA 0 0 8
[25] .bss NOBITS 0000000000004018 00003018
0000000000000010 0000000000000000 WA 0 0 4
- function’s static variable names are “global”, names are mangled.
couter:1has default value (0) therefore stored uninitialized in.BSS, whilecoutner:0fromg()has initial value and therefore stored in the.datasection.- neither can be accessed by name from other compilation units.
§§ static outside of a function
marks a thing that is only visible inside current source file.
in foo.c
static int var1;
int var2;
in bar.c
extern int var1;
extern int var2;
#include <stdio.h>
int main() {
printf("var1 = %d\n", var1); // NOPE, compile error
printf("var2 = %d\n", var2); // YEP
return 0;
}
compile with gcc -o test foo.c bar.c -> compile error, var1 is undefined
reference even declared extern in bar.c
This page is CC0-1.0