我已经检查了所有主要的编译器,sizeof(std::tuple<int, char, int, char>)所有这些都是16。大概它们只是将元素按顺序放入元组,因此由于对齐而浪费了一些空间。
如果元组在内部像这样存储元素:int, int, char, char,则其sizeof可能为12。
实现有可能执行此操作,还是该标准中的某些规则禁止这样做?
系统要求某些基元与存储器内的某些点对齐(对于4的倍数的字节,对于2的倍数的字节的短路,等等).当然,这些可以被优化以浪费填充中的最小空间.
我的问题是GCC为什么不自动执行此操作?更明显的启发式(从最大尺寸要求到最小尺寸的订单变量)是否缺乏某种方式?一些代码是否依赖于其结构的物理排序(这是一个好主意)?
我只是问,因为GCC在很多方面都是超级优化的,但不是在这个方面,我认为必须有一些相对很酷的解释(我不知道).
我知道为什么GCC默认不重新排序结构的成员,但我很少编写依赖于结构顺序的代码,所以有什么方法可以标记我的结构自动重新排序?
我花了几分钟手动重新排序结构中的字段,以减少填充效果[1],这感觉就像几分钟太多.我的直觉是说我的时间可能更好地花在编写Perl脚本上,或者为我做这种优化.
我的问题是这是否也是多余的; 是否已经有一些我不知道的工具,或者我应该能够启用[2]打包结构的一些编译器功能?
由于需要在几种不同的体系结构中进行一致优化,因此使用的任何工具都需要能够考虑不同的结构对齐和指针大小,这个问题更加复杂.
编辑:快速澄清 - 我想要做的是重新排序源代码中的字段,以避免填充,而不是"编译"结构,而不是填充编译.
编辑#2:另一个复杂因素:根据配置,某些数据类型的大小也可能会发生变化.显而易见的是针对不同体系结构的指针和指针差异,但也有浮点类型(16,32或64位,取决于'精确性'),校验和(8位或16位取决于"速度")和一些其他不明显的东西.
[1]所讨论的结构在嵌入式设备上被实例化了数千次,因此结构的每个4字节减少可能意味着该项目的go和no-go之间的差异.
[2]可用的编译器是GCC 3.*和4.*,Visual Studio,TCC,ARM ADS 1.2,RVCT 3.*以及其他一些更加模糊的编译器.
只是出于好奇,如果我有一个带有位字段的结构
struct Foo
{
char a : 1;
char b : 1;
char c : 1;
}
Run Code Online (Sandbox Code Playgroud)
另一个带有位域和 struct Foo 的结构
struct Bar
{
Foo foo;
char a : 1;
char b : 1;
char c : 1;
}
Run Code Online (Sandbox Code Playgroud)
所有这些位都会被打包成一个整数吗?
在这种情况下,这些字段是否会被重新排序以形成单个位字段?
struct Baz
{
char a : 1;
int NotBitfield;
char b : 1;
char c : 1;
}
Run Code Online (Sandbox Code Playgroud) 我有一个C++类,它有一个私有的未使用的char[]严格来添加填充到类,以防止在共享数组中使用该类时的错误共享.我的问题是双重的:
在某些情况下,编译器是否可以优化此数据成员?
private field * not used当我编译时,如何使警告静音-Wall?优选地,没有明确地使警告静音,因为我仍然希望在其他地方捕获该问题的实例.
我写了一个小测试来检查我的编译器,似乎该成员没有删除,但我想知道标准是否允许这种优化.
#include <iostream>
class A {
public:
int a_ {0};
private:
char padding_[64];
};
int main() {
std::cout << sizeof(A) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
$ clang++ --version
clang version 3.3 (tags/RELEASE_33/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
$ clang++ -std=c++11 -O3 -Wall padding.cc
padding.cc:8:8: warning: private field 'padding_' is not used [-Wunused-private-field]
char padding_[64];
^
1 warning generated.
$ ./a.out
68
Run Code Online (Sandbox Code Playgroud) 我刚刚了解了填充,我试图对其进行一些测试,我尝试打包这个结构:
struct B {
int a,b,c;
string s;
char x;
string t;
char y;
string u;
}__attribute__((packed)) ;
Run Code Online (Sandbox Code Playgroud)
但我收到这个警告:
warning: ignoring packed attribute because of unpacked non-POD field 'std::string B::u'
string u;
Run Code Online (Sandbox Code Playgroud)
这是否意味着包含的结构strings不能被打包?还有其他方法吗?如果是的话,会影响性能吗?
这个问题与如何确保成员是 4 字节对齐?
例子:
struct Aligned
{
char c;
__attribute__((__aligned__(4))) int32_t member;
}
struct Test
{
char c;
Aligned s;//is s.member 4 bytes aligned?
}
void f1()
{
char c1;
Aligned s;//is s.member 4 bytes aligned?
char c2;
}
void f2()
{
Aligned* s = new Aligned();//is s.member 4 bytes aligned?
}
Run Code Online (Sandbox Code Playgroud)
您能否解释一下“member”是否在所有情况下都是 4 字节对齐的,如果是的话,这是如何工作的?
编辑:我忘记了 Aligned 是从其他结构派生的情况:
struct Aligned : public SomeVariableSizeStruct
{
char c;
__attribute__((__aligned__(4))) int32_t member;
}
Run Code Online (Sandbox Code Playgroud)
第二次编辑:我的问题是:结构的第一个成员总是 4 字节对齐吗?因为在此处介绍的所有情况下,第一个变量地址可能不是 4 字节对齐,并且 3 字节填充不能保证“成员”是 4 字节对齐