You need to enable JavaScript to run this app. memcpy返回值赋值给int指针后用%s输出为何合法?
优惠活动
大模型
产品
解决方案
定价
更多

memcpy返回值赋值给int指针后用%s输出为何合法?

#include <stdio.h>
#include <string.h>
//Compiler version gcc  6.3.0

int main()
{
  char a1[20] ={0} , a2[20] ={0};
  int *ptr;
  fgets(a1,20,stdin);
  fgets(a2,20,stdin);
  ptr = memcpy(a1,a2,strlen(a2)-1);
  printf("%s \n",ptr);
  if(ptr)
  printf("%s",a1);
  return 0;
}
核心解答

你所说的“printf("%s",ptr);完全合法”是认知误区:这个写法在主流平台能跑出预期结果只是巧合,从C语言标准层面属于未定义行为,具体拆解如下:

编译无报错的原因

  • printf是可变参数函数,... 对应的可变参数默认不会被编译器做严格类型校验,只有开启-Wformat等高警告等级时,编译器才会对格式串和参数的类型匹配做扩展校验。
  • memcpy返回void*类型,C标准允许void*隐式转换为任意对象指针类型,所以将返回值赋值给int*类型的ptr本身是合法操作,不会触发编译错误。

运行时能正常输出的原因

memcpy返回的是目标缓冲区的首地址,也就是字符数组a1的起始地址,因此ptr存储的地址值和a1完全一致。在x86、ARM等绝大多数通用架构上,所有类型指针的底层存储都是纯内存地址,没有类型区分,所以printf处理%s格式符时,会直接按这个地址逐字节读取直到遇到\0终止符,输出效果和传入char*类型的a1没有区别。

为什么说这个写法不符合标准

C标准明确规定%s格式符对应的参数必须是指向\0结尾字符序列的char*类型指针,传入其他类型指针属于未定义行为:

  • 开启-Wall -Wformat编译参数时,GCC、Clang等编译器会直接抛出format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int *’的警告。
  • 在指针带类型标识、不同类型指针内存表示不同的特殊架构上,这段代码会直接崩溃或输出乱码。

内容的提问来源于stack exchange,提问作者Prince

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 07:09:03