目录
一、数据类型
char //字符数据类型
short //短整型
int //整型
long //长整型
long long //更长的整型
float //单精度浮点数
double //双精度浮点数
- 为什么这么多类型?
提高空间利用率
- 每种类型的大小?
#include <stdio.h>
int main()
{
printf("%d\t",sizeof(char)); //1
printf("%d\t",sizeof(short)); //2
printf("%d\t",sizeof(int)); //4
printf("%d\t",sizeof(long)); //4
printf("%d\t",sizeof(long long)); //8
printf("%d\t",sizeof(float)); //4
printf("%d\t",sizeof(double)); //8
return 0;
}
- 计算机中的单位
bit——位
byte——字节 = 8 bit
kb——1024 byte
mb——1024 kb
gb——1024 mb
tb——1024 gb
pb——1024 tb
二、变量、常量
1、变量
-
定义变量
#include <stdio.h>
int main()
{
//创建一个变量
//类型 变量的名字 = 初始值
//类型 变量的名字
int age = 20;
double weight = 70.5;
age = age + 1;
weight = weight - 10;
printf("%d\t",age);
printf("%lf\t",weight);
//%d ~ int
//%f ~ float
//%lf ~ double
return 0;
}
-
变量分类
全局变量、局部变量
#include <stdio.h>
//全局变量 ~ {}外部定义的
int a = 100;
int main()
{
//局部变量 ~ {}内部定义的
//当局部变量和全局变量名字冲突的情况下,局部优先
//不建议把全局变量和局部变量的名字写成一样的
int a = 10;
printf("$d\n",a);
return 0;
}
-
变量使用
#define _CRT_SECURE_NO_WARNINGS 1
//解决scanf函数报警,必须放在第一行!!!
#include <stdio.h>
//scanf() 输入函数
int main()
{
int a = 0;
int b = 0;
int sum = 0;
scanf("%d %d", &a, &b);
sum = a + b;
printf("sum = %d\n", sum);
return 0;
}
-
变量作用域与生命周期
- 变量作用域
#include <stdio.h>
//作用域和生命周期
//局部变量的作用域:就是变量所在的局部范围
//全局变量的作用域:整个工程
//调用同一工程下全局变量:声明变量
//extern int g_val;
int g_val = 2021;//全局变量
int main()
{
printf("1:%d\n", g_val);
{
printf("2:%d\n",g_val);
int a = 10;
printf("a = %d\n",a);
}
printf("3:%d\n", g_val);
return 0;
}
1:2021
2:2021
a = 10
3:2021
D:\2022code\Project1\Debug\Project1.exe (进程 30796)已退出,代码为 0。
按任意键关闭此窗口. . .
- 变量生命周期
变量的生命周期:变量的创建和销毁之间的时间段。
局部变量的生命周期:进入局部范围开始,出局部范围结束。
全局变量的生命周期:程序的生命周期。
2、常量
-
常量分类
//1、字面常量
//2、const修饰的常变量(具有常属性的变量)
// int arr[10] = {0};//10个元素
// const int n = 10;
// int arr2[n] = {0};//n是本质是变量,这里是不行的
//3、#define定义的标识符常量
//#define MAX 10000
//4、枚举常量
#include <stdio.h>
enum Sex
{
//这种枚举类型的变量的未来取值,
MALE,
FEMALE,
SECRET
};
int main()
{
enum Sex s = MALE;
return 0;
}
三、字符串+转义字符+注释
1、字符串
#include <stdio.h>
#include <string.h> //定义strlen()函数的头文件
//字符串是遗传字符 - 用双引号括起来的一串字符
//字符串爱结尾隐藏了一个\0字符串结束标志,不算做字符串长度
//\0是字符串的结束标志
int main()
{
char arr1[] = "abc";
char arr2[] = {'a','b','c'};//必须要有\0元素否则打印出来除已有元素外乱码
printf("%s\n",arr1); //监视结果:a,b,c,\0
printf("%s\n",arr2); //监视结果:a,b,c
int len = strlen("abc"); //求字符串长度
printf("%d\n",len); //打印3,\0不算做字符串长度
printf("%d\n",strlen(arr1));//打印3
printf("%d\n",strlen(arr2));//打印随机值,strlen检测到\0停止
return 0;
}
2、转义字符
#include <stdio.h>
int main()
{
printf("C:\\test\\test.c"); //打印C:\test\test.c
printf("C:\test\test.c"); //打印C: est est.c
// \t被识别为水平制表符
// \ddd表示1~3个八进制数
// \xdd表示2个十六进制数字
printf("%c\n",'\130'); // X (8进制的130是十进制的 88,X的ASCII的值是88
printf("%c\n",'\x30'); // 0
printf("%d\n", strlen("c:\test\327")); // 7
}
3、注释
- C语言风格的注释/*xxx*/,不支持嵌套注释
- C++风格的注释//xxx,可以注释一行也可以注释多行
四、选择语句
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int input = 0;//输入值
printf("好好学习吗(0/1)?");
scanf("%d",&input);
if(input == 1)
printf("好offer");
if(input == 0)
printf("卖红薯");
return 0;
}
五、循环语句
- while循环
- for循环
- do...while循环
六、函数
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int Add(int x,int y)
{
int z = 0;
z = x + y;
return z;
}
int main()
{
int num1 = 0;
int num2 = 0;
scanf("%d%d",&num1, &num2);
int sum = Add(num1, num2);
printf("%d\n", sum);
return 0;
}
七、数组
#include <stdio.h>
int main()
{
//数组,一组相同类型的元素的集合
//数组用下标访问
int arr[10] = {0,1,2,3,4,5,6,7,8,9};
int i = 0;
while (i < 10)
{
printf("%d", arr[i]);
i++;
}
//char ch[5] = {'a','b','c'};//不完全初始化,剩余的默认为0
return 0;
}
八、操作符
1、算数操作符
+ - * / %
#include <stdio.h>
int main()
{
int a = 9 / 2; //4
float b = 9 / 2; //4
float c = 9 / 2.0; //4.5
return 0;
}
2、移位操作符
右移位 >>
左移位 <<
#include <stdio.h>
int main()
{
int a = 2;
int b = a << 1; //二进制左移一位
printf("%d\n", b); //4
return 0;
}
3、位操作符
按位与 &
按位或 |
按位异或 ^
4、赋值操作符
= += -= /= &= |= >>= <<=
5、单目操作符
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
-- 前置、后置--
++ 前置、后置++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
- !
#include <stdio.h>
int main()
{
int a = 10;
int b = 0;
printf("%d\n",!a); //0
printf("%d\n",!b); //1
if(a)
{
//如果a为真,做事
}
if(!a)
{
//如果a为假,做事
}
return 0;
}
- sizeof
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
printf("%d\n",sizeof(arr)); //计算的是数组的总大小,单位是字节
printf("%d\n",sizeof(arr[0])); //4
int sz = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", sz); //计算数组中元素个数
return 0;
}
- ~
#include <stdio.h>
int main()
{
int a = 0;
printf("%d\n", ~a); //内存里存的是补码11111111 11111111 11111111 11111111
//打印的是原码10000000 00000000 00000000 00000001即-1
//方法减一除符号位取反
return 0;
}
整数在内存中存储的是补码
正整数原、反、补码相同
-1
原码:10000000 00000000 00000000 00000001
反码:11111111 11111111 11111111 11111110
补码:11111111 11111111 11111111 11111111
- ++ --
#include <stdio.h>
int main()
{
int a = 10;
int b = ++a;
int c = a++;
printf("%d\n",a); //12
printf("%d\n",b); //11
printf("%d\n",c); //11
return 0;
}
- (类型) 强制类型转换
#include <stdio.h>
int main()
{
int a = (int)3.14;
printf("%d\n", a);
return 0;
}
6、关系操作符
> >= < <= != ==
7、逻辑操作符
&& 逻辑与
|| 逻辑或
8、条件操作符(三目操作符)
exp1? exp2: exp3
如果exp1成立则计算exp2
如果exp不成立计算exp3
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
int max = 0;
// if(a>b)
// max = a;
// else
// max = b;
max = a > b ? a : b;
printf("%d\n",max);
}
9、逗号表达式
exp1 , exp2 , ...
从左向右计算,最后一个表达式的值。
10、下标引用、函数调用和结构成员
[] () . ->
九、关键字
1、typedef:类型重定义
#include <stdio.h>
typedef unsiged int u_int;
int main()
{
unsiged int num = =100;
u_int num1 = 1000;
return 0;
}
2、static:静态的
1、修饰局部变量:改变局部变量的生命周期(本质上改变了变量的存储类型)
2、修饰全局变量:static修饰的全局变量只能在自己所在的源文件内部使用其他源文件不能使用。
全局变量,在其他源文件内部可以使用,是因为全局变量具有外部链接属性。
但被static修饰之后变成了内部链接属性,其他源文件就不能链接到这个静态的全局变量。
3、修饰函数:static修饰的函数只能在自己所在的源文件内部使用其他源文件不能使用。
是因为函数具有外部链接属性。但被static修饰之后变成了内部链接属性。
4、内存区域:
栈区:局部变量、函数参数
堆区:动态内存分配
静态区:全局变量、static修饰的静态变量
#include <stdio.h>
void test()
{
int a = 1;
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
while(i<10)
{
test();
i++;
} //结果:2 2 2 2 2 2 2 2 2 2
return 0;
}
#include <stdio.h>
void test()
{
static int a = 1; //静态变量,生命周期变长,出作用范围不销毁
a++;
printf("%d ", a);
}
int main()
{
int i = 0;
while(i<10)
{
test();
i++;
} //结果:2 3 4 5 6 7 8 9 10 11
return 0;
}
十、#define定义常量和宏
1、define定义常量
- define是一个预处理指令
2、define定义宏
2、define定义宏
#include <stdio.h>
#define ADD(X,Y) ((X)+(Y)) //相当于把ADD(X, Y)替换为X+Y,仅仅是替换关系
int main()
{
printf("%d\n",4 * ADD(2, 3)); //20
return 0;
}
十一、指针
1、内存是怎么编号的
- 32位机,有32根地址线——物理线——通电——1/0——有2的32次方个内存单元
- 电线信号转换成数字信号:1和0组成的二进制序列
- 从00000000 00000000 00000000 00000000到11111111 11111111 11111111 11111111
- 一个内存单元管理一个字节的空间
2、指针变量
#include <stdio.h>
int main()
{
int a = 10; //a在内存中要分配空间——4个字节
printf("%p\n", &a); //%p专门用来打印地址的
int * pa = &a; //pa是用来存放地址的,在C语言中pa叫指针变量
//* 说明pa是指针变量
//int 说明pa执行的对象是int类型的
*pa = 20; //* 解引用操作 *pa就是通过pa里边的地址找到a
printf("%d\n", a); //打印20
char ch = 'w';
char * pc = &ch;
return 0;
}
指针 就是 地址
3、指针变量的大小
- 指针的大小是相同的!
- 指针是用来存地址的!
- 指针需要多大空间,取决于地址的存储需要多大空间
结论:指针大小在32位平台是4个字节,64位平台是8个字节
#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(long*));
printf("%d\n", sizeof(long long*));
printf("%d\n", sizeof(float*));
printf("%d\n", sizeof(double*));
//指针的大小是相同的!
//为什么
return 0;
}
十二、结构体
#include <stdio.h>
struct Stu
{
char name[20];
int age;
double score;
}
int main()
{
struct Stu s = ={"张三", 20, 95.5}; //结构体的创建和初始化
printf("%s %d %lf\n", s.name, s.age, s.score);//结构体变量,成员变量 张三 20 95.500000
struct Stu * ps = &s; //结构体指针
printf("%s %d %lf\n", (*ps).name, (*ps).age, (*ps).score);//张三 20 95.500000
printf("%s %d %lf\n", ps->name, ps->age, ps->score);//张三 20 95.500000
return 0;
}