ANSI C使用2dim数组通过指针

时间:2016-01-27 09:14:12

标签: c arrays pointers multidimensional-array

很久很久以前我和C玩了很多但忘记了一切。现在我正在努力解决简单的任务并失败。

我想编写一个带2dim数组或char*的函数并打印出来。但我的代码是错误的,我不明白为什么。据我所知,products是指向2dim数组的指针,所以将它增加到i * sizeof(char**)我得到指向子数组的指针,并且增加该子数组指针我得到指向char块的指针。但似乎我的代码寻找不同的内存块。

关于products数组 - 我知道它有N行和2列。

#include <stdio.h>
#include <string.h>

void print(char*** products, size_t rows, size_t cols) {
    size_t i;

    for(i = 0; i < rows; i++) {
        printf("Col1: '%s. Col2: %s'\n",
            (products + i * sizeof(char**)),
            (products + i * sizeof(char**) + sizeof(char*))
        );
    }
}

int main(void) {
    const char* a[][3] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
    print((char***)a, 3, 2);

    return 0;
}

4 个答案:

答案 0 :(得分:3)

此声明中定义的数组

const char* a[][3] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};

的类型为const char *[3][3]

考虑到数组有三个“列”,在数组声明中明确指定了3列。

const char* a[][3] =....
               ^^^

最后一列中的元素由NULL初始化。

当在表达式中使用数组时,例如作为参数,它被显式转换为指向其第一个元素的指针。

即如果您使用上面显示的数组作为参数,那么它将转换为类型

const char * ( * )[3]

它与char ***

的类型不同

因此该函数应该声明为

void print( const char * ( *products )[3], size_t rows );

或喜欢

void print( const char * products[][3], size_t rows );

并且应该像

一样调用该函数
print( a, 3 );

您可以再指定一个参数来设置您想要输出的列数

void print( const char * ( *products )[3], size_t rows, size_t cols );

在这种情况下,可以像

一样调用该函数
print( a, 3, 2 );

然而,阵列本身在任何情况下都有3列。:)

或者编译器是否支持像

这样的可变长度数组
void print( size_t rows, size_t cols, const char * ( *products )[cols] );

或为了便于阅读

void print( size_t rows, size_t cols, const char * products[rows][cols] );

可以像

一样调用
print( 3, 3, a );

这是一个演示程序,它显示了函数声明的两种方法

#include <stdio.h>
#include <string.h>

#define N 3

void print1( const char *product[][N], size_t rows )
{

    for ( size_t i = 0; i < rows; i++ ) 
    {
        for ( const char **p = product[i]; *p; ++p )
        {
            printf( "%s ", *p );
        }
        printf( "\n" );
    }
}    

void print2( size_t rows, size_t cols, const char *product[rows][cols] )
{

    for ( size_t i = 0; i < rows; i++ ) 
    {
        for ( const char **p = product[i]; *p; ++p )
        {
            printf( "%s ", *p );
        }
        printf( "\n" );
    }
}    


int main( void )
{
    const char * a[][N] = 
    {
        { "abc", "1" }, 
        { "def", "2" }, 
        { "ghi", "3" }
    };

    print1( a, N );
    printf( "\n" );

    size_t n = N;

    const char * b[n][n];

    memcpy( b, a, sizeof( a ) );

    print2( n, n, b );
    printf( "\n" );
}    

它的输出是

abc 1 
def 2 
ghi 3 

abc 1 
def 2 
ghi 3 

考虑到编译器支持的可变长度数组可能无法初始化,然后定义它们。

答案 1 :(得分:1)

  

const char* a[][3] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};

在这种情况下,您实际上可以写:

const char* a[][2] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};

但是如果你真的想要一个3列数组,你应该告诉print有3列,而不是2.但是你的打印只能打印两个第一列...

然后,T的任何N维数组都可以被视为T的简单一维数组。您只需进行一些地址计算即可访问所需的元素。一旦你有一个指向数组的第一项的指针,这是可能的。以下是工作版本:

#include <stdio.h>
#include <string.h>

typedef const char * T;

void print(T *products, size_t rows, size_t cols) {
    size_t i;

    for (i = 0; i < rows; i++) {
        // Each row has cols items so here is the current row (i-th row):
        T *row = products + i * cols;
        printf("{%s, %s}\n", row[0], row[1]);
    }
}

int main(void) {
    T a[][3] = { { "abc", "1" }, { "def", "2" }, { "ghi", "3" } };

    // Tell print that there are 3 cols, not 2
    print(&a[0][0], 3, 3);

    return 0;
}

答案 2 :(得分:1)

你混淆了你认为的列和行。解决这个问题,然后摆脱三星级的废话,让函数接受可变数量的列,你最终得到这个:

#include <stdio.h>

void print(size_t rows, size_t cols, const char* products[rows][cols]) 
{
  for(size_t r=0; r<rows; r++) 
  {
    for(size_t c=0; c<cols; c++)
    {
      printf("Col%zu: %s. ", c, products[r][c]);
    }
    printf("\n");
  }
}

int main (void) 
{
  const char* a[3][2] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
  print(3, 2, a);

  return 0;
}

就是这样,不需要再复杂化了。

答案 3 :(得分:0)

也许,这就是你想要的,这更自然!

#include <stdio.h>
#include <string.h>

void print(void *_products, size_t rows, size_t cols) {
    const char* (*products)[cols] = _products;
    size_t i;

    for (i = 0; i < rows; i++) {
        printf("Col1: %s. Col2: %s\n", products[i][0], products[i][1]);
    }
}

int main(void) {
    const char* a[][2] = {{"abc", "1"}, {"def", "2"}, {"ghi", "3"}};
    print(a, 3, 2);

    return 0;
}