【问题标题】:C++: Why does casting as a pointer and then dereferencing work?C ++:为什么强制转换为指针然后解除引用工作?
【发布时间】:2011-11-24 01:49:50
【问题描述】:

最近我一直在研究 C++ 中的套接字,我遇到了这个问题:

*(struct in_addr*)&serv_addr.sin_addr.s_addr = *(struct in_addr *)server->h_addr;

虽然这确实做到了我想要的,但我有点困惑为什么我不能这样做:

(struct in_addr)serv_addr.sin_addr.s_addr = *(struct in_addr *)server->h_addr;

既然它变成一个指针,然后立即被取消引用,第二个不应该和第一个一样好用吗?我还是 C++ 的新手,这让我有点困惑。任何帮助将不胜感激。下面是代码。它所做的只是获取主机名或 IP 并将 IP 打印到屏幕上。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>


using namespace std;

int main(){

    int socketfd, portno, rwResult; 
    struct sockaddr_in serv_addr; 
    struct hostent* server;     
    char inputName[50];

    //The next block gets the host name and port number and stores them in variables
    cout<<"Enter host(Max Size 50): ";
    cin>>inputName;
    cout<<endl<<"Enter port number: ";
    cin>>portno;
    cout<<endl;

    server = gethostbyname(inputName);
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(portno);

    *(struct in_addr*)&serv_addr.sin_addr.s_addr = *(struct in_addr *)server->h_addr;
    //This is where I am confused
    //(struct in_addr)serv_addr.sin_addr.s_addr = *(struct in_addr *)server->h_addr;


    cout<< "Server: "<<inet_ntoa(*(struct in_addr *)server->h_addr_list[0])<<endl;

    cout<< "Server: "<<inet_ntoa(*(struct in_addr *)&serv_addr.sin_addr.s_addr)<<endl;
    //The two cout's tell me if the address was copied correctly to serv_addr I believe.



    return 0;
}

【问题讨论】:

  • 如果您也可以发布类型声明会有所帮助。

标签: c++ sockets pointers struct dereference


【解决方案1】:

一个更简单的例子可能有助于解释差异:

double q = 0.5;
int n;

n = (int) q;    // #1
n = *(int*)(&q) // #2

第一个版本q转换根据语言规则转换为int类型的值。只有基本类型和定义了转换运算符/构造函数的类才能进行转换。

第二个版本将q 的二进制表示重新解释为整数。在好的情况下(例如在您的示例中),这会产生一些有用的东西,但通常这是未定义的行为,因为不允许通过指向不同类型的指针访问一种类型的变量。

您的示例可能有效,因为所讨论的两种类型都是具有相同初始成员的 POD 结构,并且您仅访问其中一个常见的初始成员。 编辑。 我检查了,server-&gt;h_addr 的类型是 char *。这可能只是用作占位符,而指针实际上指向正确类型的结构。

【讨论】:

    【解决方案2】:

    如果存在接受原始类型参数的构造函数,则对象只能转换为另一个类。

    另一方面,指针可以随意施放。但是,这样做可能非常危险。如果需要强制转换,请在执行此操作时使用 static_cast 或 dynamic_cast,并可能检查强制转换是否成功。以这种更明确的方式进行转换的另一个风格优势是它使浏览您的代码的人更加明显。

    【讨论】:

      【解决方案3】:

      代码正在尝试将serv_addr.sin_addr.s_addr 重新解释为in_addr 类型。但是,此转换不兼容。因此,如果您尝试直接强制转换,则在第二个 sn-p 中会出现编译器错误。

      在第一个 sn-p 中,您实际上是在使用指针转换来解决这种类型不兼容问题。

      【讨论】:

      • 所以这真的取决于我在投射什么。这样做并不适用于所有事情。所以在这种情况下,我有点幸运?
      • 这取决于这些结构成员是如何设置的。有一些方法可以正确完成,但是您给我们的代码没有这些结构的声明。所以我分不清是不是UB。
      • 还是不够。 serv_addr.sin_addr.s_addr 表明您至少有 3 个嵌套结构。但是您仍然没有显示他们的任何声明。编辑:我收回,看起来它们是标准库的一部分?如果是这样,我不熟悉它们。
      • 实际上这几乎总是违反严格的别名规则,所以“它确实有效”应该带有一个很大的星号。
      猜你喜欢
      • 1970-01-01
      • 2021-05-08
      • 2013-06-03
      • 1970-01-01
      • 2013-01-17
      • 1970-01-01
      • 2013-04-29
      • 2015-04-08
      • 1970-01-01
      相关资源
      最近更新 更多