C语言 函数存在数组类型输出时的写法引发的问题

161 阅读3分钟

问题背景:

某函数如果想要输出多个数据的时候,通常我会想到用指针传参,然后利用指针修改指针指向的空间的内容,从而突破函数只有一个返回值的限制,例如:

int myFunc(int inNum1, int inNum2, int* outNum1, int* outNum2){

if(outNum1 == NULL || outNum2 == NULL)
    return -1;
    
*outNum1 = inNum1+inNum2;
*outNum2 = inNum1-inNum2;

return 0;

}

上面函数的功能是提供两个整数,并存在两个输出,输出1的结果是输入的两个整数的和,另一个是差。 函数外部的使用方法是:

  • int err = 0;
  • int a = 0,b = 0;
  • err = myFunc(1,2,&a,&b);

但是我发现当处理数组型的输出时,这个方法会出问题,例如:

int myDotf2(float* inArr1, int x1, int y1, float* inArr2, int x2, int y2, float* outArr, int *outX, int *outY) {

int arrType_inArr1[2] = { x1,y1 };
int posIndex_inArr1[2] = { 0 };
int arrType_inArr2[2] = { x2,y2 };
int posIndex_inArr2[2] = { 0 };
int arrType_outArr[2] = { 0 };
int posIndex_outArr[2] = { 0 };

if (y1 != x2) {
	printf("矩阵1和2的行列长度不合法\n");
	return -1;
}
*outX = x1;
*outY = y2;
    
    if(outArr != NULL){
        free(outArr);
    }
outArr = (float*)malloc(sizeof(float) * (*outX) * (*outY));
if (outArr == NULL)
	return -2;
memset(outArr,0, sizeof(float) * (*outX) * (*outY));
arrType_outArr[0] = *outX;	arrType_outArr[1] = *outY;

//计算

for (int i = 0; i < x1; i++) {
	for (int j = 0; j < y2; j++) {
		posIndex_outArr[0] = i;	posIndex_outArr[1] = j;
		for (int k = 0;k< y1; k++) {
			posIndex_inArr1[0] = i;	posIndex_inArr1[1] = k;
			posIndex_inArr2[0] = k;	posIndex_inArr2[1] = j;

			outArr[getIndexOfArr(arrType_outArr,2, posIndex_outArr)] += inArr1[getIndexOfArr(arrType_inArr1, 2, posIndex_inArr1)] * inArr2[getIndexOfArr(arrType_inArr2, 2, posIndex_inArr2)];
			//outArr[i][j] += inArr1[j][k]*inArr2[k][j];
		}
	}
}
return 0;

}

上面的函数是在做一个二维矩阵乘法函数,请忽略内部奇怪的索引表示法,在此不细说,有兴趣可见另一篇文章。 这个函数存在多个输入和多个输出,输入包括不定长二维矩阵inArr1和不定长二维矩阵inArr2,以及他们的各维度长度。输出包括一个二维矩阵及它的各维度长度,也就是三个输出。 按照最初的想法,传入的是一个数组头,也就是一个指针变量,我在函数内部为他malloc一段内存,并进行计算赋值,且不free,按我的想法它应该不会被释放,且因操作的是指针(也就是内存地址),所以应该能正常修改值,和一般的int型指针同理。但是事实并非如此。

问题现象:

问题的现象是我在外部传入的对应指针一直是NULL,或者说我在外边怎么初始化的,该函数执行结束后,它还是什么样,不变,也就是函数并没有给它成功的赋值。相反,另两个int型的输出被正确的赋值了。

解决方法:

将数组类型的输出由指针参数的形式换成返回值形式,问题得以解决。如下:

float* myDotf2(float* inArr1, int x1, int y1, float* inArr2, int x2, int y2, int *outX, int *outY) {

int arrType_inArr1[2] = { x1,y1 };
int posIndex_inArr1[2] = { 0 };
int arrType_inArr2[2] = { x2,y2 };
int posIndex_inArr2[2] = { 0 };
int arrType_outArr[2] = { 0 };
int posIndex_outArr[2] = { 0 };
float* outArr = NULL;

if (y1 != x2) {
	printf("矩阵1和2的行列长度不合法\n");
	return NULL;
}
*outX = x1;
*outY = y2;
outArr = (float*)malloc(sizeof(float) * (*outX) * (*outY));
if (outArr == NULL)
	return NULL;
memset(outArr,0, sizeof(float) * (*outX) * (*outY));
arrType_outArr[0] = *outX;	arrType_outArr[1] = *outY;

//计算

for (int i = 0; i < x1; i++) {
	for (int j = 0; j < y2; j++) {
		posIndex_outArr[0] = i;	posIndex_outArr[1] = j;
		for (int k = 0;k< y1; k++) {
			posIndex_inArr1[0] = i;	posIndex_inArr1[1] = k;
			posIndex_inArr2[0] = k;	posIndex_inArr2[1] = j;

			outArr[getIndexOfArr(arrType_outArr,2, posIndex_outArr)] += inArr1[getIndexOfArr(arrType_inArr1, 2, posIndex_inArr1)] * inArr2[getIndexOfArr(arrType_inArr2, 2, posIndex_inArr2)];
			//outArr[i][j] += inArr1[j][k]*inArr2[k][j];
		}
	}
}
return outArr;

}