我有以下代码,我很难理解为什么打包结构会导致警告(然后在运行时出现段错误。)首先是代码:
#include <iostream>
using namespace std;
template <typename T, std::size_t D, std::size_t S>
struct __attribute__((packed)) C {
union __attribute__((packed)) ValueType {
char fill[S];
T value;
};
ValueType data_;
const T& get() const {
return data_.value;
}
friend
std::ostream& operator<<(std::ostream& str, const C& f) {
return str << f.data_.value;
}
};
template <typename T, std::size_t D>
struct __attribute__((packed)) C<T, D, D> {
T value;
const T& get() const {
return value;
}
friend
std::ostream& operator<<(std::ostream& str, const C& f) {
return str << f.value;
}
};
template <typename T, std::size_t S = 0>
struct __attribute__((packed)) D {
C<T, sizeof(T), S> c;
const T& get() const {
return c.get();
}
friend
std::ostream& operator<<(std::ostream& str, const D& f) {
return str << f.get();
}
};
template <typename T>
struct __attribute__((packed)) D<T, 0> {
T v;
const T& get() const {
return v;
}
friend
std::ostream& operator<<(std::ostream& str, const D& f) {
return str << f.get();
}
};
int main(void) {
D<int64_t> d1;
cout << d1 << endl;
D<int64_t, 8> d2;
cout << d2 << endl;
}
使用打包(它是GCC特定的)我得到以下内容(gcc 5.2.1 / 5.3.1,c ++ 14-Wall):
packed.cpp: In instantiation of ‘const T& D<T, 0ul>::get() const [with T = long int]’:
packed.cpp:58:16: required from ‘std::ostream& operator<<(std::ostream&, const D<long int>&)’
packed.cpp:64:13: required from here
packed.cpp:53:12: warning: returning reference to temporary [-Wreturn-local-addr]
return v;
^
packed.cpp: In instantiation of ‘const T& C<T, D, D>::get() const [with T = long int; long unsigned int D = 8ul]’:
packed.cpp:40:18: required from ‘const T& D<T, S>::get() const [with T = long int; long unsigned int S = 8ul]’
packed.cpp:45:16: required from ‘std::ostream& operator<<(std::ostream&, const D<long int, 8ul>&)’
packed.cpp:66:13: required from here
packed.cpp:27:12: warning: returning reference to temporary [-Wreturn-local-addr]
return value;
如果结构没有打包 - 代码正常编译然后运行正常(打印垃圾值 - 但这是预期的。)
所以我的问题是 - 为什么打包导致临时的回归?
答案 0 :(得分:1)
你好Nim我发现这个问题可能是gcc编译器的BUG,你可以在这里看到引用enter link description here
答案 1 :(得分:1)
您正在寻找的是pragma pack。它与您想要的效果相同,但更常见且cross-compiler。
注意:使用pragma pack
#include <iostream>
using namespace std;
#pragma pack(1)
template <typename T, std::size_t D, std::size_t S>
struct C {
union ValueType {
char fill[S];
T value;
};
ValueType data_;
const T& get() const {
return data_.value;
}
};
#pragma pack()
template <typename T, std::size_t D>
struct C<T, D, D> {
T value;
const T& get() const {
return value;
}
};
template <typename T, std::size_t D>
struct C<T, D, 0> {
T value;
const T& get() const {
return value;
}
};
template <typename T, std::size_t S = 0>
struct D : C<T, sizeof(T), S> {
friend
std::ostream& operator<<(std::ostream& str, const D& f) {
return str << f.get();
}
};
#pragma pack(1)
struct E {
D<int16_t> a;
D<int64_t, 9> b;
};
#pragma pack()
int main(void) {
D<int16_t> d1;
cout << d1.get() << ' ' << sizeof(d1) << endl;
D<int64_t, 9> d2;
cout << d2.get() << ' ' << sizeof(d2) << endl;
cout << sizeof(E) << endl;
}