GAME_STATUS getCombinedInfo(_OUT_ char**** combinedInfo)
{
*combinedInfo = (char***)malloc(2 * sizeof(char**));
if (*combinedInfo)
{
(*combinedInfo)[0] = (char**)malloc(COUNT_OF_NUM * sizeof(char*));
(*combinedInfo)[1] = (char**)malloc(COUNT_OF_COLOR * sizeof(char*));
}
if (*combinedInfo && (*combinedInfo)[0])
{
for (int j = 0; j < COUNT_OF_NUM; j++)
{
(*combinedInfo)[0][j] = (char*)malloc(BYTES_FOR_SINGLE_NUM * sizeof(char));
}
}
if (*combinedInfo && (*combinedInfo)[1])
{
for (int j = 0; j < COUNT_OF_COLOR; j++)
{
(*combinedInfo)[1][j] = (char*)malloc(BYTES_FOR_SINGLE_COLOR * sizeof(char));
}
}
char* Card_NUM_8 = (char*)"8\0";
char* Card_NUM_9 = (char*)"9\0";
char* Card_NUM_10 = (char*)"10";
char* Card_NUM_J = (char*)"J\0";
char* Card_NUM_Q = (char*)"Q\0";
char* Card_NUM_K = (char*)"K\0";
char* Card_NUM_A = (char*)"A\0";
char* Card_COLOR_梅花 = (char*)"梅花";
char* Card_COLOR_黑桃 = (char*)"黑桃";
char* Card_COLOR_红桃 = (char*)"红桃";
char* Card_COLOR_方片 = (char*)"方片";
if (*combinedInfo && (*combinedInfo)[0] && (*combinedInfo)[0][0] && (*combinedInfo)[0][1] && (*combinedInfo)[0][2] && (*combinedInfo)[0][3] && (*combinedInfo)[0][4] && (*combinedInfo)[0][5] && (*combinedInfo)[0][6])
{
memcpy((*combinedInfo)[0][0], Card_NUM_8, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][1], Card_NUM_9, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][2], Card_NUM_10, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][3], Card_NUM_J, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][4], Card_NUM_Q, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][5], Card_NUM_K, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][6], Card_NUM_A, BYTES_FOR_SINGLE_NUM);
}
if (*combinedInfo && (*combinedInfo)[1] && (*combinedInfo)[1][0] && (*combinedInfo)[1][1] && (*combinedInfo)[1][2] && (*combinedInfo)[1][3])
{
memcpy((*combinedInfo)[1][0], Card_COLOR_梅花, BYTES_FOR_SINGLE_COLOR);
memcpy((*combinedInfo)[1][1], Card_COLOR_黑桃, BYTES_FOR_SINGLE_COLOR);
memcpy((*combinedInfo)[1][2], Card_COLOR_红桃, BYTES_FOR_SINGLE_COLOR);
memcpy((*combinedInfo)[1][3], Card_COLOR_方片, BYTES_FOR_SINGLE_COLOR);
}
return STATUS_SUCCESS;
}
1.malloc返回的地址千万千万不要暴力赋值!!!!!!!否则无法进行FREE!!!!!
对malloc返回的地址进行赋值:《《要用“温柔地”memcpy函数》》而不是暴力的address_from_malloc = other_address!!!!!FREE不了的时候够你哭的!!!
2.为什么"梅花"这个东西是char [7]呢?目前还不理解,但是不影响写代码(伟大的编译器!)!
3.字节问题.
(*combinedInfo)[0] = (char**)malloc(COUNT_OF_NUM * sizeof(char*));
这个东西因为要存储7张牌,那么就是7个地址,COUNT_OF_ NUM = 7没问题
但是
(*combinedInfo)[0][j] = (char*)malloc(BYTES_FOR_SINGLE_NUM * sizeof(char));
这个东西要存卡牌的牌面,因为“10”的存在所以每张卡片的牌面用两个char来表示:
1).如果是8 9 J Q K A,那么他们本身加上一个 \0 来存;
2).如果是10, 那就是它本身。
关键在于传入到malloc的字节数要比实际存储的字节数加一,因为要考虑到\0!因此malloc要传3而不是2!!!!!
传了2没有任何语法错误,没有任何警告。但是程序有的时候没问题,有的时候有问题!
也就是一个程序会运行出多个结果!
此外,在LEETCODE上面用C语言写东西,如果报错也绝大多数都是这里出了问题!!!!!!!!!!!!!!!!!!!!!
4.宏
宏中用printf打印宏串,(status)表达式将status视为一个数字,而#status表达式将status是为一个%s.
a ## b 表达把a和b连接起来!
5.free函数释放高阶指针
GAME_STATUS killCombinedInfoMemory(_OUT_ char**** combinedInfo)
{
for (int j = 0; j < COUNT_OF_NUM; j++)
{
ExFreeMemoryToNULL(&((*combinedInfo)[0][j]));
}
for (int j = 0; j < COUNT_OF_COLOR; j++)
{
ExFreeMemoryToNULL(&((*combinedInfo)[1][j]));
}
for (int j = 0; j < 2; j++)
{
(*combinedInfo)[j] = NULL;
}
*combinedInfo = NULL;
return STATUS_SUCCESS;
}
void ExFreeMemoryToNULL(PVOID* mem)
{
free(*mem);
*mem = NULL;
}
#define TEST_MEMORY(address) \
do\
{\
if((ULONG)(address) == 0) \
{\
printf("Address: %s is NULL\n", #address);\
}\
else\
{\
printf("Address: %s exists\n", #address);\
}\
}while(0);
0).free只能释放由malloc以及malloc派生的函数返回的地址!
1).(假设p=malloc(8);)由上一条,free某个指针会从p所指向的字节开始,一直查8个字节,并把这些字节换为DD.(在VS2022编译器,x86,windows10系统上是这样);
2).我封装的这个ExFreeMemoryToNULL,在第一步完成之后还会把这个指针变成0x00000000(x86系统下一个指针4个字节)因为指针本质上还是一个数,x86下是4字节ULONG, x64下是8字节ULONG64而已;
3).函数内修改指针指向的值,要传指针的地址,这也是为什么在ExFreeMemoryToNULL中传的是二级指针;
4).多级指针释放逻辑:
①->先用根指针导到边缘指针(就是在解引用一次就是单个的结构成员或者字符了,在这里就是从*combinedInfo导到combinedInfo[0][j]和combinedInfo[1][j])。
导到边缘之后,ExFreeMemoryToNULL掉他们:
for (int j = 0; j < COUNT_OF_NUM; j++)
{
ExFreeMemoryToNULL(&((*combinedInfo)[0][j]));
}
for (int j = 0; j < COUNT_OF_COLOR; j++)
{
ExFreeMemoryToNULL(&((*combinedInfo)[1][j]));
}
因为这里传递的是四级指针,那么显然combinedInfo前面要加一个*才和一般语义的combinedInfo相同;又因为ExFreeMemoryToNULL要传递指针的地址来进行函数内修改指针所指向的值,所以前面还要加&;
②->把边缘指针ExFreeMemoryToNULL掉之后,剩下的高阶指针依次设置为NULL即可。
for (int j = 0; j < 2; j++)
{
(*combinedInfo)[j] = NULL;
}
*combinedInfo = NULL;
③.初始状态如下:
④.释放完之后如下:
目前卡片的源文件cardFunctions.c
#include "showHandCardDefs.h"
char* g_initialCardNum = (char*)"0\0";
char* g_initialCardColor = (char*)"无花";
GAME_STATUS initialCard(_OUT_ PCard* card, _IN_ char* num, _IN_ char* color)
{
*card = (PCard)malloc(sizeof(Card));
if (*card)
{
(*card)->num = (char*)malloc(BYTES_FOR_SINGLE_NUM * sizeof(char));
if ((*card)->num)
{
memcpy((*card)->num, num, BYTES_FOR_SINGLE_NUM);
}
(*card)->color = (char*)malloc(BYTES_FOR_SINGLE_COLOR * sizeof(char));
if ((*card)->color)
{
memcpy((*card)->color, color, BYTES_FOR_SINGLE_COLOR);
}
}
return STATUS_SUCCESS;
}
GAME_STATUS initialSentCardsStack(_OUT_ PCard** stack)
{
*stack = (PCard*)malloc(MAX_POSSIBLE_CARDS * sizeof(PCard));
if (*stack)
{
for (int j = 0; j < MAX_POSSIBLE_CARDS; j++)
{
(*stack)[j] = (PCard)malloc(sizeof(Card));
}
for (int j = 0; j < MAX_POSSIBLE_CARDS; j++)
{
if((stack[j]) != NULL)
{
((*stack)[j])->num = (char*)malloc(BYTES_FOR_SINGLE_NUM * sizeof(char));
((*stack)[j])->color = (char*)malloc(BYTES_FOR_SINGLE_COLOR * sizeof(char));
}
}
for (int j = 0; j < MAX_POSSIBLE_CARDS; j++)
{
if ((*((*stack) + j)) != NULL)
{
if ((*stack)[j]->num && (*stack)[j]->color && g_initialCardNum && g_initialCardColor)
{
memcpy(((*stack)[j])->num, g_initialCardNum, BYTES_FOR_SINGLE_NUM);
memcpy(((*stack)[j])->color, g_initialCardColor, BYTES_FOR_SINGLE_COLOR);
}
}
}
}
return STATUS_SUCCESS;
}
GAME_STATUS getCombinedInfo(_OUT_ char**** combinedInfo)
{
*combinedInfo = (char***)malloc(2 * sizeof(char**));
if (*combinedInfo)
{
(*combinedInfo)[0] = (char**)malloc(COUNT_OF_NUM * sizeof(char*));
(*combinedInfo)[1] = (char**)malloc(COUNT_OF_COLOR * sizeof(char*));
}
if (*combinedInfo && (*combinedInfo)[0])
{
for (int j = 0; j < COUNT_OF_NUM; j++)
{
(*combinedInfo)[0][j] = (char*)malloc(BYTES_FOR_SINGLE_NUM * sizeof(char));
}
}
if (*combinedInfo && (*combinedInfo)[1])
{
for (int j = 0; j < COUNT_OF_COLOR; j++)
{
(*combinedInfo)[1][j] = (char*)malloc(BYTES_FOR_SINGLE_COLOR * sizeof(char));
}
}
char* Card_NUM_8 = (char*)"8\0";
char* Card_NUM_9 = (char*)"9\0";
char* Card_NUM_10 = (char*)"10";
char* Card_NUM_J = (char*)"J\0";
char* Card_NUM_Q = (char*)"Q\0";
char* Card_NUM_K = (char*)"K\0";
char* Card_NUM_A = (char*)"A\0";
char* Card_COLOR_梅花 = (char*)"梅花";
char* Card_COLOR_黑桃 = (char*)"黑桃";
char* Card_COLOR_红桃 = (char*)"红桃";
char* Card_COLOR_方片 = (char*)"方片";
if (*combinedInfo && (*combinedInfo)[0] && (*combinedInfo)[0][0] && (*combinedInfo)[0][1] && (*combinedInfo)[0][2] && (*combinedInfo)[0][3] && (*combinedInfo)[0][4] && (*combinedInfo)[0][5] && (*combinedInfo)[0][6])
{
memcpy((*combinedInfo)[0][0], Card_NUM_8, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][1], Card_NUM_9, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][2], Card_NUM_10, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][3], Card_NUM_J, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][4], Card_NUM_Q, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][5], Card_NUM_K, BYTES_FOR_SINGLE_NUM);
memcpy((*combinedInfo)[0][6], Card_NUM_A, BYTES_FOR_SINGLE_NUM);
}
if (*combinedInfo && (*combinedInfo)[1] && (*combinedInfo)[1][0] && (*combinedInfo)[1][1] && (*combinedInfo)[1][2] && (*combinedInfo)[1][3])
{
memcpy((*combinedInfo)[1][0], Card_COLOR_梅花, BYTES_FOR_SINGLE_COLOR);
memcpy((*combinedInfo)[1][1], Card_COLOR_黑桃, BYTES_FOR_SINGLE_COLOR);
memcpy((*combinedInfo)[1][2], Card_COLOR_红桃, BYTES_FOR_SINGLE_COLOR);
memcpy((*combinedInfo)[1][3], Card_COLOR_方片, BYTES_FOR_SINGLE_COLOR);
}
return STATUS_SUCCESS;
}
GAME_STATUS verifyCardAlreadySent(_IN_ PCard card, _IN_ PCard* stack, _OUT_ INT* flag, _OUT_ INT* loc)
{
*flag = 1;
*loc = 0;
for (int j = 0; j < MAX_POSSIBLE_CARDS; j++)
{
if (strncmp(stack[j]->num, card->num, BYTES_FOR_SINGLE_NUM) == 0)
{
if (strncmp(stack[j]->color, card->color, BYTES_FOR_SINGLE_COLOR) == 0)
{
*flag = 0;
*loc = j;
}
}
}
return STATUS_SUCCESS;
}
GAME_STATUS pushCardIntoStack(_IN_ PCard card, _IN_OUT_ PCard* stack)
{
int top = 0;
for (int j = 0; j < MAX_POSSIBLE_CARDS; j++)
{
if(*(stack[j]->num) == '0')
{
top = j;
break;
}
}
memcpy(stack[top]->num, card->num, BYTES_FOR_SINGLE_NUM);
memcpy(stack[top]->color, card->color, BYTES_FOR_SINGLE_COLOR);
return STATUS_SUCCESS;
}
GAME_STATUS displaySentStackValid(_IN_ PCard* stack)
{
for (int j = 0; *(stack[j]->num) != '0'; j++)
{
printf("%ld -> %s%s\n", j + 1, stack[j]->color, stack[j]->num);
}
return STATUS_SUCCESS;
}
GAME_STATUS displayAllStack(_IN_ PCard* stack)
{
for (int j = 0; j<MAX_POSSIBLE_CARDS; j++)
{
printf("%ld -> %s%s\n", j + 1, stack[j]->color, stack[j]->num);
}
return STATUS_SUCCESS;
}
GAME_STATUS clearSentCardsStack(_IN_OUT_ PCard* stack)
{
for (int j = 0; j < MAX_POSSIBLE_CARDS; j++)
{
memcpy(stack[j]->num, g_initialCardNum, BYTES_FOR_SINGLE_NUM);
memcpy(stack[j]->color, g_initialCardColor, BYTES_FOR_SINGLE_COLOR);
}
return STATUS_SUCCESS;
}
GAME_STATUS killCardMemory(_OUT_ PCard* card)
{
ExFreeMemoryToNULL(&((*card)->num));
ExFreeMemoryToNULL(&((*card)->color));
*card = NULL;
return STATUS_SUCCESS;
}
GAME_STATUS killStackMemory(_OUT_ PCard** stack)
{
for (int j = 0; j < MAX_POSSIBLE_CARDS; j++)
{
ExFreeMemoryToNULL(&(((*stack)[j])->num));
}
for (int j = 0; j < MAX_POSSIBLE_CARDS; j++)
{
ExFreeMemoryToNULL(&(((*stack)[j])->color));
}
for (int j = 0; j < MAX_POSSIBLE_CARDS; j++)
{
(*stack)[j] = NULL;
}
*stack = NULL;
return STATUS_SUCCESS;
}
GAME_STATUS killCombinedInfoMemory(_OUT_ char**** combinedInfo)
{
for (int j = 0; j < COUNT_OF_NUM; j++)
{
ExFreeMemoryToNULL(&((*combinedInfo)[0][j]));
}
for (int j = 0; j < COUNT_OF_COLOR; j++)
{
ExFreeMemoryToNULL(&((*combinedInfo)[1][j]));
}
for (int j = 0; j < 2; j++)
{
(*combinedInfo)[j] = NULL;
}
*combinedInfo = NULL;
return STATUS_SUCCESS;
}
三个头文件
//showHandDefs.h
#pragma once
#ifndef __showHandDefs__
#define __showHandDefs__
#endif
//公共库库头文件区域↓
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <time.h>
//公共库库头文件区域↑
//类型定义↓
typedef int GAME_STATUS;
//类型定义↑
//结构定义↓
typedef struct _Card
{
char* num;
char* color;
}Card, * PCard;
//结构定义↑
//形参属性宏定义↓
#ifndef _IN_
#define _IN_
#endif
#ifndef _OUT_
#define _OUT_
#endif
#ifndef _IN_OUT_
#define _IN_OUT_
#endif
//形参属性宏定义↑
//
//卡牌属性宏定义↓
#define COUNT_OF_NUM 7
#define COUNT_OF_COLOR 4
#define BYTES_FOR_SINGLE_NUM 3
#define BYTES_FOR_SINGLE_COLOR 7
#define MAX_POSSIBLE_CARDS 25
//卡牌属性宏定义↑
//
//错误代码宏定义↓
#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS 0
#endif
#define MEMORY_FAILED_ALLOCATE 0x00000001
#define INVALID_STACK_LOCATION 0x00000002
#define NULL_MEMORY_INPUT 0x00000003
//错误代码宏定义↑
//
//功能宏定义↓
#define merge(sta1, sta2) (sta1 ## sta2)
#define CHECK_RETURN_WITH_STATUS(status) \
do\
{\
if((status) != 0x0)\
{\
printf("Operation: %s Failed. Error Code: %ld\n", #status, (status));\
}\
else\
{\
printf("Operation: %s Successfully. Returned code: %ld\n", #status, (status));\
}\
}while(0);
#define TEST_MEMORY(address) \
do\
{\
if((ULONG)(address) == 0) \
{\
printf("Address: %s is NULL\n", #address);\
}\
else\
{\
printf("Address: %s exists\n", #address);\
}\
}while(0);
//功能宏定义↑
//showHandCardDefs.h
#ifndef __showHandCardDefs__
#define __showHandCardDefs__
#include "showHandDefs.h"
GAME_STATUS initialCard(_OUT_ PCard* card, _IN_ char* num, _IN_ char* color);
GAME_STATUS initialSentCardsStack(_OUT_ PCard** stack);
GAME_STATUS getCombinedInfo(_OUT_ char**** combinedInfo);
GAME_STATUS verifyCardAlreadySent(_IN_ PCard card, _IN_ PCard* stack, _OUT_ INT* flag, _OUT_ INT* loc);
GAME_STATUS pushCardIntoStack(_IN_ PCard card, _IN_OUT_ PCard* stack);
GAME_STATUS displaySentStackValid(_IN_ PCard* stack);
GAME_STATUS displayAllStack(_IN_ PCard* stack);
GAME_STATUS clearSentCardsStack(_IN_OUT_ PCard* stack);
GAME_STATUS killCardMemory(_OUT_ PCard* card);
GAME_STATUS killStackMemory(_OUT_ PCard** stack);
GAME_STATUS killCombinedInfoMemory(_OUT_ char**** combinedInfo);
#endif
//showHandPublicDefs.h
#ifndef __showHandPublicDefs__
#define __showHandPublicDefs__
#include "showHandDefs.h"
void ExFreeMemoryToNULL(PVOID* mem);
#endif