You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用-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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 14:52:37