MinGW64 GCC编译C顺序表代码触发-Wpointer-to-int-cast警告
问题说明
Windows环境下使用MinGW64路径下的gcc.exe编译C语言实现的通用顺序表代码时,抛出[-Wpointer-to-int-cast]类型转换警告,提示存在从指针到不同大小整数的强制转换问题,警告定位在SeqList_Insert函数内的sList->node[i] = (TSeqListNode)node;语句处。
涉及的原始源码如下:
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef void SeqList; typedef void SeqListNode; typedef unsigned int TSeqListNode; typedef unsigned int TSeqListNode; typedef struct _tag_SeqList { int capacity; int length; TSeqListNode *node; }TSeqList; SeqList * SeqList_Create(int capacity) { TSeqList *ret = NULL; if(capacity>=0) { ret = (TSeqList *)malloc(sizeof(TSeqList) + sizeof(TSeqListNode)*capacity); } if(ret == NULL) { printf("malloc fail.\n"); exit(-1); } ret->capacity = capacity; ret->length = 0; ret->node = (TSeqListNode*)(ret+1); return ret; } int SeqList_Insert(SeqList *list, SeqListNode *node, int pos) { TSeqList *sList = (TSeqList*)list; int ret = (sList != NULL); int i = 0; ret = ret && (sList->length+1 <= sList->capacity); ret = ret && (0 <= pos); if(ret) { if(pos >= sList->length) { pos = sList->length; } for(i=sList->length; i > pos; i--) { sList->node[i] = sList->node[i-1]; } sList->node[i] = (TSeqListNode)node; sList->length++; } return ret; } int main() { system("pause"); return 0; }
编译命令与原始输出信息如下:
D:\mingw64\bin\gcc.exe -g D:\Cpp\DSA\test001.c -o D:\Cpp\test001.exe D:\Cpp\test001.c: In function 'SeqList_Insert': D:\Cpp\test001.c:56:26: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] sList->node[i] = (TSeqListNode)node; ^
警告触发原因
- 64位MinGW编译环境下,指针类型的位宽为64位(占8字节),但代码中定义的
TSeqListNode类型为unsigned int,在64位Windows系统下该类型位宽仅为32位(占4字节),两者长度不匹配 - 强制将64位指针转换为32位整数时,指针的高32位地址数据会被截断,不仅触发编译警告,程序运行时如果申请的内存地址超过4GB寻址范围,还会出现非法地址访问、程序崩溃的严重问题
- 源码中存在
TSeqListNode的重复typedef定义,属于冗余无效写法
修复方法
要保留通用顺序表存储任意类型节点的功能,只需要将存储节点地址的整数类型替换为C标准库定义的、位宽与当前环境指针完全一致的uintptr_t类型即可,该类型定义在<stdint.h>头文件中,专门用于安全存储指针对应的整数值,不会出现位宽不匹配的问题。
修改后的完整代码如下:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<stdint.h> // 引入uintptr_t类型定义头文件 typedef void SeqList; typedef void SeqListNode; typedef uintptr_t TSeqListNode; // 替换为位宽与指针匹配的无符号整数类型,删除重复定义 typedef struct _tag_SeqList { int capacity; int length; TSeqListNode *node; }TSeqList; SeqList * SeqList_Create(int capacity) { TSeqList *ret = NULL; if(capacity>=0) { ret = (TSeqList *)malloc(sizeof(TSeqList) + sizeof(TSeqListNode)*capacity); } if(ret == NULL) { printf("malloc fail.\n"); exit(-1); } ret->capacity = capacity; ret->length = 0; ret->node = (TSeqListNode*)(ret+1); return ret; } int SeqList_Insert(SeqList *list, SeqListNode *node, int pos) { TSeqList *sList = (TSeqList*)list; int ret = (sList != NULL); int i = 0; ret = ret && (sList->length+1 <= sList->capacity); ret = ret && (0 <= pos); if(ret) { if(pos >= sList->length) { pos = sList->length; } for(i=sList->length; i > pos; i--) { sList->node[i] = sList->node[i-1]; } sList->node[i] = (TSeqListNode)node; // 此处转换不再有位宽不匹配问题 sList->length++; } return ret; } int main() { system("pause"); return 0; }
修改后重新使用原编译命令编译,不会再出现该警告,同时通用顺序表存储任意类型节点的功能完全保留,32位/64位环境下均可正常编译运行。
注意:如果后续需要从顺序表中取出节点使用,直接将存储的
TSeqListNode值强制转换回对应节点的指针类型即可,不会出现地址截断问题。
内容的提问来源于stack exchange,提问作者linyb
相关产品推荐
相关产品推荐

