C语言中左手的类型转换

rnmwe5a2  于 2023-06-28  发布在  其他
关注(0)|答案(1)|浏览(84)

我有一个这样的示例程序:

#include <stdio.h>

int main()
{
    unsigned long long a;
    unsigned short b;
    b = 10;
    *(unsigned short *)&a = b;
    printf("a = %lld\n", a);
    return 0;
}

我对*(unsigned short *)&a = b;这行有一个疑问,通常我们在右手边进行类型转换,这里我看到类型转换在左手边。
我看到上面的语句所实现的是,short int存储在unsigned long long的LSB位中,unsigned long long变量中其余位的值可能保持不变。所以像这样的情况我们在左手边做类型转换?
对此有何见解,请分享。

owfi6suc

owfi6suc1#

由于多种原因,代码具有未定义的行为:

  • 通过*(unsigned short *)&a = b;修改a的初始2个字节实际上具有未定义的行为:如果您正在通过指向非字符类型的不同类型的指针修改a的值,编译器可能会认为尚未设置a的值,因为自定义a以来,未通过类型unsigned long long执行赋值
  • a是未初始化的,因此即使前2个字节被修改,剩余的6个字节也是未初始化的,因此将值传递给printf具有未定义的行为。
  • 你正在传递一个unsigned long long类型的值到printf,它需要一个long long类型的值。使用%llu进行无符号转换。下面是一个带有定义行为的修改版本:
#include <stdio.h>
#include <string.h>

int main(void)
{
    unsigned long long a = 0;
    unsigned short b = 10;
    memcpy(&a, &b, sizeof(b));
    printf("a = %llu\n", a);
    return 0;
}

但是请注意,输出是实现定义的:根据unsigned shortunsigned long long的大小和表示,用b的字节修改a的一部分可以产生不同的值,可能是陷阱值,尽管不太可能。
在当前的little endian系统上,输出应该是a = 10,而在big endian系统上:a = 42949672960 .

相关问题