如何用指针与offsetof()正确访问结构体?代码赋值报错求解
Fixing the "incompatible types" Error When Accessing Struct Fields via Offset
Let's break down what's going wrong here and fix your pointer arithmetic properly.
Why You're Seeing the Error
That line *(ptr + offset) = data; is the root of the problem. Here's why:
ptris astruct osc_in_data*pointer. In C, pointer arithmetic with struct pointers uses the full size of the struct as the unit of measurement—not individual bytes.- So
ptr + offsetdoesn't point to the field inside your struct atoffsetbytes. Instead, it jumps to an entirely separatestruct osc_in_datainstance in the array. That's why the compiler complains about assigning anint32_tto astruct osc_in_datatype.
The Correct Pointer Offset Approach
To access a field using a byte offset (which is exactly what offsetof returns), you need to adjust your pointer arithmetic to work at the byte level:
- Convert the struct pointer to a byte-based pointer (like
uint8_t*) so arithmetic operations use single bytes as the unit. - Add your byte offset to this pointer to reach the exact memory address of the target field.
- Convert the result back to a pointer matching the field's type (in your case,
int32_t*) before assigning the value.
Here's the fixed line for your function:
*(int32_t*)((uint8_t*)ptr + offset) = data;
Full Modified Code
Make sure you include the necessary headers for offsetof and fixed-size integers:
#include <stddef.h> #include <stdint.h> #define NumHarmonics 10 int32_t data1; int32_t data2; struct osc_in_data { int32_t LevelAttackRate; int64_t LevelPeakLevel; int32_t LevelDecayRate; } OscControl[NumHarmonics]; void SetADSRvalues(int32_t offset, int32_t data) { int32_t harmonic; struct osc_in_data *ptr; for (harmonic = 0; harmonic < NumHarmonics; harmonic++) { ptr = &OscControl[harmonic]; // Correct pointer arithmetic to target the desired field *(int32_t*)((uint8_t*)ptr + offset) = data; } } // Example usage void initialize_adsr() { SetADSRvalues(offsetof(struct osc_in_data, LevelAttackRate), data1); SetADSRvalues(offsetof(struct osc_in_data, LevelDecayRate), data2); }
Key Notes
- This solution works because both
LevelAttackRateandLevelDecayRateareint32_ttypes. If you wanted to setLevelPeakLevel(anint64_t), you'd need to cast toint64_t*instead and adjust the function'sdataparameter type to match. - Always ensure the offset you pass aligns with the data type you're assigning—mismatched types will lead to undefined behavior.
内容的提问来源于stack exchange,提问作者Mike Bryant
相关产品推荐
相关产品推荐

