假设我有一个结构并将偏移量提取给成员:
struct A {
int x;
};
size_t xoff = offsetof(A, x);
Run Code Online (Sandbox Code Playgroud)
如果指针以struct A标准符合方式提取成员,我该怎么办?当然假设我们有struct A*正确的偏移量.一种尝试是做类似的事情:
int getint(struct A* base, size_t off) {
return *(int*)((char*)base + off);
}
Run Code Online (Sandbox Code Playgroud)
这可能会工作,但要注意的例子指针算术只有似乎标准中定义,如果指针是相同的阵列(或一个过去的结束)的指针,这不一定是这种情况.从技术上讲,构造似乎依赖于未定义的行为.
另一种方法是
int getint(struct A* base, size_t off) {
return *(int*)((uintptr_t)base + off);
}
Run Code Online (Sandbox Code Playgroud)
这也可能会起作用,但请注意,intptr_t不需要存在,据我所知,算术intptr_t不需要产生正确的结果(例如我记得有些CPU有能力处理非字节对齐的地址,这会建议在数组中intptr_t每个步骤增加8 char.
看起来标准中有遗忘的东西(或者我错过的东西).
我正在寻找一种方法来获得非POD性质的C++类数据成员的偏移量.
原因如下:
我想以HDF5格式存储数据,这似乎最适合我的材料(数值模拟输出),但它可能是一个相当C的库.我想通过C++接口来使用它,这需要我申报存储类型像这样,(从文件在这里和这里(第4.3.2.1.1)):
class example {
public:
double member_a;
int member_b;
} //class example
H5::CompType func_that_creates_example_CompType() {
H5::CompType ct;
ct.insertMember("a", HOFFSET(example, member_a), H5::PredType::NATIVE_DOUBLE);
ct.insertMember("b", HOFFSET(example, member_b), H5::PredType::NATIVE_INT);
return ct;
} //func_that_creates_example_CompType
Run Code Online (Sandbox Code Playgroud)
其中HOFFSET是使用offsetof的HDF特定宏.
问题当然是,只要示例类变得更有用,它就不再是POD类型,因此使用offsetof将给出不确定的结果.
我能想到的唯一解决方法是首先将我想要存储的数据导出到更简单的结构,然后将其传递给HDF.然而,这确实涉及数据复制,这正是HDF试图避免的(以及为什么他们有这个CompType使得库能够到达你的对象以将他们的数据保存到文件中).
所以我希望你有更好的想法.理想情况下,我会为这个问题寻找一个可移植的解决方法,但如果没有,你可以给我一个适用于x86和x86_64与GCC的想法,我已经非常感激了.
-----后来添加:-----
Greg Hewgill建议在下面将数据存储在一个简单的结构中,然后通过继承来构建实际的类.特别是对于HDF,我认为这可能实际上不起作用.比上面更精细的使用场景:
class base_pod {
public:
double member_a;
int member_b;
}; //class base_pod
class derived_non_pod : private base_pod {
public:
//the following method is only virtual to illustrate the problem
virtual double get_member_a() {return member_a; }
}; //class …Run Code Online (Sandbox Code Playgroud) 我想在编译时找到struct成员的字节偏移量.例如:
struct vertex_t
{
vec3_t position;
vec3_t normal;
vec2_t texcoord;
}
Run Code Online (Sandbox Code Playgroud)
我想知道字节偏移量normal是(在这种情况下它应该是12.)
我知道我可以使用offsetof,但这是一个运行时功能,我宁愿不使用它.
我正在努力实现甚至可能吗?
编辑:offsetof是编译时,我的坏!
我在一本书中找到了这个代码示例,但是我无法理解printf语句中的表达式.并且这个程序成功编译输出为4.友好建议...
void main(){
unsigned char c;
typedef struct name {
long a;
int b;
long c;
}r;
r re = {3,4,5};
r *na=&re;
printf("%d",*(int*)((char*)na + (unsigned int ) & (((struct name *)NULL)->b)));
}
Run Code Online (Sandbox Code Playgroud) 有没有办法在编译时找到结构成员的偏移量?我希望创建一个包含结构成员偏移量的常量.在下面的代码中,offsetof()宏在第一个printf语句中工作.但是,在第10行中使用声明会ofs生成错误:
"无法解析' - >'运算符作为常量表达式".
这样做还有其他办法吗?
struct MyStruct
{
unsigned long lw;
unsigned char c[5];
int i;
int j;
unsigned long last;
};
const int ofs = offsetof(struct MyStruct, i); // This line in error
int main(void)
{
printf("Offset of c = %d.\n", offsetof(struct MyStruct, c) );
printf("Offset of i = %d.\n", ofs );
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我目前正在尝试计算一个增强融合适应结构中数据成员的偏移量,但我不确定是否有一种优雅的方法可以做到这一点.我想做类似以下的事情:
#include <iostream>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/sequence/intrinsic/at.hpp>
#include <boost/fusion/include/at.hpp>
#include <cstddef.h>
struct test {
int a;
char c;
double b;
};
BOOST_FUSION_ADAPT_STRUCT(
test,
(int, a)
(char, c)
(double, b)
)
int main() {
test s{1, 2, 3.0};
// The following code doesn't work... I'm just trying to get my point across
std::cout << "offset is :" << offsetof(test, at<1>(s)) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
关键是我不想在offsetof函数中明确声明'a'或'b'或'c'.这本身并没有那么有用,但是我想在boost for_each循环中使用它,这样我就可以在编译时计算任何结构的所有数据成员的偏移量.
如果您有任何想法,我很乐意听到他们!
我是C语言的新手,刚刚学习了结构和指针.
我的问题与offsetof我最近看到的宏有关.我知道它的工作原理和背后的逻辑.
在<stddef.h>文件中定义如下:
#define offsetof(type,member) ((unsigned long) &(((type*)0)->member))
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果我有一个如下所示的结构:
struct test {
int field1:
int field2:
};
struct test var;
Run Code Online (Sandbox Code Playgroud)
为什么我不能直接获取地址field2:
char * p = (char *)&var;
char *addressofField2 = p + sizeof(int);
Run Code Online (Sandbox Code Playgroud)
而不是写这样的东西
field2Offset = offsetof (struct test, field2);
Run Code Online (Sandbox Code Playgroud)
然后将偏移值添加到var的起始地址?
有什么区别吗?使用offsetof效率更高吗?
我有这段代码.它似乎在这里取消引用空指针,但随后按位与结果和unsigned int.我真的不明白整个部分.它打算做什么?这是指针算术的一种形式吗?
struct hi
{
long a;
int b;
long c;
};
int main()
{
struct hi ob={3,4,5};
struct hi *ptr=&ob;
int num= (unsigned int) & (((struct hi *)0)->b);
printf("%d",num);
printf("%d",*(int *)((char *)ptr + (unsigned int) & (((struct hi *)0)->b)));
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是44.但它是如何工作的?
在嵌入式编程中,当描述硬件时,通常需要将结构元素放置在HW工程师设计它们的已知预定义位置.例如,让我们定义一个结构FPGA,它有大约100个寄存器/区域,如下面的简化示例所示:
struct __attribute__ ((__packed__)) sFPGA {
uchar Spare1[0x24];
ushort DiscreteInput;
uchar Spare2[0x7A];
//CPLD_Version is required to be at offset 0xA0, so 0xA0-0x24-2=0x7A
ushort CPLD_Version;
};
Run Code Online (Sandbox Code Playgroud)
现在,我对手动计算感到沮丧和愤怒,并且在结构发生变化时可能出现错误.有没有办法做得更健壮/方便?我试着这样写:
uchar Spare2[0xA0 - offsetof(sFPGA, Spare2)];
Run Code Online (Sandbox Code Playgroud)
但这不会编译抱怨不完整的结构...注意,我的例子是简化的.实际上,必须定义大约20-30个这样的备用字段 - 结构非常大.
在使用指针算法时offsetof,是否采用了良好定义的行为来获取结构的地址,向其添加成员的偏移量,然后取消引用该地址以获取基础成员?
请考虑以下示例:
#include <stddef.h>
#include <stdio.h>
typedef struct {
const char* a;
const char* b;
} A;
int main() {
A test[3] = {
{.a = "Hello", .b = "there."},
{.a = "How are", .b = "you?"},
{.a = "I\'m", .b = "fine."}};
for (size_t i = 0; i < 3; ++i) {
char* ptr = (char*) &test[i];
ptr += offsetof(A, b);
printf("%s\n", *(char**)ptr);
}
}
Run Code Online (Sandbox Code Playgroud)
这应该打印"那里","你呢?" 并且"很好".连续三行,它目前与clang和gcc一起使用,因为你可以在wandbox上验证自己.但是,我不确定这些指针强制转换和算术是否违反某些规则会导致行为变为未定义.
offsetof ×10
c ×6
struct ×6
c++ ×4
boost ×1
boost-fusion ×1
casting ×1
char-pointer ×1
compile-time ×1
hdf5 ×1
macros ×1
null-pointer ×1
offset ×1
pointers ×1