2017-03-31 183 views
1

我正在学习C,因为我被卡在指针章节。附属于指针(** p)部分的指针,用于处理2维数组。C指针指针数组

以下函数生成一个2维的阵列,其所有元素都等于0。

double** example(int rows, int cols){ 
    static double tr[rows][cols]; 
    for(int i = 0; i < rows; i++) 
     for(int j = 0; j < cols; j++) 
      tr[j][i] = 0; 
    return tr; 
    } 
int main(void){ 

    double **tr; 
    int m = 2 ; 
    int n = 2 ; 

    tr = transpose(m, n); 
    return 0;} 

是对tr通过的功能的“双指针” tr阵列的第一个元素返回?还是它的价值?此外,现在(函数调用后)如何在** tr指向的内存部分访问数组的元素?

有人可以解释我是如何工作的?或者给我一本书中的文章或章节呢?

+0

'example'返回一个双指向第一个元素的指针。你可以用同样的方式访问它的元素,即'tr [0] [1]'< - 行0,列1。 – Geoff

+0

扔掉这本书,它教你*垃圾*。请参阅下面的Vlad的答案。 'double **'不是*返回二维数组的正确类型。 –

回答

2

提交的程序完全不正确。可变长度阵列可以不具有静态存储持续时间/按照C标准(6.7.6.2组声明)

2如果identi音响ER被声明为具有可变MODI音响版型,它 应是一个普通的identi音响ER(如6.2.3所定义的)不具有链接, 并且具有块范围或函数原型范围。 如果一个 标识符声明为静态或线程存储的持续时间为 的对象,则它不应具有可变长度的数组类型。

此外double **double (*)[cols](这是该阵列,只要它被宣布正确转换表达式)的指针类型不兼容。所以这个功能是错误的。

double** example(int rows, int cols){ 
    static double tr[rows][cols]; 
    for(int i = 0; i < rows; i++) 
     for(int j = 0; j < cols; j++) 
      tr[j][i] = 0; 
    return tr; 
    } 

这是一个演示程序,展示了如何处理变长数组。

#include <stdio.h> 

void init(size_t rows, size_t cols, double a[rows][cols]) 
// or 
// void init(size_t rows, size_t cols, double a[][cols]) 
// or 
// void init(size_t rows, size_t cols, double (*a)[cols]) 
{ 
    for (size_t i = 0; i < rows; i++) 
    { 
     for (size_t j = 0; j < cols; j++) a[i][j] = 0.0; 
    } 
} 

void display(size_t rows, size_t cols, double a[rows][cols]) 
// or 
// void display(size_t rows, size_t cols, double a[][cols]) 
// or 
// void display(size_t rows, size_t cols, double (*a)[cols]) 
{ 
    for (size_t i = 0; i < rows; i++) 
    { 
     for (size_t j = 0; j < cols; j++) printf("%lf", a[i][j]); 
     putchar('\n'); 
    } 
} 

int main(void) 
{ 
    while (1) 
    { 
     size_t m, n; 

     printf("Enter numbers of rows and columns (0 - exit): "); 

     if (scanf("%zu%zu", &m, &n) != 2 || m == 0 || n == 0) break; 

     double a[m][n]; 

     putchar('\n'); 

     init(m, n, a); 
     display(m, n, a); 

     putchar('\n'); 
    } 

    return 0; 
} 

它的输出可能看起来像

Enter numbers of rows and columns (0 - exit): 2 3 

0.0000000.0000000.000000 
0.0000000.0000000.000000 

Enter numbers of rows and columns (0 - exit): 3 4 

0.0000000.0000000.0000000.000000 
0.0000000.0000000.0000000.000000 
0.0000000.0000000.0000000.000000 

Enter numbers of rows and columns (0 - exit): 0 0 

两个函数的第三个参数调整为指针类型double (*a)[cols]内。它与double **a不一样。

