- 公开视频 -> 链接点击跳转公开课程
- 博客首页 -> 链接点击跳转博客主页
目录
变量
-
变量含义 -> 程序运行期间可能会出现变动的值,称为变量(variable)
-
变量本质 -> 变量相当于给一块内存区域(定长)起个别名,操作变量就等于操作对应内存
-
-
变量定义
-
语法格式 -> 数据类型 变量名 = 初始值;
-
变量名称为标识符,定义规则如下
- 标识符不能是关键字
- 标识符只能由数字-字母-下划线组成
- 标识符的第一个字符不能为数字
- 标识符中字母区分大小写
-
随堂代码
-
#include <stdio.h> #include <stdlib.h> int main() { //变量定义 //数据类型 变量名; int Age; //变量赋值 Age = 18; //变量定义及初始化 //数据类型 变量名(标识符) = 初始值; //初始化(initialize)变量赋初始值 int Money = 0; return 0; }
-
-
-
变量声明 -> extern int a; -> 不占用内存空间
-
变量定义 -> int a; -> 占用内存空间
-
随堂代码
-
#include <stdio.h> #include <stdlib.h> int main() { //变量定义 -> 占用内存空间 int a; a = 1; //变量声明 -> 不占内存空间 extern int b; //发生错误 -> 无法解析的外部符号_b b = 2; return 0; }
-
-
类型限定符
- extern - 声明变量
- const - 常量
- register - 寄存器变量
- volatile - 防止编译器优化
常量
-
常量含义 -> 程序运行期间不会改变的值称为常量(constant)
-
常量作用 -> 常量作用于记录程序固定的值
-
常量特性 -> 常量默认是不允许修改的(IDE限制 / 内存属性限制) - 将常量内存地址对应物理页属性(R/W)修改后即可随意更改常量值
-
常量表现
-
常量类型 表现形式 整数常量 100 - 200 小数常量 3.14 - 1.23 字符常量 ‘a’ - 'c' 字符串常量 "Hello" 宏常量 #define Age 18 const修饰的变量 cosnt int Age 18
-
-
const 修饰的变量
-
变量原有特性的基础之上增加修改限制
-
语法规则 -> const 数据类型 常量名 = 初始值;
-
随堂代码
-
#include <stdio.h> #include <stdlib.h> //全局变量 const int G_Num = 10; int main() { //局部变量 -> 存储在当前线程栈区中(可读可写) int a = 0; a = 1; //const 数据类型 常量名 = 初始值; const int Ver = 1; //编译器限制 -> 表达式必须是可修改的左值 Ver = 2; //编译器限制 == 内存属性限制 G_Num = 2; return 0; }
-
-
拓展
-
突破常量限制
-
编译器
-
局部变量/常量存储在运行线程栈区
-
栈区内存属性可读可写
-
-
编译器发现左值为const修饰的变量则抛出错误
-
代码示例(突破编译器限制)
-
#include <stdio.h> #include <stdlib.h> int main() { //局部变量 int a = 0; a = 1; //局部常量 const int b = 0; //IDE限制 //b = 0; //指针类型 int* p = &b; *p = 2; return 0; }
-
-
-
内存
-
全局常量对应内存地址属性为只读(ONLY READ)
-
只读内存尝试写入时会发生异常
-
通过API修改对应内存属性为PAGE_READWRITE(可读可写)
-
VirtualProtect(内存地址, 修改大小, 内存属性, 默认属性);
-
代码示例(修改内存属性)
-
#include <stdio.h> #include <stdlib.h> #include <Windows.h> //全局常量 -> 内存属性只读(ONLY READ) const int g_Num = 1; int main() { /* 函数原型 BOOL VirtualProtect( [in] LPVOID lpAddress, //修改内存地址 [in] SIZE_T dwSize, //修改内存大小 [in] DWORD flNewProtect, //修改内存属性 [out] PDWORD lpflOldProtect //默认内存属性 ); */ //默认数据 DWORD dwOld = 0; //修改属性 VirtualProtect(&g_Num, sizeof(g_Num), PAGE_READWRITE, &dwOld); //指针类型 int* p = &g_Num; //操作内存 *p = 100; //恢复属性 VirtualProtect(&g_Num, sizeof(g_Num), dwOld, &dwOld); return 0; }
-
-
-
物理页
-
示例代码
-
#include <stdio.h> #include <stdlib.h> #include <Windows.h> //全局常量 -> 内存属性只读(ONLY READ) const int g_Num = 1; int main() { printf("Addr -> 0x%016llx Data-> %d", &g_Num, g_Num); system("pause"); int* p = &g_Num; *p = 0x100; printf("Addr -> 0x%016llx Data-> %d", &g_Num, g_Num); system("pause"); return 0; }
-
-
操作过程
-
双机内核调试环境
-
挂靠指定进程
-
Break
-
!process 0 0 ProcessName
-
.process /i Kprocess
-
-
获取对应物理页属性
-
!pte VirtualAddress
-
-
修改RW位
-
PTE at FFFF84BFFB02B0F8
-
ontains 820000005738F005
-
eq FFFF84BFFB02B0F8 82000000`5738f007
-
-
完成测试
-
-
-
-
整型
-
数据类型 -> 变量分配对应大小的内存空间以及存储规则
-
整数类型 -> 正数-负数-0-(整数不存在小数部分)
-
数据类型 内存大小 char 1BYTE(08BIT) short 2BIYE(16BIT) int 4BYTE(32BIT) long 4BYTE(32BIT) long long 8BYTE(64BIT)
-
变量定义
-
#include <stdio.h> #include <stdlib.h> int main() { //数据类型 变量名 = 初始值; char c = 1; short s = 2; int i = 3; long l = 4; long long ll = 5; return 0; }
-
-
变量输出
-
格式化字符串 含义 %d 输出有符号十进制数 %u 输出无符号二进制数 %o 输出八进制数 %x 输出十六进制数 %hd short %ld long %lld long long %hu unsigned short %lu unsigned long %llu unsigned long long -
#include <stdio.h> #include <stdlib.h> int main() { //数据类型 变量名 = 初始值; char c = 65; short s = 2; int i = 3; long l = 4; long long ll = 5; //整型输出 printf("%c \r\n", c); printf("%hd \r\n", s); printf("%d \r\n", i); printf("%ld \r\n", l); printf("%lld \r\n", ll); return 0; }
-
正负数
-
无符号 - unsigned
-
有符号 - signed
-
定义整数类型变量时不增加前缀默认均为signed
-
取值范围
-
signed
-
数据类型 内存大小 取值范围 char 1BYTE -27 ~ 27-1 short 2BYTE -215 ~ 215-1 int 4BYTE -231 ~ 231-1 long 4BYTE -231 ~ 231-1 long long(__int64) 8BYTE -263 ~ 263-1
-
-
unsigned
-
数据类型 内存大小 取值范围 unsigned char 1BYTE 0 ~ 28-1 unsigned short 2BYTE 0 ~ 216-1 unsigned int 4BYTE 0 ~ 231-1 unsigned long 4BYTE 0 ~ 231-1 unsigned long long(__int64) 8BYTE 0 ~ 263-1
-
-
随堂代码
-
#include <stdio.h> #include <stdlib.h> int main() { //有符号 %d signed int a = 4294967295; printf("%d \r\n", a); //无符号 %u unsigned int b = 4294967295; printf("%u \r\n", b); return 0; }
-
-
-
-
数字越界
-
数据溢出
-
#include <stdio.h> #include <stdlib.h> int main() { //2BYTE最大的正数 0x00007FFF short num = 32767; printf("%hd \r\n", num); //2BYTE最小的负数 0xFFFF8000 num++; printf("%hd \r\n", num); return 0; }
-
-
精度丢失
-
#include <stdio.h> #include <stdlib.h> int main() { //1BYTE -> 8BIT //1HEX -> 4BIN //无符号4字节能够存储最大的正数 0xFFFFFFFF unsigned int num = 4294967295; printf("%u \r\n", num); //4294967295 + 1 = 4294967296 //0xFFFFFFFF + 0x1 = 0x100000000 num++; printf("%u \r\n", num); return 0; }
-
-
-
数据类型大小
-
语法规则 -> sizeof(变量/类型);
-
随堂代码
-
#include <stdio.h> #include <stdlib.h> int main() { printf("int size -> %d \r\n", sizeof(int/*数据类型*/)); long long ll; printf("long long size -> %d \r\n", sizeof(ll/*变量名*/)); return 0; }
-
-
-
整数常量
-
整数类型变量或者常量赋值时等号后边初始值为整数常量
-
整数常量可以添加前缀或者后缀来修改其含义
-
前缀
-
进制 表达 (BIN)二进制 0b + 二进制数 0b11111111 (OCT)八进制 0 + 八进制数 0377 (DEC)十进制 十进制数 255 (HEX)十六进制 0x + 十六进制数 0xFF -
#include <stdio.h> #include <stdlib.h> int main() { printf("%d \r\n", 0b11111111); //BIN 二进制 printf("%d \r\n", 0377); //OCT 八进制 printf("%d \r\n", 255); //DEC 十进制 printf("%d \r\n", 0xFF); //HEX 十六进制 return 0; }
-
-
后缀
-
符号 含义 L\l long LL\ll long long U\u unsigned -
10 int 10L long 10LL long long 10U unsigned int 10UL unsigned long 10ULL unsigned long long
-
-
-
-
实型
-
实型也称作浮点型-也就是数学当中的小数-即存储小数的数据类型
-
整数与小数在计算机中存储规则截然不同-1.0与1虽然在数值上完全一样但是其存储方式不同
-
整数类型按照补码存储
-
小数类型按照IEEE规则将浮点数分为指数部分与小数部分存储
-
整数没有小数部分-浮点数存在小数部分
-
-
浮点型类型
-
单精度浮点数float - 4Byte
-
双精度浮点数double- 8Byte
-
double类型比float类型所表示的浮点数更精确
-
类型 大小 有效范围 float 4 7位有效数字 double 8 15 ~ 16位有效数字
-
-
浮点数变量
-
常规定义
-
#include <stdio.h> #include <stdlib.h> int main() { //小数常量后增加f当作float类型处理 float f = 3.14f; printf("size of float -> %d \r\n", sizeof(f)); double d = 3.14; printf("size of double -> %d \r\n", sizeof(double)); return 0; }
-
-
科学计数
-
#include <stdio.h> #include <stdlib.h> int main() { //科学计数法 //3 * 10^2 float f = 3e2f; printf("%f \r\n", f); //3 * 0.1^2 double d = 3e-2f; printf("%lf \r\n", d); return 0; }
-
-
-
浮点数输出
-
float - %f
-
double - %lf
-
%.2f保留有效位数
-
%e输出指数计数法的浮点数
-
#include <stdio.h> #include <stdlib.h> int main() { //小数常量后增加f当作float类型处理 float f = 3.1415926f; printf("size of float -> %d \r\n", sizeof(f)); printf("float -> %f \r\n", f); double d = 3.1415926; printf("size of double -> %d \r\n", sizeof(double)); printf("double -> %lf \r\n", d); //限制输出位数 printf("%.3f \r\n", f); return 0; }
-
-
-
浮点数存储
-
示例代码
-
#include <stdio.h> #include <stdlib.h> int main() { float f = 12.25f; //0x41440000 return 0; }
-
-
存储规则
-
将12.25转换成为二进制数
-
整数部分12 == 1100
-
小数部分0.25 == 01
-
转换数据1100.01
-
-
移动小数点使小数点前面只有一个有效位 -> 小数点向左移动3位(左加右减 - 127) == 130(指数部分) == 1.10001(尾数部分)
-
-
符号位(31 ~ 31) -> 0
-
指数位(30 ~ 23) -> 1000 0010
-
尾数位(22 ~ 00) -> 1000 1000 0000 0000 0000 000
-
拼接二进制数据 -> 0100 0001 0100 0100 0000 0000 0000 0000 -> 0x41440000
-
布尔
-
布尔类型代表真或者假
-
true为真
-
false为假
-
bool类型占用内存大小为1字节
-
#include <stdio.h> #include <stdlib.h> #include <stdbool.h> int main() { bool b; printf("sizeof bool -> %d \r\n", sizeof(b)); //1 b = true; printf("true -> %d \r\n", b); //0 b = false; printf("false -> %d \r\n", b); printf("bool -> %d \r\n", 1 + 1 > 0); return 0; }
-
-
字符
-
语法 -> char ch = 'a';
-
作用 -> char类型通常用于存储字符(字母-数字-符号)
-
注意事项
-
初始化字符变量时,需要将内容放在单引号内
-
单引号内只能有一个字符
-
单引号内可以填写字符数字字母
-
字符变量不是将字符存储在内存中而是按照对应的编码格式存储
-
char类型通常用于存储字母但也可以按照整数类型表示
-
char类型占用内存大小为一字节
-
从底层角度考虑char类型也为整数类型存储字符等均按照整数存储
-
#include <stdio.h> #include <stdlib.h> int main() { //字符放在单引号内 //单引号内只能填写一个字符 //单引号内只能写字母 数字 字符 char ch = '1'; printf("%d \r\n", ch); printf("%c \r\n", ch); //ASCII -> 2 -> 50 char ch1 = 50; printf("%d \r\n", ch1); printf("%c \r\n", ch1); printf("size of char -> %d \r\n", sizeof(char)); return 0; }
-
-
-
字符存储
-
计算机只认识二进制,字符'A'存储不是将A存放在内存中,而是将字符'A'对应的ASCII码值存放在内存里
-
ASCII表
-
字符输入
-
#include <stdio.h> #include <stdlib.h> int main() { char ch; int i; //字符输入 scanf_s("%c", &ch); printf("%c \r\n", ch); //整数输入 scanf_s("%d", &i); printf("%c \r\n", i); return 0; }
-
-
字符转换
-
#include <stdio.h> #include <stdlib.h> int main() { //'A' -> 65 //'a' -> 97 char ch = 'a'; printf("%c \r\n", ch - 32); return 0; }
-
-