1.常量
-
字符常量
'a' 'b' 'c' 'd' '\0' '\n' '\t'
通过ascii查看,在ubuntu上用man ascii命令查看对应的字符。
-
ascii
'\0' :0
'\n':10
'A':65
-
整型常量
0b10110 二进制
50 十进制
-50 十进制
0661 八进制
0x1234567f 十六进制
-
实型常量
3.14
1.25
3.0e5
2.3E-2
-
字符串常量
"hello"
-
标识常量
#define N 6(宏)
2.变量
2.1 字符类型的变量
字符变量赋值
#include <stdio.h> int main(int argc, const char *argv[]) { char a;//随机值 char b = 48; char c = '0'; char d = '\101'; char e = '\x42'; char f = 0b010000001; char g = 0101; char h = 0x42; printf("a=%c\n",a); printf("b=%c\n",b); printf("c=%c\n",c); printf("d=%c\n",d); printf("e=%c\n",e); printf("f=%c\n",f); printf("g=%c\n",g); printf("h=%c\n",h); return 0; }
结果是:
字符变量越界问题
int main(int argc, const char *argv[]) { char a = 128; printf("a=%d\n",a); //a的最大数值是127,赋值为128的时候,值为-128 return 0; }
结果为
2.1整型的变量
整型变量赋值
#include <stdio.h> int main(int argc, const char *argv[]) { int a = 123; int b = 0b10110; int c = 0101; int d = 0xffac; unsigned int e = 0xaa55; printf("a = %d\n",a); printf("b = %d\n",b); printf("c = %#o\n",c); printf("d=%#x\n",d); printf("e = %u\n",e); return 0; }
结果为
整数值在内存上以补码形式存储
#include <stdio.h> int main(int argc, const char *argv[]) { int a = -5; //源码:1000 0101 //反码:1111 1010 //补码:1111 1011 0xfb printf("a=%d\n",a); printf("a=%#x\n",a); return 0; }
结果为
2.3浮点数
赋值
#include <stdio.h> int main(int argc, const char *argv[]) { float a = 3.146; printf("a=%f\n",a); printf("a=.%f\n",a);//小数点后两位,四舍五入 printf("a=%e\n",a);//指数形式 printf("a=%f\n",a);//有效位 return 0; }
浮点数在内存上的存储
-
浮点数组成部分
类型 符号位 指数位 小数位 float(4字节) 1 8 23 double(8字节) 1 11 52 -
浮点数在内存上存储实例分析
比如十进制的4.5对应的二进制如下:
先说一下小数的二进制
0.1------->2-1 (0.5)
0.01------>2-2 (0.25)
0.001----->2-3 (0.125)
0.0001---->2-4 (0.0625)
那么4.5对应的二进制如下: 100.1 = 1.001 * 22
从上述的转化过程我们知道符号位为0,指数位为2,
但是根据 IEEE的标准,对于float类型需要加上127,
对于double类型需要 加上1023。那么指数位float 129(10000001)
double 1025(10000000001), 小数位1.001(这个小数点前1可以省略),
即小数位001。所以这个结果如下:
float 0 10000001 00100000000000000000000
3.宏定义常量
#define PI 3.14
4.printf函数
printf的功能:向终端输出字符串
打印类型 | 打印符号 | 用法实例 |
---|---|---|
char a=65; | %c/%d | printf("%c\n",a);/printf("%d\n",a); |
short a=97; | %d(十进制) | printf("%d\n",a); |
unsigned short a=97; | %u(十进制) | printf("%u\n",a); |
int a=97; | %d(十进制) | printf("%d\n",a); |
unsigned int a=97 | %u(十进制) | printf("%u\n",a); |
long a=123; | %ld(十进制) | printf("%ld\n",a); |
long long a=123; | %lld(十进制) | printf("%ld\n",a); |
int a=97; | %#o(八进制) | printf("%#o\n",a); #结果0141 |
int a=97; | %#x(十六进制) | printf("%#x\n",a); #结果0x61 |
float a=3.14; | %f | printf("%f\n",a);%f:显示小数点后六位 |
float a=3.14; | %.2f | printf("%.2f\n",a);%f:显示小数点后两位 |
float a=3.14; | %e | printf("%e\n",a);%e:以指数形式显示 |
float a=3.14; | %g | printf("%g\n",a);%g:显示小数点后有效位 |
double a=3.14; | %lf | printf("%lf\n",a);%f:显示小数点后六位 |
5.C语言的运算符
5.1运算符:
-
单目运算符:
+(正) -(负) & (取地址) *(取地址中内容) ++ (自加1) --(自减1)
!(取反) ~(按位取反)
*和&含义:
++和--使用实例:
#include <stdio.h> int main(int argc, const char *argv[]) { int a = 5; //++a写在变量之前,表示先运算++,然后将结果打印出来 printf("%d\n",++a); //6 a=a+1 a = 5; //a++写在变量之后,先去打印a的值,打印完之后a的值在自加1 printf("%d\n",a++);//5 printf("%d\n",a); //6 //printf("%d\n",(a+1)++); // 这个表达式是错误的,因为要对a+1常量赋值 // 等价于(a+1) = (a+1)+1; int b; a = 5; b = ++a; //b的值是6 a的值是6 printf("a = %d,b = %d\n",a,b); a = 5; b = a++; //b的值是5 a的值是6 printf("a = %d,b = %d\n",a,b); return 0; }
!的实例:
#include <stdio.h> int main(int argc, const char *argv[]) { //非0是真,0是假 //对非0取反就是0,对0取反就是1 printf("!10 = %d\n",!10); //结果是0 printf("!-5 = %d\n",!-5); //结果是0 printf("!0 = %d\n",!0); //结果是1 int t = !100; printf("t = %d\n",t); //这里t的结果是0 int w = !t; printf("w = %d\n",w); //这里w的结果是1 return 0; }
~按位取反实例(在补码基础上取反):
#include <stdio.h> int main(int argc, const char *argv[]) { char a = 10; //a:0b 0000 1010 //~a:0b 1111 0101 = 0xf5 补码 //0b 1000 1010 //0b 1000 1011 源码 //%#x显示的是内存补码值,%#x显示4字节 //%d显示的是源码的值 printf("~a = %#x\n",~a); //结果:对a进行按位取反 0xffff fff5 printf("~a = %d\n",~a); //结果:-11,内存补码符号位是1,会转换为源码输出 printf("a = %d\n",a); //结果:10 ,因为上述的操作没有对a赋值,所有a的值没有改变 return 0; }
-
算术运算符
+(加) - (减) *(乘) /(除) %(取余)
+和-算术运算符:
#include <stdio.h> int main(int argc, const char *argv[]) { int a = 5,b = 6,c; c = a + b; printf("c = %d\n",c); //c = 11 c = a + b++; printf("c = %d,b = %d\n",c,b); //c=11 b=7 c = a +++b; // c = a++ + b; 以后尽量别这样写,因为会歧义 printf("c = %d,a=%d,b = %d\n",c,a,b);//c=12 a=6 b=7 return 0; }
使用+和-交换两个变量的值:
#include <stdio.h> int main(int argc, const char *argv[]) { int a = 5,b = 6; //请使用+ -运算将a和b的值进行交换,不允许定义新的变量 printf("a = %d,b = %d\n",a,b); a = a + b; //a=11 b=6 b = a - b; //a=11 b=5 a = a - b; //a=6 b=5 printf("a = %d,b = %d\n",a,b); return 0; }
/除运算符实例:
#include <stdio.h> int main(int argc, const char *argv[]) { int a=5,b=3,c; float d; //如果/运算符前后都是整数,在运算的时候按照整数运算 //如果在/运算符前后有小数,整个表达式都按照小数运算 //如果/运算符分子小于分母结果都是0(分子和分母前提都是整数) c = a/b; printf("c = %d\n",c); // 1 c = 2/3; printf("c = %d\n",c); // 0 d = a/b; printf("d = %f\n",d); // 1.000000 d = 5/3.0; printf("d = %f\n",d); // 1.666667 return 0; }
%取余运算符实例:
#include <stdio.h> int main(int argc, const char *argv[]) { int a=2,b = 3,c; c = a%b; //c的结果是2 printf("c = %d\n",c); float d; d = 2.0%3; //这个表达式是错误的,%符号前后都必须是整数 printf("d = %.2f\n",d); return 0; }
-
移位运算符
<< >>
<<和>>的实例:
#include <stdio.h> int main(int argc, const char *argv[]) { int a=5,b=8; a = a>>1; //0b101 >> 1 结果是2 (右移除2) b = b<<1; //0b1000 <<1 结果是16 (左移乘2) printf("a = %d,b = %d\n",a,b); int aa = -7; //源码0x80000007 反码0xFFFF FFF8 补码0xFFFF FFF9 aa = aa >> 2; //0xFFFF FFFE printf("aa = %#x\n",aa); // 0xFFFF FFFE printf("aa = %d\n",aa); // -2 //总结:对有符号数进行移位运算,如果是右移动,左侧补符号位 //如果是左移,右侧补0。 //如果对无符号数,进行移位,左右都是补充0 return 0; }
-
关系运算符
>(大于) <(小于) ==(等于) !=(不等于)
=(大于等于) <=(小于等于)
#include <stdio.h> int main(int argc, const char *argv[]) { int a=5,b=6,d=20,c; c = a > b; //因为a是5,b是6,所以a>b是假,假就是0 printf("c = %d\n",c); //结果是0 c = d > b; //因为d是20,b是6,所以d>b是真,真就是1 printf("c = %d\n",c); //结果是1 c = d > b > a; //有两个关系运算符,运算的结合方向是从左向右 //d > b结果是1 //1 > a结果是0 printf("c = %d\n",c); //结果是0 return 0; }
#include <stdio.h> int main(int argc, const char *argv[]) { int c; c = 1==2; printf("c = %d\n",c); //0 c = 0==0; printf("c = %d\n",c); //1 return 0; }
-
与运算符
& :按照位进行与运算
0 & 0 结果是0
0 & 1结果是0
1 & 1结果是1
0和任何数相与都为0,1和任何数相与都为任何数
5 & 7 = 5;
5 & -7 = 1;
使用与运算将变量的某个bit清零,不改变其他位:
int a = 0x123f ffff;
//请将a的第3个bit位清零,但不改变其他的位
a = a & (~(1<<3));
//请将a的第10和15bit位清零,但改变其他的位
a = a & (~(0x21<<10));
//请将a的低14bit清零,但改变其他的位
a = a &(~(0x3fff<<0));
//请将a的bit2,bit4,bit 6清零,但改变其他的位
a = a & (~((1<<2)|(1<<4)|(1<<6)));
0b10101 <<2 a = a &(~(0x15<<2));
0b101 0100<<0 a = a &(~(0x54<<0));
-
异或运算符
^ :按照位进行异或
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 1 = 0
相同位假,相异为真
5 ^ 7 = 0b101 ^ 0b111 = 2
使用异或交换两个变量的值:
#include <stdio.h> int main(int argc, const char *argv[]) { int a=5,b=6; //0b101 a //0b110 b // ^ //0b011 = a a = a ^ b; //0b011 a //0b110 b // ^ //0b101 = b b = a ^ b; //0b011 a //0b101 b // ^ //0b110 = a a = a ^ b; printf("a = %d,b = %d\n",a,b); return 0; }
-
或运算符
| :按照位进行或运算
0 | 0 = 0
0 | 1 = 1
1 | 1 = 1
0和任何数相或都为任何数,1和任何数相或都为1
5 | 7 = 0b101 | 0b111 = 0b111 = 7
使用或运算将变量的某个bit置位,不改变其他位:
int a = 0x123f 0001;
请将a的第3个bit位置位,但不改变其他的位
a = a | (1<<3);
请将a的第bit12和bit13位置位,但不改变其他的位
a = a | (3<<12);
#include <stdio.h> int main(int argc, const char *argv[]) { int a=5,b=6,c=10,d; d = (a && 0); //d=0 printf("d = %d\n",d); c = (0 && (a=b+b));//a=b+b没有参与运算,c = 0 printf("c = %d\n",c); d = ((c=a+b) && (d=(b+c))); //d=1 printf("d = %d\n",d); d = ((c=a+b) && (d=(b-b))); //d=0 printf("d = %d\n",d); a=5; b=6; c=10; d = (a || (c=a+b)); //d=1 但是c=a+b没有执行 printf("d = %d\n",d); c = (0 || (a=b+b));//a=b+b参与运算,c=1 printf("c = %d\n",c); d = ((c=a+b) || (d=(b+c))); //d=1 d=b+c没有参与运算 printf("d = %d\n",d); d = ((c=a-a) || (d=(b-b))); //d=0 printf("d = %d\n",d); return 0; }
-
逻辑运算符
&& 逻辑与
|| 逻辑或
-
条件运算符
-
赋值运算符
-
逗号运算符
5.2运算符的优先级
优先级:左侧最高,右侧优先级最低
单算移关与,异或逻条赋
5.3同优先级运算符结合方向
单条赋运算方向是从右向左,其余的是从左向右
6.c语言中的强制类型转换
#include <stdio.h>
int main(int argc, const char *argv[])
{
int w=12456;
char t;
//强制类型转换,在c语言中如果使用赋值运算符
//等号两边不是相同的类型,就可以使用强制类型转换
//将等号右侧强制类型转换为左侧的类型
//语法格式:(类型)表达式;
//错误的写法:类型(表达式);
t = (char)w;
printf("t = %#x\n",t);
return 0;
}
7.c语言中的隐式类型转
隐式类型转换的规则如下:
char 和 unsigned char ===>unsigned char
char 和short ===>short
short和int ===>int
int 和unsigned int ===> unsigned int
int 和long ===>long
int 和long long ===> long long
int 和float ===>float
float 和double ===>double
整型提升问题:
- 如果一个char类型和short类型参与运算,都会提升为int类型
- int类型和long类型进行运算,按照long进行运算
- 如果float类型参与运算,默认会提升为double
8.float类型判断相等的问题
float pi=3.14;
不能拿一个浮点类型的变量和一个浮点数比较是否
相等,原因是浮点数有一个精度问题,例如取浮点数
的精度是小数点后六位,如果有两个数是
3.1415921和3.1415922其实这两个数是不相等的,但是
你的精度只取到了小数点后六位,判断出来是相等。所以
以后判断一个浮点是是否等于否一个值的方法是:
|pi - 3.14| <= 0.000001