目录
一.结构体传参
1.传值方式
struct A
{
int arr[100];
int n;
};
void Changed(struct A aa)
{
int i = 0;
for (; i < 3; i++)
{
printf("%d ", aa.arr[i]);
}
printf("%d\n", aa.n);
}
int main()
{
struct A a;
a = { {1,2,3},10 };
Changed(a);
return 0;
}
2.传址方式
struct A
{
int arr[100];
int n;
};
void Changed1(const struct A* aa)//const,指针指向的内容不能被修改
{
for (int i = 0; i < 3; i++)
{
printf("%d ", aa->arr[i]);
}
printf("%d\n", aa->n);
}
int main()
{
struct A a;
a = { {1,2,3},10 };
Changed1(&a);
return 0;
}
3.总结
1.传址比传值效率高 。
前者在传参时只需要传递地址即可;而后者传递的是一个结构体的值,占用更多的内存空间,传输入效率缓慢。
2.传值比传址安全高。
前者是一种拷贝复制,内容的修改并不会影响到源结构体内容。而后者的地址传参,是直接改变源结构体的内容。所以,为了保证源数据的安全,在使用传址方式时,需要用const去修饰指针。
二.位段
1.解释(维基百科)
位段(或称“位域”,Bit field)为一种数据结构,可以把数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作。这种数据结构的好处:可以使数据单元节省储存空间,当程序需要成千上万个数据单元时,这种方法就显得尤为重要。位段可以很方便的访问一个整数值的部分内容从而可以简化程序源代码。而位域这种数据结构的缺点在于,其内存分配与内存对齐的实现方式依赖于具体的机器和系统,在不同的平台可能有不同的结果,这导致了位段在本质上是不可移植的。
2.位段的声明和使用
- 位段只能在结构体里使用。结构体就像一个盒子,而位段就像里面紧挨的小格子。这些小格子大小并不相同的。
- 这是一个定义好的位段(Visual Studio 2022,x86环境)
struct S
{
char _a : 3;
char _b : 4;
char _c : 5;
char _d : 4;
};
int main()
{
struct S s = { 0 };
s._a = 10;//1010
s._b = 12;//1100
s._c = 3;//11
s._d = 4;//100
printf("%d\n", sizeof(s));
return 0;
}
注意:
a.位段的单位是bit;
b.位段成员的类型只能是整型家族的,例如:int, unsigned int, signed int, char。
3.位段内部内存分配
前提:以上面的定义好的位段,来作解释说明。
按照数据类型分配内存空间
以int来定义,首先系统会先分配一个int大小的空间,即4字节。
以char来定义,系统会先分配一个char大小的空间,即一个字节。
...
若第一个数据存入第一个字节后,第一个字节剩下的空间不足以存储第二个数据,它会向后寻找适合的空间来存储。以此类推。
若开始分配的数据类型大小空间不够,会再分配一个数据类型大小的空间。
数据的存储方向(机器是以小端存储的)
假设(从右向左):
进行程序调试,看看程序内存是否跟我们推算的一致。
结论:很明显调试结果与我们所作的假设相吻合。证明了位段在内存中的存储是按照从右向左存储的。
4.位段的实际应用
1.节省空间,虽然没有可移植性,但可以人为创造移植性。为不同的平台,编写适合它的位段代码。这需要对每个平台内存分配规则的熟练掌握。
2.位段由于跨平台的问题,真正的用途的其中一个是计算计网洛的IP数据报:
看到这里不妨点个赞,关注一下吧。你的赞是我写文章的动力哦!
最后,感谢你的观看。