- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
这是一个在struct shape
、struct rectangle
和struct triangle
类型的指针之间进行类型转换的程序。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
enum { RECTANGLE, TRIANGLE, MAX };
struct shape {
int type;
};
struct rectangle {
int type;
int x;
int y;
};
struct triangle {
int type;
int x;
int y;
int z;
};
struct shape *get_random_shape()
{
int type = rand() % MAX;
if (type == RECTANGLE) {
struct rectangle *r = malloc(sizeof (struct rectangle));
r->type = type;
r->x = rand() % 10 + 1;
r->y = rand() % 10 + 1;
return (struct shape *) r;
} else if (type == TRIANGLE) {
struct triangle *t = malloc(sizeof (struct triangle));
t->type = type;
t->x = rand() % 10 + 1;
t->y = rand() % 10 + 1;
t->z = rand() % 10 + 1;
return (struct shape *) t;
} else {
return NULL;
}
}
int main()
{
srand(time(NULL));
struct shape *s = get_random_shape();
if (s->type == RECTANGLE) {
struct rectangle *r = (struct rectangle *) s;
printf("perimeter of rectangle: %d\n", r->x + r->y);
} else if (s->type == TRIANGLE) {
struct triangle *t = (struct triangle *) s;
printf("perimeter of triangle: %d\n", t->x + t->y + t->z);
} else {
printf("unknown shape\n");
}
return 0;
}
这是输出。
$ gcc -std=c99 -Wall -Wextra -pedantic main.c
$ ./a.out
perimeter of triangle: 22
$ ./a.out
perimeter of triangle: 24
$ ./a.out
perimeter of rectangle: 8
您可以在上面看到程序编译并运行时没有任何警告。我试图了解将 struct shape
的指针类型转换为 struct rectangle
是否有效,反之亦然,即使这两个结构的大小不同。
如果您的回答是这无效,那么请考虑网络编程书籍通常在 struct sockaddr *
、struct sockaddr_in *
和 struct sockaddr_in6 之间进行类型转换*
指针取决于套接字系列(AF_INET 与 AF_INET6),然后解释为什么这种类型转换在 struct sockaddr *
的情况下是可以的,但在上面的 情况下却不行结构形状 *
。这是使用 struct sockaddr *
进行类型转换的示例。
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main()
{
struct addrinfo *ai;
if (getaddrinfo("localhost", "http", NULL, &ai) != 0) {
printf("error\n");
return EXIT_FAILURE;
}
if (ai->ai_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *) ai->ai_addr;
printf("IPv4 port: %d\n", addr->sin_port);
} else if (ai->ai_family == AF_INET6) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *) ai->ai_addr;
printf("IPv6 port: %d\n", addr->sin6_port);
}
return 0;
}
此代码也可以正常编译和运行。此外,根据有关套接字编程的书籍,这是编写此类程序的推荐方式。
$ gcc -std=c99 -D_POSIX_SOURCE -Wall -Wextra -pedantic foo.c
$ ./a.out
IPv6 port: 20480
最佳答案
Is it legal to type-cast pointers of different struct types (e.g. struct sockaddr * to struct sockaddr_in6 *)?
是的。 C明确规定:
A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. Otherwise, when converted back again, the result shall compare equal to the original pointer.
(C2011, 6.3.2.3/7)
正如其他答案所指出的那样,问题不在于类型转换本身,而在于您如何处理结果。这归结为严格的别名规则:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
- a type compatible with the effective type of the object,
[... plus several other alternatives that cannot apply in this case ...]
(C2011,6.5/7;已强调)
因此,主要问题是 struct sockaddr *
对象的有效类型是什么?点?重要的是要了解 我们无法从 getaddrinfo()
的声明中分辨出来, 也不是 struct addrinfo
的。特别是,没有理由假设有效类型是 struct sockaddr
.
事实上,鉴于您询问的转换是访问地址详细信息的标准和预期方法,我们有充分的理由假设 getaddrinfo()
通过确保有效类型是由关联的 ai_family
指示的类型来支持这一点代码。然后相应的转换产生一个与地址信息的有效类型相匹配的指针。在这种情况下,通过强制转换获得的指针访问地址信息本身就没有问题。
我的观察支持上述观点,假设所讨论的指针指向一个动态分配的对象是合理的。此类对象的有效类型取决于上次设置其存储值的方式 (C2011, 6.5/6)。 getaddrinfo()
这不仅是合理的,而且很可能将以赋予它所需的有效类型的方式设置该值。例如,沿着与您的形状示例相同的代码行进行编码。
最终,类型转换 struct sockaddr *
指向和指向地址族特定结构的指针是预期用途,没有理由假设提供 getaddrinfo()
的环境实际上,会让这些行为变得可疑。如果有必要,POSIX(指定函数的人)可以合并一个允许强制转换的特殊规则。但是在这种情况下不需要这样的规则,尽管 POSIX 让您相信它。
关于c - 对不同结构类型的指针进行类型转换是否合法(例如,将 struct sockaddr * 转换为 struct sockaddr_in6 *)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39425409/
这个问题在这里已经有了答案: C++ Redefinition Header Files (winsock2.h) (15 个答案) 关闭 6 年前。 我使用 Visual Studio 2012
struct sockaddr { unsigned short sa_family; // address family, AF_xxx char sa_da
当我运行时 cc -c -o rawudp.o rawudp.c 我明白了 在 rawudp.c:1:0 包含的文件中: rawudp.h:48:23: 错误:未知类型名称‘sockaddr’ mak
我想知道确定使用哪个 sockaddr 变体的正确方法。 来自Beej's Guide to Network Programming : if (p->ai_family == AF_INET) {
我目前正在编写一个使用网络结构(例如 sockaddr)的 C 库。在我的代码中,我使用这个三元条件来推断这种结构的大小。 addrlen = sourceaddr->sa_family ==
在尝试以下操作时,第二个 sockaddr 中的地址发生了变化: /*Stuff*/ sockaddr add1, add2; recvfrom(/*socket*/, /*buffer*/, /*c
我正在尝试创建一个 void mksockaddr(int af, int proto, char addr[], struct sockaddr* dst) 来创建一个 sockaddr 结构,这是
我正在尝试学习网络编程,并在此过程中学习 C。我对作为通用地址的结构 sockaddr 和 sockaddr_in 感到困惑。我的书是这样说的: Thus, we can fill in the fi
根据msdn的这篇文章( http://msdn.microsoft.com/en-us/library/windows/desktop/ms740496(v=vs.85).aspx ) 结构因选择的
我正在打开一个 Linux 数据包套接字并尝试将接收到的数据包读入一个结构中: type msg struct { n, oobn, flags int p, oob []byte
我一直在阅读 Beej 的网络编程指南,在他的一个示例中,他将指向 struct sockaddr 的指针转换为 struct sockaddr_in6 指针,如下所示。 void *addr
'operator sockaddr *()'在这里是什么意思?类 Raw 是一个内部类,sockaddr 是一个结构。 struct sockaddr { __SOCKADDR_COMM
var sa_tab:[sockaddr?] = [sockaddr](repeating: sockaddr(), count: Int(RTAX_MAX)) let addr:sockaddr =
我遇到过这段代码: (stuct sockadrr*)&servaddr 这是什么意思?您以某种方式将结构强制转换为 servaddr? 我只是想弄清楚这段代码的语法及其在 C 中的含义。 最佳答案
概览 我正在用 C++ 编写一个简单的测试游戏服务器。目前,我有一个监听任何人的绑定(bind)套接字,当某种数据包类型到达时,我想将 sockaddr 结构保存到一个对象中,该对象将传递给一个单独的
我正在编写一个从命令行提供地址的 UDP 套接字程序。 为了使发送和写入更容易,我使用 getaddrinfo 将地址转换为 sockaddr 结构:sockaddr_in 或 sockaddr_in
手册页未涵盖在发生错误时通过引用传递到 accept() 函数的 sockaddr 变量的状态。 是否可以安全地假设如果在客户端连接和您接受它之间出现问题,导致 accept() 的返回值小于 0,那
目前我正在尝试部署一个用C++编写的网络应用程序,由于网络问题,它看起来陷入了死循环: [isaev@feck-5 ~]$ sudo strace -p 26252 -f -e trace=netwo
我用 C 编写了一个简短的 TCP 服务器示例,它持续监听端口 12701 上的连接,并将对等方的 sockaddr.sa_family 的值输出到标准输出。程序在无限循环中调用 accept(),它
我在 Mac OS X 中做了一些干预(本质上是拦截 C 调用),我注意到 ping 应用程序试图调用 addrlen 值为 16 的 sendto 函数。在 sys/socket.h 中我可以清楚地
我是一名优秀的程序员,十分优秀!