《黑客:漏洞利用的艺术》中代码出现指针-整数类型转换警告求助
指针与整数类型转换警告的原因分析及解决方法
我正在阅读《黑客:漏洞利用的艺术》一书,书中的代码编译时出现指针与整数类型转换相关的警告,下面是具体的错误信息、原代码,以及对应的原因分析和解决方法。
错误信息
pointer_types5.c: In function ‘main’: pointer_types5.c:11:28: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 11 | hacky_nonpointer = (unsigned int) char_array; | ^ pointer_types5.c:15:33: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 15 | hacky_nonpointer, *((char *) hacky_nonpointer)); | ^ pointer_types5.c:19:28: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 19 | hacky_nonpointer = (unsigned int) int_array; | ^ pointer_types5.c:23:33: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 23 | hacky_nonpointer, *((int *) hacky_nonpointer)); |
原代码
#include <stdio.h> int main() { int i; char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; int int_array[5] = {1, 2, 3, 4, 5}; unsigned int hacky_nonpointer; hacky_nonpointer = (unsigned int) char_array; for(i=0; i < 5; i++) { // 用int_pointer遍历int数组 printf("[hacky_nonpointer] points to %p, which contains the char '%c'\n", hacky_nonpointer, *((char *) hacky_nonpointer)); hacky_nonpointer = hacky_nonpointer + sizeof(char); } hacky_nonpointer = (unsigned int) int_array; for(i=0; i < 5; i++) { // 用int_pointer遍历int数组 printf("[hacky_nonpointer] points to %p, which contains the integer %d\n", hacky_nonpointer, *((int *) hacky_nonpointer)); hacky_nonpointer = hacky_nonpointer + sizeof(int); } }
原因分析
- 核心问题是指针类型和
unsigned int的内存宽度不匹配。现在主流的64位系统中,指针占8字节,而unsigned int通常只占4字节。把8字节的指针强制转换成4字节的整数时,会丢失高位地址信息;反过来把4字节的整数转回8字节指针时,会补零或导致地址错误,编译器因此抛出类型转换的警告。 - 原代码用
unsigned int存储数组的地址(数组名会隐式转换为指针),之后又把这个整数转回指针,这种跨类型转换在地址宽度和整数宽度不一致的平台上必然触发警告。
解决方法
这里提供两种实用的处理方式:
方式一:使用标准指针类型存储地址(推荐)
直接把hacky_nonpointer的类型改成void*(通用指针类型),完全避免整数和指针的转换,代码逻辑更安全规范:
#include <stdio.h> int main() { int i; char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; int int_array[5] = {1, 2, 3, 4, 5}; void* hacky_nonpointer; hacky_nonpointer = char_array; for(i=0; i < 5; i++) { printf("[hacky_nonpointer] points to %p, which contains the char '%c'\n", hacky_nonpointer, *((char *) hacky_nonpointer)); hacky_nonpointer = (char*)hacky_nonpointer + 1; // sizeof(char)就是1,直接写1更简洁 } hacky_nonpointer = int_array; for(i=0; i < 5; i++) { printf("[hacky_nonpointer] points to %p, which contains the integer %d\n", hacky_nonpointer, *((int *) hacky_nonpointer)); hacky_nonpointer = (int*)hacky_nonpointer + 1; // 指针算术会自动按int宽度偏移,不用加sizeof(int) } }
这里用void*作为通用指针,转换时明确转为对应类型的指针再做算术运算,完全符合C语言标准,不会触发任何警告。
方式二:使用uintptr_t类型保留原书思路
如果想保留原书用整数操作地址的实验性写法,应该用标准库定义的uintptr_t类型——它是专门用来存储指针的无符号整数类型,宽度和当前平台的指针完全一致,定义在<stdint.h>头文件中:
#include <stdio.h> #include <stdint.h> int main() { int i; char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; int int_array[5] = {1, 2, 3, 4, 5}; uintptr_t hacky_nonpointer; hacky_nonpointer = (uintptr_t) char_array; for(i=0; i < 5; i++) { printf("[hacky_nonpointer] points to %p, which contains the char '%c'\n", (void*)hacky_nonpointer, *((char *) (void*)hacky_nonpointer)); hacky_nonpointer = hacky_nonpointer + sizeof(char); } hacky_nonpointer = (uintptr_t) int_array; for(i=0; i < 5; i++) { printf("[hacky_nonpointer] points to %p, which contains the integer %d\n", (void*)hacky_nonpointer, *((int *) (void*)hacky_nonpointer)); hacky_nonpointer = hacky_nonpointer + sizeof(int); } }
注意用%p打印时,需要把uintptr_t转换为void*,这是printf要求的指针格式对应的类型。这种写法既保留了用整数操作地址的思路,又符合标准,不会触发警告。
内容的提问来源于stack exchange,提问作者Ecce
相关产品推荐
相关产品推荐

