在 C 中,将数组的头指针分配给联合中的现有数组
Assigning an array's head pointer to an existing array in a union, in C
我想要 "equate" 两个数组,其中一个在固定联合内(不应更改)。我不使用 memcpy,而是将 myUnion.RawBytes
的头部指向 array
的头部。但是编译器会为 myUnion.RawBytes = &array[0];
assignmet 抛出错误。为什么会这样?有什么办法可以绕过这个问题吗?
下面的错误代码试图说明这一点。
#include <stdio.h>
typedef union{
unsigned char RawBytes[2];
unsigned short RawWord;
} MyUnion;
int main(){
MyUnion myUnion;
char array[2] = {1, 1};
myUnion.RawBytes = &array[0];
printf("%d", myUnion.RawWord);
return 0;
}
错误:
main.c: In function ‘main’:
main.c:12:22: error: assignment to expression with array type
myUnion.RawBytes = &array[0];
为了解决您的问题,您可以使用以下方法。
Note: Below approach doesn't follow strict aliasing rule.
#include <stdio.h>
typedef union{
unsigned char RawBytes[2];
unsigned short RawWord;
} MyUnion;
int main(){
MyUnion *myUnion;
unsigned char array[2] = {1, 1};
myUnion = &array;
printf("%d", myUnion->RawWord);
printf("\n%d %d", myUnion->RawBytes[0], myUnion->RawBytes[1]);
return 0;
}
我强烈建议你在 union 中使用数组并使用 memcpy 或 for 循环。
双关语的正确做法
#include <stdio.h>
typedef union{
unsigned char RawBytes[2];
unsigned short RawWord;
} MyUnion;
int main(){
MyUnion myUnion;
char array[2] = {1, 1};
myUnion.RawBytes[0] = array[0];
myUnion.RawBytes[1] = array[1];
printf("%d", myUnion.RawWord);
return 0;
}
我读到的问题是 可以使用 any 2 个字符的数组并将其值解释为 unsigned short
而无需复制,通过使用此聪明union
把戏,答案是不,你不能。
原因是不是严格别名的原因,但它会破坏对齐要求。几乎所有平台对 unsigned short
的对齐要求至少为 2。如果一个指针被转换为另一个没有基本对齐要求的指针,行为是 未定义。
是的,这个可以。忘掉能够使用机器语言访问未对齐的对象吧——你是在 C 中编程,而不是在汇编中编程。
正确的方法是使用memcpy
,将告诉编译器访问可以不对齐, 即
char array[2] = {1, 1};
uint16_t raw_word;
memcpy(&raw_word, array, 2);
请注意,memcpy
是一个标准库函数,编译器可以生成 任何 类型的机器代码,只要其行为符合 as if 调用了标准库中的 memcpy
函数。
我想要 "equate" 两个数组,其中一个在固定联合内(不应更改)。我不使用 memcpy,而是将 myUnion.RawBytes
的头部指向 array
的头部。但是编译器会为 myUnion.RawBytes = &array[0];
assignmet 抛出错误。为什么会这样?有什么办法可以绕过这个问题吗?
下面的错误代码试图说明这一点。
#include <stdio.h>
typedef union{
unsigned char RawBytes[2];
unsigned short RawWord;
} MyUnion;
int main(){
MyUnion myUnion;
char array[2] = {1, 1};
myUnion.RawBytes = &array[0];
printf("%d", myUnion.RawWord);
return 0;
}
错误:
main.c: In function ‘main’:
main.c:12:22: error: assignment to expression with array type
myUnion.RawBytes = &array[0];
为了解决您的问题,您可以使用以下方法。
Note: Below approach doesn't follow strict aliasing rule.
#include <stdio.h>
typedef union{
unsigned char RawBytes[2];
unsigned short RawWord;
} MyUnion;
int main(){
MyUnion *myUnion;
unsigned char array[2] = {1, 1};
myUnion = &array;
printf("%d", myUnion->RawWord);
printf("\n%d %d", myUnion->RawBytes[0], myUnion->RawBytes[1]);
return 0;
}
我强烈建议你在 union 中使用数组并使用 memcpy 或 for 循环。
双关语的正确做法
#include <stdio.h>
typedef union{
unsigned char RawBytes[2];
unsigned short RawWord;
} MyUnion;
int main(){
MyUnion myUnion;
char array[2] = {1, 1};
myUnion.RawBytes[0] = array[0];
myUnion.RawBytes[1] = array[1];
printf("%d", myUnion.RawWord);
return 0;
}
我读到的问题是 可以使用 any 2 个字符的数组并将其值解释为 unsigned short
而无需复制,通过使用此聪明union
把戏,答案是不,你不能。
原因是不是严格别名的原因,但它会破坏对齐要求。几乎所有平台对 unsigned short
的对齐要求至少为 2。如果一个指针被转换为另一个没有基本对齐要求的指针,行为是 未定义。
是的,这个可以
正确的方法是使用memcpy
,将告诉编译器访问可以不对齐, 即
char array[2] = {1, 1};
uint16_t raw_word;
memcpy(&raw_word, array, 2);
请注意,memcpy
是一个标准库函数,编译器可以生成 任何 类型的机器代码,只要其行为符合 as if 调用了标准库中的 memcpy
函数。