"(类型)变量"和"*((类型*)和变量)之间的区别是什么",如果有的话?

Sam*_*Sam 15 c pointers casting

我想知道是否存在以下区别:

  1. 将基元变量转换为另一种基本类型
  2. 将原始变量的地址的转换解除引用到另一个基本类型的指针

我还想知道是否有充分的理由使用(2)超过(1).我在遗留代码中看到过(2)这就是我想知道的原因.从上下文来看,我无法理解为什么(2)被优先于(1).从我写的下面的测试中,我得出的结论是,至少上传的行为在两种情况下都是相同的:

/* compile with gcc -lm */
#include <stdio.h>
#include <math.h>

int main(void)
{
    unsigned max_unsigned = pow(2, 8 * sizeof(unsigned)) - 1;

    printf("VALUES:\n");
    printf("%u\n", max_unsigned + 1);
    printf("%lu\n", (unsigned long)max_unsigned + 1);          /* case 1 */
    printf("%lu\n", *((unsigned long *)&max_unsigned) + 1);    /* case 2 */

    printf("SIZES:\n");
    printf("%d\n", sizeof(max_unsigned));
    printf("%d\n", sizeof((unsigned long)max_unsigned));       /* case 1 */
    printf("%d\n", sizeof(*((unsigned long *)&max_unsigned))); /* case 2 */

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

VALUES:
0
4294967296
4294967296
SIZES:
4
8
8
Run Code Online (Sandbox Code Playgroud)

从我的角度来看,(1)和(2)之间应该没有区别,但我想咨询SO专家进行健全性检查.

das*_*ght 9

第一次演员是合法的; 第二个演员可能不合法.

第一个演员告诉编译器使用变量类型的知识来转换为所需的类型; 只要在语言标准中定义了正确的转换,编译器就会这样做.

第二个演员告诉编译器忘记它对变量类型的了解,并将其内部表示重新解释为不同类型*的内部表示.这具有有限的适用性:只要二进制表示与目标指针指向的类型匹配,该转换就可以工作.但是,这不等同于第一次投射,因为在这种情况下,价值转换永远不会发生.

将正在转换的变量的类型切换为具有不同表示的变量(例如a)float,可以很好地说明这一点:第一次转换产生正确的结果,而第二次转换产生垃圾:

float test = 123456.0f;
printf("VALUES:\n");
printf("%f\n", test + 1);
printf("%lu\n", (unsigned long)test + 1);
printf("%lu\n", *((unsigned long *)&test) + 1); // Undefined behavior
Run Code Online (Sandbox Code Playgroud)

这打印

123457.000000
123457
1206984705
Run Code Online (Sandbox Code Playgroud)

(演示)


*仅当其中一种类型是字符类型且指针对齐有效,类型转换很简单(即没有转换时),更改限定符或签名,或者转换为/来自struct/时union第一个成员是有效的转换源/目标.否则,这会导致未定义的行为.有关完整说明,请参阅C 2011(N1570),6.5 7.谢谢Eric Postpischil指出定义第二次转换的情况.