有C++基础学OC有多快?10分钟搞定变量和基本数据类型
有C++基础学OC有多快?10分钟搞定变量和基本数据类型👋
哈喽各位有C++基础的小伙伴们!如果你正准备入坑iOS开发,那恭喜你——OC的基本数据类型和变量这块,你几乎已经会了90%!因为OC本身就是C语言的超集,C++又是基于C扩展的,所以很多概念和语法都是完全通用的。今天我们就用最快的速度把剩下10%的差异点和坑点彻底搞懂,看完就能直接写OC的基础代码啦!
变量的声明与初始化 👋
概念解释
变量就像你电脑里的文件夹,先给它起个名字,指定它能存什么类型的文件,然后就能往里面放数据了。OC的变量声明遵循“类型+变量名”的格式。
C++类比
变量声明的语法结构和C++完全一致,唯一的核心区别是:OC的所有可执行代码必须写在@autoreleasepool{}块内部(main函数里),这是OC内存管理机制的要求,而C++的代码直接写在main函数里就行。
✅ Objective-C 完整代码
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool { // OC特有:所有可执行代码必须写在这里
// 先声明,再赋值
int age;
age = 22;
// 声明同时初始化(推荐写法)
float height = 1.75f;
char gender = 'M';
NSLog(@"年龄:%d,身高:%.2f,性别:%c", age, height, gender);
}
return 0;
}
🆚 对应的 C++ 对比代码
#include <iostream>
using namespace std;
int main() {
// 代码直接写在main函数里即可
int age;
age = 22;
float height = 1.75f;
char gender = 'M';
cout << "年龄:" << age << ",身高:" << height << ",性别:" << gender << endl;
return 0;
}
避坑指南
💣 坑点1:忘记把代码写在@autoreleasepool里
错误代码示例:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
int age = 22; // 错误:代码不在@autoreleasepool内
NSLog(@"年龄:%d", age);
return 0;
}
正确代码示例:参考上面的OC完整代码,所有可执行代码都包裹在@autoreleasepool{}中。
💣 坑点2:变量未初始化就使用
和C++完全一样,未初始化的局部变量会存储垃圾值,导致程序运行结果异常。
错误代码示例:
int score;
NSLog(@"分数:%d", score); // 输出随机垃圾值
正确代码示例:
int score = 0; // 初始化默认值
NSLog(@"分数:%d", score); // 输出0
核心基本数据类型详解 ✨
OC的基本数据类型完全继承自C语言,所以和C++的基本类型几乎100%一致,只有一个BOOL类型是OC特有的,需要特别注意。
2.1 整数类型(int、short、long、long long)
概念解释
用来存储没有小数的数字,不同类型的区别是占用内存大小不同,能表示的数值范围也不同。
C++类比
和C++完全一致,包括signed(有符号,默认)和unsigned(无符号)修饰符的用法,占用字节数也和C++相同(32/64位系统下int均占4字节)。
✅ Objective-C 代码
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
int a = 100;
short b = 32767; // short类型最大值
long c = 100000L; // long常量加L后缀
long long d = 10000000000LL; // long long常量加LL后缀
unsigned int e = 200; // 无符号整数
NSLog(@"int: %d, short: %hd, long: %ld, long long: %lld, unsigned: %u", a, b, c, d, e);
}
return 0;
}
🆚 对应的 C++ 代码
#include <iostream>
using namespace std;
int main() {
int a = 100;
short b = 32767;
long c = 100000L;
long long d = 10000000000LL;
unsigned int e = 200;
cout << "int: " << a << ", short: " << b << ", long: " << c << ", long long: " << d << ", unsigned: " << e << endl;
return 0;
}
避坑指南
💣 坑点:整数溢出
和C++完全一样,当赋值超过类型能表示的最大值时,会发生溢出,结果未定义。
错误代码示例:
short maxShort = 32767;
short overflow = maxShort + 1; // 溢出,结果为-32768
NSLog(@"overflow: %hd", overflow);
正确做法:根据数值大小选择合适的类型,大数值优先使用long long。
2.2 浮点类型(float、double)
概念解释
用来存储带小数的数字,float是单精度(占4字节),double是双精度(占8字节,精度更高)。
C++类比
和C++完全一致,默认的浮点常量(如3.14)是double类型,float常量需要加f后缀(如3.14f)。
✅ Objective-C 代码
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
float piFloat = 3.14159f; // float常量必须加f后缀
double piDouble = 3.141592653589793; // 默认是double类型
NSLog(@"float精度: %.7f", piFloat); // 保留约6-7位有效数字
NSLog(@"double精度: %.15f", piDouble); // 保留约15-16位有效数字
}
return 0;
}
🆚 对应的 C++ 代码
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
float piFloat = 3.14159f;
double piDouble = 3.141592653589793;
cout << "float精度: " << fixed << setprecision(7) << piFloat << endl;
cout << "double精度: " << fixed << setprecision(15) << piDouble << endl;
return 0;
}
避坑指南
💣 坑点:用float存储高精度小数导致精度丢失
错误代码示例:
float money = 99.99f;
NSLog(@"金额:%.2f", money); // 可能输出99.98,精度丢失
正确代码示例:
double money = 99.99; // 用double存储高精度小数
NSLog(@"金额:%.2f", money); // 输出99.99
2.3 字符类型(char)
概念解释
用来存储单个字符,本质是1字节的整数,存储的是字符的ASCII码值。
C++类比
和C++完全一致,字符用单引号包裹,双引号包裹的是字符串。
✅ Objective-C 代码
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
char ch1 = 'A';
char ch2 = 65; // 直接用ASCII码赋值,和'A'等价
NSLog(@"ch1: %c, ASCII码: %d", ch1, ch1);
NSLog(@"ch2: %c, ASCII码: %d", ch2, ch2);
}
return 0;
}
🆚 对应的 C++ 代码
#include <iostream>
using namespace std;
int main() {
char ch1 = 'A';
char ch2 = 65;
cout << "ch1: " << ch1 << ", ASCII码: " << (int)ch1 << endl;
cout << "ch2: " << ch2 << ", ASCII码: " << (int)ch2 << endl;
return 0;
}
避坑指南
💣 坑点:用双引号包裹字符
错误代码示例:
char ch = "A"; // 错误:"A"是字符串,不是单个字符
正确代码示例:
char ch = 'A'; // 正确:单引号包裹单个字符
2.4 OC特有的布尔类型(BOOL)💡
概念解释
OC的BOOL类型用来表示真和假,取值为YES和NO。但注意!BOOL本质上是typedef signed char BOOL;,也就是说它其实是一个1字节的有符号整数。
C++类比
和C++的bool类型有本质区别!C++的bool是真正的布尔类型,只能存true和false两个值;而OC的BOOL本质是char,任何非0值都会被当作YES。
✅ Objective-C 代码
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// OC的BOOL本质是signed char,YES=1,NO=0
BOOL isSuccess = YES;
BOOL isError = NO;
NSLog(@"isSuccess: %d, isError: %d", isSuccess, isError); // 输出1和0
// 非0值都会被当作YES
BOOL flag1 = 2;
BOOL flag2 = -1;
NSLog(@"flag1: %d, flag2: %d", flag1, flag2); // 输出2和-1
}
return 0;
}
🆚 对应的 C++ 代码
#include <iostream>
using namespace std;
int main() {
// C++的bool是真正的布尔类型,只能存true和false
bool isSuccess = true;
bool isError = false;
cout << "isSuccess: " << isSuccess << ", isError: " << isError << endl; // 输出1和0
// 其他值会被自动转换为1或0
bool flag1 = 2; // 转换为true(1)
bool flag2 = -1; // 转换为true(1)
cout << "flag1: " << flag1 << ", flag2: " << flag2 << endl; // 输出1和1
return 0;
}
避坑指南(OC最容易踩的坑!)
💣 坑点1:直接用整数赋值给BOOL,导致逻辑错误
错误代码示例:
int result = 3;
BOOL isTwo = result; // 本意是判断result是否等于2
if (isTwo) {
NSLog(@"result等于2"); // 这里会执行!因为3是非0值
}
正确代码示例:
int result = 3;
BOOL isTwo = (result == 2); // 用比较表达式赋值,结果只能是YES或NO
if (isTwo) {
NSLog(@"result等于2"); // 不会执行,逻辑正确
}
💣 坑点2:用== YES判断BOOL值
错误代码示例:
BOOL flag = 2;
if (flag == YES) { // YES是1,2不等于1,条件不成立
NSLog(@"flag为真"); // 不会执行,但flag实际为真
}
正确代码示例:
BOOL flag = 2;
if (flag) { // 直接判断,非0即为真
NSLog(@"flag为真"); // 正确执行
}
常量的定义方式 📌
常量就是一旦定义就不能修改的量,OC有两种常用的定义方式,和C++完全一致。
3.1 #define宏常量
概念解释
预处理阶段的文本替换,没有类型检查,直接把宏名替换成后面的内容。
C++类比
和C++完全一致,用法和注意事项都相同。
✅ Objective-C 代码
#import <Foundation/Foundation.h>
#define PI 3.1415926
#define MAX(a,b) ((a)>(b)?(a):(b)) // 带参数的宏
int main(int argc, const char * argv[]) {
@autoreleasepool {
double radius = 5.0;
double area = PI * radius * radius;
NSLog(@"圆的面积:%.2f", area);
int x = 10, y = 20;
NSLog(@"最大值:%d", MAX(x, y));
}
return 0;
}
🆚 对应的 C++ 代码
#include <iostream>
using namespace std;
#define PI 3.1415926
#define MAX(a,b) ((a)>(b)?(a):(b))
int main() {
double radius = 5.0;
double area = PI * radius * radius;
cout << "圆的面积:" << area << endl;
int x = 10, y = 20;
cout << "最大值:" << MAX(x, y) << endl;
return 0;
}
避坑指南
💣 坑点:宏定义不加括号,导致运算优先级错误
错误代码示例:
#define ADD(a,b) a+b
int result = ADD(2,3) * 4; // 替换后是2+3*4=14,不是预期的20
NSLog(@"result: %d", result);
正确代码示例:
#define ADD(a,b) ((a)+(b)) // 每个参数和整个表达式都加括号
int result = ADD(2,3) * 4; // 替换后是((2)+(3))*4=20
NSLog(@"result: %d", result);
3.2 const修饰的常量
概念解释
有类型检查的常量,编译阶段确定值,存储在常量区,不能修改。
C++类比
和C++完全一致,const修饰的变量是只读的,定义时必须初始化。
✅ Objective-C 代码
#import <Foundation/Foundation.h>
const int MAX_AGE = 120;
const double PI = 3.1415926;
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"最大年龄:%d", MAX_AGE);
NSLog(@"圆周率:%.7f", PI);
}
return 0;
}
🆚 对应的 C++ 代码
#include <iostream>
using namespace std;
const int MAX_AGE = 120;
const double PI = 3.1415926;
int main() {
cout << "最大年龄:" << MAX_AGE << endl;
cout << "圆周率:" << PI << endl;
return 0;
}
避坑指南
💣 坑点:试图修改const常量
错误代码示例:
const int MAX_AGE = 120;
MAX_AGE = 150; // 编译错误:只读变量不能被修改
正确做法:const常量定义时必须初始化,之后不能再修改。
数据类型转换 🔄
当不同类型的数据一起运算时,会发生类型转换,分为隐式转换和显式转换,和C++完全一致。
4.1 隐式类型转换
概念解释
编译器自动进行的转换,规则是“小范围类型向大范围类型转换”,避免数据丢失。
C++类比
和C++完全一致,转换顺序为:char → short → int → long → long long → float → double。
✅ Objective-C 代码
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
int a = 10;
double b = 3.14;
double result = a + b; // int自动转换为double
NSLog(@"result: %.2f", result); // 输出13.14
}
return 0;
}
🆚 对应的 C++ 代码
#include <iostream>
using namespace std;
int main() {
int a = 10;
double b = 3.14;
double result = a + b;
cout << "result: " << result << endl;
return 0;
}
4.2 显式类型转换(强制转换)
概念解释
程序员手动指定转换类型,用于把大范围类型转换为小范围类型。
C++类比
和C++的C风格强制转换完全一致,OC不支持C++的static_cast、dynamic_cast等新式转换语法。
✅ Objective-C 代码
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
double pi = 3.14159;
int intPi = (int)pi; // 强制转换为int,丢失小数部分
NSLog(@"intPi: %d", intPi); // 输出3
}
return 0;
}
🆚 对应的 C++ 代码
#include <iostream>
using namespace std;
int main() {
double pi = 3.14159;
int intPi = (int)pi; // C风格强制转换
// C++新式转换:int intPi = static_cast<int>(pi);
cout << "intPi: " << intPi << endl;
return 0;
}
避坑指南
💣 坑点:大类型转小类型导致数据丢失
错误代码示例:
long long bigNum = 10000000000LL;
int smallNum = (int)bigNum; // long long转int,数据丢失
NSLog(@"smallNum: %d", smallNum); // 输出随机值
正确做法:确保转换后的值在目标类型的范围内,否则不要强制转换。
变量的作用域与生命周期 🕒
变量的作用域指的是变量能被访问的范围,生命周期指的是变量从创建到销毁的时间,和C++完全一致。
概念解释
- 局部变量:定义在函数或代码块内,作用域是当前代码块,生命周期是代码块执行期间。
- 全局变量:定义在函数外部,作用域是整个程序,生命周期是程序运行期间。
- 静态局部变量:用
static修饰的局部变量,作用域是当前代码块,生命周期是程序运行期间,只初始化一次。
C++类比
和C++完全一致,包括static修饰符的用法和效果。
✅ Objective-C 代码
#import <Foundation/Foundation.h>
int globalVar = 100; // 全局变量
void test() {
static int staticVar = 0; // 静态局部变量,只初始化一次
int localVar = 0; // 局部变量,每次调用都重新初始化
staticVar++;
localVar++;
NSLog(@"staticVar: %d, localVar: %d", staticVar, localVar);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
test(); // 输出staticVar: 1, localVar: 1
test(); // 输出staticVar: 2, localVar: 1
test(); // 输出staticVar: 3, localVar: 1
NSLog(@"globalVar: %d", globalVar); // 输出100
}
return 0;
}
🆚 对应的 C++ 代码
#include <iostream>
using namespace std;
int globalVar = 100;
void test() {
static int staticVar = 0;
int localVar = 0;
staticVar++;
localVar++;
cout << "staticVar: " << staticVar << ", localVar: " << localVar << endl;
}
int main() {
test();
test();
test();
cout << "globalVar: " << globalVar << endl;
return 0;
}
避坑指南
💣 坑点:全局变量命名冲突
和C++一样,全局变量在整个程序中可见,多个文件定义同名全局变量会导致链接错误。
正确做法:尽量少用全局变量,必须用时用static修饰,限制其作用域在当前文件内。
static int fileGlobalVar = 200; // 只在当前文件可见
总结 🎯
今天我们把OC的变量和基本数据类型全部过了一遍,核心要点其实就5个:
- 除了BOOL类型,OC的所有基本数据类型(int、float、double、char)和C++完全一致,语法和用法无缝衔接。
- OC的BOOL本质是
signed char,判断时直接用if(flag),绝对不要用if(flag==YES)。 - OC的所有可执行代码必须写在
@autoreleasepool{}块内,这是和C++最大的语法区别之一。 - 常量定义推荐用
const代替#define,因为const有类型检查,更安全也更容易调试。 - 类型转换、变量作用域和生命周期的规则和C++完全相同,之前学的知识直接套用就行。
怎么样,是不是感觉OC入门其实很简单?搞定了基础数据类型,下一篇我们就正式进入OC的面向对象世界,学习类和对象的定义,看看OC的类和C++的类有什么不一样。
更多推荐


所有评论(0)