如果将例如因为p[0]认为a[0][1]取决于存储在元素a[0][0]的值(或者存储在元件组合的值a[0][0]和编写以下程序

#include <stdio.h> 

#define M 2 
#define N 3 

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

    int **p = (int **)a; 

    p[0][0] = 10; 

    return 0; 
} 

那么它将有不确定的操作指针大小),即值1作为指针值,并尝试访问表达式p[0][0]中地址1处的内存。

2

在C中,函数将不得不返回与该函数相同类型的值/变量。在这个例子中,tr是一个双指针,它指向第一行。

使用双指针创建二维数组时,实际上是创建一个指向指向数组的指针,数组中的指针指向存储在每行中的字符串/值。双指针将指向指针数组中的第一个指针,它将指向第一行中的第一个元素。

您可以使用括号表示法(如 tr[row][column]*(*(tr + row) + column))访问二维数组中的值。对于第二种表示法,*(tr + row)将访问指向所需行的指针,然后您可以使用*(found_row + column)引用该值,从而为您提供所需列中的元素。

+0

问题是'tr'的类型是* not *'double **',它是'double(*)[cols]'。 –

0

丢掉包含此代码的书 - 它甚至没有正确编译编译。我收到以下错误:

[[email protected]]~/prototypes/buf: gcc -o stack -std=c99 -pedantic-errors -Wall stack.c 
stack.c: In function âexampleâ: 
stack.c:2: error: storage size of âtrâ isnât constant 
stack.c:6: error: return from incompatible pointer type 

您不能创建static存储持续时间变长数组。具有static存储持续时间的对象在程序启动时被分配,所以它们的大小在编译时需要知道。 VLA只有在运行时知道其尺寸的大小后才能实例化。

除了当它是sizeof或一元&运营商的操作数,或是使用在声明初始化字符数组文本字符串,类型“的T N元件阵列”的表达将被转换(“衰减”)转换为类型为“指向T的指针”的表达式,并且表达式的值将是该数组的第一个元素的地址。

表达tr的类型为 “colsdouble - 元素阵列的rows - 元素阵列”;在return语句中,此表达式将“衰减”以键入“指向cols - 元素数组double”或double (*)[cols]。这是一个完全不同的类型double **

多重间接显示了很多,但这不是一个有效的例子。

通常,你会看到多个间接当你想要一个函数写指针类型的参数:

void bar(T **p) // for any type T 
{ 
    *p = new_pointer_value(); // write a new value to the thing p points to 
} 

void foo(void) 
{ 
    T *ptr; 

    bar(&ptr); // bar writes a value to ptr 
} 

您可以使用多个间接创建胜负的外观和行为像一个2D的结构数组,但它是不一样的事,作为一个二维数组:

double **arr; 
size_t rows = some_number_of_rows(); 
size_t cols = sime_number_of_cols(); 

arr = malloc(sizeof *arr * rows); // allocates an array of pointers to double 
if (arr) 
{ 
    for (size_t i = 0; i < rows; i++) 
    { 
    arr[i] = malloc(sizeof *arr[i] * cols); // allocates an array of double 
    } 
} 

当你做,你有一个看起来像这样的结构:

+---+  +---+  +---+---+---+  +---+ 
a: | | ---> | | ---> | | | | ... | | 
    +---+  +---+  +---+---+---+  +---+ 
       | | -+ 
       +---+ | +---+---+---+  +---+ 
       ... +-> | | | | ... | | 
       +---+  +---+---+---+  +---+ 
       | | -+ 
       +---+ | +---+---+---+  +---+ 
         +-> | | | | ... | | 
          +---+---+---+  +---+ 

可以访问使用常规下标符号(a[i][j])等的2D阵列元件,但在本结构中的存储器是不是连续地分配像这将是用于2D阵列:

+---+---+---+---+---+ 
a: | | | | | | 
    +---+---+---+---+---+ 
    | | | | | | 
    +---+---+---+---+---+ 
    | | | | | | 
    +---+---+---+---+---+ 
    ...