C/C++指向POD结构的指针也指向第一个结构成员

aka*_*tis 1 c c++ struct pointers

我可以假设C/C++结构指针总是指向第一个成员吗?
例1:

typedef struct {
 unsigned char  array_a[2];
 unsigned char  array_b[5];
}test;
//..
test var;
//..
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,&var总是指向array_a吗?在上面的例子中,是否可以将指针强制转换为unsigned char指针并分别访问每个字节?
例2:

function((unsigned char *)&var,sizeof(test));
//...
//...
void function(unsigned char *array, int len){
 int i;
 for( i=0; i<len; i++){
    array[i]++;
 }
}
Run Code Online (Sandbox Code Playgroud)

这会正常吗?

注意:我知道字符在结构中是字节对齐的,因此我假设上面结构的大小是7个字节.

Sah*_*een 7

从C99标准部分6.7.2.1要点13:

在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址.指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.结构对象中可能存在未命名的填充,但不是在其开头.

因此,你的问题的答案是肯定的.

参考(参见第103页)

  • "你的问题的答案是肯定的"......对于C. (3认同)

Tri*_*dle 7

对于C结构,是的,你可以依赖它.这就是几乎所有"面向对象"风格的API在C中的工作方式(例如GObject和GTK).

对于C++,您只能依赖于"普通旧数据"(POD)类型,它们保证以与C结构相同的方式布局在内存中.究竟是什么构成POD类型有点复杂,并且在C++ 03和C++ 11之间发生了变化,但关键是如果你的类型有任何虚函数那么它就不是POD.

(在C++ 11中,您可以使用std::is_pod在编译时测试结构是否是POD类型.)

编辑:这告诉你什么构成了C++中的POD类型:http://en.cppreference.com/w/cpp/concept/PODType

EDIT2:实际上,在C++ 11中,它不需要是POD,只需要"标准布局",这是一个轻微的弱化条件.第9.2节[class.mem]标准第20段:

指向标准布局结构对象的指针,使用reinterpret_cast进行适当转换,指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.[注意:因此,在标准布局结构对象中可能存在未命名的填充,但不是在其开头,以实现适当的对齐. - 结束说明]