使用-Werror编译C代码时%p格式化int*报错,%ls不兼容C90,为何强制转换?
问题解决与原理说明
一、直接解决办法
把代码中传给%p的指针参数强制转换为void*类型即可,修改后的代码如下:
int main(int argc, char *argv[]) { int var = 789, *ptr, **ptr1; ptr = &var; ptr1 = &ptr; printf("var: %d\n", var); printf("address of var: %p\n", (void*)&var); // 强制转换为void* printf("address: %p references: %d\n", (void*)ptr, *ptr); // 强制转换为void* return (0); }
二、为什么必须强制转换为void*
根据C语言标准(包括C90)的规定,printf的%p格式符要求对应的参数必须是void*类型:
printf属于可变参数函数,这类函数不会自动对指针类型进行隐式转换(普通函数调用时的指针转换规则不适用)。int*、char*等其他指针类型和void*属于不同类型,直接传递会违反格式符与参数类型的匹配要求。- 虽然多数现代系统中所有指针类型的内存大小、表示方式一致,但这只是平台特性而非标准规定。显式转换为
void*是符合标准的写法,能保证代码的可移植性。
三、关于%ls的误区
编译器报错信息里提到的%ls是完全的误导,它和地址输出毫无关系:
%ls是用于打印宽字符字符串(wchar_t*类型)的格式符,根本不能用来输出内存地址。- 因为启用了
-Werror,编译器把格式不匹配的警告升级为错误,此时不要理会%ls的提示,坚持用%p加void*强制转换才是正确做法。
内容的提问来源于stack exchange,提问作者n8s
相关产品推荐
相关产品推荐

