数据类型 常量 补码 阶码
左值和右值:
左值必须要有内存实体,能放在赋值号左边的值
寄存器的数据一般都是右值,能放在赋值号右边的值
int num = 1;
num+1 的值不在内存,在寄存器里(CPU里)。绝对不能取寄存器地址。
#include <stdio.h>int main(){int num = 3;int data = 0;_asm{mov eax, num //num移动到eaxadd eax, 4mov data, eax}printf("%d", data); //结果输出7return 0;}
cpu是处理计算的。
内存是存储的,内存不负责计算。
变量的赋值就算拷贝二进制。
内存之间不可以直接拷贝,必须通过CPU。
变量的值发生变化,就是变量的那一段内存,可以存放不同的二进制数据。
const的注意事项:
const int num; //错误的,常量必须初始化
const int num=20;//const常量只有在初始化的时候是左值
num = 30; //错误,不能被改变
如果要改变的话
const int num = 10;
int * p = (int *)#
*p = 3;
const define 定义常量的差别:
#define不会类型检查
const 会类型检查
#define N 10
const int M = 100; //伪常量
int a[N];//ok
int b[M];//不ok
赋值号会自动进行数据类型转换
#include <stdio.h>#define M 10.0const int N = 10.0;int main(){printf("%d\n", M); // 0printf("%d\n", N); // 10return 0;}
printf()的注意事项:
printf不会进行 数据类型转换,注意下面错误的例子
printf("%d", 10.0); // 0printf("%d\n",10.3); // -1717986918printf("%f\n",10); // 0.000000
printf连带效应,第一个错误,连带第二个错误
printf("%d\n%d\n", 10.0, 10); // 0 1076101120
类型不仅决定了大小,而且决定了二进制数据的解析方式
#include <stdio.h>int main(){int num = 100;int *p1 = #float *p2 = #double *p3 = #printf("%d\n", *p1);printf("%f\n", *p2);printf("%f\n", *p3);return 0;}

数据类型的极限:
#include <stdio.h>#include <limits.h>#include <float.h>int main(){printf("INT_MAX = %d\n", INT_MAX);printf("INT_MIN = %d\n", INT_MIN);printf("LONG_MAX = %ld\n", LONG_MAX); //32位平台,long和int最大值一样printf("LONG_MIN = %ld\n", LONG_MIN);printf("LLONG_MAX = %lld\n", LLONG_MAX);printf("LLONG_MIN = %lld\n", LLONG_MIN);printf("FLT_MAX = %.100f\n", FLT_MAX);printf("FLT_MIN = %.100f\n", FLT_MIN);printf("DBL_MAX = %.500f\n", DBL_MAX);printf("DBL_MIN = %.500f\n", DBL_MIN);return 0;}

