【C/C++】结构体对齐、四舍五入计算、枚举使用等

C语言中改变结构体的对齐方式

1. sizeof()与strlen()区别
2. 结构体对齐方式
3. C++中char 类型的一个问题
4. 四舍五入计算
5. 枚举使用

1. sizeof()与strlen()区别
(1) sizeof是C/C++中的一个运算符,其作用是返回一个对象或者类型在内存中所占用的字节数。sizeof不能返回动态地被分配的数组的大小。sizeof在编译期完成。

(2) strlen是C语言中的库函数,所在头文件为#include <string.h>其函数原型为*unsigned int strlen(char s); 其中s为指定的字符串。
注意:strlen只能用char *作为参数,它求的是字符串的实际长度,方法是从开始到遇到第一个’\0’结束。strlen()是函数,在运行期间完成。

/* 用sizeof()返回元素字节数 */

// 数据类型
a = sizeof(char);		// char - 1个字节
b = sizeof(short int);	//short int - 2个字节
c = sizeof(int);			//int - 4个字节
d= sizeof(long);		//long - 4个字节
e = sizeof(long long);	//long long - 8个字节

// 数组
int pt[10];
int length = sizeof(pt); //length = 40;

char pt[20] = "0123456789";
int a = sizeof(pt);	//a = 20
int b = strlen(pt); //b = 10  strlen计算的是字符串的实际长度

char pt2[] = "0123456789";
int c = sizeof(pt2);	//c = 11;
int d = strlen(pt2); 	//d = 10;
/* 上面结果为a = 10,这是因为strlen计算的是字符串的实际长度,以第一个'\0'为结束符;b = 20,这是因为sizeof计算的是分配的数组str[20]所占的空间大小,不受里面存储内容的影响。*/

// 结构体
typedef struct stu1
{
	int a;
	char b;
	int c;
}People;
People people_01;
int a = sizeof(people_01);		//a = 12 	结构体4字节对齐

对于一个整型数组,要求用户输入数据,但是数据长度未知,如何实现输入,并得到数据长度??
分析:sizeof()——可以计算数据长度,但计算的是数据在内存中分配的长度,此处为有效数据的长度。不满足条件;
strleng()——可以计算字符串数组有效长度,但不能计算整形数组有效长度。不满足条件。
(1) 定义终止数据,当输入终止数据时,停止输入循环;
(2) 当输入有效数据时,把有效数据放入数组,并更新有效数组长度;

	for (i = 0;i < 100;i++)
	{
		cin >> tempIn; //输入数据存入临时变量
		if (tempIn != 99999)   //以9999作为输入终止标志
		{
			num[i]= tempIn;
			length++;		//有效数据,数据有效长度递增1
		}
		else
		{
			break;  //跳出循环
		}	
	}
输入不确定长度字符串的实现
 C++中可以中cin.getline();来输入不定长度字符串,以换行符结束;
 判断字符是否是 结束符 '\0'来计算递增长度变量或直接利用strlen()来求字符串长度;

2. 结构体对齐方式

typedef struct stu1
{
	int a;
	char b;
	int c;
}People;
People people_01;
int a = sizeof(people_01);		//a = 12 	结构体4字节对齐

int 型占4个字节,char 型占1个字节,那么people_01应该占用2*4+1也就是9个字节啊。那为什么回事12个字节呢?
结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。

先介绍一个相关的概念——偏移量。偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。第一个成员a的偏移量为0。第二个成员b的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员c的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。
然而,在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:
(1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
(2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。

上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。

struct stu2  
{  
      int k;  
      short t;  
}; 

成员k的偏移量为0;成员t的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员k大小的整数倍。因此,编译器会在成员t后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。

由此可见,结构体类型需要考虑到字节对齐的情况,不同的顺序会影响结构体的大小。

可以使用**#pragma pack(n)**改变对齐方式。编译器会从“n”和”结构体中最长的数据类型长度“中选较小的那个作为对齐标准
如#pragma pack(1),相当于取消对齐,那么结构体people_01所占字节数就为9了。

3. C++中char 类型的一个问题

在C/C++中,char 类型的数据也是以数据存储的,只不过该数字对应特定的字符;

/* C语言中 uc可以输出 以10进制、16进制输出存储的数值*/
	unsigned char uc;
	uc = 50;
	printf("%d\n",uc);  //50
	printf("%x\n",uc);  //32
	unsigned char uc;
	uc = 50;
	cout << dec << uc << endl;  // 2    ASCII
	cout << hex << uc << endl;  // 2

	cout << dec << (int)uc << endl; //50
	cout << hex << (int)uc << endl; //32

为什么在C++中char字符不能以数据形式输出???如果不能输出数字量,那C++ 中signed char 和unsigned char 又有什么作用?
虽然C++中char字符以字符形式输出,但在计算过程中,还是以数字参与运算

	char a = 1;
	int b = 3;
	cout << (b + a) << endl;   //输出4

4. 四舍五入计算
(1) 小数四舍五入取整

average = int(average + 0.5); 				//四舍五入取整

(2) 保留两位小数点

value = int(value * 100 + 0.5) / 100; 

6. 枚举变量使用规则
(1) 枚举类型时C/C++中的一种基本数据类型有,和 整型、浮点型、字符型一样。

	enum Week { Sun = 7, Mon = 1, Tes, Wed, Thu, Fri, Sat };
	Week begin, end;

	cin >> begin;//直接输入枚举变量,错误
	begin = 1;	//整数赋值给枚举变量,错误

	begin = Mon; //将枚举常量赋值给枚举变量,正确
	begin = end; //相同类型的枚举变量赋值,正确
	begin = (Week)1; //整数强制类型转换后赋值,正确
	int a = begin;	//将枚举变量赋值给整数,正确
	int b = Mon;	//将枚举常量赋值给整数,正确
	int c= Sun-Mon;	//枚举变量可以直接参加数学运算,结果为数值类型,正确
	cout << begin;	//直枚输出枚举变量,正确
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值