int [] []和int **(noobie)之间有什么区别

时间:2017-03-26 11:20:27

标签: c arrays

例如,我想将一个二维整数数组传递给C中的函数。该函数应该被定义为

java.lang.IllegalStateException: any(CategoriesRepository…riesListener::class.java) must not be null at com.boyukliev.verseattack.ui.categories.CategoriesActivityPresenterTest.shouldPassCategoriesToView2(CategoriesActivityPresenterTest.kt:60) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:68) at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:74) at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39) at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:161) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Misplaced or misused argument matcher detected here: -> at com.boyukliev.verseattack.ui.categories.CategoriesActivityPresenterTest.shouldPassCategoriesToView2(CategoriesActivityPresenterTest.kt:60) You cannot use argument matchers outside of verification or stubbing. Examples of correct usage of argument matchers: when(mock.get(anyInt())).thenReturn(null); doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject()); verify(mock).someMethod(contains("foo")) This message may appear after an NullPointerException if the last matcher is returning an object like any() but the stubbed method signature expect a primitive argument, in this case, use primitive alternatives. when(mock.get(any())); // bad use, will raise NPE when(mock.get(anyInt())); // correct usage use Also, this error might show up because you use argument matchers with methods that cannot be mocked. Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode(). Mocking methods declared on non-public parent classes is not supported. at org.mockito.internal.runners.DefaultInternalRunner$1$1.testFinished(DefaultInternalRunner.java:58) at org.junit.runner.notification.SynchronizedRunListener.testFinished(SynchronizedRunListener.java:56) at org.junit.runner.notification.RunNotifier$7.notifyListener(RunNotifier.java:190) at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:72) at org.junit.runner.notification.RunNotifier.fireTestFinished(RunNotifier.java:187) at org.junit.internal.runners.model.EachTestNotifier.fireTestFinished(EachTestNotifier.java:38) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:331) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:68) at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:74) at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39) at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:161) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117) at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

void foo(int**,int m,int n);

我在第一个原型声明中遇到错误,但在使用GCC进行编译时,我收到一条警告“不兼容的指针类型”。请解释如何传递2D数组。主要方法是给出

void foo(int[][],int m,int n);

3 个答案:

答案 0 :(得分:2)

两个函数声明

void foo(int**,int m,int n);

void foo(int[][],int m,int n);

错了。具有数组类型的参数的声明被调整为指向元素类型的指针。因此,如果您声明参数具有二维数组类型,如此

int a[M][N]

然后将其调整为

int ( *p )[N}

必须为函数定义知道N的值。如果N是一个编译时常量,例如

#define N 10

然后函数声明看起来像

void foo( int[][N], int );

void foo( int[][N], size_t );

其中第二个参数指定"行的数量"。 "列的数量"是众所周知的,因为我说它是一个编译时常量。

如果N是在运行时计算的,并且编译器支持可变长度数组,那么你应该声明像

这样的函数
void foo( int, int, int[*][*] );

或者代替维度类型int,最好使用类型size_t。例如

void foo( size_t, size_t, int[*][*] );

考虑到至少第二个参数必须在数组声明之前,因为它用于确定数组的元素类型(其大小应为函数定义所知)。

对于不是其定义的函数声明,参数名称不是必需的。

这里显示了如何使用可变长度数组表示法声明和定义函数。

#include <stdio.h>

void foo( size_t, size_t, int[*][*] );

void foo( size_t m, size_t n, int a[m][n] )
{
    for ( size_t i = 0; i < m; i++ )
    {
        for ( size_t j = 0; j < n; j++ ) printf( "%d ", a[i][j] );
        putchar( '\n' );
    }
}

#define M   2
#define N   3

int main(void) 
{
    int a[M][N] =
    {
        { 1, 2, 3 },
        { 4, 5, 6 }
    };

    foo( M, N, a );

    size_t m = 3;
    size_t n = 2;

    int b[m][n];

    for ( size_t i = 0; i < M; i++ )
    {
        for ( size_t j = 0; j < N; j++ ) b[j][i] = a[i][j];
    }

    putchar( '\n' );

    foo( m, n, b );

    return 0;
}

程序输出

1 2 3 
4 5 6 

1 4 
2 5 
3 6 

第三个参数也可以声明为

void foo( size_t m, size_t n, int a[][n] )

void foo( size_t m, size_t n, int ( *a )[n] )

因为正如指出的那样,数组被调整为指向其元素类型的指针。

答案 1 :(得分:1)

您的问题中的任何一种形式都不正确;后者,[][]在语法上也是非法的。

您正在使用名为可变长度阵列VLA的C99和C11功能。要正确声明接受VLA的函数,您需要提供维度 first ,然后是实际数组,并在参数中提供维度的参数名称:

void foo(int m, int n, int array[m][n]);

(在声明中但在定义中)也可以使用[*]来指定未指定的维度,但我没有看到太多的意义因为这使得它明确哪个参数对应于哪个维度。

请注意,提供维度的参数(mn)必须在参数列表中数组之前出现。

答案 2 :(得分:0)

在声明变量时,了解内存的布局方式非常重要。

线性/基于堆栈的阵列

以下声明了一个2D数组,'堆栈'上有5x5个元素:

void foo(void) {
    int a[5][5];

    ...
}

内存看起来像这样:

Liner/Stack Array

如果要将此数组传递给函数,那么您将传递第一个元素a[0][0]的地址(如紫色箭头所示)。 当接收函数然后希望访问第二维时,它需要知道' stride ',这是你没有提供void foo(int a[][])原型的东西 - 因此错误。

基于指针/堆的数组

以下将在''上声明相同的5x5 2D数组(可以在堆栈上完成所有操作):

void foo(void) {
    int **a;
    int *a_data;
    int i;

    a_data = malloc(sizeof(*a_data) * (5 * 5);
    a = malloc(sizeof(*a) * 5);

    for (i = 0; i < 5; i++) {
        a[i] = &(a_data[i * 5]);
    }

    ...

    free(a);
    free(a_data);
}

内存看起来像这样:

Pointers/Heap Array

将此函数传递给函数时,会传递“第一维”的地址。由于此处的内存结构不同,我们可以轻松查找维度开头的地址,而“ stride ”现在无关紧要。