在做这到道题目时,使用到了二维数组和二级指针,直接将二维数组num赋值给二级指针moves,编译过程会报如下告警:
warning: assignment to ‘int **’ from incompatible pointer type ‘int (*)[2]’ [-Wincompatible-pointer-types]
于是将二维数组进行类型强制转换:moves=(int **)num; 再次编译告警消失,但是运行会报段错误“Segmentation fault (core dumped)”。
力扣
int main()
{
char *res;
int num[9][2]={{0,0},{1,1},{2,0},{1,0},{1,2},{2,1},{0,1},{0,2},{2,2}};
int movesSize = 9;
int size[9]={2,2,2,2,2,2,2,2,2};
int ** moves;
moves=(int **)num;
int *movesColSize;
movesColSize=size;
res = tictactoe(moves, movesSize, movesColSize);
printf("tic_tac_toe_game result is %sn",res);
return 0;
}
于是开始考虑二维数组和二级指针的关系。
二维数组:
根据以上告警内容可知,二维数组类型为 int (*)[2],即一个指针数组,数组内容为指向int类型的指针,指针大小为2。num就是num[0]的地址,把二者进行输出,可以看出指向的地址是一样的。也就是二维数组的数组名是一个一维数组的首地址。
int main()
{
char *res;
int num[9][2]={{0,0},{1,1},{2,0},{1,0},{1,2},{2,1},{0,1},{0,2},{2,2}};
int movesSize = 9;
int size[9]={2,2,2,2,2,2,2,2,2};
int ** moves;
printf("num is %x, num[0] is %x, num[0][0] is %dn", num,num[0],num[0][0]);
//num is ffffcbc0, num[0] is ffffcbc0, num[0][0] is 0
printf("num add is %x, num[0] add is %x, num[0][0] add is %xn", &num,&num[0],&num[0][0]);
//num add is ffffcbe0, num[0] add is ffffcbe0, num[0][0] add is ffffcbe0
return 0;
}
此时可以定义一个指针数组与二维数组进行一一对应:
注意num和num[0]虽然地址相同,但是类型不同,num是 int (*)[2]类型,而num[0]是int *类型,不同类型表示指向的内存大小和对内存的取址方式不同,例如num[0]是int *类型,num[0]是没法取值到num[1]所指向的内存范围的,而num是可以的。
如果int *p=num[0],是没有方法通过p获取到num[1]的。
而下面的方法是可以通过p获取到num[1]的,即*(p+1)。
int main()
{
char *res;
int num[9][2]={{0,0},{1,1},{2,0},{1,0},{1,2},{2,1},{0,1},{0,2},{2,2}};
int movesSize = 9;
int size[9]={2,2,2,2,2,2,2,2,2};
int ** moves;
int (* p)[2];
p = num;
//p = num[0] warning: assignment to ‘int (*)[2]’ from incompatible pointer type ‘int *’ [-Wincompatible-pointer-types]
printf("*(p+0) is %xn",*(p+0)); // *(p+0) is ffffcbd0
printf("*(p+8)[0] is %xn",*(p+8)[0]); // *(p+8)[0] is 2
return 0;
}
如果要使用二级指针,就需要对多个一级指针进行一一赋值:
int main()
{
char *res;
int num[9][2]={{0,0},{1,1},{2,0},{1,0},{1,2},{2,1},{0,1},{0,2},{2,2}};
int movesSize = 9;
int size[9]={2,2,2,2,2,2,2,2,2};
int ** moves;
moves = (int **)malloc(movesSize*sizeof(int *));
int i;
for(i=0;i
对应关系如下图:
最后附上所有题解代码:
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#define MAX 5
char res[4][10]={"A","B","Draw","Pending"};
//num=[0,0] in A=[[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]] or not
int inOrNot(int *num, int **A, int Asize){
int i;
for(i=0;i{0,0},{1,1},{2,2},{2,0},{0,2}};
if(inOrNot(num[0],A,a)==1 && inOrNot(num[1],A,a)==1 && inOrNot(num[2],A,a)==1)
{
free(A);
free(B);
return res[0];
}
if(inOrNot(num[3],A,a)==1 && inOrNot(num[4],A,a)==1 && inOrNot(num[1],A,a)==1)
{
free(A);
free(B);
return res[0];
}
if(countNum(0,A0,a)==3 || countNum(1,A0,a)==3 || countNum(2,A0,a)==3)
{
free(A);
free(B);
return res[0];
}
if(countNum(0,A1,a)==3 || countNum(1,A1,a)==3 || countNum(2,A1,a)==3)
{
free(A);
free(B);
return res[0];
}
if(b<3)
{
free(A);
free(B);
return res[3];
}
if(inOrNot(num[0],B,b)==1 && inOrNot(num[1],B,b)==1 && inOrNot(num[2],B,b)==1)
{
free(A);
free(B);
return res[1];
}
if(inOrNot(num[3],B,b)==1 && inOrNot(num[4],B,b)==1 && inOrNot(num[1],B,b)==1)
{
free(A);
free(B);
return res[1];
}
if(countNum(0,B0,b)==3 || countNum(1,B0,b)==3 || countNum(2,B0,b)==3)
{
free(A);
free(B);
return res[1];
}
if(countNum(0,B1,b)==3 || countNum(1,B1,b)==3 || countNum(2,B1,b)==3)
{
free(A);
free(B);
return res[1];
}
if(movesSize>=9)
{
free(A);
free(B);
return res[2];
}
free(A);
free(B);
return res[3];
}
//测试函数
int main()
{
char *res;
int num[9][2]={{0,0},{1,1},{2,0},{1,0},{1,2},{2,1},{0,1},{0,2},{2,2}};
int movesSize = 9;
int size[9]={2,2,2,2,2,2,2,2,2};
int ** moves;
moves = (int **)malloc(movesSize*sizeof(int *));
int i;
for(i=0;i



