一、hello,world!
#include <stdio.h>
int main()
{
printf("hello world!\n");
return 0;
}
#:预处理标识符
include:包含头文件的标准格式
<>:从C语言的标准库中找头文件
“”:从指定的路径中找头文件,一般用于导入自己写的头文件,如果找不到指定的头文件就去标准库中找
stdio.h:标准输入输出的库文件
int:函数的返回值类型
main:函数名,主函数,是程序的入口,每一个C程序有且仅有一个主函数
(int argc, const char *argv[]):()函数的参数列表,int argc, const char argv[]主函数的外部参数
{}:函数体
printf(“hello world\n”); //printf是标准输出函数
printf:中*" "**内的内容,除了转义字符和占位符外,都原封不动的输出
\n:是转义字符,换行
;:每一条语句,都要有一个;,C语言中语句结束的标志
return:返回函数的返回值
0:函数的返回值
二、gcc编译器
1.一步编译
gcc xxx.c
—>默认生成一个名为a.out
的可执行文件—>./a.out
可以执行编译过的C文件
-o参数
- 多个C程序只能保留用一个
a.out
,生成其他的可执行文件,实现可以同时保留多个源文件可执行文件。 gcc xxx.c -o hello
—>gcc编译后生成指定的hello可执行文件-o <===> out ./hello
gcc -o hello xxx.c
—>生成指定的hello文件,./hello
2.分步编译
- gcc编译器的编译过程分为四部
- 预处理–>编译–>汇编–>链接
- 预处理
gcc -E hello.c -o hello.i
- 预处理阶段,展开头文件,替换宏定义,删除注释
- 编译
gcc -S hello.i -o hello.s
- 编译阶段,检查语法错误,并生成汇编文件
- 汇编
gcc -c hello.s -o hello.o
- 汇编阶段,生成二进制文件
- 链接
gcc hello.o -o hello
- 链接阶段,连接到程序执行所需要的动态库/静态库,生成可执行文件
- 运行程序
./hello
3、数据类型的作用
数据类型相当于一个模子,规定了由它定义的变量,需要占用多大的内存
4、数据类型的分类
基本类型
字符类型
整数类型
浮点型
枚举
构造类型
数组
结构体
共用体
指针类型
空类型 void
4.1 整数类型
整数类型又分为 char ,short, int, long, longlong类型
这些类型分为有符号的 signed 和无符号的 unsigned
默认都是有符号的
对于有符号的数而言,最高位称为符号位 其他位成为数据位
最高位为0是正数,为1是负数
4.1.1 char类型
char类型定义的变量在内存上占用 1字节
存储数据的范围
无符号:[0 , 2^8-1]
有符号:[-27,27-1] 1000 0000规定为 -128的补码
4.1.2 short 类型
short类型定义的变量在内存上占用2个字节
存储数据的范围
无符号:[0, 2^16-1]
有符号:[-215,215-1]
4.1.3 int 类型
int类型定义的变量在内存上占用4个字节
存储数据的范围
无符号:[0, 2^32-1]
有符号:[-231,231-1]
4.1.4 long 类型
在32位的系统上和int一样
在64位的系统上和long long一样
4.1.5 long long 类型
long long 类型定义的变量在内存上占用8个字节
存储数据的范围
无符号:[0,2^64-1]
有符号:[-263,263-1]
4.2 空类型
void 就是空类型的意思, void一般不单独使用一般会配合指针,void*
4.3 浮点类型
浮点数在内存的存储方式为:符号位,指数,尾数
类型 | 符号位 | 指数 | 尾数 |
---|---|---|---|
float | 1位(第31位) | 8位(第23~30位) | 23位(第0位~22位) |
double | 1位(第63位) | 11位(第52~62位) | 52位(第0~51位) |
float 4字节
double 8字节
5、数据类型转换
5.1 强制类型转换
int main()
{
long l = 800;
int i = (int)l; //强制类型转换
return 0;
}
5.1.1 强制类型转换的语法
==(Type)==var_name;
==(Type)==value
5.1.2 强制类型转换结果
目标类型能够容纳目标值:结果不变
目标类型不能容纳目标值:结果将产生截断
5.1.3 小结
- 强制类型转换由程序员负责完成
- 转换可能产生截断
- 转换不区分类型的高低
- 转换不成功时,编译器会给出错误信息
5.2 隐式类型转换
int main()
{
short s = 800;
int i = s; //隐式类型转换
//no error, no warning
return 0;
}
5.2.1 隐式类型转换的发生点
- 算术运算式中,低类型转换为高类型
- 赋值表达式中,表达式的值转换为左边变量的类型
- 函数调用时,实参转换为形参的类型
- 函数返回值,return表达式转换为返回值类型
5.2.2 安全的隐式类型转换
char --> short --> int --> unsigned int --> long --> unsigned long --> float --> double
5.2.3 小结
- 隐式类型转换由编译器自动完成
- 低类型向高类型转换是安全的
- 高类型向低类型转换是不安全的
- 标准C编译器类型检查比较宽松,隐式类型转换可能带来意外错误
6.原码、反码和补码
原码:数据的二进制
反码:原码转补码的中间形式
补码:机器语言
6.1 原码、反码和补码的转换
原码:数据的二进制
反码:原码除符号位其余位取反
补码:反码+1
6.2 计算机中数据的存取问题
- 计算机中存的都是数据的补码格式
- 存储数据时,看数据的正负
- 取出数据时,看数据的类型
6.2.1 原码、反码和补码举例
-35
- 原码:1101 1101
- 反码:1010 0010
- 补码:1010 0011
-124
- 原码:1000 0100
- 反码:1000 1011
- 补码:1000 1100
-85
- 原码:1010 1011
- 反码:1101 0100
- 补码:1101 0101
-113
- 原码:1000 1111
- 反码:1111 0000
- 补码:1111 0001
6.2.2 数据类型越界,数据存取的体现
unsigned char c = -10
存储:
- 原码:1000 1010
- 反码:1111 0101
- 补码:1111 0110
读取: - 补码:1111 0110
结果打印得到:246
signed char p = 213;
存储: - 原码:1101 0101
取出 - 补码:1101 0101
- 反码:1101 0100
- 原码:1010 1011
结果打印得到:-43
7.C语言中的宏定义
- #define是预处理器处理的单元实体之一
- #define定义的宏可以出现在程序的任意位置
- #define定义之后的代码都以使用这个宏
7.1 定义宏常量
- #define定义的宏常量可以直接使用
- #define定义的宏常量本质为字面量
7.2 宏定义表达式
- #define表达式的使用类似于函数调用
- #define表达式可以比函数更强大
- #define表达式比函数更容易出错
宏表达式计算数组大小#define _DIM_(a) sizeof(a)/sizeof(*a)
7.3 宏表达式与函数的对比
- 宏表达式被预处理器处理,编译器不知道宏表达式的存在
- 宏表达式用 “实参” 完全替代形参,不进行任何运算
- 宏表达式没有任何 “调用” 开销
- 宏表达式中不能出现递归定义
#include <stdio.h>
#define N 10
#define M N*2+4
#define NUM M*N/M*3+M
int main()
{
printf("N = %d\n", N);
printf("M = %d\n", M);
printf("NUM = %d\n", NUM);
return 0;
}