何时使用指针与结构的直接成员

时间:2014-07-24 14:42:59

标签: c sockets pointers struct

所以我在C中发现了this关于套接字的惊人教程。到目前为止,这一切都很有意义,但我很好奇我看到了用指针和没有指针的结构。当你应该或不应该使用指针结构时,我感到很困惑。

我在教程中找到了这个例子:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MAX_LENGTH 2000

int main(int argc, char *argv[]) {

    int socket_desc;
    struct sockaddr_in server;
    char *message, server_reply[MAX_LENGTH];

    socket_desc = socket(AF_INET, SOCK_STREAM, 0);

    if (socket_desc == -1) {
        puts("Could not create socket :(");
    }

    server.sin_addr.s_addr = inet_addr("173.194.121.2");
    server.sin_family = AF_INET;
    server.sin_port = htons(80);

    if (connect(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) {
        puts("Connection error.");
        return 1;
    }
    puts("Connected!\n");

    close(socket_desc);
    return 0;
}

所以我决定将服务器变量转换为指针,看看发生了什么。这就是我想出的:

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MAX_LENGTH 2000

int main(int argc, char *argv[]) {

    int socket_desc;
    struct sockaddr_in *server;
    char *message, server_reply[MAX_LENGTH];

    socket_desc = socket(AF_INET, SOCK_STREAM, 0);

    if (socket_desc == -1) {
        puts("Could not create socket :(");
    }

    server->sin_addr.s_addr = inet_addr("173.194.121.2");
    server->sin_family = AF_INET;
    server->sin_port = htons(80);

    if (connect(socket_desc, (struct sockaddr *)server, sizeof(*server)) < 0) {
        puts("Connection error.");
        return 1;
    }
    puts("Connected!\n");

    close(socket_desc);
    return 0;
}

这也编译得很好,但是当我运行它时给了我Segmentation fault: 11

所以我的问题是为什么这段代码不起作用,我怎么知道何时需要指向结构或普通结构的指针。谢谢!

3 个答案:

答案 0 :(得分:4)

在第一个版本中,您声明了一个完整的结构,这意味着结构的内存放在堆栈上。

在第二个版本中,您声明了一个指向struct的指针,但是没有为它分配内存,因此当您尝试寻址结构中不存在的成员时,就会出现段错误。

如果更改第二个以为结构分配内存:

struct sockaddr_in *server = malloc(sizeof(struct sockaddr_in));

然后在退出之前记住free(server);,你将正确处理内存。

要回答问题的第二部分,如果您需要将数据(在本例中为连接信息)存储在某些其他数据结构中以跟踪它,您可能只需要指向结构的指针,或者如果由于某种原因需要将其传递给另一个例程。

但是,对于后一种情况,使用&运算符来获取地址,堆栈上的结构用作传递给例程的指针,通常在connect()调用中完成在第一个例程中,它使用此参数执行此操作:(struct sockaddr *)&server

答案 1 :(得分:0)

服务器是一个指针。它指向什么?你没说。服务器可以指向struct sock_addr_in,但它没有。

它就像一辆在路上开得很好的汽车,但是你试图在路标上行驶。

答案 2 :(得分:0)

如果要传递指针的API打算取消引用该指针,则代表您在其中存储值,您需要将其传递给有效的内存位置,以便存储操作成功。

如果您传递指针的API只想将其传递给您(例如通过回调函数),那么指针值可以是当您获得值时对您有意义的任何值。 / p>