目录
一、注意点
1.字符串输出
#include<stdio.h>
int main()
{
puts("C语 言 中文网");
puts("C语言
中文网");
return 0;
}
第 5~6 行代码是错误的,字符串必须在一行内结束,不能换行。
2.控制台颜色设置
WORD
在windows.h
中定义,等同于unsigned short
,使用低4位表示文字(前景)颜色,高4位表示文字背景颜色,所以它的取值为xx
。x为一位16进制数,即0~F
都可以使用,可以随意组合。
0~F 分别代表的颜色如下:
0 = 黑色 8 = 灰色 1 = 淡蓝 9 = 蓝色
2 = 淡绿 A = 绿色 3 = 湖蓝 B = 淡浅绿
C = 红色 4 = 淡红 5 = 紫色 D = 淡紫
6 = 黄色 E = 淡黄 7 = 白色 F = 亮白
例如,将背景设置为淡绿色,文字设置为红色:
#include <stdio.h>
#include <windows.h>
int main(){
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, 0x2C );
puts("C语言中文网");
return 0;
}
如果只希望设置文字颜色,背景保持黑色,那么也可以只给出一位16进制数,例如:
SetConsoleTextAttribute(hConsole, 0xC ); //将文字颜色设置为红色
SetConsoleTextAttribute(hConsole, 0xF ); //将文字颜色设置为白色
3.最简单的数据类型及数据类型长度
说 明 | 字符型 | 短整型 | 整型 | 长整型 | 单精度浮点型 | 双精度浮点型 | 无类型 |
---|---|---|---|---|---|---|---|
数据类型 | char | short | int | long | float | double | void |
在32位环境中,各种数据类型的长度一般如下:
说 明 | 字符型 | 短整型 | 整型 | 长整型 | 单精度浮点型 | 双精度浮点型 |
---|---|---|---|---|---|---|
数据类型 | char | short | int | long | float | double |
长 度 | 1 | 2 | 4 | 4 | 4 | 8 |
4.如何在字符串中书写或者输出长文本
#include <stdio.h>
int main()
{
puts(
"C语言中文网,一个学习C语言和C++的网站,他们坚持用工匠的精神来打磨每一套教程。"
"坚持做好一件事情,做到极致,让自己感动,让用户心动,这就是足以传世的作品!"
"C语言中文网的网址是:http://c.biancheng.net"
);
return 0;
}
本节讲到的 puts、printf,以及后面要讲到的 fprintf、fputs 等与字符串输出有关的函数,都支持这种写法。
二、整型数据类型的长度及输出
2.1整型数据类型的长度
对于 32 位的 Windows、Linux 和 Mac OS,short 的长度为 2 个字节,int 为 4 个字节,long 也为 4 个字节。PC和服务器上的 32 位系统占有率也在慢慢下降,嵌入式系统使用 32 位越来越多。
在 64 位环境下,不同的操作系统会有不同的结果,如下所示:
操作系统 | short | int | long |
---|---|---|---|
Win64(64位 Windows) | 2 | 4 | 4 |
类Unix系统(包括 Unix、Linux、Mac OS、BSD、Solaris 等) | 2 | 4 | 8 |
目前我们使用较多的PC系统为 Win XP、Win 7、Win 8、Win 10、Mac OS、Linux,在这些系统中,short 和 int 的长度都是固定的,分别为 2 和 4,大家可以放心使用,只有 long 的长度在 Win64 和类 Unix 系统下会有所不同,使用时要注意移植性。
要注意可以通过sizeof操作符来获取某个数据类型的长度,即所占字节大小。
#include <stdio.h>
int main()
{
short a = 10;
int b = 100;
int short_length = sizeof(a);
int int_length = sizeof(b);
int long_length = sizeof(long);
int char_length = sizeof(char);
printf("short=%d, int=%d, long=%d, char=%d\n", short_length, int_length, long_length, char_length);
return 0;
}
2.2 不同整型的输出
使用不同的格式控制符可以输出不同类型的整数,它们分别是:
%hd
用来输出 short int 类型,hd 是 short decimal 的简写;%d
用来输出 int 类型,d 是 decimal 的简写;%ld
用来输出 long int 类型,ld 是 long decimal 的简写。
读者需要注意,当格式控制符和数据类型不匹配时,编译器会给出警告,提示程序员可能会存在风险。
2.3 不同类型的整型数据格式的取值范围与数据溢出情况分析
我们可以计算出所有有符号数的取值范围(括号内为假设的长度):
char | short | int(4个字节) | long(8个字节) | |
---|---|---|---|---|
最小值 | -27 = -128 | -215 = -32,768 ≈ -3.2万 | -231 = -2,147,483,648 ≈ -21亿 | -263 ≈ -9.22×1018 |
最大值 | 27 - 1= 127 | 215 - 1 = 32,767 ≈ 3.2万 | 231 - 1 = 2,147,483,647 ≈ 21亿 | 263 - 1≈ 9.22×1018 |
若存在数据溢出的情况:
#include <stdio.h>
int main()
{
unsigned int a = 0x100000000;
int b = 0xffffffff;
printf("a=%u, b=%d\n", a, b);
return 0;
}
运行结果:a=0, b=-1
变量 a 为 unsigned int 类型,长度为 4 个字节,能表示的最大值为 0xFFFFFFFF,而 0x100000000 = 0xFFFFFFFF + 1,占用33位,已超出 a 所能表示的最大值,所以发生了溢出,导致最高位的 1 被截去,剩下的 32 位都是0。也就是说,a 被存储到内存后就变成了 0,printf 从内存中读取到的也是 0。
变量 b 是 int 类型的有符号数,在内存中以补码的形式存储。0xffffffff 的数值位的原码为 1111 1111 …… 1111 1111,共 32 位,而 int 类型的数值位只有 31 位,所以最高位的 1 会覆盖符号位,数值位只留下 31 个 1,所以 b 的原码为:
1111 1111 …… 1111 1111
这也是 b 在内存中的存储形式。
当 printf 读取到 b 时,由于最高位是 1,所以会被判定为负数,要从补码转换为原码:
[1111 1111 …… 1111 1111]补
= [1111 1111 …… 1111 1110]反
= [1000 0000 …… 0000 0001]原
= -1
最终 b 的输出结果为 -1。
三、二进制数、八进制数和十六进制数的表示
3.1 二进制数
二进制由 0 和 1 两个数字组成,使用时必须以0b
或0B
(不区分大小写)开头,例如:
//合法的二进制
int a = 0b101; //换算成十进制为 5
int b = -0b110010; //换算成十进制为 -50
int c = 0B100001; //换算成十进制为 33
//非法的二进制
int m = 101010; //无前缀 0B,相当于十进制
int n = 0B410; //4不是有效的二进制数字
读者请注意,标准的C语言并不支持上面的二进制写法,只是有些编译器自己进行了扩展,才支持二进制数字。换句话说,并不是所有的编译器都支持二进制数字,只有一部分编译器支持,并且跟编译器的版本有关系。
下面是实际测试的结果:
- Visual C++ 6.0 不支持。
- Visual Studio 2015 支持,但是 Visual Studio 2010 不支持;可以认为,高版本的 Visual Studio 支持二进制数字,低版本的 Visual Studio 不支持。
- GCC 4.8.2 支持,但是 GCC 3.4.5 不支持;可以认为,高版本的 GCC 支持二进制数字,低版本的 GCC 不支持。
- LLVM/Clang 支持(内嵌于 Mac OS 下的 Xcode 中)。
3.2 八进制数
八进制由 0~7 八个数字组成,使用时必须以0
开头(注意是数字 0,不是字母 o),例如:
/合法的八进制数
int a = 015; //换算成十进制为 13
int b = -0101; //换算成十进制为 -65
int c = 0177777; //换算成十进制为 65535
3.3 十六进制
十六进制由数字 0~9、字母 A~F 或 a~f(不区分大小写)组成,使用时必须以0x
或0X
(不区分大小写)开头,例如:
//合法的十六进制
int a = 0X2A; //换算成十进制为 42
int b = -0XA0; //换算成十进制为 -160
int c = 0xffff; //换算成十进制为 65535
3.4 这几种进制的输出格式
short | int | long | unsigned short | unsigned int | unsigned long | |
---|---|---|---|---|---|---|
八进制 | %ho | %o | %lo | %ho | %o | %lo |
十进制 | %hd | %d | %ld | %hu | %u | %lu |
十六进制 | %hx 或者 %hX | %x 或者 %X | %lx 或者 %lX | %hx 或者 %hX | %x 或者 %X | %lx 或者 %lX |
十六进制数字的表示用到了英文字母,有大小写之分,要在格式控制符中体现出来:
- %hx、%x 和 %lx 中的
x
小写,表明以小写字母的形式输出十六进制数; - %hX、%X 和 %lX 中的
X
大写,表明以大写字母的形式输出十六进制数。
八进制数字和十进制数字不区分大小写,所以格式控制符都用小写形式。
区分不同进制数字的一个简单办法就是,在输出时带上特定的前缀。在格式控制符中加上#
即可输出前缀,例如 %#x、%#o、%#lX、%#ho 等,请看下面的代码:
#include <stdio.h>
int main()
{
short a = 0b1010110; //二进制数字
int b = 02713; //八进制数字
long c = 0X1DAB83; //十六进制数字
printf("a=%#ho, b=%#o, c=%#lo\n", a, b, c); //以八进制形似输出
printf("a=%hd, b=%d, c=%ld\n", a, b, c); //以十进制形式输出
printf("a=%#hx, b=%#x, c=%#lx\n", a, b, c); //以十六进制形式输出(字母小写)
printf("a=%#hX, b=%#X, c=%#lX\n", a, b, c); //以十六进制形式输出(字母大写)
return 0;
}
运行结果:
a=0126, b=02713, c=07325603
a=86, b=1483, c=1944451
a=0x56, b=0x5cb, c=0x1dab83
a=0X56, b=0X5CB, c=0X1DAB83
- 注意,整数和小数的有符号数在内存中都是以补码形式存储的,这样方便加减运算。
- 所以在将无符号数输出为有符号数的时候,需要考虑将无符号数看做是有符号数的补码,并进行从补码到原码的变换。
四、小数的输出
小数也可以使用 printf 函数输出,包括十进制形式和指数形式,它们对应的格式控制符分别是:
- %f 以十进制形式输出 float 类型;
- %lf 以十进制形式输出 double 类型;
- %e 以指数形式输出 float 类型,输出结果中的 e 小写;
- %E 以指数形式输出 float 类型,输出结果中的 E 大写;
- %le 以指数形式输出 double 类型,输出结果中的 e 小写;
- %lE 以指数形式输出 double 类型,输出结果中的 E 大写。
下面的代码演示了小数的表示以及输出:
#include <stdio.h>
#include <stdlib.h>
int main()
{
float a = 0.302;
float b = 128.101;
double c = 123;
float d = 112.64E3;
double e = 0.7623e-2;
float f = 1.23002398;
printf("a=%e \nb=%f \nc=%lf \nd=%lE \ne=%lf \nf=%f\n", a, b, c, d, e, f);
return 0;
}
五、类型转换
5.1 自动类型转换
- 自动类型转换是按数据长度增加的方向进行,以保证数据不失真,或者精度不降低。
- 另外,所以的浮点运算都是以双精度进行的,即无论如何要转换为double类型才能进行运算。
- char 和 short参与运算时,必须先转换成Int 类型。
5.2 强制类型转换
直接上代码
#include <stdio.h>
int main(){
double total = 400.8; //总价
int count = 5; //数目
double unit; //单价
int total_int = (int)total;
unit = total / count;
printf("total=%lf, total_int=%d, unit=%lf\n", total, total_int, unit);
return 0;
}