赣州企业网站建设,八大员继续教育入口,绵阳企业网站建设公司,wordpress描述引用.先来介绍它的第一条也是最重要的一条#xff1a;隐藏。#xff08;static函数#xff0c;static变量均可#xff09;
当同时编译多个文件时#xff0c;所有未加static前缀的全局变量和函数都具有全局可见性。 举例来说明。同时编译两个源文件#xff0c;一个是a.c….先来介绍它的第一条也是最重要的一条隐藏。static函数static变量均可
当同时编译多个文件时所有未加static前缀的全局变量和函数都具有全局可见性。 举例来说明。同时编译两个源文件一个是a.c另一个是main.c。
//a.c
char a A; // global variable
void msg()
{printf(Hello\n);
}//main.cint main()
{extern char a; // extern variable must be declared before useprintf(%c , a);(void)msg();return 0;
}
程序的运行结果是 A Hello 为什么在a.c中定义的全局变量a和函数msg能在main.c中使用前面说过所有未加static前缀的全局变量和函数都具有全局可见性其它的源文件也能访问。此例中a是全局变量msg是函数并且都没有加static前缀因此对于另外的源文件main.c是可见的。 如果加了static就会对其它源文件隐藏。例如在a和msg的定义前加上staticmain.c就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量而不必担心命名冲突。static可以用作函数和变量的前缀对于函数来讲static的作用仅限于隐藏.
2.static的第二个作用是保持变量内容的持久。static变量中的记忆功能和全局生存期
存储在静态数据区的变量会在程序刚开始运行时就完成初始化也是唯一的一次初始化。共有两种变量存储在静态存储区全局变量和static变量只不过和全局变量比起来static可以控制变量的可见范围说到底static还是用来隐藏的。虽然这种用法不常见
PS如果作为static局部变量在函数内定义它的生存期为整个源程序但是其作用域仍与自动变量相同只能在定义该变量的函数内使用该变量。退出该函数后 尽管该变量还继续存在但不能使用它。
include stdio.hint fun(){static int count 10; //在第一次进入这个函数的时候变量a被初始化为10并接着自减1以后每次进入该函数areturn count--; //就不会被再次初始化了仅进行自减1的操作在static发明前要达到同样的功能则只能使用全局变量 }int count 1;int main(void)
{printf(global\t\tlocal static\n);for(; count 10; count)printf(%d\t\t%d\n, count, fun());return 0;
}
程序的运行结果是 global local static 1 10 2 9 3 8 4 7 5 6 6 5 7 4 8 3 9 2 10 1
---基于以上两点可以得出一个结论把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域 限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。
3.static的第三个作用是默认初始化为0static变量
其实全局变量也具备这一属性因为全局变量也存储在静态数据区。在静态数据区内存中所有的字节默认值都是0x00某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵我们可以一个一个地把所有元素都置0然后把不是0的几个元素赋值。如果定义成静态的就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用但又觉得每次在字符数组末尾加‘\0’;太麻烦。如果把字符串定义成静态的就省去了这个麻烦因为那里本来就是‘\0’;不妨做个小实验验证一下。
include stdio.hint a;int main()
{int i;static char str[10];printf(integer: %d; string: (begin)%s(end), a, str);return 0;
}
程序的运行结果是 integer: 0; string: (begin) (end) 最后对static的三条作用做一句话总结。首先static的最主要功能是隐藏其次因为static变量存放在静态存储区所以它具备持久性和默认值0. 4.static的第四个作用C中的类成员声明static有些地方与以上作用重叠 在类中声明static变量或者函数时初始化时使用作用域运算符来标明它所属类因此静态数据成员是类的成员而不是对象的成员这样就出现以下作用
(1)类的静态成员函数是属于整个类而非类的对象所以它没有this指针这就导致 了它仅能访问类的静态数据和静态成员函数。
(2)不能将静态成员函数定义为虚函数。
(3)由于静态成员声明于类中操作于其外所以对其取地址操作就多少有些特殊 变量地址是指向其数据类型的指针 函数地址类型是一个“nonmember函数指针”。
(4)由于静态成员函数没有this指针所以就差不多等同于nonmember函数结果就 产生了一个意想不到的好处成为一个callback函数使得我们得以将C和C-based X W indow系统结合同时也成功的应用于线程函数身上。 这条没遇见过
(5)static并没有增加程序的时空开销相反她还缩短了子类对父类静态成员的访问 时间节省了子类的内存空间。
(6)静态数据成员在定义或说明时前面加关键字static。
(7)静态数据成员是静态存储的所以必须对它进行初始化。 程序员手动初始化否则编译时一般不会报错但是在Link时会报错误
(8)静态成员初始化与一般数据成员初始化不同:
初始化在类体外进行而前面不加static以免与一般静态变量或对象相混淆 初始化时不加该成员的访问权限控制符privatepublic等 初始化时使用作用域运算符来标明它所属类 所以我们得出静态数据成员初始化的格式 数据类型类名::静态数据成员名值
(9)为了防止父类的影响可以在子类定义一个与父类相同的静态变量以屏蔽父类的影响。这里有一点需要注意我们说静态成员为父类和子类共享但我们有重复定义了静态成员这会不会引起错误呢不会我们的编译器采用了一种绝妙的手法name-mangling 用以生成唯一的标志。 转载自https://www.cnblogs.com/songdanzju/p/7422380.html
static和extern区别
extern
1 基本解释extern可以置于变量或者函数前以标示变量或者函数的定义在别的文件中提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。 也就是说extern有两个作用第一个,当它与C一起连用时如: extern C void fun(int a, int b);则告诉编译器在编译fun这个函数名时按着C的规则去翻译相应的函数名而不是C的C的规则在翻译这个函数名时会把fun这个名字变得面目全非可能是funaBc_int_int#%$也可能是别的这要看编译器的脾气了(不同的编译器采用的方法不一样)为什么这么做呢因为C支持函数的重载啊在这里不去过多的论述这个问题如果你有兴趣可以去网上搜索相信你可以得到满意的解释! 第二当extern不与C在一起修饰变量或函数时如在头文件中: extern int g_Int; 它的作用就是声明函数或全局变量的作用范围的关键字其声明的函数和变量可以在本模块或者其他模块中使用记住它是一个声明不是定义!也就是说B模块(编译单元)要是引用模块(编译单元)A中定义的全局变量或函数时它只要包含A模块的头文件即可,在编译阶段模块B虽然找不到该函数或变量但它不会报错它会在连接时从模块A生成的目标代码中找到此函数。
static和extern区别 (1) extern 表明该变量在别的地方已经定义过了,在这里要使用那个变量. (2) static 表示静态的变量分配内存的时候, 存储在静态区,不存储在栈上面. static 作用范围是内部连接的关系, 和extern有点相反.它和对象本身是分开存储的,extern也是分开存储的,但是extern可以被其他的对象用extern 引用,而static 不可以,只允许对象本身用它. 具体差别首先static与extern是一对“水火不容”的家伙也就是说extern和static不能同时修饰一个变量其次static修饰的全局变量声明与定义同时进行也就是说当你在头文件中使用static声明了全局变量后它也同时被定义了最后static修饰全局变量的作用域只能是本身的编译单元也就是说它的“全局”只对本编译单元有效其他编译单元则看不到它,
extern 和const C中const修饰的全局常量具有跟static相同的特性即它们只能作用于本编译模块中但是const可以与extern连用来声明该常量可以作用于其他编译模块中, 如extern const char g_str[]; 然后在原文件中别忘了定义: const char g_str[] 123456; 所以当const单独使用时它就与static相同而当与extern一起合作的时候它的特性就跟extern的一样了所以对const我没有什么可以过多的描述我只是想提醒你const char* g_str 123456 与 const char g_str[] 123465是不同的 前面那个const 修饰的是char *而不是g_str,它的g_str并不是常量它被看做是一个定义了的全局变量可以被其他编译单元使用 所以如果你像让char*g_str遵守const的全局常量的规则最好这么定义const char* const g_str123456.
参考自https://www.cnblogs.com/yuxingli/p/7821102.html