传递多个维阵列C中的函数 [英] Pass multiple-dimensional array to a function in C
问题描述
我有这样的功能:
无效MYFUNC(INT **改编,诠释N){
INT I,J;
对于(i = 0; I< N ++我){
为(J = 0; J< N ++ j)条{
的printf(%d个,*(ARR + I * N + J)); //用逗号打印号码
}
的printf(\\ n); //只是断裂线
}
}
在其他功能我有一个二维数组是这样的:
INT的main(){
INT seqs [8] [8] = {
{0,32,36,52,48,16,20,4},
{0,16,20,52,48,32,36,4},
{0,32,36,44,40,8,12,4},
{0,8,12,44,40,32,36,4},
{0,32,36,38,34,2,6,4},
{0,2,6,38,34,32,36,4},
{0,32,36,37,33,1,5,4},
{0,1,5,37,33,32,36,4}
}; //调用到MYFUNC
MYFUNC(seqs,8); //这是观念
}
但是编译器把我这个错误:
lab.c:在函数'主':
lab.c:75:5:警告:传递从兼容的指针类型'MYFUNC'的参数1 [默认启用]
lab.c:4:6:注:应为** INT,但参数的类型为INT(*)[8]
什么是传递这个数组以正确的方式( seqs
)的功能( MYFUNC
)?
在C99或C11,你会做这样的:
无效MYFUNC(INT N,INT ARR [N] [N])
{
的for(int i = 0; I< N ++ I)
{
对于(INT J = 0; J< N ++ j)条
的printf(%d个,编曲[I] [J]);
的printf(\\ n);
}
}
请注意,这个大小precedes,不遵循,数组。此功能将与正常工作:
INT主要(无效)
{
INT seqs [8] [8] =
{
{0,32,36,52,48,16,20,4},
{0,16,20,52,48,32,36,4},
{0,32,36,44,40,8,12,4},
{0,8,12,44,40,32,36,4},
{0,32,36,38,34,2,6,4},
{0,2,6,38,34,32,36,4},
{0,32,36,37,33,1,5,4},
{0,1,5,37,33,32,36,4},
};
MYFUNC(8,seqs); INT MATRIX3X3 [3] [3] = {{1,2,3},{2,4,6},{3,6,9}};
MYFUNC(3 MATRIX3X3);
}
有人问我:
您例子并看起来好多了确实,但它明确定义?为
N
确实保证前INT ARR进行评估[N] [N]
?不会的功能参数计算顺序是不确定的行为?
块引用>旧标准(ISO / IEC 9899:1999)说,在§6.7.5.2*的数组声明的*:
¶5的如果大小是前pression不是整型常量前pression:如果在它发生
声明在函数原型范围,如果它是由替换*
将被处理;除此以外,
每次评价时,应当有一个大于零的值。每个实例的大小
可变长度数组类型的在其寿命期间不会改变。凡大小
前pression是的sizeof
运算符的操作数的一部分,并且不断变化的价值
大小当然pression不会影响操作的结果,它是未指定是否
规模前pression进行了评价。的
块引用>和它提供了一个例子(这是不规范的文本,因为它是一个例子,但强烈表示期望是什么):
例4动态可变(VM)类型的所有声明都必须在任块范围或
函数原型范围。与静态声明数组对象
或的extern
存储类说明
不能有一个可变长度数组(VLA)型。然而,随着静态声明的对象
存储类
符可以具有一个虚拟机的类型(即,一个指向VLA类型)。最后,所有标识与申报
VM类型必须是普通的标识符,并且不能,因此,是结构或联合的成员。的extern INT N;
int类型的[N]; //无效:文件范围VLA
EXTERN INT(* P2)[N]; //无效:文件范围内的VM
INT B〔100〕; //有效:文件范围内,但不是VM
无效fvla(INT男,INT C [M] [M]); //有效:VLA与原型范围
无效fvla(INT男,INT C [M] [M]。)//有效:调整自动指向VLA
{
的typedef诠释VLA [M] [M]; //有效:块范围的typedef VLA
结构标记{
INT(* Y)[N]; //无效:Y不是普通的标识符
诠释Z [N]; //无效:Z不是普通的标识符
};
INT D [M]; //有效:汽车VLA
静态INT E [M]; //无效:静态块范围VLA
EXTERN INT F [M]; //无效:F有挂钩,VLA
INT(* S)[M]。 //有效:自动指向VLA
EXTERN INT(* R)[M]。 //无效:r的联动点VLA
静态INT(* Q)[M] =和B; //有效:q是一个静态块指针VLA
}
块引用>有显示动态可变功能参数的其他例子。
此外,在§6.9.10函数定义,它说:
¶10进入时的功能,每一个可变地修改的参数的大小前pressions是
评估和每个参数的前pression的值转换为的类型
相应的参数仿佛被分配。 (阵列前pressions和功能
代号为参数转换为调用之前的指针。)
块引用>I have a function like this:
void myfunc(int** arr, int n) { int i, j; for(i=0; i<n; ++i) { for(j=0; j<n; ++j) { printf("%d,", *(arr + i*n + j) ); // Print numbers with commas } printf("\n"); // Just breakline } }
in other function I have an two-dimensional array like this:
int main() { int seqs[8][8] = { {0, 32, 36, 52, 48, 16, 20, 4}, {0, 16, 20, 52, 48, 32, 36, 4}, {0, 32, 36, 44, 40, 8, 12, 4}, {0, 8, 12, 44, 40, 32, 36, 4}, {0, 32, 36, 38, 34, 2, 6, 4}, {0, 2, 6, 38, 34, 32, 36, 4}, {0, 32, 36, 37, 33, 1, 5, 4}, {0, 1, 5, 37, 33, 32, 36, 4} }; // Call to myfunc myfunc(seqs, 8); // This is the idea }
But compiler throw me this error:
lab.c: In function 'main': lab.c:75:5: warning: passing argument 1 of 'myfunc' from incompatible pointer type [enabled by default] lab.c:4:6: note: expected 'int **' but argument is of type 'int (*)[8]'
What is the right way to pass this array (
seqs
) to function (myfunc
)?解决方案In C99 or C11, you would do it like this:
void myfunc(int n, int arr[n][n]) { for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) printf("%d,", arr[i][j]); printf("\n"); } }
Note that the size precedes, not follows, the array. This function will work correctly with:
int main(void) { int seqs[8][8] = { { 0, 32, 36, 52, 48, 16, 20, 4 }, { 0, 16, 20, 52, 48, 32, 36, 4 }, { 0, 32, 36, 44, 40, 8, 12, 4 }, { 0, 8, 12, 44, 40, 32, 36, 4 }, { 0, 32, 36, 38, 34, 2, 6, 4 }, { 0, 2, 6, 38, 34, 32, 36, 4 }, { 0, 32, 36, 37, 33, 1, 5, 4 }, { 0, 1, 5, 37, 33, 32, 36, 4 }, }; myfunc(8, seqs); int matrix3x3[3][3] = { { 1, 2, 3 }, { 2, 4, 6 }, { 3, 6, 9 } }; myfunc(3, matrix3x3); }
I was asked:
Your example does look much better indeed, but is it well-defined? Is
n
really guaranteed to be evaluated beforeint arr[n][n]
? Wouldn't the order of evaluation of function parameters be unspecified behavior?The old standard (ISO/IEC 9899:1999) says in §6.7.5.2*Array declarators*:
¶5 If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by
*
; otherwise, each time it is evaluated it shall have a value greater than zero. The size of each instance of a variable length array type does not change during its lifetime. Where a size expression is part of the operand of asizeof
operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated.And it gives an example (it is non-normative text because it is an example, but strongly indicative of what is expected):
EXAMPLE 4 All declarations of variably modified (VM) types have to be at either block scope or function prototype scope. Array objects declared with the
static
orextern
storage-class specifier cannot have a variable length array (VLA) type. However, an object declared with thestatic
storage class specifier can have a VM type (that is, a pointer to a VLA type). Finally, all identifiers declared with a VM type have to be ordinary identifiers and cannot, therefore, be members of structures or unions.extern int n; int A[n]; // invalid: file scope VLA extern int (*p2)[n]; // invalid: file scope VM int B[100]; // valid: file scope but not VM void fvla(int m, int C[m][m]); // valid: VLA with prototype scope void fvla(int m, int C[m][m]) // valid: adjusted to auto pointer to VLA { typedef int VLA[m][m]; // valid: block scope typedef VLA struct tag { int (*y)[n]; // invalid: y not ordinary identifier int z[n]; // invalid: z not ordinary identifier }; int D[m]; // valid: auto VLA static int E[m]; // invalid: static block scope VLA extern int F[m]; // invalid: F has linkage and is VLA int (*s)[m]; // valid: auto pointer to VLA extern int (*r)[m]; // invalid: r has linkage and points to VLA static int (*q)[m] = &B; // valid: q is a static block pointer to VLA }
There are other examples showing variably modified function parameters.
Also, in §6.9.10 Function definitions, it says:
¶10 On entry to the function, the size expressions of each variably modified parameter are evaluated and the value of each argument expression is converted to the type of the corresponding parameter as if by assignment. (Array expressions and function designators as arguments were converted to pointers before the call.)
这篇关于传递多个维阵列C中的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!