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,
static
marks variables that are preserved and visible to the function across function calls. - outside a function,
static
means only visible to the current source file. (can’t be linked even if declaredextern
in other units. It modifies the symbol’sBind
attribute 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,
const
variable (i.e. globals) only take compile-time-constant initializer - inside a function,
const
variable can be modified at runtime once, e.g. static const
means (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
inline
does what it says but not a guaranteeconstexpr
is 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_assert
assertion of a constexpr during compile timevolatile
means 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:1
has default value (0) therefore stored uninitialized in.BSS
, whilecoutner:0
fromg()
has initial value and therefore stored in the.data
section.- 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