我对
提供的答案有疑问@ dan04。 What is aligned memory allocation?
特别是,如果我有这样的事情:
int main(){
int num; // 4byte
char s; // 1byte
int *ptr;
}
如果我有32位机器,你认为默认情况下它仍会填充数据吗?
在上一个问题中,有人询问struct
,我问的是main
中声明的变量。
更新
a = 2 bytes
b = 4 bytes
c = 1 byte
d = 1 byte
0 1 2 3 4 5 6 7
|a|a|b|b|b|b|c|d| bytes
| | | words
答案 0 :(得分:5)
这没有规则。这取决于您使用的实现。此外,它可能会根据编译器选项而改变。您可以做的最好是打印每个变量的地址。然后你可以看到内存布局是怎样的。
这样的事情:
int main(void)
{
int num;
char s;
int *ptr;
printf("num: %p - size %zu\n", (void*)&num, sizeof num);
printf("s : %p - size %zu\n", (void*)&s, sizeof s);
printf("ptr: %p - size %zu\n", (void*)&ptr, sizeof ptr);
return 0;
}
可能的输出:
num: 0x7ffee97fce84 - size 4
s : 0x7ffee97fce83 - size 1
ptr: 0x7ffee97fce88 - size 8
另请注意,如果您不接受变量的地址(&
),编译器可能会优化您的代码,以便变量永远不会被放入内存中。
通常,对齐通常是为了从所使用的HW平台中获得最佳性能。这通常意味着变量与其大小对齐,或者对于大小大于4的变量至少4字节对齐。
<强>更新强>
OP在更新中给出了一个特定的布局示例,并询问是否可以/将要发生该布局。
答案是:这是依赖于实现的
所以原则上它可能发生在某个特定的系统上。这就是说我怀疑它会在任何主流系统上发生。
还有另一个使用 gcc -O3
编译的代码示例int main(void)
{
short s1;
int i1;
char c1;
int i2;
char c2;
printf("s1: %p - size %zu\n", (void*)&s1, sizeof s1);
printf("i1: %p - size %zu\n", (void*)&i1, sizeof i1);
printf("c1: %p - size %zu\n", (void*)&c1, sizeof c1);
printf("i2: %p - size %zu\n", (void*)&i2, sizeof i2);
printf("c2: %p - size %zu\n", (void*)&c2, sizeof c2);
return 0;
}
我的系统输出:
s1: 0x7ffd222fc146 - size 2 <-- 2 byte aligned
i1: 0x7ffd222fc148 - size 4 <-- 4 byte aligned
c1: 0x7ffd222fc144 - size 1
i2: 0x7ffd222fc14c - size 4 <-- 4 byte aligned
c2: 0x7ffd222fc145 - size 1
注意内存中的位置与代码中定义的顺序变量的不同之处。这确保了良好的对齐。
按地址排序:
c1: 0x7ffd222fc144 - size 1
c2: 0x7ffd222fc145 - size 1
s1: 0x7ffd222fc146 - size 2 <-- 2 byte aligned
i1: 0x7ffd222fc148 - size 4 <-- 4 byte aligned
i2: 0x7ffd222fc14c - size 4 <-- 4 byte aligned
再次回答更新问题:
在大多数系统上,我怀疑你会看到一个4字节变量放在地址xxx2,xxx6或xxxa,xxxe。但是,系统可能存在于可能发生的地方。
答案 1 :(得分:1)
很难准确预测,但肯定会有一些填充。 以这两个代码为例(我在Coliru上运行它们,64位机器)
#include<iostream>
#include <vector>
using namespace std;
//#pragma pack(push,1)
int main(){
int num1(5); // 4byte
int num2(3); // 4byte
char c1[2];
c1[0]='a';
c1[1]='a';
cout << &num1 << " " << &num2 << " " << endl;
cout << sizeof(c1) << " " << &c1 << endl;
}
//#pragma pack(pop)
#include<iostream>
#include <vector>
using namespace std;
//#pragma pack(push,1)
int main(){
int num1(5); // 4byte
int num2(3); // 4byte
char c1[1];
c1[0]='a';
cout << &num1 << " " << &num2 << " " << endl;
cout << sizeof(c1) << " " << &c1 << endl;
}
//#pragma pack(pop)
第一个节目输出:
0x7fff3e1f9de8 0x7fff3e1f9dec
2 0x7fff3e1f9de0
第二个节目输出:
0x7fffdca72538 0x7fffdca7253c
1 0x7fffdca72537
你绝对可以注意到第一个程序中有一个填充,查看我们可以看到的地址: 第一个程序:CHAR | CHAR | 6-BYTE PADDING | INT | INT 第二个程序:CHAR | INT | INT
所以对于基本问题,是的,默认情况下可能是填充。 我也尝试使用pragma pack来避免填充,与struct的情况相反,我没有设法避免填充,因为输出完全相同。