基本输入输出
头文件包含:stdio.h
1.格式化输入输出
输出:
printf("格式化控制字符串", 输出项);
“格式化控制字符串”的形式为:
格式化输出函数printf
:
%[输出最小宽度][.精度][长度]类型
例如:
double d = 123.456;
print("d=%9.2f", d);
输出结果为:d= 123.46
,前面由三个空格因为宽度为9,包含小数点的位数不够前补空格,.2
表示精度为小数点后两位,四舍五入。
常见的输出格式符:
d,i //以十进制形式输出带符号整数(正数不输出符号)
o //以八进制形式输出无符号整数(不输出前缀0)
x //以十六进制形式输出无符号整数(不输出前缀0x)
u //以十进制形式输出无符号整数
f //以小数形式输出单、双精度浮点数
e //以指数形式输出单、双精度浮点数
c //输出单个字符
s //输出字符串
注意以o, x, u
格式输出负数时,取的是模2^32
,例如:
int d = -1;
unsigned int b = (1 << 32) - 1;
printf("d=%u,%o,%x, b=%u", d, d, d, b);
输出结果为:
d=4294967295,37777777777,ffffffff, b=4294967295
八进制的37777777777和十六进制的ffffffff均为4294967295。
格式化输入函数scanf
:
scanf("格式控制字符串",输入项的地址);
这里的格式控制字符串和printf函数中的相同,但是不能显示非格式字符串,不同点在于:
- 不能指定数据的精度
- 输入long必须使用ld
,输入double必须使用lf
例如:
long a;
double b;
scanf("%ld%lf", &a,&b);
常见的复合数据类型
包括class, struct, union, enum
。
在C++中,class
和struct
都可以表示类,区别在于默认的数据访问权限和默认类的继承权限,struct
的默认的数据访问权限和默认类的继承权限都是public
,而class
则是private,还有一个区别就是模板不再支持struct
:
template<struct T> //不支持的,只能是class或者typename
在C中,struct
只能包含数据成员。
struct
和union
的主要区别:
内存:struct
中的各个变量都独自占有各自的内存空间;union
的各个变量则共用相同的一段内存空间,内存的起始位置相同,所以某一个变量的改变会覆盖其它变量值。
struct
的占用的内存大小是所有数据成员的大小的和,还需要进行内存对齐。
何为内存对齐?
- 每个数据成员的首地址(相对于结构体首地址的偏移量)必须是该数据成员大小的整数倍;特别地,当指定了#pragma pack(n)
时, 对齐值为min(基本成员的大小,n)
,不足要补齐。
- 结构体的总大小必须是最大基本成员的整数倍。
内存对齐的原因:
- 平台移植: 某些平台对某些特定类型的数据只能从某些特定地址开始存取,需要保证字节对齐。
- 性能原因:内存对齐,访问效率提升。
64和32位机器的数据类型的大小:
数据类型 | 32位大小 | 64位大小 |
---|---|---|
char | 1 | 1 |
short int | 2 | 2 |
int | 4 | 4 |
usigned int | 4 | 4 |
float | 4 | 4 |
long | 4 | 8 |
double | 8 | 8 |
long long | 8 | 8 |
unsigned long | 4 | 8 |
type *(指针类型) | 4 | 8 |
不同的只有long, unsigned long, type *
这三者。举个例子:
struct str {
char *ch; //4
char c; //1
int a[3]; //4*3
double d; //8
long l; //4
}st;
假设为32位机器,那么有:
sizeof(st) = 40 = 4 + 1 + (3) + 4 * 3 + (4) + 8 + 4 + (4)
其中括号中的数字都是用于对齐的。
对于联合体union,由于所有变量共用一个内存位置,所以内存空间的大小为最大变量长度的整数倍,且要大于等于最大成员的存储空间,例如:
union demo {
int i;
char ch[5];
}d;
union dem2 {
int i;
char ch[9];
}c;
那么会有:
sizeof(d) = 8 = 2 * sizeof(i) >= sizeof(char) * 5
sizeof(d) = 12 = 3 * sizeof(i) >= sizeof(char) * 9
利用union来判断大小端模式:
- 大端模式,是指数据的高字节保存在内存的低地址中。
- 小端模式,是指数据的高字节保存在内存的高地址中。
例如:给定一个数0x12345678
,
箭头表示内存由高地址到低地址:
下图是小端模式:
graph LR;
0x12-->0x34
0x34-->0x56
0x56-->0x78
大端模式如下:
graph LR;
0x78-->0x56
0x56-->0x34
0x34-->0x12
利用union判断的代码:
union test {
int a;
char c;
}T;
T.a = 1;
如果T.c == 1
,说明高字节保存在高地址,即小端模式;否则为大端模式。
枚举类型enum
,例如:
enum enumType {
Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
}WeekDay;
声明enumTyp
为枚举类型,声明Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
为枚举量,默认值为0~6,未被初始化的枚举值的值默认将比其前面的枚举值大1,例如:
enum enumType {
Monday = 1, Tuesday, Wednesday = 1, Thursday, Friday, Saturday, Sunday
}WeekDay;
那么有:
Tuesday = 2, Thursday = 2, Friday = 3, Saturday = 4, Sunday = 5
枚举的取值范围:
- 如果枚举常量均大于0,枚举的范围:[0, 2^n-1]
- 如果存在枚举常量小于等于0,范围为[2^m+1, 2^n-1].
枚举定义的时常量集合,大小为sizeof(int) = 4
。