一、static关键字
(1)在修饰变量的时候,static 修饰的静态局部变量只执行初始化一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放。
(2)static 修饰全局变量的时候,只能在当前.c文件中访问,不能在其它文件中访问,即便是 extern 外部声明也不可以。
(3)static 修饰一个函数,该函数只能是当前.c文件能调用,其他.c不能调用。static 修饰的变量存放在全局数据区的静态变量区,包括全局静态变量和局部静态变量,都在全局数据区分配内存。初始化的时候自动初始化为 0。
(4)不想被释放的时候,可以使用static修饰。比如修饰函数中存放在栈空间的数组。如果不想让这个数组在函数调用结束释放可以使用 static 修饰。
(5)考虑到数据安全性和程序耦合度时,当只想当前文件使用时优先考虑static修饰变量和函数养成良好的编程习惯。
1.静态局部变量
#include<stdio.h>
void f(void)
{
int n = 10;
printf("n=%d\n", n);
n++;
printf("n++=%d\n", n);
}
void f_static(void)
{
static int n = 10;
printf("static n=%d\n", n);
n++;
printf("n++=%d\n", n);
}
int main(void)
{
f();//10 11
printf("--------------------\n");
f_static();//10 11
printf("--------------------\n");
f();//10 11
printf("--------------------\n");
f_static();//11 12
return 0;
}
转载于https://blog.csdn.net/guotianqing/article/details/79828100
再次调用f_static函数输出11 12的原因是:
静态变量是指变量在内存中的地址不变,但值可改变,局部变量每次都会被初始化,而静态局部变量被初始化一次。
1.程序进程中内存中分布为栈区、堆栈增长区、堆区、其他段、.bss段、.data段、text段。
data段:在程序中所有赋了初值的全局变量,存放在这里
.bss段:在程序中没有初始化的全局变量;内核将此段初始化为0。
栈:增长方向:自顶向下增长;自动变量以及每次函数调用时所需要保存的信息(返回地址;环境信息)
堆:动态存储部分。
局部静态变量:内存中的位置是静态存储区,会被程序自动初始化为0,作用域为局部作用,当定义它的函数或语句结束时,作用域随之结束,但它离开作用域时,并没有被销毁,仍然在内存当中,直至程序结束,不能再次对它进行访问。若想访问时需再次执行该函数,程序才能访问它所指定的对象,其他函数想要使用可通过该函数提供的存储区地址间接访问该对象,例如通过指针形参或返回值
静态存储区是指程序执行过程中它一直都存在,文件作用域变量具有静态存储区,块区域变量具有静态储存区。
2.静态全局变量
因静态全局变量仅对当前文件可见,其他文件不可访问,所以其他文件定义相同的变量互不影响,降低了程序模块之间的耦合,若是需要其他文件访问时,可定义全局变量(其他文件利用extern引用使用即可)。
静态全局变量:内存中的位置是静态存储区,会被程序自动初始化为0,作用域是整个文件。
3.静态函数
在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。
定义静态函数的好处:
1.其他文件中可以定义相同名字的函数,不会发生冲突
2. 静态函数不能被其他文件所用。
存储说明符auto,register,extern,static,对应两种存储期:自动存储期和静态存储期
auto register 只能用于块作用域的变量声明中。register它把变量归为寄存器存储类别。
自动变量例子:
#include<stdio.h>
int main(){
int x = 30;//局部变量,作用域是开始到结束
printf("%d,%p\n",x,&x);
{
int x = 77;//新的x 占用外部x的内存地址,当块函数结束地址还给外部
x
printf("%d,%p\n",x,&x);
}
while(x++<33){
int x = 100;//新的X
printf("%d,%p\n",x,&x);
}
return 0;
}
自动变量初始化方式可有:
int main(){
int x;
int y =10;
或
int x = 1;
int y = 2 * x;
}
自动变量不会初始化,需显式初始化。
全局变量:
若全局变量,未初始化会被自动初始化为0
int x = 10;
int y = 3 + 20;
int z = x * 2 ;//错误,初始化方式,与自动变量不同,不能这样进行初始化。
例子
:i
gcc demon3.c demon4.c -o test
malloc()函数 该函数接受所需的内存字节数,进行分配内存(匿名形式),且返回动态分配内存块的首地址,通过将地址赋值给指针变量,并使用指针访问这块内存。通常是以指向void的指针(通用指针),再通过强制类型转换到所匹配类型的指针。
例子:
/*动态分配数组 demon5.c gcc demon5.c -0 demon5*/
#include<stido.h>
#include<stdlib.h>
int main(void){
double *ptd;
int max;
int number;
int i = 0;
puts("what is maximum number of type double entries");
if (scanf("%d",&max)!=1)
{
puts("Number not corrently entered = = bye");
exit(EXIT_FAILURE);
}
ptd = (double *) malloc(max*sizeof(double));
if (ptd == NULL)
{
puts("Memory allocation failed.bye");
exit(EXIT_FAILURE);//执行失败
}
puts("Enter the value to array");
while(i < max && scanf("%d",&ptd[i])==1)
++i;//先计算再操作
printf("Here are your %d entries:\n",number=i);
for ( i = 0; i < number; i++){
printf("%7.2f",ptd[i]);
if (i%7==6)
{
puts("\n");
}
}
if (i % 7 !=0)
{
puts("\n");
}
puts("Done");
free(ptd);//释放malloc()函数分配的内存,可以避免内存泄漏问题。
return 0;
}
calloc()函数 作用与malloc()函数类似:
声明规则有所不同
long *test;
test = (long *) calloc(100,sizeof(long));//100*4=400 内存大小
const float * pf;//指向float类型的常量值 pf本身值可以改变,但是指向的float的不能被改变
float * const pf;//常量指针 ,本身值不可以改变,但是指向的float的值可以改变,也就是可以被其他的float地址值再次赋值。
const float * const pf;//两个都是常量不可以改变。
volatile int local //local是一个易变的位置
volatile int *ploc //ploc是一个指向易变的位置的指针。
restrict关键字,它只能用于指针,表明该指针是访问数据对象的位置且初始方式
int arr[10];
int * restrict restart = int(*) malloc(10*sizeof(int));//唯一且初始方式访问数据
int * pf = ar;
_Atomic类型限定符 常用于多线程中。当一个线程对一个原子类型的对象执行原子操作时,其他线程不能访问该对象。
以上内容个人学习总结,若有错误请谅解,谢谢。