C语言无法通过数组索引修改结构体成员的原因及解决方法
问题产生原因
这是C语言默认值拷贝语义导致的,和任天堂DS平台本身没有关系:
你在初始化humanoid objects[1] = {zombie};时,并不是把之前定义的zombie变量本身存入了数组,而是将zombie当前的所有成员值复制了一份,存到了数组专属的独立内存空间里。也就是说数组里的元素和外面定义的zombie是两个完全独立、互不影响的humanoid实例。
你写的两段修改逻辑操作的根本不是同一块内存:
- 直接修改
zombie.y、zombie.speed时,改动的是你单独定义的原zombie变量的内存 - 循环里通过
objects[i]修改时,改动的是数组里保存的zombie副本的内存
如果你后续的渲染、碰撞检测等逻辑读取的是原zombie变量的值,自然看不到数组遍历修改的效果——你改的副本根本没有被其他逻辑用到。
可行解决方案
根据你的代码组织需求选一种即可,不要混用避免逻辑混乱:
- 方案1:移除独立定义的敌人变量,所有需要批量管理的人形对象直接在数组中初始化
这是最简单、最不容易出指针错误的写法,适合敌人数量固定、不需要动态增减的场景。后续新增敌人直接扩展数组长度、加初始化值就行,所有状态更新全走数组遍历,需要单独操作特定对象时直接通过索引访问。
参考实现:void game(){ humanoid player = {12, 12, 0, false, false}; // 直接在数组里初始化僵尸,不再单独定义zombie变量 humanoid objects[1] = {{226, 12, 0, false, false}}; while(1){ for(int i = 0; i < sizeof(objects)/sizeof(objects[0]); i++){ objects[i].y += objects[i].speed; objects[i].speed += 0.125; } // 需要操作僵尸时直接访问objects[0]即可 } } - 方案2:改用指针数组存储各个人形对象的内存地址
如果你希望保留独立命名的变量(比如用zombie比objects[0]可读性更高),可以把数组定义为humanoid指针类型,存入各个独立变量的地址,遍历数组时通过指针直接修改原变量的内存,不会产生副本。
参考实现:void game(){ humanoid player = {12, 12, 0, false, false}; humanoid zombie = {226, 12, 0, false, false}; // 数组存储指向humanoid实例的指针 humanoid* objects[1] = {&zombie}; while(1){ // 直接修改变量生效 zombie.y += zombie.speed; zombie.speed += 0.125; // 通过指针修改原变量,和直接操作zombie效果完全一致 for(int i = 0; i < sizeof(objects)/sizeof(objects[0]); i++){ objects[i]->y += objects[i]->speed; objects[i]->speed += 0.125; } } }
注意:如果后续需要做动态生成/销毁敌人的逻辑,指针数组方案可以配合NDS的内存分配函数
malloc()/free()使用,灵活度更高,但要注意避免野指针、内存泄漏问题。
内容的提问来源于stack exchange,提问作者JuanR4140
相关产品推荐
相关产品推荐

