C语言基础:实型、进制转换、原反补码、char取值范围、特殊限定字、字符串、算术运算符、赋值运算符、关系运算符、逻辑运算符
1.实型(浮点型):float 单精度 4字节、double 双精度 8字节
① 实型常量
-
void fun1()
-
{
-
// 实型常量
-
// 不以F结尾的实型常量,为double类型
-
printf("sizeof(3.14) = %u\n", sizeof(3.14));// double
-
// 以F结尾的为float类型
-
printf("sizeof(3.14F) = %u\n", sizeof(3.14F));// float
-
}
② 实型变量
-
void fun2()
-
{
-
// 赋值语句,尽量保证 = 两边类型匹配
-
float F = 0.0F;
-
double D = 0.0;
-
printf("F = %f\n", F);
-
printf("D = %lf\n", D);
-
// 获取键盘输入
-
scanf("%f", &F);
-
printf("F = %f\n", F);
-
scanf("%lf", &D);
-
printf("D = %lf\n", D);
-
}
③ 实型存储
2.二进制、八进制、十进制、十六进制的转换
① 十进制转二进制、八进制、十六进制
方法:短除法
② 二进制、八进制、十六进制转十进制
方法:进制的位次方
例: 1100 1100 → 1*2^7+1*2^6+0*2^5+0*2^4+1*2^3+1*2^2+0*2^1+0*2^0
=128+64+0+0+8+4+0+0=204
0123 → 1*8^2+2*8^1+3*8^0=64+16+3=83
0x12 → 1*16^1+2*16^0=16+2=18
③ 二进制转八进制、十六进制
a、二进制转八进制:二进制从右往左,每三位二进制对应一位八进制
1100 1100 → 011 001 100 → 314
b、二进制转十六进制:二进制从右往左,每四位二进制对应一位十六进制
1100 1110 → 12 14 → 0xCE
④ 八进制、十六进制转二进制
a、八进制转二进制:八进制从右往左,每一位八进制对应三位二进制
0567 → 101 110 111 → 1 0111 0111
b、十六进制转二进制:十六进制从右往左,每一位十六进制对应四位二进制
0xAB → 1010 1011
一位16进制数占1字节空间
3.数值在计算机中的存取方式
① 存(任何数据在计算机存放的都是补码)
数据的表现形式(原码、反码、补码)
a、原码:数据本身的二进制
无符号数:
15 原码 → 0000 1111
有符号数:
正数:+15 原码 → 0000 1111
负数:- 15 原码 → 1000 1111
b、反码:
无符号数:反码 = 原码
15 反码 → 0000 1111
有符号数:
正数:反码 = 原码
+15 原码 → 0000 1111
负数:符号位不变,其他位取反
- 15 原码 → 1111 0000
c、补码:
无符号数:补码 = 原码
15 补码 → 0000 1111
有符号数:
正数:补码 = 原码
+15 原码 → 0000 1111
负数:反码+1
- 15 原码 → 1111 0001
综上所述:无符号数及有符号正数,计算机存放的是原码(=补码=反码)
有符号负数,计算机存放的是补码
① 取(类型不匹配,按变量原符号输出)
a、有符号取 %d %ld %lld %f %lf
步骤:先看最高位(符号位)是否是1?
如果是1,表示该数是一个负数的补码,符号位不变,其他取反,+1 补码的补码为原码
如果是0,表示该数是一个正数的补码,原样输出
b、无符号取 %u %lu %llu %o %x
步骤:内存数据原样输出
-
void fun3()
-
{
-
int num = -15;
-
// 1000 1111 原码
-
// 1111 0000 反码
-
// 1111 0001 补码
-
printf("signed int:%d\n", num);// 有符号取 -15
-
printf("unsiged int:%u\n", num);// 无符号取 241(不对,int32位)
-
char num2 = -15;
-
printf("signed char:%d\n", num2);// 有符号取 -15
-
printf("unsiged char:%u\n", num2&0x00ff);// 无符号取 241(不对,%u取32位不足补1)
-
unsigned char num1 = 0xff;
-
printf("num1 = %x\n", num1);
-
printf("num1 = %d\n", num1);
-
printf("num1 = %u\n", num1);
-
printf("num1 = %d\n", (char)num1);
-
}
补码的意义
① 统一了领的编码
② 将符号位和其他位统一处理
③ 将减法运算转换为加法运算
④ 两个用补码表示的数相加时,如果最高位(符号位)有进位则被舍弃
十六进制原样存取
-
void fun4()
-
{
-
char num = 0x9b;// 1001 1011
-
printf("signed char:%d\n", num);
-
// 1001 1011 → 1110 0100 → 1110 0101 →
-
// 1*2^6+1*2^5+1*2^2+1*2^0=64+32+4+1= -101
-
printf("unsiged char:%x\n", num);
-
printf("unsiged char:%x\n", num&0x00ff);
-
}
数据的溢出
-
void fun5()
-
{
-
char num = 0xfe + 3;
-
// 1111 1110 + 0000 0011
-
// 计算机存储 1 0000 0001
-
printf("signed num = %d\n", num);
-
printf("unsigned num = %u\n", num &= 0x00ff);
-
printf("unsigned num(16) = %#x\n", num);
-
}
4.char的取值范围
char为例,说明有符号数、无符号数之间的范围
signed char → 1111 1111 ~ 1000 0000 -127~ -0
0000 0000 ~ 0111 1111 +0 ~ 127
将-0直接定义为-128(1 0000 0000), signed char → -128~127
-
void fun06()
-
{
-
char num = 0x80;// 1000 000 -127
-
printf("%d\n", num);
-
}
unsigned char → 0000 0000 ~ 1111 1111 0 ~ 255
signed\unsigned char表示256个数(空间范围相同)
5.特殊的限定符关键字 → const extern register volatile
① const 只读变量,修饰变量为只读,不可被修改,必须初始化(gcc随机值)
-
void fun7()
-
{
-
// num只读变量,本质是变量,只是无法被赋值(写)
-
const int num = 10;
-
//num = 100;// error
-
printf("num = %d\n", num);
-
}
② register 寄存器变量,编译器尽可能将修饰变量放入寄存器中,如果失败将存放在内存中
禁止对修饰变量取地址操作,&地址操作针对内存而言
-
void fun8()
-
{
-
register int num = 10;
-
num = 15;
-
printf("num = %d\n", num);
-
//printf("num = %p\n", &num);// error
-
}
③ volatile 防止编译器优化,强制访问内存,修饰变量禁止存入寄存器,禁止编译器忽略编译(逐条编译修饰变量)
6.字符串常量
① 由一个或多个字符组成,且以字符'\0'结尾(编译器自动添加的结尾标记),双引号“”作用(字符串类型说明,取地址)
② '\0'作用:
a、字符串遍历:%s输出字符串,必须给定输出首地址,遇到'\0'结束输出
-
void fun9()
-
{
-
// 字符串常量
-
printf("sizeof(%s) = %u\n", "hello world", sizeof("hello world"));// 12
-
// "hello world" 告诉编译器是字符串,取字符串首元素地址
-
printf("%%s = %s\n%%u = %u\n%%s+1 = %s\n", "hello world", "hello world", "hello world"+1);// "hello world"-1 访问非法内存,结果未知
-
// 'A' 告诉编译器是字符,取ASCII码值
-
printf("%%c = %c\n%%d = %d\n%%c+1 = %c\n", 'A', 'A', 'A'+1);
-
// %s遇到反'\0'结束
-
printf("%s\n", "hello\0world");// hello
-
printf("%s\n", "\0hello\0world");//
-
}
7.putchar( ) getchar( ) 区别
① getchar( ) 获取键盘缓冲区的一个字符,带阻塞
-
void fun10()
-
{
-
printf("请输入一个字符:\n");
-
char ch = 0;// 0 == '\0'
-
ch = getchar();// 获取的字符通过返回值返回
-
printf("ch = %c\n", ch);
-
getchar();// 无变量接返回值丢弃
-
ch = getchar();
-
printf("ch = %c\n", ch);
-
}
② putchar('ch'/ASCII) 输出一个字符/ASCII码值
-
void fun11()
-
{
-
printf("%c\n", 'a');
-
putchar('a');
-
putchar('\n');
-
putchar(97);
-
putchar('\n');
-
putchar(200);// 不确定
-
}
8.printf( ) 输出格式补充 %md %0md %-md %m.nf
-
void fun12()
-
{
-
// %md m表示所占终端的显示位宽,默认右对齐
-
printf("#############\n");
-
printf("##%5d##\n", 123);
-
printf("##%2d##\n", 123);// 小于数据长度,原样输出
-
// %0md 空出的位置补0
-
printf("##%05d##\n", 123);
-
// %-md 左对齐
-
printf("##%-5d##\n", 123);
-
// - 和 0 不可同时使用,%-0md不会补0
-
// %m.nf m表示显示位宽,n表示小数显示位数,自动四舍五入
-
printf("##%6.2f##\n", 1.236F);
-
}
9.算数运算符 / 取整 % 取余 ++ 自加 -- 自减
① / %
-
void fun13()
-
{
-
// / 取整
-
printf("1/2 = %d\n5/2 = %d\n", 1 / 2, 5 / 2);
-
// % 取余数 判断一个数能否被另一个数整除
-
printf("1%%2 = %d\n5%%2 = %d\n", 1 % 2, 5 % 2);
-
if (5 % 2 == 0)
-
{
-
printf("5被2整除\n");
-
}
-
else
-
{
-
printf("5不被2整除\n");
-
}
-
// 将num的每位数字单独输出
-
int num = 1234;
-
printf("%d,%d,%d,%d\n", num / 1000, num / 100 % 10, num / 10 % 10, num % 10);
-
printf("%d,%d,%d,%d\n", num / 1000, num % 1000 / 100, num % 100 / 10, num % 10);
-
}
① ++ --
a、作为独立语句时,i++与++i效果一致
-
void fun14()
-
{
-
int i = 10;
-
i++;// i=i+1
-
printf("i = %d\n", i);
-
int j = 10;
-
++j;// i=j+1
-
printf("j = %d\n", j);
-
int k = 10;
-
k--;// k=k-1
-
printf("k = %d\n", k);
-
int h = 10;
-
--h;// h=h-1
-
printf("h = %d\n", h);
-
// ++ -- 作为独立语句时,i++与++i效果一致
-
}
b、非独立语句时,在变量右边i++:先使用后自增/减,在变量左边++i:先自增/减在使用
-
void fun15()
-
{
-
int i = 10;
-
int j = 0;
-
int k = 0;
-
j = i++;// j=i; i=i+1;
-
// i=11,j=10
-
k = ++i;// i=i+1; j=i;
-
// i=12,k=12
-
printf("i = %d, j = %d, k = %d\n", i, j, k);
-
}
10.赋值运算符 = += -= *= /= %=
① 将=右边的值,赋值给=左边
左值:能被写操作,能在=左边,也可在右边
右值:不能在=左边的值,只能在=右边
-
void fun16()
-
{
-
int num = 0;// num左值
-
num = 100;// 100为右值
-
const int data = 10;// data为右值
-
int num2 = 0;
-
num2 = num;// num2,num都为左值
-
}
② [+= -= *= /= %= ]中=右边为一个整体
a+=b+c → a=a+(b+c)
-
void fun17()
-
{
-
int num = 10;
-
num *= 3 + 5;// num = num*(3+5)
-
printf("num = %d\n", num);
-
}
11.关系运算符
关系运算符为双目运算符,其结合性均为左结合
当条件成立时结果为1,条件不成立结果为0
12.逻辑运算符
“真”对应的值为1,“假”对应的值为0
a、! 逻辑非
-
void fun18()
-
{
-
printf("!0 = %d\n", !0);
-
printf("!1 = %d\n", !1);
-
printf("!100 = %d\n", !100);
-
printf("!-100 = %d\n", !-100);
-
}
b、&& 逻辑与 A&&B AB同真为真,当A为真才会判断B表达式
-
fun19()
-
{
-
printf("3 > 4 && 5 < 3, %d\n", 3 > 4 && 5 < 3);
-
printf("3 < 4 && 5 < 3, %d\n", 3 < 4 && 5 < 3);
-
printf("3 < 4 && 5 > 3, %d\n", 3 < 4 && 5 > 3);
-
4 < 3 && printf("one\n");
-
4 > 3 && printf("two\n");
-
}
c、|| 逻辑或 A||B AB同假为假,当A为假才会判断B表达式
-
fun20()
-
{
-
printf("3 > 4 || 5 < 3, %d\n", 3 > 4 || 5 < 3);
-
printf("3 < 4 || 5 < 3, %d\n", 3 < 4 || 5 < 3);
-
printf("3 < 4 || 5 > 3, %d\n", 3 < 4 || 5 > 3);
-
4 < 3 || printf("one\n");
-
4 > 3 || printf("two\n");
-
}