Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中将数组内容强制转换为算术类型_C_Pointers_Casting_Access Violation_Dereference - Fatal编程技术网

在C中将数组内容强制转换为算术类型

在C中将数组内容强制转换为算术类型,c,pointers,casting,access-violation,dereference,C,Pointers,Casting,Access Violation,Dereference,我面临着将数组中的单个项强制转换(甚至取消引用)为单个算术类型的奇怪行为 以下是简化的测试用例: void test1() { unsigned char test[10] = {0}; unsigned long i=0xffffffff; *((unsigned long *)(&test[3])) = i; int it; for ( it = 0 ; it < 10 ; it++ ) { printf

我面临着将数组中的单个项强制转换(甚至取消引用)为单个算术类型的奇怪行为

以下是简化的测试用例:

void test1()
{
    unsigned char test[10] = {0};
    unsigned long i=0xffffffff;

    *((unsigned long *)(&test[3])) = i;


    int it;

    for ( it = 0 ; it < 10 ; it++ )

    {
        printf("%02x ", test[it]);

    }
}
void test2()
{
    unsigned char test[10] = {0};
    unsigned char test2[10] = {0};
    test[2]=0xFF;
    test[3]=0xFF;

    *((unsigned short *)(&test2[1])) = *((unsigned short *)(&test[2]));


    int it;

    for ( it = 0 ; it < 10 ; it++ )

    {
        printf("%02x ", test2[it]);

    }
}
我在其他一些平台(主要是嵌入式平台,如PIC24)上遇到访问冲突

所以我的问题是:这是符合C的吗?我在C-standard中找不到任何东西,但也许我只是个盲人

您知道没有这种强制转换(不意味着循环字节到字节的复制/展开等)的情况下执行此操作的其他方法吗?我不需要知道平台的当前字节顺序

谢谢

 *((unsigned short *)(&test2[1]))
这是未定义的行为,您违反了对齐和别名规则。不要这样做

您的
test2
对象是一个
无符号字符的数组
,通过强制转换,您可以作为
无符号短
对象访问其元素。不能保证
无符号字符
对齐要求与
无符号短字符
对齐要求相同

在C标准中,您可以在6.3.2.3p7(C99)中找到有关对齐的信息,并在6.5p7中找到有关别名规则的信息

一个很好的经验法则是,在
=
操作符左侧出现强制类型转换时,始终要非常小心

*((无符号长*)(&test[3]))=i具有未定义的行为。这取决于机器的长度和尺寸。

一般来说,您不应该在不同的指针类型之间强制转换(除了
void*
)。

这里的问题几乎可以肯定是您正在进行未对齐的访问。如果char是1字节,shorts是2字节(这很可能),那么您正在对奇数执行写短操作。这并不总是受支持的,这也是您最有可能遇到访问冲突的原因。如果您真的想这样做(您可能不想这样做),您可以通过使字符数组的前面长一个字符来填充字符数组,然后不使用第一个字符(将数组视为1索引而不是0索引),这可能会在没有这样做的平台上起作用,但即使这样也不能保证

是的,那可能是个问题。但是你可以用
#pragma pack
来修复这个问题,编译器将在2字节边界上对齐
字符。@cha0site:我认为
#pragma pack
只对结构元素打包有影响-在我们有array@PaulR:看来你是对的。但是GCC扩展允许您对齐数组。@cha0site:是的,但aligned属性仅适用于数组的开头(即第一个元素)。如果您试图访问字符数组的第三个元素,就好像它是一个更广泛的类型,如int,那么它将始终未对齐,这可能会或可能不会导致硬件异常。@PaulR:确定吗?文档将其描述为
union{inti;double d;}x[ARRAY_SIZE];的一种甜的替代方案,我很确定它会将数组的每个元素对齐到
sizeof(double)
边界。当然要小心,但有时确实需要做一些奇怪的事情,而且C允许你这么做是件好事。虽然我通常更喜欢使用
union
s来处理这类事情,但它是一个比指针强制转换更干净的解决方案。
 *((unsigned short *)(&test2[1]))