【问题标题】:Is there a situation where type casting a pointer automatically dereferences it?是否存在类型转换指针自动取消引用它的情况?
【发布时间】:2021-06-06 07:03:04
【问题描述】:

我不太记得在哪里[可能完全是错误的,因为我不记得确切的情况] 我想我在指针类型转换中遇到了一种情况,只是简单地对指针进行类型转换,就是取消引用它。但我不记得它发生的确切情况。

我知道事情以通常的方式运作的方式,例如:

   int main()
   {
        int x=99;
        void* p=&x;
        int y= *(int*)p; //------------------------(1)
        printf("%d\n",y);
   }

我主要关心的是 (1) 形式的陈述。类型可能不像提到的那样具体。但是是否存在* 之前的(int *) 是可选的情况或情况? [我的意思是虽然(int *)之前的*可以省略,但LHS上的变量应该存储指针值。我想问的是,即使我省略*是什么情况,只使用指针的类型转换实际上给出了指针的数据内容]

虽然我将类型转换称为(int *),但可以假定为通用类型转换,我试图解释上下文。

有没有发生这种情况的情况?

PS:我昨晚睡不着,因为这个问题一直困扰着我......

【问题讨论】:

  • 如果这是让你彻夜难眠的东西,那么你的生活一定很顺利!
  • @obe 不是真的
  • 好的,很遗憾听到这个消息......无论如何,我不记得曾经看到过“通过类型转换取消引用”,但我已经多年没有使用 C 了,所以最好让更多的人(最近?)经验答案...
  • 不,没有。
  • 您不能取消引用void*,因为void 是不完整的类型,因此编译器不知道void 有多少字节。因此,在取消引用 void* 之前,您必须将其转换为编译器知道它有多大的类型。 (int*) 是指向int 的指针的强制转换,当然'*' 将强制转换的结果取消引用到int。但是你必须确保你没有通过void* 以避免严格的别名规则。 C11 Standard - §6.5 Expressions (p6,7)

标签: c pointers


【解决方案1】:

在 C 语言中,唯一会自动取消引用的指针是在函数调用中使用的函数指针。所以下面不需要解引用操作符:

#include <stdio.h>

int greet(const char *whom) { return printf("Hello, %s!", whom); }
int main(void) {
    void* pgreet = (void*)&greet;
    ((int(*)(const char*))(pgreet))("world");
    return 0;
}

(在coliru 上直播。正如您在输出中看到的那样,这并不是真正可移植的,因为将函数指针转换为void* 在非Posix 平台上可能会失败。)

所以这完全一样

#include <stdio.h>

int greet(const char *whom) { return printf("Hello, %s!", whom); }
int main(void) {
    void* pgreet = (void*)&greet;
    (*(int(*)(const char*))(pgreet))("world");
    return 0;
}

但解除引用的不是演员阵容;这是函数调用。 (函数,如数组,只能在非常特定的上下文中用作值。)


*(T*)(&amp;buffer) hack 旨在从编译器中生成更好的代码。但是使用现代编译器,您可以使用可移植的memcpy 获得高效的代码。如果将其包装在函数中,则不必很冗长。见https://gcc.godbolt.org/z/Tj7PWTK57:

#include <string.h>
int get_unaligned_int(void* v) {
    int temp;
    memcpy(&temp, v, sizeof temp);
    return temp;
}

可以看出,在启用优化的情况下编译,结果是一个简单的加载操作。

【讨论】:

  • *(T*)(&amp;buffer) hack 旨在从编译器中生成更好的代码。 我想说,大多数情况下,这样的代码都是由那些不知道这一事实的人编写的该内存不仅仅是 C 中的内存,而且 *(T*)(&amp;buffer) 通常是未定义的行为,因为它是严格的别名违规,同时由于对齐限制,还存在另一级别未定义行为的风险。
  • @andrew 随便。尽管我不是读心者,但我仍然很确定我对编码器意图的描述接近准确,无论你或我如何看待他们的能力。无论如何,我的意思是表明这是不必要的,并提供可以替代使用的代码。
猜你喜欢
  • 2016-04-18
  • 2020-12-22
  • 1970-01-01
  • 2018-07-23
  • 2015-08-27
  • 2021-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多