面试常见问题很常

iOS const,static,extern,宏

2021-03-29  本文已影响0人  学不来的凡人

1.const (常量)

const的作用和宏是很类似的,当有字符串常量的时候,苹果推荐我们使用const,苹果经常把常用字符串定义成const。
const仅仅用来修饰右边的变量(基本数据变量p,指针变量*p,对象变量)
被const修饰的变量是只读的且是全局的。

const 与宏的区别

 1.编译时刻 : const: 编译时刻 ,  宏:预编译
 2.编译检查: const  会检查错误 , 宏: 不会检查错误
 3.宏的好处: 可以定义代码
 4.宏的坏处: 编译时间过长, 因此常用的字符串通常使用 const修饰
 注意:很多博客说宏使用的多了会造成内存不断增加,每次都会分配一个内存, 打印地址可以验证

const 作用:

 1.仅仅是用来修饰右边的变量(只能修饰变量:基本变量,指针变量,对象变量)
 2.const修饰的变量表示只读
    int * const p; // p:只读 *p:变量
    const int *p1; // *p1:只读 p1:变量
    int const *p2; // *p2:只读 p2:变量
    int const * const p3; // *p3:只读 p3:只读
    const int  * const p4; // *p4:只读 p4:只读

2.static

static作用

 1.修饰局部变量 
   * 延长这个局部变量的生命周期,只要成员运行,局部变量就会一直存在 
   * 局部变量只会分配一次内存,为什么?用 static修饰的代码,只会在程序一启动,就会执行,以后就不会再执行 
 2.修饰全局变量 
   * 只会修改全局变量的作用域,表示会只能是当前文件使用

static修饰变量注意点

用于定义一个内部全局变量
为了提高数据的安全性, 不让别人在其它文件中修改我们的全局变量
只要用static修改的全局变量就是内部全局变量, 只能在当前文件中使用
如果多个文件中存在同名的内部全局变量, 相互不会影响
如果既有外部全局变量也有内部全局变量, 那么会优先访问内部全局变量

3.extern

作用:

extern主要是用来引用全局变量,它的原理就是先在本文件中查找,本文件中查找不到再到其他文件中查找。
用于声明一个外部全局变量,声明变量是其他文件的外部变量。
不能定义变量
声明只需要在使用变量之前声明就可以了

声明和定义的区别:(声明不会开辟存储空间,定义会开辟存储空间)
注意:UIKIT_EXTERN == extern

总结:

用法总结:
 1. 在函数外,直接定义对象,不需要额外添加修饰符,对象可被修改; 一般形式的全局变量
 2. 只用static修饰,对象可以被修改,但是生命周期在APP运行期; 用static修饰就是静态变量(也叫全局静态变量),不用static修饰的就是全局非静态变量;
 修饰局部变量:让局部变量只初始化一次;局部变量在程序中只有一份内存;并不会改变局部变量的作用域,仅仅是改变了局部变量的生命周期(只到程序结束,这个局部变量才会销毁)
 修饰全局变量:全局变量的作用域仅限于当前文件
 
 3. 用const修饰:一般不定义在本文件内,字符串可以被修改,也可以不被修改(主要);用const修饰的就是常量;全局非静态/静态常量
 4. 用static,const一起修饰:全局静态常量,在本文件内字符串可以被修改,也可以不被修改(主要);

 常用的三种:
 1. static 修饰全局静态变量,比如cell的标识符
 2. static+const在本文件内使用,修饰不可变字符串,全局静态常量
 3. const在单独一个文件内使用,修饰字符串,变成不可变的常量。
 */

4. 宏

宏的常见用法(常见字符串抽成宏,常见代码抽成宏)当有字符串常量的时候,苹果推荐我们使用const,苹果经常把常用字符串定义成const

宏与const的区别:

编译时刻:宏是预编译(编译之前处理),const是编译阶段。
编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。
宏的好处:宏能定义一些函数,方法。 const不能。
宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换。
注意:swift中, 苹果已经将宏杀掉, 所以项目开发中, 须用const代替宏.

宏定义:

//注意:
//1.宏名和参数列表之间不能有空格,否则空格后面的所有字符串都作为替换的字符串。
//2.带参数的宏在展开时,只作简单的字符和参数的替换,不进行任何计算操作。所以在定义宏时,一般用一个小括号括住字符串的参数。并且计算结果最好也括起来防止错误。


#define NAME @"henry"  //不带参数的宏定义 (格式: #define 标示符 字符串(“字符串”可以是常数、表达式、格式串等。)宏名的有效范围是从定义位置到文件结束。如果需要终止宏定义的作用域,可以用#undef命令。)
#define average(a, b) (a+b)/2 //带参数的宏定义:(对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。格式:#define 宏名(形参表) 字符串)
//条件编译后面的条件表达式中不能识别变量,它里面只能识别常量和宏定义
#define SCORE 67
#if SCORE > 90
    //("优秀\n");
#elif SCORE > 60
    //NSLog("良好\n");
#else
    //NSLog("不及格\n");
#endif

#ifdef MACRO_Define  // 如果已定义MACRO_Define这个宏
    //代码块1
#else
    //代码块2
#endif

5. 结构体,枚举(typeof与typedef)

typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型。可以理解为:我们根据typeof()括号里面的变量,自动识别变量类型并返回该类型。
typeof 常见运用于Block中,避免循环引用发生的问题。
用法:

//定义一个和self相同数据类型的bself ,并赋值为self,在block中使用
__weak typeof (self) weakSelf = self;

注意: typeof 括号中的值和等于后面的值是相同的类型。

__weak typeof(self.contentView) ws = self.contentView;

typedef:定义一种类型的别名,而不只是简单的宏替换。
typedef 常用于命名(枚举和Block)
用法1-结构体

//结构体
typedef struct Myrect {
    float width;
    float height;
}myRect;

用法2-枚举

//枚举值 它是一个整形(int)  并且,它不参与内存的占用和释放,枚举定义变量即可直接使用,不用初始化.
//在代码中使用枚举的目的只有一个,那就是增加代码的可读性.
typedef NS_ENUM (NSUInteger,direction){
    left=0,
    right=1,
    top =2,
    down =3
};
typedef NS_ENUM (NSUInteger,direction_2){
    left2 = 0,
    right2 = 1 << 0,
    top2 = 1 << 1,
    down2 = 1 << 2
};

用法3-Block

//1.重新起个名字
typedef void(^PassValueBlock)(NSString *);
@interface BlockViewController : BaseViewController
//2.声明block属性
@property(nonatomic,copy)PassValueBlock  passValueBlock;
上一篇下一篇

猜你喜欢

热点阅读