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

C语言中传递数组到函数时出现异常行为的问题分析

问题分析与解决:函数参数中数组的sizeof计算异常

问题场景

我实现了getTrainData函数,接收两个RailwayStation枚举参数和一个RailwayTrack数组参数。通过宏MAP1_TRAIN_N1调用时传入了包含4个元素的数组,但函数内用sizeof(railwayPath)/sizeof(RailwayTrack)计算数组长度并遍历打印,仅输出前2个元素;而函数内部定义的同结构测试数组却能正常打印全部4个元素。最终确认需要额外传递数组大小作为参数才能解决这个问题。

问题代码

typedef enum { MA1, MA2, MA3, MA4, MA5, MA6, MA7, 
    MA8, MA9, MA10, MA11, MA12, MA13, MA14, MA15, MA16} RailwayTrack;

typedef enum { S1, S2, S3, S4, S5, S6} RailwayStation;

typedef struct TrainData {
    int currentProgress;
    RailwayStation startStation;
    RailwayStation endStation;
    int railwayPathLength;
    RailwayTrack *railwayPath;
} TrainData;

#define MAP1_TRAIN_N1 getTrainData(S1, (RailwayTrack[]){ MA1, MA2, MA3, MA8 }, S6)

TrainData getTrainData(RailwayStation startStation, RailwayTrack railwayPath[], RailwayStation endStation) { 
  TrainData trainData;
  trainData.startStation = startStation;
  for (int i = 0; i < sizeof(railwayPath)/sizeof(RailwayTrack); i++)
  {
    printf("Eli: %d\n",railwayPath[i]);
  }
  // 输出:Eli: 0, Eli: 1

  RailwayTrack test[] = { MA1, MA2, MA3, MA8 }; // 测试数组能正常工作
  for (int i = 0; i < sizeof(test)/sizeof(RailwayTrack); i++)
  {
    printf("Eli: %d\n",test[i]);
  }
  // 输出:Eli: 0, Eli: 1, Eli: 2, Eli: 3
  
  trainData.railwayPath = railwayPath;
  trainData.endStation = endStation;
  return trainData;
}

原因分析

C语言的核心特性导致了这个问题:

  • 数组作为函数参数传递时会自动退化为指向数组首元素的指针。也就是说,函数里的railwayPath本质是RailwayTrack*类型,而不是真正的数组。
  • sizeof(railwayPath)获取的是指针的内存大小(64位系统为8字节,32位系统为4字节),sizeof(RailwayTrack)是枚举类型的大小(通常为4字节)。在64位环境下,8/4=2,所以循环只执行2次,仅打印前2个元素。
  • 函数内部的test是真正的数组变量,sizeof(test)会计算整个数组的总字节数(4个元素×4字节=16字节),16/4=4,因此循环能完整遍历所有元素。

解决方案

必须显式传递数组的长度作为函数参数,具体修改如下:

  1. 修改函数签名,新增数组长度参数
TrainData getTrainData(RailwayStation startStation, RailwayTrack railwayPath[], size_t pathLength, RailwayStation endStation)
  1. 用传入的长度替代sizeof计算
for (int i = 0; i < pathLength; i++)
{
    printf("Eli: %d\n", railwayPath[i]);
}
  1. 更新宏定义,传递数组长度
#define MAP1_TRAIN_N1 getTrainData(S1, (RailwayTrack[]){ MA1, MA2, MA3, MA8 }, 4, S6)

如果不想手动维护数组长度,也可以用宏自动计算(仅在数组定义的作用域内有效):

#define ARRAY_LEN(arr) (sizeof(arr)/sizeof((arr)[0]))

#define MAP1_TRAIN_N1 do { \
    RailwayTrack tempPath[] = { MA1, MA2, MA3, MA8 }; \
    getTrainData(S1, tempPath, ARRAY_LEN(tempPath), S6); \
} while(0)

总结

C语言中数组传参退化为指针是无法避免的特性,因此无法在函数内部通过sizeof获取原数组的实际长度,必须通过额外参数显式传递数组大小。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 09:13:11