我有以下 Cpp 函数:
u_long stringIpV4ToBinary(const char * ipv4)
{
u_long * buff[1];
int ret = InetPton(AF_INET, ipv4, &buff);
if (ret == -1) return 1;
if (ret == 0) return 1; // more handling needs to be added
// return ntohl(*buff[0]); // crash, no warning
// return ntohl((*buff)[0]); // same meaning above (??) crash, no warning
// return ntohl(**buff); // crash, no warning
// return ntohl(*(buff[0])); // crash, no warning
// return ntohl(*(u_long*)buff[0]); // crash, no warning
// return ntohl((u_long)buff[0]); // works, but produces warnings:: 'type cast': truncation from 'u_long *' to 'u_long'
// return ntohl(*(u_long*)&buff); // works
// return ntohl(*(u_long*)&buff[0]); // works
// return ntohl(*(u_long*)buff[0]); // crash, no warning
// return ntohl(*(u_long*)buff); // works
}
我花了一些时间尝试提取需要传递给 ntohl()
的 buff 值(这样您就可以忽略前几行)。我正在玩 *buff[0]
*buff
等,没有意识到我需要转换数组第一个元素的值(&buff[0]
、buff
或 &buff
)。
问题:为什么我需要将检索到的值转换为(u_long*)
,然后遵循指针? @runtime 是否不清楚或不清楚 buff[0]
中保存的值将是 u_long *
类型?我的期望是 ntohl(**buff) - (buff 是数组名称,它会衰减为指针,并且由于数组本身就是 u_long 指针)双重解引用就足够了。
最佳答案
您已将 buff
定义为指向 u_long
的指针数组(大小为 1)。因此,InetPton
将结果 IP 地址直接存储在该指针变量中。然后您会崩溃,因为该 IP 地址被解释为内存地址并被取消引用。
buff
应定义为简单的 u_long
,其地址传递给 InetPton
:
u_long buff;
int ret = InetPton(AF_INET, ipv4, &buff);
然后你可以这样做:
return ntohl(buff);
对此进行了改进,如果第一个参数的值为 AF_INET
,MSDN 页面会显示以下内容:
INT WSAAPI InetPton( _In_ INT Family, _In_ PCTSTR pszAddrString, _Out_ PVOID pAddrBuf );
...
When this parameter is specified, the
pszAddrString
parameter must point to a text representation of an IPv4 address and thepAddrBuf
parameter returns a pointer to anIN_ADDR
structure that represents the IPv4 address.
因此,您应该为第三个参数传递 IN_ADDR
的地址:
IN_ADDR addr;
int ret = InetPton(AF_INET, ipv4, &addr);
...
return ntohl(addr.S_addr);
编辑:
进一步解释为什么 Actor 阵容会产生影响,结果发现事实并非如此。造成差异的是间接级别和取消引用的次数。
关于c++ - 在特定场景中指针取消引用和强制转换之间的关系不明确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47675506/