简体   繁体   English

是否可以使用C语言中的指针数学来访问结构中的数据?

[英]Is it possible to access data in a struct using pointer math in C?

Is it possible to use pointer math to move through a struct and assign data to its members? 是否可以使用指针数学在结构中移动并将数据分配给其成员? I have a large struct with exclusively uint8_t data and writing the names of all these members of the struct is a lot of work. 我有一个仅包含uint8_t数据的大型结构,编写结构中所有这些成员的名称需要进行大量工作。 I was hoping I could just assign a pointer to the first data and then add 8 to the address. 我希望我可以只为第一个数据分配一个指针,然后将8加到该地址。 Is this possible? 这可能吗?

/* All pieces of data are the same size */
typdef struct 
{
    uint8_t a;
    uint8_t b;
    uint8_t c:
}Mydata;

int main(void){

    /* New struct created */
    Mydata NewData;
    /* Pointer P points to the address of "NewData"*/
    uin8_t *p = &NewData;

    *p = 5;
    p = p + 1; // increment 1 byte to next address where data is stored
    *p = 7;
    p = p + 1;
    *p = 10;

return 0;
}

Pointer math is done in bytes , not bits. 指针数学以字节为单位 ,而不是位。
So where you suggested adding by 8-bits, you should actually be adding 1-byte 因此,在您建议加8位的地方,实际上应该添加1字节

Structure layout is not guaranteed to be contiguous. 结构布局不保证是连续的。 The compiler may choose to put additional blank spaces in the middle of structures that help with alignment and memory access. 编译器可以选择在结构的中间放置其他空格,以帮助对齐和访问内存。 Even though you may not know it, it is possible to have: 即使您可能不知道,也可能有:

typdef struct 
{
    uint8_t a;
    char    padding_A[3];
    uint8_t b;
    char    padding_B[3];
    uint8_t c:
}Mydata;

This will throw off your assumptions and math. 这将偏离您的假设和数学。
You can often get around this with compiler-specific attributes such as #pragma pack or __attribute__((__packed__)) 您通常可以使用特定于编译器的属性来解决此问题,例如#pragma pack__attribute__((__packed__))

Finally, if you ever used this technique, very few engineers would be comfortable maintaining your code. 最后,如果您曾经使用过这种技术,那么很少有工程师会愿意维护您的代码。 If any member of the structure ever has its type changed, if any member is added or removed, then every single element-access after that has to be carefully updated. 如果结构的任何成员的类型发生了更改,如果添加或删除了任何成员,则此后的每个单个元素访问都必须仔细更新。 The risk of a bug is enormous. 错误的风险是巨大的。

There is a common macro available, called offsetof that can calculate the byte offset of members from the start of the structure. 有一个通用的可用宏,称为offsetof ,可以从结构的开头计算成员的字节偏移。 This can avoid many of the problems I outlined, and is occasionally used to write highly specialized code. 这样可以避免我概述的许多问题,并且偶尔可以用来编写高度专业的代码。

If you must do this, use the offsetof macro, but before that, take every possible precaution to avoid needing this technique in the first place. 如果必须执行此操作,请使用offsetof宏,但在此之前,请采取一切可能的预防措施,以避免首先使用此技术。

Although it is almost always a bad decision, since it leads to faults in portability, and in code readability, it can be done. 尽管这几乎总是一个错误的决定,但由于它会导致可移植性和代码可读性方面的错误,因此可以这样做。

Pointer math, in C, is based on the datatype of the pointer. C语言中的指针数学基于指针的数据类型。 The compiler needs to know the size of each element in your pointer to know how to increment the offset. 编译器需要知道指针中每个元素的大小才能知道如何增加偏移量。

Declare your pointer as uint8_t *p since your are iterating over uint8_t . 将指针声明为uint8_t *p因为您正在遍历uint8_t Then, just p++ everytime you want to go to the next member in your struct (since the compiler knows the type of your pointer, it know what "1" unit is equivalent to). 然后,每次要转到结构中的下一个成员时,只需使用p++ (因为编译器知道指针的类型,所以它知道“ 1”单元等效)。

I would recommend studying up on pointer math (and pointers in general since they are a major part of C) and, more importantly, I would advise strongly against using pointer math for practicality reasons. 我建议学习指针数学(以及指针,因为它们是C的主要组成部分,因此通常也应加以研究),更重要的是,出于实用性考虑,我强烈建议不要使用指针数学。

Edit: mispells 编辑:拼写错误

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM