OC中的全局变量,静态全局变量,常量,静态局部变量

作者:Love@YR
链接:http://blog.csdn.net/jingqiu880905/article/details/51997126
请尊重原创,谢谢!

首先说几个词:
头文件指.h文件,源文件指.m文件。

extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量或函数时,在其它模块中寻找其定义。另外,extern也可用来进行链接指定

用extern int a是声明,而直接int a或者int a =10 或者extern int a = 10是指定义。声明可以多次,定义只能一次。多次定义的那就不是同一个变量了。

全局变量是指定义在@implement(@interface)和@end之外的变量。全局变量即外部变量。

下面我们假设有4个文件,A.h A.m 和B.h B.m

  1. 在A.m里定义一个全局变量int i =1, 在B.m里直接访问。
    A中的任意方法都能访问i,但B中方法访问i时
    预编译不能通过,报use of undeclared identifier _i错误

  2. 在A.m里定义一个全局变量int i =1, 在B.m里 extern int i。
    A中的任意方法都能访问i,B中的方法对i也是可读可写。他们用的是同一个i

  3. 在A.m里定义一个静态全局变量static int i =1,在B.m里直接访问。
    A中的任意方法都能访问i,但B中方法访问i时
    预编译不能通过,报use of undeclared identifier _i错误

  4. 在A.m里定义一个静态全局变量static int i =1,在B.m里 extern int i;
    A中的任意方法都能访问i,但B中方法访问i时
    编译不能通过,报Undefined symbols i 错误

  5. 在A.m和B.m里分别定义静态全局变量static int i=200; static int i =300;
    则互不影响,有两个同名但不同存储位置的i,各源文件里的方法访问各自源文件里的i。

  6. 在A.m和B.m里分别定义静态全局变量static int i=200; 和全局变量 int i =300;
    仍然互不影响。如果我在A里extern int i了,A中方法访问的i仍然是200那个,而不是B中那个i

  7. 在A.m和B.m里分别定义全局变量int i=200; 和 int i =300;
    则编译不通过,报duplicate symbol _i错误
    同样在A.m和B.m里分别定义全局常量const int i =200;和全局变量int i =300 也编译不通过
    同样的上面7条都适用于全局常量。
    const int i = 11;和 static const int i =1
    不同的只是不加const可写,加了const只可读。

  8. 在A.h里声明全局变量extern int i;
    在A.m里定义全局变量int i = 1;
    在其他源文件里import "A.h"即可访问A中定义的i

结论:
非静态全局变量具有全局作用域。
其只需在一个源文件中定义,就可以作用于所有的源文件。
其他不包括全局变量定义的源文件可以通过extern的方式引用。 (对应第1,2条)

静态全局变量的作用域只在其源文件内,不能被其他源文件使用或修改,所以不必担心其它源文件使用相同变量名,彼此相互独立。 ( 对应第3,4,5条)

如果全局变量和局部变量重名,则在局部变量作用域内,全局变量会被屏蔽不起作用。(对应第6条)

全局变量不能被重复定义,可以多次声明( 对应第7条)

我们一般不要在.h文件里定义全局变量,这样一旦.h被import,相当于.h的代码拷过去一份,会出现多次定义的情况。
如果是非static的直接编译报错duplicate symbol 。
如果是static的,多少个源文件import就会生成多少个作用于此源文件的静态全局变量。(效果和第5条一样)

下面说下静态局部变量:
(非静态)全局变量的作用域是整个源程序,静态全局变量的作用域是定义它的那个源文件,静态局部变量的作用域是定义它的那个方法。

以上三者都是在静态数据存储区分配,只在程序开始运行时初始化一次(并不是该类实例化后才初始化的),程序运行期间一直都在,自动赋值为缺省值。
都是在编译时就初始化了。
在下一次使用时还能保存原来的赋值

所以说上面三者是存储位置和生命周期都一样,作用域不同。static关键字告知编译器自己仅在变量的作用域范围内可见。

所以说如果一个方法里有句static int i = 9; 并不是每次走到这个方法的时候这个i就赋值成9了,只是初始化的时候是9而已,实际上编译之后相当于这句话被从此方法里拿出来了。

而非静态的局部变量存储在栈上,出了方法就释放了。下次使用就新初始化一下

最后说一下关于定义在@implement 和@end之外的C函数:
C函数不依赖于类和对象。
作用域为定义它的源文件。其他文件需要调用import就可以了。
参考:http://bbs.itheima.com/thread-138029-1-1.html

再最后说下关于OC里的类方法:


  self.arr =[@[@"str1", @"str2"]mutableCopy];
    [FirstViewController anyClassMehodWithParam:self.arr];
    
    
+(void)anyClassMehodWithParam:(NSMutableArray *)arr
{
    variableStr =@"";//实例变量variableStr,报错
    [self.arr replaceObjectAtIndex:0 withObject:@"modifiedStr1"];//arr属性,报错
    
    NSLog(@"arr is %@",arr);
    [arr replaceObjectAtIndex:0 withObject:@"modifiedStr1"];
    
    [self anyClassMethod];//类方法
   
    [self deallocReloadable];//实例方法,报错
    FirstViewController *fv = [[self alloc]init];
    [fv deallocReloadable];
    
	timeDuration=22;//全局变量timeDuration
	i = 33;//静态全局变量i
	static int i =6;
    NSLog(@"i = %d",i);//静态局部变量i

}

上面例子说明:
类方法里不能访问实例变量instance variable
类方法里不能访问属性
类方法里不能直接调用实例方法

类方法可以直接调用类方法(用self)
类方法可以直接访问全局和静态变量
类方法可以通过创建对象来访问实例方法

1.栈 - 由编译器自动分配释放
2.堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收
3.全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。- 程序结束释放
4.另外还有一个专门放常量的地方。- 程序结束释放

全局方法或变量是在一个.m文件的@implement之前或者在@end之后定义的方法或者变量
或者 在一个.h文件的@interface之前或者在@end之后声明的方法或者变量
方法前无+/-, 因为和类无关了,不能用self调用,也不能用类名调用
如void add() 直接调用就add();

2018年10月25日补充:
在a.h里static CGFloat cellHeight = 30;
然后某个b.m里引用此a.h
会生成一个不同的cellHeight (相当于多次定义 那么就不是同一个变量)
在b.m里把cellHeight重新赋值为60,会发现a.m中的值不会改变!
所以 不要把static 变量放.h里定义然后在.m里引用.h!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值