c语言 - 返回 malloc'd 结构给出段错误和不同的地址



我正在开发一个处理C中某些网络连接的库,我的计划是让init函数返回一个结构,该结构包含连接的所有相关数据,然后调用方将这些数据传递给任何库函数。我还希望调用程序可以访问结构的内容。

这是我的init(库(代码

//here is the struct
typedef struct {
SSL_CTX* ctx;
SSL* ssl;
int socket;
int usingSSL;
} twitch_connection;

struct twitch_connection* twlibc_init(int usingSSL){ //returns a pointer to a struct that has to be freed
twitch_connection *temp;
temp = malloc(sizeof(twitch_connection)); //creates the address for the struct
struct sockaddr_in twitchaddr;
...
if(usingSSL == 0){
//not using SSL
temp->ctx = NULL;
temp->ssl = NULL;
}else {
//using SSL
temp->ctx = ctx; //how I assign values to the struct
temp->ssl = ssl;
}

temp->socket = twitchsock;
return temp; //returns the struct back to caller
}

这是我演示的代码

int main(){

twitch_connection* twlibc = twlibc_init(1);

printf("address of struct from main of callers code is: %pn", twlibc);
}

然而,当我打印结构的地址时,当从代码中的不同区域打印时,我会得到不同的结果:

address of struct from inside init function: 0x56299befd260
address of struct from main of callers code is: 0xffffffff9befd260

如果我试图从主函数打印结构的一个成员,我会得到一个分段错误。

twitch_connection* twlibc = twlibc_init(1);

由于此时未声明twlibc_init,因此C假定返回值为int,因此上述内容等效于twlibc = (twitch_connection*)(int)twlibc_init(1);

在具有32位int类型的64位平台上,这将把0x56299befd260截断为32位整数0x9befd260,然后将其符号扩展为64位指针0xffffffff9befd260

解决方案是在主文件中声明函数struct twitch_connection* twlibc_init(int usingSSL);,或者更好的是,将声明移动到包含在两个位置的公共标头中。


[EDIT]将int强制转换为指针时的符号扩展取决于实现,不受C标准的保证,因此另一个编译器可能打印了0x9befd260,或者实际上打印了任何东西。从cppreference C cast操作符页面:

任何整数都可以强制转换为任何指针类型。除了null(不需要强制转换(等空指针常量外,结果是实现定义的,可能没有正确对齐,可能没有指向引用类型的对象,并且可能是陷阱表示