在不同地方定义变量, 在内存中占用不同的位置:.bss, .data, .text, stack, heap.

分别在不同地方增加变量,用size 命令查看可执行文件的text, data, bss段的大小变化情况

在所有函数外定义变量(变量占用位置+占用长度)    在main函数中定义变量(变量:占用位置)      在其他局部函数中定义变量(变量:占用位置)
0:
1:int i;bss                                    int i;no effect(stack)                   int i;no effect(stack)
2:int i = 1;data+sizeof(int)                   int i = 1;no effect(stack )              int i = 1;no effect(stack)
3:static int i;bss+sizeof(int)                 static int i:bss                         static int i:bss
4:static int i=2;data+sizeof(int)              static int i=4;data                      static int i=4;data
5:int *arr;bss+sizeof(int*)                    int *arr;no effect(stack)                int *arr;no effect(stack)
6:int *arr=&i;data                             int *arr=&i2;no effect(stack)            int *arr=&i2;no effect(stack)
7:char buf[4];bss+数组长度                     char buf[4];no effect(stack )            char buf[4];no effect(stack )
8:char buf[4]="1234";data+数组长度             char buf[4]="1234";no effect(stack)      char buf[4]="1234";no effect(stack)

A static variable declared inside a function is placed in the data or bss portion of memory and can retain it’s value between calls to the same function. In this way it is similar to a global variable, except it is only used in one function. The restriction on the scope of static variables is a compiler implemented restriction; being that, an assembly language program could easily access any data stored in either the data or bss sections of memory.

A static variable declared as a global variable is also called a static external variable. Here the keyword static produces the opposite results as the extern keyword. The variable is global to the file where it is declared, but may not be referenced in any other files. Thus the keyword static can produce a form of data hiding.

restrict keyword

摘抄自维基百科

If the compiler knows that there is only one pointer to a memory block, it can produce better optimized code. For instance:

void updatePtrs(size_t *ptrA, size_t *ptrB, size_t *val)
{
  *ptrA += *val;
  *ptrB += *val;
}

In the above code, the pointers ptrA, ptrB, and val might refer to the same memory location, so the compiler may generate less optimal code:

load R1 ← *val  ; Load the value of val pointer
load R2 ← *ptrA ; Load the value of ptrA pointer
add R2 += R1    ; Perform Addition
set R2 → *ptrA  ; Update the value of ptrA pointer
; Similarly for ptrB, note that val is loaded twice, because
; ptrA may be equal to val (i.e., point to the same location).
load R1 ← *val
load R2 ← *ptrB
add R2 += R1
set R2 → *ptrB

However, if the restrict keyword is used and the above function is declared as

void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val);

then the compiler is allowed to assume that ptrA, ptrB, and val point to different locations and updating one pointer will not affect the other pointers. The programmer, not the compiler, is responsible for ensuring that the pointers do not point to identical locations.

Now the compiler can generate better code as follows:

load R1 ← *val
load R2 ← *ptrA
add R2 += R1
set R2 → *ptrA
; Note that val is not reloaded,
; because the compiler knows it is unchanged
load R2 ← *ptrB
add R2 += R1
set R2 → *ptrB

Note that the above assembly code is shorter because val is loaded once.