long long 和 long double
long long moblie = 18611210283;//老师手机号printf("%lld", moblie);
long long 占 8个字节 主要是为了存储手机号~qq号
整数的补码:
有符号整数
0(+0 -0)
0000 0000 0000 0000
+1
0000 0000 0000 0001
-1
1111 1111 1111 1111
+2147483637
0111 1111 1111 1111
-2147483638
1000 0000 0000 0000
无符号整数
+4294967295
1111 1111 1111 1111
输出只会根据格式解析对应的二进制:
#include <stdio.h>#include <limits.h>int main(){unsigned int num = -1;int data = 4294967295;printf("%d\n", num); //-1printf("%d\n", data); //-1printf("%u\n", num); //4294967295printf("%u\n", data); //4294967295return 0;}
字节不同 数据之间的转换:
小字节转换为大字节数据的时候,有符号位就填充符号位
char ch = -1;int num = ch;printf("%d\n",num);//-1
无符号位就填充0
unsigned char ch = 3;unsigned int num = ch;printf("%d\n",num);//3
实数用阶码表示:
对于大小为32-bit的浮点数(32-bit为单精度,64-bit浮点数为双精度,80-bit为扩展精度浮点数),
1、其第31 bit为符号位,为0则表示正数,反之为-数,其读数值用s表示;
2、第30~23 bit为幂数,其读数值用e表示; 8位
3、第22~0 bit共23 bit作为系数,视为二进制纯小数,假定该小数的十进制值为x;
41200000 10.0
0100 0001 0 010 0000 0000 0000 0000 0000
c1200000 -10.0
1100 0001 0 010 0000 0000 0000 0000 0000
4124cccd 10.3
0100 0001 0 010 0100 1100 1100 1100 1101
40ebced9 7.369
0100 0000 1 110 1011 1100 1110 1101 1001
内存检索:
_declspec(dllexport) void go(){void *p1 = 0xae0000;void *p2 = 0xaef000;for (char *p = p1; p != p2; p++)//内存最小单位是字节{int *px = p;//设定步长为4if (*px == 90)*px = 99;}}
位 与 运算符 &
1和0 对 1 相与 都是原来的值 1 & 1 = 1 0 & 1 = 0
1和0 对 0 相与 都会变成0 1 & 0 = 0 0 & 0 = 0 和0相与可以用来关灯
位 或 运算符 |
1和0 对 1 相或 都会变成1 1 | 1 = 1 0 | 1 = 1 和1相或 可以用来开灯
1和0 对 0 相或 都是原来的值 1 | 0 = 1 0 | 0 = 0
位 异或 运算符 ^
相同为0 不同为1, 搞基即变0
1和0 对 1 异或 都会发生改变 1 ^ 1 = 0 0 ^ 1 = 1 只要和1异或 值都会发生改变
1和0 对 0 异或 都是原来的值 1 ^ 0 = 1 0 ^ 0 = 0
异或可以实现交换数据的作用
#include <stdio.h>int main(){char ch1 = 6;char ch2 = 5;ch1 ^= ch2;ch2 ^= ch1;ch1 ^= ch2;printf("%d\n", ch1); // 5printf("%d\n", ch2); // 6return 0;}
然而,这里面却存在着一个非常隐蔽的陷阱。
通常我们在对数组进行操作的时候,会交换数组中的两个元素,如exchang(&a[i], &b[j]), 这儿如果i==j了(这种情况是很可能发生的),得到的结果就并非我们所期望的。
异或可以指定 位进行反转:
对前四个反转,后四个保持原样
1010 0101 //前四个进行异或1 后四个进行异或0
//1111 0000
//0101 0101
位 取反 运算符 ~ 注意(!是逻辑取反)
char a = 240;printf("%d\n", ~a); //15 位取反printf("%d\n", !a); //0 逻辑取反
给出一个整数,计算出补码里有多少个1
while循环:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int get_num(int num){int index = 0;while (num){num &= num - 1;index++;}return index;}int main(){int num;scanf("%u", &num);printf("%d\n", get_num(num));return 0;}
for循环:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int get_num(int num){int index = 0;for (; num; num &= num - 1){index++;}return index;}int main(){int num;scanf("%u", &num);printf("%d\n", get_num(num));return 0;}
goto循环:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int get_num(int num){int index = 0;AAAA:if (num){num &= num - 1;index++;goto AAAA;}return index;}int main(){int num;scanf("%u", &num);printf("%d\n", get_num(num));return 0;}
递归:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int get_num(int num){if (num == 0)return 0;return 1 + get_num(num & num - 1);}int main(){int num;scanf("%u", &num);printf("%d\n", get_num(num));return 0;}
给出一个整数,打印出来它的补码,原码,反码:
补码循环:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(){int num;scanf("%u", &num);int data, i;data = 1 << 31;for (i = 1; i <= 32; i++){printf("%c", num & data ? '1' : '0');num <<= 1;if (i % 4 == 0) putchar(' ');}return 0;}
另外一种方法让data右移:注意是无符号unsigned:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(){int num;scanf("%u", &num);unsigned int data, i;data = 1 << 31;for (i = 1; i <= 32; i++){printf("%c", num & data ? '1' : '0');data >>= 1;if (i % 4 == 0) putchar(' ');}return 0;}
//1111 1111 1111 1111 1001
//1000 0000 0000 0000 0000 补码递归:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>void buma(int num , int i){if (i == 0)return;int data = 1 << 31;if (i % 4 == 0) putchar(' ');printf("%c", num & data ? '1' : '0');num <<= 1;i--;buma(num, i);}int main(){int num;scanf("%u", &num);buma(num,32);return 0;}
原码循环:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(){int num;scanf("%u", &num);int data, i;data = 1 << 31;if (num < 0){num = ~num + 1;num = num | data; //保证符号位是负的}for (i = 1; i <= 32; i++){printf("%c", num & data ? '1' : '0');num <<= 1;if (i % 4 == 0) putchar(' ');}return 0;}
原码递归:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>void yuanma(int num, int i){if (i == 0)return;int data = 1 << 31;if (i % 4 == 0) putchar(' ');printf("%c", num & data ? '1' : '0');num <<= 1;i--;yuanma(num, i);}int main(){int num;scanf("%u", &num);int data = 1 << 31;if (num < 0){num = ~num + 1;num = num | data; //保证符号位是负的}yuanma(num, 32);return 0;}
反码循环:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>int main(){int num;scanf("%u", &num);int data, i;data = 1 << 31;if (num < 0){num = num - 1;num = num | data;}for (i = 1; i <= 32; i++){printf("%c", num & data ? '1' : '0');num <<= 1;if (i % 4 == 0) putchar(' ');}return 0;}
反码递归:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>void fanma(int num, int i){if (i == 0)return;int data = 1 << 31;if (i % 4 == 0) putchar(' ');printf("%c", num & data ? '1' : '0');num <<= 1;i--;fanma(num, i);}int main(){int num;scanf("%u", &num);int data = 1 << 31;if (num < 0){num = num - 1;num = num | data;}fanma(num, 32);return 0;}

浙公网安备 33010602011771号