C语言:如何在函数内修改数组指针地址以实现外部数组元素位置交换(卡牌洗牌场景)
我来帮你梳理下问题所在,以及如何正确实现你的洗牌需求:
首先,你的代码里有几个关键错误需要先修正
错误1:尝试free/malloc字符串字面量数组
你在shuffleArray里调用free(*array)和malloc是完全错误的。因为values和types是栈上的字符串指针数组,它们的元素指向的是字符串字面量(存储在只读内存区),不是通过malloc分配的堆内存。对这些指针调用free会触发未定义行为,而重新分配内存后赋值给*array也无法同步到外部的栈数组(因为数组名是常量指针,不能被重新赋值)。错误2:数组传递方式不对
你尝试用&values作为参数传递,但values是char*[13]类型,会自动退化为char**,直接传values就可以匹配shuffleArray的char** array参数。
你的核心需求其实不需要修改数组的指针地址
你想要的是打乱数组元素的顺序,也就是交换数组里的字符串指针指向,而不是替换整个数组的内存位置。所以正确的做法是用洗牌算法交换数组内的元素,而不是重新分配数组。
正确的实现方案
这里用经典的Fisher-Yates洗牌算法,它能高效地打乱数组,而且只需要在原数组上交换元素,不需要额外内存。
修正后的shuffleArray函数
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <time.h> // 洗牌函数:打乱char*类型的数组 void shuffleArray(char** array, uint8_t size) { for (uint8_t i = size - 1; i > 0; i--) { // 生成0到i之间的随机索引 uint8_t j = rand() % (i + 1); // 交换array[i]和array[j]的指针值,这就是你想要的交换逻辑 char* temp = array[i]; array[i] = array[j]; array[j] = temp; } }
修正后的initializeCards函数
typedef struct { char* value; char* type; } CARD; CARD cards[52]; void initializeCards() { // 修正types数组的长度(你之前写的10是笔误) char* types[4] = {"Spade", "Club", "Hearts", "Diamonds"}; char* values[13] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "B", "D", "K"}; // 直接传入数组名即可,自动退化为char**类型 shuffleArray(types, 4); shuffleArray(values, 13); // 生成打乱后的卡牌数组 for (int i = 0; i < 4; i++) { for (int e = 0; e < 13; e++) { int index = i * 13 + e; cards[index].type = types[i]; cards[index].value = values[e]; } } }
补充说明
- 随机数种子:记得在程序入口(比如
main函数)里调用srand((unsigned int)time(NULL));,否则每次运行程序的洗牌结果都会完全一致。 - 为什么这个方案符合你的需求:通过交换
types和values数组内的指针,后续生成cards数组时,就会用打乱后的花色和数值组合,间接实现了洗牌的效果,而且只需要分别打乱4个元素和13个元素的数组,迭代次数远少于直接打乱52张卡牌,完全贴合你的初衷。
内容的提问来源于stack exchange,提问作者Niels
相关产品推荐
相关产品推荐

