ch01变量和数据结构
C语言关键字 [1]
C语言有32个关键字
- auto:定义自动变量,主要是声明变量的生存周期
- break, continue : break 语句在遇到最内层循环时立即终止。还用于终止 switch 语句。
- case, switch, default:使用 switch 和 case 语句声明一个switch分支
- char:用于声明character 类型的变量
- const:声明常量
- do…while:
- double: double-precision 浮点数变量类型
- float:single-precision 浮点数的变量类型
- if, else:声明if/else 条件判断
- enum:用于声明枚举类型
- extern:关键字声明变量或函数在其声明的文件之外具有外部链接。
- for:C 语言的三种循环之一,for循环
- goto: 用于将程序的控制权转移到指定的标签
- int:声明 integer 类型的变量
- short, long, signed, unsigned:是类型修饰符,它们改变基本数据类型的含义以产生新类型。
- short int: -32768 to 32767
- long int: -2147483648 to 214743648
- signed int: -32768 to 32767
- unsigned int: 0 to 65535
- return: 终止函数并返回值
- sizeof:评估变量或常量的大小
- register:创建比普通变量快得多的寄存器变量。
- static:创建一个静态变量。静态变量的值持续到程序结束。
- struct:用于声明结构体。结构体可以包含不同类型的变量。
- typedef:用于将类型与标识符显式关联。
- union:用于将不同类型的变量分组在一个名称下。
- void:没有任何意义,函数修饰为没有返回值,参数修饰为没有参数
- volatile:提醒编译器它后面所定义的变量随时都有可能改变
C语言控制语句
C语言有9种控制语句 (control statements)
- If…else
- for
- while
- do…while
- continue
- break
- switch
- goto
- return
C语言运算符 [2]
C语言有45种运算符 (operator)
- 算数运算符 (Arithmetic Operators) :
+
,-
,*
,/
,%
- 赋值运算符 (Assignment Operators) :
=
,+=
,-=
,*=
,/=
,%=
- 关系运算符 (Relational Operators):
==
,>
,<
,!=
,>=
,<=
- 逻辑运算符 (Logical Operators):
&&
,||
,!
- 位运算符 (Bitwise Operators):
&
,|
,^
,~
,<<
,>>
- 逗号运算符 (Comma Operator):链接相关表达式 ,
int a, c = 5, d;
- sizeof运算符(sizeof operator):一元运算符,它返回数据的大小(常量、变量、数组、结构)
- 杂项运算符():
&
取址,*
取指针,?:
二元条件表达式
GCC编译四部曲 [3]
- 预处理 (Preprocessing):在预处理步骤,将生成一个扩展名为
.i
的文件;使用命令gcc -E file.c
操作- 头文件展开,不检查语法错误,将展开所有头(include)文件(任意)
- 宏定义替换
- 删除注释
- 展开条件编译,根据条件来展开指令
- 编译 (Compilation) :会生成一个扩展名为
.s
的文件,命令是:gcc -S file.c
- 检查语法错误
- 将文件翻译成汇编语言
- 汇编 (Assembler):将汇编代码转换为纯二进制代码或机器代码(零和一)。此代码也称为目标代码;将生成一个带有
.o
扩展名的文件:gcc -c file.c
- 链接 (Linker):链接是编译的最后一步。链接器将来自多个模块的所有目标代码合并为一个,如果使用了库也会引用。这个步骤也是包含前三个步骤的。
gcc file.o -o hello.exe
- 接收由汇编步骤生成的 .o 扩展名文件
- 数据地址回填
- 数据段合并
- 库引入
变量
变量 (variables) 是用于存储数据的内存位置名称,可以改变的内容
变量的命名规则
- 不能以数字开头
- 由数字、字母,甚至是下划线 (
_
) 等特殊符号组成 - 变量名不能是任何关键字
- 变量名中不能有空格或空白
- 变量名是区分大小写的
变量的数据类型
C 语言中数据类型主要包含以下类型
变量类型 | 实际代表名称 | 描述 | 用途 |
---|---|---|---|
char | Character | 代表1bytes(8bit),是以单引号引起的字符 | 通常以单个字母的形式使用X、r等,或 ASCII 字符集。 |
int | Integer | 自然整数 | 用来存储整数,如 4, 300, 8000 … |
float | Floating- Point | 单精度浮点数 | 表示实数值或小数值(7位小数),例如 20.8, 18.56 … |
double | Double | 双精度浮点值 | 比float类型要大 4bytes,允许15位小数 |
void | Void | 表示没有类型。 | 这种数据类型是为了用于修饰没有意义函数或变量,如函数用其修饰标识没有返回值,参数用其修饰表示没有参数。 |
变量声明与定义
- 变量的定义 (Declaration):告诉编译器应为变量创建多少存储空间或者在哪里创建存储空间(借助于数据类型)
- **变量声明 **(Definition):只声明不赋值的变量叫做变量定义,
int a
定义与声明的区别:
- 变量定义会开辟内存空间。变量声明不会开辟内存空间
- 变量要想使用必须有定义
- 声明指示编译器存在变量,而定义表示编译器为变量创建的存储位置和存储量
变量的分类
- 全局变量 (global) :在块或函数之外声明的变量称为全局变量
- 局部变量 (Local):在块或函数中声明的一种变量
- 静态变量 (static):使用 static 关键字声明的变量。该变量在各种函数调用之间保留给定值
- 自动变量 (auto):变量具有自动存储期,程序在进入该变量声明所在的块时变量存在,程序在退出该块时变量消失
- 外部变量 (extren):能够在多个源文件中共享一个变量
extern int a=10;
变量的数据大小 [6]
C 编程语言有两种基本数据类型:基本与衍生
类型 | 范围 | 大小(以字节为单位) | 格式化符号 |
---|---|---|---|
unsigned char | 0 ~ 255 | 1 | %c |
signed char/char | -128 ~ +127 | 1 | %c |
unsigned int | 0 ~ 65535 | 2 | %u |
signed int or int | -32,768 ~ +32767 | 2 | %d |
unsigned short int | 0~ 65535 | 2 | %hu |
signed short int/short int | -32,768 ~ +32767 | 2 | %hd |
unsigned long int | 0 ~ +4,294,967,295 | 4 | %lu |
signed long int/long int | -2,147,483,648 ~ 2,147,483,647 | 4 | %ld |
long long int | -(2^63) to (2^63)-1 | 8 | %lld |
unsigned long long int | 0 to 18,446,744,073,709,551,615 | 8 | %llu |
float [5] | 7位精度 | 4 | %f |
double [5] | 15位精度 | 8 | %lf |
类型转换
隐式类型转换
隐式类型 (Implicit) 转换也称自动类型转换,这种类型的转换包含如下特点:
- 编译器自动完成,无需用户干预触发
- 当表达式中存在多种类型时触发,这是为了保证数据不被丢失
- 所有的数据类型都将升级为该类型最大值
- 转换的顺序为:bool -> char -> short int -> int -> unsigned int -> long -> unsigned -> long long -> float -> double -> long double
- 该转换类型会存在一些问题,如符号消失,数据丢失等。
#include<stdio.h>
int main()
{
int x = 10; // integer x
char y = 'a'; // character c
// y 被隐式转换为 char类型,a=97
x = x + y;
// 计算中,存在浮点数值,结果将被转换为float
float z = x + 1.0;
// 自动转换为long long
int h = 2147483648;
// int 到 short int值溢出将为23352减去int大小65536
short int g = 88888 + x;
printf("x = %d, z = %f\n", x, z);
printf("g = %li, h = %lli\n", g, h);
return 0;
}
显式类型转换
用户定义类型转换的过程称为显式类型转换 (Explicit)
(type) expression
显示转换示例
#include<stdio.h>
int main()
{
float x = 1.2;
// 显示转换一个float为int
int sum = (int) x + 1;
printf("sum = %d", sum);
return 0;
}
进制转换
十进制
十进制转二进制: 除2反向取余法
十进制转八进制:除8反向取余法
十进制转十六进制:除16反向取余法
例如:16进制转10进制
- 将十进制数除以 16。将除法视为整数除法
- 写下余数(十六进制)
- 将结果再次除以 16。将除法视为整数除法
- 重复步骤 2 和 3,直到结果为 0
- 求出的十六进制值是从最后到第一个的余数的数字序列
427的16进制
-
将数字除以 16,余数(小数部分乘16为余数),最终为1AB
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mvvZOtMS-1663925137458)(…/…/…/images/day1%20helloworld/decimal-to-hexadecimal.png)]
八进制
8进制转10进制:从后向前,8的0次方,8的1次方,8的2次方…按照该顺序乘8的
- 8进制75转10进制为: 56 + 5 = 61 56+5=61 56+5=61
- 8进制77655转10进制为: 7 ( 8 4 ) + 7 ( 8 3 ) + 6 ( 8 2 ) + 5 ( 8 1 ) + 5 ( 8 0 ) = 28672 + 3584 + 384 + 40 + 5 = 32685 7(8^4)+7(8^3)+6(8^2)+5(8^1)+5(8^0)=28672+3584+384+40+5=32685 7(84)+7(83)+6(82)+5(81)+5(80)=28672+3584+384+40+5=32685
2进制转8进制:自右向左,每3位一组,按421码转换。高位不足三位补0
-
1 010 111 010 110 二进制转八进制如下表,最后算出结果为12726
-
4 2 1 0 0 1 0 1 0 1 1 1 0 1 0 1 1 0
十六进制
16进制转10进制:从后向前依次展开,16的0次方,16的1次方,16的2次方…,每位相加,例如:
- 0x1A = 16 + 10 = 26 16 + 10 = 26 16+10=26
- 15DE = 1 ( 1 6 3 ) + 5 ( 1 6 2 ) + 13 ( 1 6 1 ) + 14 = 4096 + 1280 + 208 + 14 = 5598 1(16^3)+5(16^2)+13(16^1)+14= 4096+1280+208+14=5598 1(163)+5(162)+13(161)+14=4096+1280+208+14=5598
16进制转二进制:4位一组一次填充。例如 0X1A的二进制,即00011010如下
8 | 4 | 2 | 1 |
---|---|---|---|
1 | 0 | 1 | 0 |
0 | 0 | 0 | 1 |
二进制转16进制:自右向左,每4位一组,按8421码转换。高位不足三位补0
例如 0001 0011 1111的16进制为,如下表 1 3 F(15)
8 | 4 | 2 | 1 |
---|---|---|---|
0 | 0 | 0 | 1 |
0 | 0 | 1 | 1 |
1 | 1 | 1 | 1 |
源码反码补码
源码 (*** true form****), 反码 (1‘s complement) [7], 补码 (2‘s complement) [8] 是操作系统中存储和计算数据的一种方式
任何数据都以二进制机器码存储与计算机中。对于的机器码,第一位是用来表示正负值的:0是正数,1是负数。故要表示 -2,对应的机器码是 10000010。
机器码不可以直接通过权重展开计算,例如 10000010 为 1 ( 2 7 ) + 1 ( 2 1 ) = 130 1(2^7) + 1(2^1) = 130 1(27)+1(21)=130 。因为第一位是1,所以是负数,接下来计算后一位的权重展开为 − 2 -2 −2
-
原码:机器码表示的值成为源码:如 43 = 00101011,-43 = 10101011
-
反码:符号位不变,其余位取反:如 43 = 00101011,-43 = 11010100
-
补码:符号位不变,counter code then LSB (least significant bit) + 1:如 43 = 00101011,-43 = 11010101
-
128 64 32 16 8 4 2 1 0 0 1 0 1 0 1 1 1 1 0 1 0 1 0 0+1(如果需要进位则进一位) 1 1 0 1 0 1 0 1
-
Note:二进制 10000000 为 -128
反码, 补码 是为了计算和存储正负数诞生的,正如 C语言的数据结构 中 有符号和没符号表示的数值位置不一样。
Reference
[1] keywords c language
[2] Arithmetic Operators
[3] four stages of compilation c
[4] offline installation visual studio
[5] difference float double
[6] data type in c
[7] 1‘s complement
[8] 2‘s complement