---------------------------------------------------------------------------------
【C语言的类型】
1. 整型(都分为有符号signed和无符号unsigned两个版本):
char, short, int, long, long long
# 注:long long 为C99标准,是64位长整型,需要编译器对C标准的支持。
引:C标准规定整型值相互间大小规则,长整型至少应该和整型一样长,而整型至少应该和短整型一样长。
short int 至少为16位,long int 至少32位,至于缺省的 int 究竟是16还是32,通常选择的缺省值是这种机器最为高效的位数。
头文件 limits.h 说明了各种不同的整数类型的特点。 ———《C和指针》
2. 浮点型:
float,double,long double
3. 布尔类型:
bool:通过头文件定义,只需要引入stdbool.h即可使用
# 注:C99之前没有布尔型,C99标准引入新关键字_Bool表示布尔类型,引入stdbool.h可以用 bool 代替_Bool,true代替1,false代替0
4. 指针
自定义类型
【类型有什么不同】
类型名称:int,long,double
输入输出时的格式化:%d,%ld,%lf
所表达的数的范围:char < short < int < float < double # 注意,它们的大小与编译器和操作系统
内存中所占据的大小:1个字节到16个字节,使用sizeof()得到大小,sizeof是静态运算符,它的结果在编译时刻就决定了,sizeof的运算不会计算。
内存中的表达形式:二进制数(补码),编码
【整数类型】
// main.c // Created by weichen on 15/3/25. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> int main(int argc, const char * argv[]) { printf("sizeof(char)=%ld ", sizeof(char)); //1 字节(8bite) printf("sizeof(short)=%ld ", sizeof(short)); //2 字节 printf("sizeof(int)=%ld ", sizeof(int)); //4 取决于编译器(cpu),通常的意义是“1个字” printf("sizeof(long)=%ld ", sizeof(long)); //8 取决于编译器(cpu),通常的意义是“1个字” printf("sizeof(long long)=%ld ", sizeof(long long));//8 8字节 //gcc ./test.c -o -m32 #以32平台架构编译显示 char c = 255; int i = 255; printf("c=%d, i=%d ", c, i); //c=-1, d=255 unsigned char d = 255; //用来表示整数不以补码的形式表示,看做纯二进制 printf("d=%d ", d); //d=255 char e = 127; e = e + 1; printf("e=%d ", e); //-128 unsigned char f = 127; f = f + 1; printf("f=%d ", f); //128 return 0; } //int 是用来表达寄存器的 /* 计算机以二进制表达正整数,表达负数用补码: 0 -> 00000000 1 -> 00000001 11111111 + 00000001 -> 1000000000 | 00000000 - 00000001 -> (负1) | | (1)00000000 - 00000001 -> 11111111 / ① 11111111被当做纯二进制时,是255,被当作补码时,是-1 ② 同样,对于-a,实际是(2^n - 1),n是这种类型的位数;补码是0-a ③ 补码的意思是拿补码和原码可以加出一个溢出的“零” */ //数的范围 /* 一个字节(8位),表达的是: 00000000 - 11111111 其中,00000000 -> 0 11111111 ~ 10000000 -> -1 ~ -128 //用补码表示 00000001 ~ 01111111 -> 1 ~ 127 //纯二进制表示 */ //unsigned /* 如果一个字面量常数想要表达自己是unsigned,可以在后面加u或U 255U 用l或L表示long(long) unsigned的初衷并非扩展数能表达的范围,而是为了做纯二进制运算,主要是为了移位。 */ //整数越界 /* 整数是以纯二进制方式进行计算的,所以: 11111111 + 1 -> 100000000 -> 0 01111111 + 1 -> 10000000 -> -128 10000000 - 1 -> 01111111 -> 127 */ //整数的输入输出 /* 只有两种形式:int或long long %d:int %u:unsigned %ld:long long %lu:unsigned long long */ //8进制和16进制 /* 一个以0开始的数字字面量是8进制 一个以0x开始的数字字面量是16进制 %o用于8进制,%x用于16进制 8进制和16进制只是如何把数字表达为字符串,与内部如何表达数字无关 16进制很适合表达二进制数据,因为4位二进制正好是一个16进制位 8进制的一位数字正好表达3位二进制 因为早期计算机的字长是12的倍数,而非8 */ //选择整数类型 /* 为什么整数要有那么多种? 为了准确表达内存,做底层程序的需要 没有特殊需要,就选择int 现在的CPU的字长普遍是32位或64位,一次内存读写就是一个int,一次计算也是一个int,选择更短的类型不会更快,甚至可能更慢 现代的编译器一般会涉及内存对齐,所以更短的类型实际在内存中有可能也占据一个int的大小(虽然sizeof告诉你更小) unsigned与否只是输出的不同,内部计算是一样的,所以现代高级语言大多已不区分非负。 */
【浮点类型】
// main.c // Created by weichen on 15/4/6. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> int main(int argc, const char * argv[]) { // 浮点类型 /* 类型 字长 范围 有效数字 float 32 ±(1.20*10^-38 ~ 3.40*10^38), 0, ±inf(无穷大), nan(非数字) 7(准确的位数) double 64 ±(2.2*10^-308 ~ 1.79*10^308),0, ±inf, nan 15 类型 scanf printf float %f %f,%e(科学计数法) double %lf %f,%e */ double ff = 12.345; printf("%e, %f ", ff, ff); //1.234500e+01, 12.34500 printf("%E ", ff); //1.234500E+01 //在%和f之间加上.n可以指定输出小数点后几位,这样的输出是做四舍五入的 printf("%.3f ", -0.0049); //-0,005 小数点后保留三位 printf("%.30f ", -0.0049); //-0.004899999999999999841793218991 printf("%.3f ", -0.00049); //0.000 printf("%f ", 1.0/0.0); //inf printf("%f ", -1.0/0.0); //-inf printf("%f ", 0.0/0/0); //nan //printf("%d ", 12/0); //无法编译通过,无穷大无法用整数表达,可以用浮点数表达 float a, b, c; a = 1.34f; b = 1.22f; c = a + b; if( c == 2.56) { printf("a = b "); } else { printf("a != b, c=%.10f 或 %f ", c, c); //a != b, c=2.5599999428 或 2.560000(七位有效数字四舍五入而来) } //浮点运算的精度 /* 带小数点的字面量是double而非float float需要用f或F后缀来表明身份 float1 == float2 可能失败 fabs(f1-f2) < 1e^-12 #计算绝对值与最小误差比较,来判断是否相等 */ //浮点数的内部表达 /* 浮点数在计算时是由专用的硬件部件实现的 计算double和float所用的部件是一样的 */ //选择浮点类型 /* 如果没有特殊需要,只使用double 现代CPU能直接对double做硬件运算,性能不会比float差,在64位的机器上,数据存储的速度也不比float慢 */ return 0; }
【逻辑类型】
// main.c // Created by weichen on 15/4/8. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> #include <stdbool.h> int main(int argc, const char * argv[]) { // bool /* C语言本没有逻辑类型,在内部计算中使用整数表达关系运算和逻辑运算的结果,0表示false,而非0的值表示true。 在C99中,也没有固定的逻辑类型,但是通过一个头文件定义了可以直接使用的true和false这两个值,以及bool这个类型。 逻辑运算则是C语言固有的成分。 #include <stdbool.h> 之后就可以使用bool和true、false */ bool a = 6 < 5; bool b = true; printf("%d ", a); //0 printf("%d ", b); //1 //逻辑运算 /* 逻辑运算是对逻辑量进行的运算,结果只有0或1 逻辑量是关系运算或逻辑运算的结果 ! 逻辑非 && 逻辑与 || 逻辑或 如果要表达数学中的区间,如:x∈(4,6) 或 x∈[4,6] 应该如何写C的表达式? 像 4 < x < 6 这样的式子,不是C能正确计算的式子,因为 4 < x 的结果是一个逻辑值(0或1), 应该写成 (x > 4 && x < 6) 或 (x >= 4 && x <= 6) 判断一个字符a是否是大写字母? a >= 'A' && a <= 'Z' 优先级 运算符 结合性 1 () 从左到右 2 ! + - ++ -- 从右到左(单目+和-) 3 * / % 从左到右 4 + - 从左到右 5 < <= > >= 从左到右 6 == != 从左到右 7 && 从左到右 8 || 从左到右 9 = += -= *= /= %= 从右到左 */ return 0; }
【类型转换与条件运算】
// main.c // Created by weichen on 15/4/8. // Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> int main(int argc, const char * argv[]) { //自动类型转换 //当运算符的两边出现不一致的类型时,会自动转换成较大的类型,能表达范围更大的数 //char -> short -> int -> long -> long long //int -> float -> double //对于printf,任何小于int的类型会被转换成int;float会被转换成double //但是scanf不会,要输入short,需要%hd,即short int,要输入long long,需要%ld。 (h:短整数或单精度浮点数,l:长整数或双精度浮点数) // 强制类型转换的优先级高于四则运算 //1. (类型)值 double a = 1.0; double b = 2.0; int i = (int)a/b; int j = (int)(a/b); int c = 5; int d = 6; double e = (double)(c/d); printf("%d ", i); printf("%d ", j); printf("%lf ", e); //2. 小的变量不总能表达大的量 printf("%d ", (short)32768); //-32768,short最多能表示32767 printf("%d ", (char)32768); //0 //3. 强制类型转换只是从那个变量计算出了一个新的类型的值,它并不改变那个变量,无论是值还是类型都不改变 int k = 32768; short kk = (short)k; printf("%d ", k); //32768 //条件运算符 //c = (count > 20) ? count - 10 : count + 10; //条件运算符的优先级高于赋值运算符,但是低于其他运算符 //逗号运算符 //逗号用来连接两个表达式,并以其右边的表达式的值作为它的结果。逗号的优先级是所有的运算符中最低的,所以它两边的表达式会先计算;逗号的组合关系是自左向右,所以左边的表达式会先计算,而右边的表达式的值就留下来作为逗号运算的结果。 //在for中使用, for(i=0,j=0;i<j;i++,j--){},这里逗号划分两个表达式。 int n; int m; n = 1+2,3+4; //n=1+2是一个表达式,3+4没有用到,最终结果是3 m = (1+2,3+4); //组合关系,右边表达式的值作为结果 printf("%d ", n); //3 printf("%d ", m); //7 return 0; }