一.运算符
🔔计算机存储数据的二进制补码形式
1.位运算符号
1.1 & 按位与:
(看成*)
两个二进制操作数对应位同为 1 ,结果位才为 1 ,其余情况为 0。
eg:5&-2
(1)先写出 5,-2 的补码 .
5 的补码:00000000 00000000 00000000 00000101
-2 的原码:10000000 00000000 00000000 00000010
-2 的反码:11111111 11111111 11111111 11111101
-2 的补码:11111111 11111111 11111111 11111110
(2)
5 的补码:00000000 00000000 00000000 00000101
-2 的补码:11111111 11111111 11111111 11111110
5 & -2 的补码:00000000 00000000 00000000 00000100
(3)此时得到的是补码,要原码才能打印
5 &- 2 的原码:00000000 00000000 00000000 00000100
(正整数原、反、补相同)
此时打印结果是:4
1.2 | 按位或:
(看成+)
两个二进制操作数对应位只要有一个为 1 ,结果 位 就为 1 ,其余情况为 0 。
eg:5|-2
(1)先写出 5,-2 的补码
5 的补码:00000000 00000000 00000000 00000101
-2 的原码:10000000 00000000 00000000 00000010
-2 的反码:11111111 11111111 11111111 11111101
-2 的补码:11111111 11111111 11111111 11111110
(2)
5 的补码:00000000 00000000 00000000 00000101
-2 的补码:11111111 11111111 11111111 11111110
5 | -2 的补码:11111111 11111111 11111111 11111111
(3)
5 | -2 的补码:11111111 11111111 11111111 11111111
5 | -2 的反码:11111111 11111111 11111111 11111110
5 | -2 的原码:10000000 00000000 00000000 00000001
此时打印结果是:-1
1.3 ^ 按位异或
两个二进制操作数对应位相同为 0 ,不同为 1
eg:先写出 5,-2 的补码
(1)
5 的补码:00000000 00000000 00000000 00000101
-2 的原码:10000000 00000000 00000000 00000010
-2 的反码:11111111 11111111 11111111 11111101
-2 的补码:11111111 11111111 11111111 11111110
(2)
5 的补码:00000000 00000000 00000000 00000101
-2 的补码:11111111 11111111 11111111 11111110
5 ^ -2 的补码:11111111 11111111 11111111 11111011
(3)
5 ^ -2 的补码:11111111 11111111 11111111 11111011
5 ^ -2 的反码:11111111 11111111 11111111 11111010
5 ^ -2 的原码:10000000 00000000 00000000 00000101
1.4 ~ 取反
一个二进制操作数,对应位为 0 ,结果位为 1 ;对应位为 1 ,结果位为 0.
作用是将每位二进制取反
eg:先写出 5 的补码
(1)
5 的补码:00000000 00000000 00000000 00000101
(2)
5 的补码:00000000 00000000 00000000 00000101
取反:11111111 11111111 11111111 11111010
(3)此时得到的是补码,需要原码才能打印
取反后(补码):11111111 11111111 11111111 11111010
反码:11111111 11111111 11111111 11111001
原码:10000000 00000000 00000000 00000110
此时打印的结果是:-6
1.5 << 左移运算符
代码:
#include<stdio.h>
int main()
{
int a = -5;
int b = a << 1;
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
结果是 -10
规则:
正数:所有数据位向左移动n位,右边空位补0
eg:
(1)先写出 -5 的补码
原码:10000000 00000000 00000000 00000101 (最高位为1)
反码:11111111 11111111 11111111 11111010 (按位取反,符号位不变)
补码:11111111 11111111 11111111 11111011 (反码加1)
(2)补码向左移动一位,左边去掉,右边补0,如图:
(3)此时得到的是补码,还要反推原码才能打印
补码:11111111 11111111 11111111 11110110
反码:11111111 11111111 11111111 11110101(补码 -1 得到反码)
原码:10000000 00000000 00000000 00001010(按位取反得到原码)
注:求原码也可以补码符号位不变,其余位取反再+1。
此时得到的原码就可以打印了,结果是 -10。
1.6 >> 右移运算符
代码:
#include<stdio.h>
int main()
{
int a = -5;
int b = a >> 1;
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
原码:10000000 00000000 00000000 00000101 (最高位为1)
反码:11111111 11111111 11111111 11111010 (按位取反,符号位不变)
补码:11111111 11111111 11111111 11111011 (反码加1)
(2)补码向右移动一位,右边丢弃,左边补符号位,如图:
(3)
补码:11111111 11111111 11111111 11111101
反码:11111111 11111111 11111111 11111100(补码 -1 得到反码)
原码:10000000 00000000 00000000 00000011(按位取反得到原码)
此时得到的原码就可以打印了,结果是 -3
🔔不能移动数位是负数的。
2.赋值运算符
= += -= *= /= %= >>= <<= &= |= ^=
a = 18;
a += 18 == a = a+18;
a = 20;
a + 5;
printf("a=%d\n",a);//a==20
3.递增递减运算符
前缀++ 后缀++ 前缀-- 后缀--
a = 18;
a++;//18->19
++a;//19->20
a--;//20->19
--a;//19->18
a = 18;
a++ + 5 == 23;//a+5 a+=1
a = 18;
++a + 5 == 24;//a+=1 a+5
前缀++:先自身的值加1再参与运算
后缀++:先参与运算再自身的值加1
🔔:a++与a--,是复制一个自己,用复制的自己去参与运算。
4.地址运算符
&
不同程序直接变量名可以重复,但是地址编号是唯一的
&变量名得到变量的存储地址编号
printf("&a=%p\n",&a);
printf("&b=%p\n",&b);
5.逗号运算符
int a = (3+5,5*3,7+4,9-
4);//8,15,11,5
printf("a=%d\n",a);//a==5
a = (a+=1,a*=2,a-3);//6,12,9
printf("a=%d\n",a);//a==9
6.sizeof运算符
7.条件运算符
8.短路法则
二.数据类型
1.基本数据类型
signed:有符号数,不写时默认
unsigned:无符号数,需要指定
2.char 字符型 1个字节
取值范围:0~255
-125~127
3.int 整型 4个字节
取值范围:0~2^32-1
-2^31~2^31-1
4.short 短整型 2个字节
取值范围:0~65535
-32768~32767
5.long长整型 8个字节
取值范围:0~2^64-1
-2^63~2^63-1
6.float 4个字节 单精度浮点型,double 8个字节 双精度浮点型
double使用两个存储单元,所以在64和32位系统中都是8个字节
浮点:他们小数点最后一位是上下浮动的。
三.常量和变量
1.常量
程序运行期间数值不发生变化
1.整型常量:13
2.字符常量:a
3.浮点常量:1.34
4.字符串常量:“abcd”
5.标识符常量:是指用标识符替代常量使用的一种常量,其名称统称是一个标识符。
与变量的区别:一般使用大写英文字母表示,表示常量在使用前必须预先定义。
放在main外面: #define 标识符常量名 常量;
#define X 10
#define X 10
#define Y X+15 //10+15
#define z X*Y //10*10+15
int main(int argc, char *argv[])
{
int a = z;
printf("a=%d\n",a);//115
return;
}
🔔标识符常量是严格的同义替换,不会提前计算 。
2.变量
1.变量名由用户根据其用途任意命名,变量名命名遵从标
2.1局部变量
2.2全局变量
3.强制类型转换
四.输入输出
4.1字符输出函数 putchar
int a = 78;
char b = '*';
char d = putchar(a);
printf("d:%c\n",d);
putchar(b);
putchar(97);
putchar('A');
putchar(10);//打印10的字符'\n'
4.2字符输入函数 getchar
char a = getchar();
printf("%c\n",a);
🔔🔔🔔查看问题汇总---(1)。
4.3标准输出函数 printf
4.4标准输入函数 scanf
代码演示:
int a;
scanf("%d",&a);
4.4.1.scanf结束条件:
4.4.2.scanf对不同类型输入的处理方式:
希望读者记住scanf函数在读取除字符之外的输入的时候会遵守以下原则
scanf函数每次读取一个字符,跳过所有的空白字符,直到遇到第一个非空白字符的时候才开始读取。(同时也说明sanf不可以加\n)
(1).整数%d
对于整型数据的输入,也就是说"%d"类型的输入,scanf默认的分割符是所有的空白字符(空格,换行符\n、制表符以及回车\r)。也就是说如果一个scanf函数中出现scanf("%d%d",&a,&b),那么用任何一个空白字符来分隔两个整数a,b的值,变量a,b都可以接收到正确的输入。
eg:
scanf("%d %d",&a,&b);
输入1:
7 3
输出:7 3
输入2:
7 3:
输出:7 3
输入3:
7
3
输出:7 3
输入队列中的7和3以及中间的空格,制表符或者回车符都会被送入缓冲区,但是scanf只接受非空白字符,因此无论以上三种格式输入都不会改变输入结果,理由是scanf会跳过所有的空白字符,将其丢在缓冲区内。所以,程序在下一次读取输入的时候会首先读取到的是被丢弃在缓冲区中的空白字符。
如果接下来的转换说明是%c,或者%s,将会直接读取该空白字符而不是跳过,空白字符会从打印队列中显示出来。
eg:
#include <stdio.h>
void main()
{
int a;
char c;
scanf("%d%c",&a,&c);
printf("a=%d c=%c",a,c);
}
---------------------------------------------------------------------------------------
输入:5 //这里的输入是5然后按下enter键(也就是换行符)
输出:a=5 c=
//这里多出来的空白一行就是输入的\n
---------------------------------------------------------------------------------------
(2).字符串%s
如果使用%s转换说明,scanf会读取除了空白以外的所有字符。
scanf在读取字符串时,在遇到第一个空白的时候会停止不再读取输入。第一个空白字符后的所有字符都会被保留在缓冲区中,直到缓冲区被刷新或者被scanf读取走。
(3).字符%c
scanf在处理对字符数据的输入时,既不会忽略前导空白字符,默认也没有任何分隔字符。所有的字符,包括空白字符都会被当成输入字符。(被称为脏字符:只有在获取%c字符的时候才出现,其它不会出现)
脏字符解决方案:
1.抑制符
char a,b;
scanf("%c%*c%c",&a,&b);
输入;a b 此时,你输入的 (空格)会被第二个%*c代替。
也可以代替回车,Tap。
输出a b
2.用空白符吸收
char a,b;
scanf("%c %c",&a,&b);
输入;a b 此时,你输入的 (空格)会被第空格代替
输出a b
3.使用getchar吸收
getchar是用在scanf与scanf之间,getchar()吸收回车键。
scanf("%c",&a);
getchar();
scanf("%c",&b)
4.5字符串输入输出函数
由一个或多个字符组成,用""包含,由‘\0’结尾。
4.5.1puts
调用puts()函数实现字符串的输出。
puts(字符数组);
功能:将字符数组起始地址开始的一个字符串(以’\0’结束的字符序列)输出到终端,并将字符串结束标志’\0’转化成’\n’,自动输出一个换行符。
三种方式:
puts("hello");//输出字符串
puts("");//实现换行
char c[ ]= "How\nare\nyou!";
puts(c);
输出结果:
How
are
you!
4.5.2gets
功能:从终端输入一个字符串(包括空格)赋给从字符数组起始的存储单元中,直到读入一个回车符为止。回车符读入后,不作为字符串的内容,系统将自动用’\0’替换,作为字符串结束的标志。
int main(int argc, char *argv[])
{
char c[20];
gets(c);
printf("%s",c);
return 0;
}
hqyj@ubuntu:~/c/day5$ ./demo5
hello word
hello wordhqyj@ubuntu:~/c/day5$ ^C
同时,puts可以和gets联合使用,代码如下:
#include <stdio.h>
int main(int argc, char *argv[])
{
char c[20];
gets(c);
puts(c);
return 0;
}
hqyj@ubuntu:~/c/day5$ ./demo5
hello word
hello word
hqyj@ubuntu:~/c/day5$
两段代码对比:此时可以看出puts可以代替printf输出字符串,不再需用写%s。
🔔求方程的根 函数:sqrt();
计算三角周长s,面积all
#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[])
{
float a,b,c,all,s;
scanf("%f %f %f",&a,&b,&c);
s = (a+b+c)/2.0;
all = sqrt(s*(s-a)*(s-b)*(s-c));
printf("ZC:%.2f\nMJ:%.2f\n",s,all);
return 0;
}
hqyj@ubuntu:~/c/day5$ gcc demo3.c -o demo3 -lm
hqyj@ubuntu:~/c/day5$ ./demo3
2 2 2
ZC:3.00
MJ:1.73
hqyj@ubuntu:~/c/day5$