目录
1. 语言的发展:
【二进制语言】
硬件 – 电:正电(1)、负电(0)
101010000101000111001 – 手册 ------> 低级语言
101011011101 – ADD – 助记符 – 【汇编语言】
【B语言】
【C语言】、【C++】 …… 高级语言 -------> 高级语言
2. C 语言国际标准
国际标准 --> ANSI C - C89 - > C90 -> C98
C99 / C11 并不流行 – 不少编译器不支持
3. 第一个C语言 程序
// 包含一个叫stdio.h的文件
// std - 标准 standard input output
#include <stdio.h>
// int 整型的意思
// main 前面的int表示 main函数调用返回一个整型值。
int main() // 主函数 - 程序入口,main函数有且仅有一个
{
// 函数 - print function -- printf - 打印函数
// 库函数 - C语言本身提供给我们使用的函数
// 别人的东西 - 打招呼
printf("hehe\n");
return 0; // 返回 0
}
// 过时写法
// void main()
// {}
4. 数据类型
- 内置类型 – int,float ……
- 自定义类型 – 结构体,枚举,共用体。
计算字符类型所占字节数 :sizeof()
– 是操作符/运算符,不是函数。
C 语言标准规定:
sizeof(long)
>=sizeof(int)
- Win X86和X64都为 4。
- Linux X86为4,X64为8。
计算机中的单位:
- bit
- 1 byte = 8bit;
- 1 kb = 210 byte;
- mb = 210 kb;
- gb = 210 mb;
- tb = 210 gb;
- pb = 210 tb;
数据类型 | 类型名 | 所占字节数(单位:byte) |
---|---|---|
char | 字符型 | 1 |
short [int] | 短整型 | 2 |
int | 整型 | 4 |
long [int] | 长整型 | 4/8 |
long long [int](C99中提出) | 更长的整型 | 8 |
float | 单精度浮点数 | 4 |
double | 双精度浮点数 | 8 |
字符格式 | 意义 |
---|---|
%c | 字符型格式符 |
%s | 字符串型格式符 |
%d | 整型 (十进制数据) |
%u | 打印无符号整型 |
%x | 打印16进制数字 |
%f | 浮点型 - - 小数 |
%lf | 双精度浮点数 |
%p | 以地址的形式打印 |
#include <stdio.h>
int main()
{
char arr[5] = {0};
scanf("%s", arr);
return 0;
}
注:
输入的字符个数应比 数组长度小1 。因为,输入格式为字符串,编译器会在字符串末尾自动加'\0'
。若输入的字符个数与数组长度相等,会报数组越界的错误。
5. 常量、变量
C语言中的常量分为以下几种:
- 字面常量
const
修饰的常变量#define
定义的标识符常量- 枚举常量
#include <stdio.h>
// 3. #define 定义的标识符常量
#define MAX 10 // define 属于预处理指令,不属于关键字
// 4. 枚举常量 --- 有值且不可被改变
// 枚举 : 一一列举
// 性别 : 男、女、保密
// 三原色:红、黄、蓝
enum Sex
{
MALE,
FEMALE,
SECRET
};
// MALE,FEMALE.SECRET -- 枚举常量
int main()
{
// 1. 字面常量
// 3;
// 3.14;
// 2. const - 常属性 -- 不能被修改的属性。
// const 修饰的常变量
const int num = 4;
printf("%d\n", num); // 4
// num = 8; // 报错
printf("%d\n", num);
const int n = 10; // n是变量,但是又有常属性,所以我们说n是常变量
// int arr[n] = { 0 }; // 报错 -- 在C99标准之前,数组的大小只能是常量,VS2019对C99支持的不是很好,不支持变长数组,所以这里报错了。
// MAX = 200; // error -- 不能修改
int arr[MAX] = { 0 };
printf("%d\n", MAX); // 10
enum Sex s = FEMALE; // 定义枚举类型变量
s = MALE; // 枚举类型定义出来的变量可以改变;
// MALE = 6; // 枚举常量不可被改变。
printf("%d\n", MALE);// 0
printf("%d\n", FEMALE);// 1
printf("%d\n", SECRET);// 2
return 0;
}
变量
指定数据类型为 单精度且 小数部分不为0时,要加上后缀f,否则会有警告。float weight = 94.3f;
(直接写出来的浮点数默认是double类型)。
6. 局部变量、全局变量
-
局部变量的作用域是变量的局部范围 – 不初始化 – 默认为随机值(直接用
printf
函数输出未初始化的变量值,会报错); -
全局变量的作用域是整个工程 – 不初始化,默认是 0 。
-
变量前加
static
,不初始化,默认值也是0;#include <stdio.h> int i; int main() { int j; printf("%d\n", i); // 0 // printf("%d\n", j); // 报错 return 0; }
在一个项目的不同源文件中的代码,可以相互使用,但是得加extern
。
// num.c 中代码
#include <stdio.h>
int g_val = 111;
// test.c中代码
#include <stdio.h>
int main()
{
extern int g_val;
// extern g_val; // 两种写法都可以
printf("%d", g_val); // 111
return 0; // 返回 0
}
7. 字符串 + 转义字符 + 注释
C语言 没有字符串类型。
7.1 字符串
"hello bit.\n"
双引号(Double Quo)引起来的一串字符称为 字符串字面值 (String Literal),或者简称 字符串。
注:
字符串的结束标志是一个 \0
的转义字符。在计算字符串长度的时候 \0
是结束标志,不算做字符串内容。
#include <stdio.h>
#include <string.h>
int main()
{
// 数据在计算机上存储的时候,存储的是2进制
// ASCII 编码 ASCII 码值
// A 65
// a 97
// \0 0
char arr1[] = "abc";
// "abc" --- 'a' 'b' 'c' '\0' --> 字符串末尾隐藏一个'\0' ---> '\0'字符串结束标志
char arr2[] = { 'a','b','c'};
char arr3[] = { 'a','b','c','\0'}; // '\0'的值为0,所以这里最后一个字符写'\0'或0都可以
printf("%s\n", arr1); // abc
printf("%s\n", arr2); // abc烫烫烫烫蘟bc
// 打印完 'a' 'b' 'c' 之后不会结束,会接着打印随机值。
printf("%s\n", arr3); // abc
// strlen -- strlen length -- 计算字符串长度(不将'\0'算在内)
printf("%d\n",strlen(arr1)); // 3
printf("%d\n",strlen(arr2)); // 随机值 (a b c x x x x x)
printf("%d\n",strlen(arr3)); // 3
printf("%s\n", "abc0def"); // abc0def -- 字符串中的0是字符零('0'),不会被认为是字符串结束标志。
printf("%s\n", "abc\0def"); // abc
return 0;
}
7.2 转义字符
转义字符 | 释义 |
---|---|
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词。 |
\' | 用于表示字符常量' 。 |
\" | 用于表示一个字符串内部的双引号。 |
\\ | 用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字。 如: \130 X |
\xdd | dd表示2个十六进制数字。 如: \x30 0 |
举例1:
#include <stdio.h>
int main()
{
printf("c:\test\32\test.c"); // c: est est.c
printf("c:\\test\\32\\test.c"); // c:\test\32\test.c
return 0;
}
举例2:
??
+ )
--> 三字母词
int main()
{
printf("(are you ok\??)\n"); // 输出 (are you ok??)
return 0;
}
举例3:
#include <stdio.h>
#include <string.h>
int main()
{
printf("%s\n", "dsf\091"); // dsf
printf("%d\n",strlen("c:\test\32\test.c")); // 13
printf("%d\n",strlen("c:\test\328\test.c")); // 14
// \328 会被看作2个字符 \32 和 8;
return 0;
}
7.3 注释
- C语言注释风格 :
/* */
– 不支持嵌套的(不太好)。 - C++注释风格:
//
- 快捷键:
ctrl + k + c
或ctrl + shift + /
: 进行注释;ctrl + k + u
: 取消注释;
8. 常见关键字
- 关键字不能自己创建。
- 变量名不能是关键字。
auto(自动) break case char const continue default do double else enum
extern(声明/引入外部符号) float for goto if int long register(寄存器关键字) return short signed(有符号数)
sizeof static struct switch typedef(类型定义(或类型重命名)) union(联合体 / 共用体) unsigned void volatile(Linux系统部分) while
int main()
{
auto int a = 10; // 局部变量 -- 自动变量(auto 基本不写,省略)
register int b = 10; // 建议 将b定义成寄存器变量
// int 定义的变量是有符号的
// signed int c; (signed 一般省略不写)
return 0;
}
计算机存储数据: 速度: 寄存器 > 高速缓存 > 内存 > 硬盘
8.1 关键字 typedef
typedef
类型定义,可以理解为类型重命名。
#include <stdio.h>
int main()
{
// num1 和 num2 这两个变量的类型是一样的。
typedef unsigned int u_int;
u_int num1 = 0;
unsigned int num2 = 20;
return 0;
}
8.2 关键字 static
在C语言中:
static
是用来修饰变量和函数的
- 修饰局部变量 – 静态局部变量
- 修饰全局变量 – 静态全局变量
- 修饰函数 – 静态函数
1. 修饰局部变量:
//代码1
#include <stdio.h>
void test()
{
int a = 0;
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
for (i = 0; i < 5; i++)
{
test();
}
return 0;
}
// 运行结果 >: 1 1 1 1 1
//代码2
#include <stdio.h>
void test()
{
//static修饰局部变量
static int a = 0;
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
for (i = 0; i < 5; i++)
{
test();
}
return 0;
}
// 运行结果 >: 1 2 3 4 5
结论:
static
修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域仍然存在,到程序结束,生命周期才结束。
2. 修饰全局变量
//代码1
//add.c
int g_val = 2018;
//test.c
// 声明外部变量
extern g_val;
int main()
{
printf("%d\n", g_val);
return 0;
}
// 可以正常运行
//代码2
//add.c
static int g_val = 2018;
//test.c
// 声明外部变量
extern g_val;
int main()
{
printf("%d\n", g_val);
return 0;
}
// 编译时会报连接性错误
结论:
全局变量本身是具有外部链接属性的,但是一个全局变量被
static
修饰,使得这个全局变量失去外部链接属性,只能在本源文件内使用,不能在其他源文件内使用。
3. 修饰函数
//代码1
//add.c
int Add(int x, int y)
{
return x+y;
}
//test.c
// 声明外部符号
// extern 最好加上
extern int Add(int x,int y);
int main()
{
printf("%d\n", Add(2, 3));
return 0;
}
// 可以正常运行
//代码2
//add.c
static int Add(int x, int y)
{
return x+y;
}
//test.c
// 声明外部符号
int Add(int x,int y);
int main()
{
printf("%d\n", Add(2, 3));
return 0;
}
// 编译时会报连接性错误
结论:
函数默认具有外部链接属性,但是一个函数被
static
修饰,使得函数失去外部链接属性,变成内部链接属性,这个函数只能在本源文件内使用,不能在其他源文件内使用。
static
修饰函数改变了函数的链接属性。由外部链接属性 变为 内部连接属性。
9. #define 定义常量和宏
#include <stdio.h>
// #define #include -- 预处理指令
#define MAX 100
// #define 定义宏
// 函数的实现
int Max(int x, int y)
{
if (x > y)
return x;
else
return y;
}
// 宏的定义
#define MAX(X, Y) (X>Y?X:Y)
#define ADD(x, y) (x+y)
int main()
{
int a = 10;
int b = 20;
// 函数
int max = Max(a, b);
printf("max = %d\n", max);
// 宏的定义
max = MAX(a, b);
// max = ((a)+(b));
printf("max = %d\n", max);
return 0;
}
10. #define 和 typedef 的区别
-
#define
是预处理指令,在编译时不进行任何检查,只进行简单的替换。 -
typedef
是C语言中用来为复杂的声明定义简单的别名,它本身是一种存储类的关键字,与auto、extern、mutable、static、register等关键字不能出现在同一个表达式中。 -
区别
-
#define
之后不带分号,typedef
之后带分号。 -
#define
可以使用其他类型说明符对宏类型名进行扩展,而typedef
不能这样做。如:#define INT1 int unsigned INT1 n; //没问题 typedef int INT2; unsigned INT2 n; //有问题 // INT1可以使用类型说明符unsigned进行扩展,而INT2不能使用unsigned进行扩展。
-
在连续定义几个变量的时候,
typedef
能够保证定义的所有变量均为同一类型,而#define
则无法保证。如:#define PINT1 int*; P_INT1 p1,p2; //即int *p1,p2; typedet int* PINT2; P_INT2 p1,p2; //p1、p2 类型相同 // PINT1定义的p1与p2类型不同,即p1为指向整形的指针变量,p2为整形变量;PINT2定义的p1与p2类型相同,即都是指向 int 类型的指针。
-
希望可以对大家有所帮助,如果有什么不对的地方,还烦请指教,谢谢!