资讯动态

第二章 数据类型和运算符

发布时间:2026/10/22 17:39:30 来源:尧图企业网站定制
第二章 数据类型和运算符┌────────────────────────────────────────────────────────────────┐ │ 这一章要讲的事一张图看完 │ ├────────────────────────────────────────────────────────────────┤ │ 第二章 数据类型和运算符 │ │ │ │ │ ├── 1. C 基本数据类型 整型浮点字符布尔各占多大地方 │ │ ├── 2. 常量和变量 认领内存的规矩命名和初始化 │ │ ├── 3. 运算符 加减乘除到移位外加优先级 │ │ ├── 4. 数据类型转换 隐式自动转显式手动转坑最多 │ │ └── 5. 小结 一张表收口加练习和下一章预告 │ └────────────────────────────────────────────────────────────────┘老规矩例子都自己敲一遍。这一章尤其别偷懒类型和运算符的细节看的时候都懂一写就错不敲一遍发现不了。一、C 基本数据类型┌──────────────────────────────────────────────────┐ │ C 类型的家谱 │ ├──────────────────────────────────────────────────┤ │ 一套类型一套脾气各管各的 │ │ │ │ 整型 │ │ ├─ short 2 字节小整数 │ │ ├─ int 4 字节日常主力 │ │ ├─ long 4 或 8 字节看平台 │ │ └─ long long 8 字节大数专用 │ │ 每家整型都有带符号和不带符号两版 │ │ 不带符号的只放 0 和正数范围翻倍 │ │ │ │ 浮点型 float、double、long double管小数 │ │ 字符型 char一个字节存的是编号 │ │ 布尔型 bool一个字节只放 true 和 false │ └──────────────────────────────────────────────────┘1.1 类型是内存的图纸内存是一条超长的字节带一个字节 8 位每个字节有自己的地址。同样的字节序列按不同类型解释读出来的东西完全不同。类型就是图纸它告诉编译器这几字节按什么规矩摆、怎么读。比如 0x01020304 这四字节当成四个编号看是四个小数字当成一个 int 看就是 16909060。声明类型就是提前把图纸交给编译器后面怎么摆怎么算全按它来。┌────────────────────────────────────────────────────────┐ │ 一个 int 的四字节怎么摆 │ ├────────────────────────────────────────────────────────┤ │ 同一个数字节顺序两样0x01020304就是 16909060 │ │ │ │ 小端低字节放低地址 大端高字节放低地址 │ │ │ │ 地址 0 04 地址 0 01 │ │ 地址 1 03 地址 1 02 │ │ 地址 2 02 地址 2 03 │ │ 地址 3 01 地址 3 04 │ │ │ │ x86 和主流 ARM 用这套 网络传输和部分老平台 │ │ │ │ 两种摆法读出来都是同一个数自己电脑上不用操心 │ │ 跨机器传二进制才分大小端那是网络编程的事 │ └────────────────────────────────────────────────────────┘int 的四字节怎么摆有大小端两种规矩。普通开发者一辈子感知不到这个差别除非去写网络协议或者跟别的机器交换二进制文件所以这页图看过就算了不用记。1.2 整型一家整型管整数按能放多大的数分四档每一档都有带符号和不带符号两个版本。带符号的能放负数是默认版本不带符号的只放 0 和正数范围翻倍。类型字节能放的范围short2-32768 到 32767unsigned short20 到 65535int4-2147483648 到 2147483647unsigned int40 到 4294967295long4 或 8看平台Windows 上 4Linux 上 8long long8-9223372036854775808 到 9223372036854775807unsigned long long80 到 18446744073709551615日常用 int 就够。数大的场合销量、库存、金额乘个几百倍就可能过 21 亿上 long long。计数、编号、位运算这种不会出现负数的场景用 unsigned 就对了。有一条要注意C 标准只规定了每种类型的最小范围没规定精确字节数。long 在 Windows 上是 4 字节在 Linux 上是 8 字节同一份代码两边行为不一致。要精确控制宽度后面章节有固定宽度类型现在先知道这个坑。1.3 浮点型浮点型管小数三兄弟按精度排。类型字节有效数字大致范围float4约 7 位1.2e-38 到 3.4e38double8约 15 到 16 位2.2e-308 到 1.8e308long double看平台不低于 double看平台写代码时 3.14 默认是 double要 float 得加后缀3.14f。多数场合用 double精度够速度也不慢。浮点数有个著名陷阱。0.1 这个数二进制里存不住精确值存进去的是近似值两个近似值加起来误差就露出来了。0.1 0.2 的结果是 0.30000000000000004所以比较浮点数别用 要看两个数的差距够不够小。差值的绝对值小于 1e-6就当它们相等这是惯用写法。涉及钱的计算更别碰浮点用整数存分显示的时候再除以 100一分钱都不许它飘。1.4 字符型和布尔型char 一个字节存的是编号不是字本身。字符按 ASCII 编号入库A 是 65a 是 97大小写相差 320 是 48。char 参与运算时按整数算A 1 等于 66正好是 B。常用的转义字符有这么几个。转义符含义\n换行\t制表符按一下 Tab 那么宽\反斜杠自己双引号单引号\0空字符字符串的结尾标记bool 一个字节只放 true 和 false。C 里非零即真0 为假这个习惯后面到处都用。1.5 一张表记住常见占用每种类型占几个字节不用背写几行代码问出来。#include iostream using namespace std; int main() { cout bool sizeof(bool) 字节 endl; cout char sizeof(char) 字节 endl; cout short sizeof(short) 字节 endl; cout int sizeof(int) 字节 endl; cout long sizeof(long) 字节 endl; cout long long sizeof(long long) 字节 endl; cout float sizeof(float) 字节 endl; cout double sizeof(double) 字节 endl; return 0; }64 位机器上跑出来是这样。bool 1 字节 char 1 字节 short 2 字节 int 4 字节 long 4 字节 long long 8 字节 float 4 字节 double 8 字节64 位 Windows 和 64 位 Linux 的差别在 long其他一样。自己的机器什么结果敲一遍就知道比信任何教程都强。二、常量和变量2.1 变量是认领下来的一块内存变量就是在内存里认领一块地认领的时候要说清三样这块地多大、叫什么、先放什么。┌─────────────────────────────────────────────────────────┐ │ 变量是认领下来的一块内存 │ ├─────────────────────────────────────────────────────────┤ │ 一条声明三样东西 │ │ │ │ ------------------------------------------------ │ │ |成分 |代码里 |例子 |管什么 | │ │ ------------------------------------------------ │ │ |类型 |int |4 字节 |格子多大 | │ │ |名字 |score |贴标签 |代码怎么称呼它| │ │ |值 |90 |装内容 |随时能改 | │ │ ------------------------------------------------ │ │ │ │ int score 90; 这一行三样全占齐 │ │ 没初始化的变量里是内存残留读到什么全看运气 │ └─────────────────────────────────────────────────────────┘声明的时候不给初值这块地里的数据是上一位房客留下的。同一个程序跑两遍读到的数可能都不一样这种 bug 查起来最费劲。好习惯只有一条声明的时候就初始化。初始化的写法有四种效果等价。int a 5; // 传统写法 int b(5); // 构造函数写法 int c{5}; // 列表初始化C11 起 int d{}; // 列表初始化值为 0推荐列表初始化那一对花括号。它多一道检查窄化转换直接拦下。int x{3.7}; // 编译报错小数变整数不许悄悄发生 int y 3.7; // 能过y 变成 3小数部分丢了同一行声明多个同类型变量也合法int a 1, b 2;。别滥用一行一个看得清楚。2.2 命名规则名字只能由字母、数字、下划线组成数字不能打头大小写敏感不能撞关键字。名字行不行原因score行纯字母score2行数字不在开头_total行下划线可以开头2score不行数字打头my-score不行短横线不是下划线int不行撞了关键字Score 和 score两个名字大小写敏感风格上建议两条。名字见名知意totalPrice 比 tp 强一百倍三个月后回来看tp 是谁你根本想不起来。多个单词之间用下划线或者驼峰选一种用到底别混着来。2.3 常量认领了就不许改常量的值定下来不许改写法有两种。#define MAX_SIZE 100 // 宏常量 const int maxSize 100; // const 常量推荐 const。宏常量是预处理阶段的文本替换编译器只看见 100不知道它原来叫什么出错了报错信息里连名字都不留。const 常量有类型、有名字受编译器检查还能进调试器看。#defineconst干活阶段预处理文本替换编译期有类型吗没有有出错了只看见数值看不见名字名字和类型都在报错里能进调试器吗不能能const 后面还有花样const 指针、const 引用、const 成员函数到指针和类那两章再展开。现在记住一句新代码用 const别用宏。2.4 关键字这些名字被占了C 留了一批名字自己用变量不能跟它们重名。常用的有这么些。类别关键字类型相关int、double、float、char、bool、void、short、long类型修饰const、unsigned、signed、static、auto流程相关if、else、switch、case、default、for、while、do、break、continue、return真值与内存true、false、sizeof、new、delete、this结构和类struct、class、public、private、protected、enum、union其他using、namespace、typedef、try、catch、throw完整名单有九十多个不用背。用到的时候编辑器会给它上个色变色了就别当变量名。三、运算符3.1 算术运算符运算符作用例子加3 2 得 5-减3 - 2 得 1*乘3 * 2 得 6/除看两边类型见下%取余7 % 3 得 1只认整数除号是重灾区。两边都是整数除出来还是整数小数部分直接丢不是四舍五入。┌─────────────────────────────────────────────────────┐ │ 整数除法不要小数 │ ├─────────────────────────────────────────────────────┤ │ 同样的两个数不同的下场 │ │ │ │ 7 / 2两边都是整数 7.0 / 2有个小数 │ │ │ │ │ │ v v │ │ 3小数部分被丢掉 3.5小数保住了 │ │ │ │ 算平均数、算比例、算百分比先把一边转成 double │ └─────────────────────────────────────────────────────┘把开篇那个平均分程序写全看得更清楚。#include iostream using namespace std; int main() { int total 285; int count 3; cout total / count endl; // 95碰巧整除了 cout total / 4 endl; // 7171.25 被丢成 71 return 0; }取余号只认整数3.5 % 2 直接编不过。除零更狠整数除以 0 程序当场崩溃浮点除以 0 得 inf不报错但结果没法用。3.2 赋值和复合赋值等号是赋值把右边的值装进左边的变量不是数学里的相等。等号左边只能放一个变量a b 3能写从右边开始算b 先得 3再把 b 的值给 a。复合赋值是懒人写法效果和拆开一样。写法等价于a 2a a 2a - 2a a - 2a * 2a a * 2a / 2a a / 2a % 2a a % 23.3 自增自减 放前放后不一样 让变量加一-- 让变量减一各有两种放法差别只在嵌进表达式的时候露出来。┌────────────────────────────────────────────────────┐ │ 放前面和放后面 │ ├────────────────────────────────────────────────────┤ │ i 从 3 起步两条路不一样 │ │ │ │ j i j i │ │ 先用旧值再加一 先加一新再用新值 │ │ │ │ │ │ v v │ │ j 得 3i 变 4 j 得 4i 变 4 │ │ │ │ 单独一行用没区别嵌进表达式就差在这里 │ └────────────────────────────────────────────────────┘代码走一遍。#include iostream using namespace std; int main() { int i 3; int j i; // 先把 3 给 ji 再加成 4 cout j i endl; // 3 4 int x 3; int y x; // x 先加成 4再把 4 给 y cout y x endl; // 4 4 return 0; }建议只有一条别把 塞进复杂表达式cout i i这种代码除了炫技没有任何好处行为还容易看错。3.4 关系运算符比大小和比相等结果都是 bool成立是 true不成立是 false。运算符作用大于小于大于等于小于等于相等两个等号!不相等经典事故是把 写成 。if (x 5)是赋值5 非零条件恒为真if 里永远执行。现代编译器会给警告警告别当没看见。浮点数之间别用 比回 1.3 节用差值小于一个小数来判断。3.5 逻辑运算符和短路运算符作用两边都真才真两个竖线有一边真就真!取反真变假假变真 和 两个竖线会抄近路。左边已经能定输赢右边根本不看。┌──────────────────────────────────────────────────────────┐ │ 逻辑运算会抄近路 │ ├──────────────────────────────────────────────────────────┤ │ 碰到假就收工|| 碰到真就收工 │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ if (x ! 0 10 / x 1) │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ 左边先算x 是 0 的话整个式子直接假 │ │ 右边的除法压根不发生顺手把除零也挡了 │ │ │ │ 判空的表达式要写在左边越界访问放右边 │ │ 顺序写反了右边先炸左边白写 │ └──────────────────────────────────────────────────────────┘短路是标准规定的行为不是哪个编译器的好心可以放心用。写复合条件有个讲究便宜又安全的放左边贵又有风险的放右边。3.6 位运算符位运算直接在二进制位上动手只认整型。运算符叫什么例子结果和规律按位与5 31两位都是 1 才留 1单竖线按位或5 单竖线 37有一位是 1 就留 1^按位异或5 ^ 36相同为 0不同为 1~按位取反~5-60 变 11 变 0左移5 220后面补 0右移5 12前面补 0左移就是往高位搬每搬一位数值翻倍。┌──────────────────────────────────────────────────────────┐ │ 左移右移在干什么 │ ├──────────────────────────────────────────────────────────┤ │ 1 往左搬三位每搬一位翻一倍 │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ 起步 00000001 十进制 1 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ 左移一位 00000010 十进制 2 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ 左移两位 00000100 十进制 4 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ 左移三位 00001000 十进制 8 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ 右移是反着搬每搬一位除以 2零头丢掉 │ │ 1 10 就是 1024乘除 2 的幂用它最快 │ └──────────────────────────────────────────────────────────┘位运算的实用场合有两个。权限标志一个 int 的 32 位当 32 个开关用第 n 位是 1 表示有这个权限。判奇偶x 1是 1 就是奇数是 0 就是偶数比取余快。乘除 2 的幂图上画了记住位移比乘法快就行。两个注意。有符号数左移丢了高位是未定义行为别赌编译器。右移负数填 0 还是填 1 看编译器想要确定行为先转无符号。3.7 三元运算符三元运算符是压缩版的 if else问号前面是条件冒号两边是两个结果。int max (a b) ? a : b; // a 大取 ab 大取 b简单场合用着顺手嵌套三元是灾难。a ? b : c ? d : e这种看得人想砸键盘老老实实写 if。3.8 优先级不确定就加括号运算符有先后全表在这儿从高到低。档位运算符一句话第一档括号想先算的套起来第二档单目运算 -- ! ~ 正负号、强制转换、sizeof第三档乘除取余* / %第四档加减 -第五档位移 第六档比大小 第七档比相等 !第八档按位与第九档按位异或^第十档按位或单竖线第十一档逻辑与第十二档逻辑或两个竖线第十三档三元? :第十四档赋值 和 那一族第十五档逗号最低这张表不用背背了也会忘。记两条就够不确定的地方加括号括号永远最先算。位运算的优先级比普通人直觉低a b c先算相等再按位与想要按位与先算就套括号。四、数据类型转换4.1 隐式转换编译器悄悄干活类型之间会互相转不用你开口的那种叫隐式转换。方向只有一个往高了转。┌──────────────────────────────────────────────────────────┐ │ 隐式转换的阶梯 │ ├──────────────────────────────────────────────────────────┤ │ 自动转换的方向一路往高爬 │ │ │ │ ┌────────────────────────────────────────────────────┐ │ │ │ bool 只有真假两个值 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ char 一个字节编号 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ short 两个字节 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ int 四个字节日常主力 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ long 四到八个字节 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ long long 八个字节大数 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ float 小数起步 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ │ v │ │ ┌────────────────────────────────────────────────────┐ │ │ │ double 小数主力 │ │ │ └────────────────────────────────────────────────────┘ │ │ │ │ 两边类型打架低的自动升级成高的那个再算 │ │ int 和 double 相加int 先变成 double │ └──────────────────────────────────────────────────────────┘规矩有两条。小的参与运算先提升char 和 short 不管是加减还是打印先升成 int 再上场。两边类型不一样低的自动爬成高的算完的结果按高的那个类型存。赋值的时候也转double d 3;里的 3 悄悄变成 3.0。编译器做这些事不吭声好处是省事坏处是错了你不知道。4.2 显式转换自己开口要清楚自己要求的转换叫显式转换两种写法。int total 285; int count 4; double avg1 (double)total / count; // C 风格 double avg2 static_castdouble(total) / count; // C 风格两种效果一样都得到 71.25。推荐 static_cast理由和 2.3 节推荐 const 一样它在代码里长得显眼搜索能搜到编译器能检查出错了报错信息带类型名。C 风格那个括号混在代码里肉眼难找。C 还有 const_cast、reinterpret_cast、dynamic_cast 三种各有各的场合到指针和类那两章再见。现在记住日常转换 static_cast 一把够用。4.3 转换的坑挨个排雷转换是 bug 密度最高的地方常见事故有这么几款。事故现场原因解法平均数丢小数285 除以 4 得 71两个 int 相除一边转 doubleint 溢出大数乘大数得负数结果超过 21 亿中间量用 long long无符号回绕unsigned 减到 0 再减回绕是标准行为不报错边界处加判断混合比较翻车-1 大于 1有符号转无符号后成了巨大正数别混着比浮点丢精度float 存 16777217 变 16777216有效数字不够换 doublechar 溢出char 装 200超出一个字节换类型混合比较这款最反直觉光看代码不信跑一遍就服了。#include iostream using namespace std; int main() { unsigned int u 1; int i -1; cout (u i) endl; // 1true-1 居然大于 1 return 0; }有符号和无符号比大小有符号的先被转成无符号-1 转过去变成 4294967295当然大于 1。规矩只有一条比较的两边类型一致不一致就先转成一样的。4.4 转换不报错这才最危险语法错误编译器会拦类型转换它基本不拦。该丢的小数丢了该报的溢出没报程序跑得欢结果离谱这种 bug 调试起来最耗人。应对办法也简单每一处转换心里有数。写除法前问一句两边是不是都想要整数。比较大小时问一句两边类型一样吗。存大数前问一句这个类型装得下吗。三个问题问完这一章的坑就躲掉大半。五、小结5.1 本章知识收口表模块你现在应该能做对的事自测基本类型说清四大家庭和各自字节数□ 能说出 int 和 double 的字节数sizeof会用它验字节数□ 跑一遍 1.5 节的程序变量常量声明即初始化常量用 const□ 能写出列表初始化运算符算术关系逻辑位移都会用□ 能心算 5 3 和 5 2优先级知道括号最优先□ 能排出 1 2 * 3 的顺序类型转换隐式往高转显式用 static_cast□ 能修好平均分程序┌─────────────────────────────────────────────────────────┐ │ 一章走完该带走的东西 │ ├─────────────────────────────────────────────────────────┤ │ 学完这一章兜里该有这些 │ │ │ │ -------------------------------------------------- │ │ |模块 |带走什么 | │ │ -------------------------------------------------- │ │ |类型四家 |整型浮点字符布尔字节数用 sizeof 验| │ │ |变量常量 |声明即初始化const 胜过 #define | │ │ |运算符 |整数除法丢小数位运算只认整数 | │ │ |类型转换 |隐式一路往高转显式用 static_cast | │ │ -------------------------------------------------- │ │ │ │ 哪一块心里没底回去找对应小节别急着往下翻 │ └─────────────────────────────────────────────────────────┘5.2 五句话记住本章类型是图纸字节数用 sizeof 现算别背。整数除法丢小数要小数先把一边转成 double。变量声明就初始化常量用 const别用宏。 放前放后不一样别塞进复杂表达式。有符号和无符号别混着比比就先转成一路的。5.3 课后练习打印 1.5 节那张 sizeof 表在自己机器上跑一遍和书上的数对一遍long 是几字节。算班级平均分。先用两个 int 相除再把除数转成 double对比两次结果说清差别在哪。输入一个大写字母输出它的小写形式提示大小写编号相差 32。用位运算判断输入的整数是奇数还是偶数提示看二进制最低那一位。有 a、b 两个变量不用第三个变量把两个值换过来。做不出来正常第三章学完再回头看。挑战题输入一个 0 到 255 的整数输出它的二进制写法提示从第 7 位开始一位位问过去。附录运算符速查卡类别成员一句话提醒算术 - * / %整数除法丢小数% 只认整数复合赋值 - * / %懒人写法左右类型不变自增自减 --放前面先加放后面先用关系 ! 是两个等号写成一个就完蛋逻辑 两个竖线 !会短路判空的写左边位运算 单竖线 ^ ~ 只认整型判奇偶用 x 1三元? :简单场合用嵌套是灾难优先级括号最高逗号最低不确定就加括号

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