C语言中的三重指针:这是样式问题吗? [英] Triple pointers in C: is it a matter of style?

查看:563
本文介绍了C语言中的三重指针:这是样式问题吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得C中的三重指针被视为错误".对我来说,有时使用它们是很有意义的.

I feel like triple pointers in C are looked at as "bad". For me, it makes sense to use them at times.

从基础开始,单个指针具有两个目的:创建数组,并允许函数更改其内容(通过引用传递):

Starting from the basics, the single pointer has two purposes: to create an array, and to allow a function to change its contents (pass by reference):

char *a;
a = malloc...

void foo (char *c); //means I'm going to modify the parameter in foo.
{ *c = 'f'; }

char a;
foo(&a);

双指针可以是2D数组(或数组的数组,因为每个列"或行"的长度不必相同).我个人喜欢在需要传递一维数组时使用它:

The double pointer can be a 2D array (or array of arrays, since each "column" or "row" need not be the same length). I personally like to use it when I need to pass a 1D array:

void foo (char **c); //means I'm going to modify the elements of an array in foo.
{ (*c)[0] = 'f'; }

char *a;
a = malloc...
foo(&a);

对我来说,这有助于描述foo在做什么.但是,没有必要:

To me, that helps describe what foo is doing. However, it is not necessary:

void foo (char *c); //am I modifying a char or just passing a char array?
{ c[0] = 'f'; }

char *a;
a = malloc...
foo(a);

也可以.

根据对此问题的第一个答案,如果foo修改了数组的大小,将需要一个双指针.

According to the first answer to this question, if foo were to modify the size of the array, a double pointer would be required.

一个人可以清楚地看到将需要一个三重指针(甚至更多).就我而言,如果我要传递一个指针数组(或数组数组),我会使用它.显然,如果要传递的函数正在更改多维数组的大小,则需要这样做.当然,由数组组成的数组不是很常见,但其他情况很常见.

One can clearly see how a triple pointer (and beyond, really) would be required. In my case if I were passing an array of pointers (or array of arrays), I would use it. Evidently it would be required if you are passing into a function that is changing the size of the multi-dimensional array. Certainly an array of arrays of arrays is not too common, but the other cases are.

那么那里有哪些约定?这是否真的只是样式/可读性的问题,再加上许多人都很难将头缠绕在指针上?

So what are some of the conventions out there? Is this really just a question of style/readability combined with the fact that many people have a hard time wrapping their heads around pointers?

推荐答案

使用Triple +指针会损害可读性和可维护性.

Using triple+ pointers is harming both readability and maintainability.

假设您在此处有一个小函数声明:

Let's suppose you have a little function declaration here:

void fun(int***);

嗯.参数是三维锯齿形数组,还是指向二维锯齿形数组的指针,还是指向数组的指针(例如,函数在函数内分配数组并在int指针)

Hmmm. Is the argument a three-dimensional jagged array, or pointer to two-dimensional jagged array, or pointer to pointer to array (as in, function allocates an array and assigns a pointer to int within a function)

让我们将其与:

void fun(IntMatrix*);

当然,您可以使用三重指针对int进行运算以处理矩阵. 但这不是他们.在此处将它们实现为三重指针的事实与用户不相关.

Surely you can use triple pointers to int to operate on matrices. But that's not what they are. The fact that they're implemented here as triple pointers is irrelevant to the user.

复杂的数据结构应封装.这是面向对象编程的明显思想之一.即使在C语言中,您也可以在一定程度上应用此原理.将数据结构包装在struct中(或者在C语言中很常见,使用"handles",即指向不完整类型的指针-该惯用法将在后面的答案中进行解释).

Complicated data structures should be encapsulated. This is one of manifest ideas of Object Oriented Programming. Even in C, you can apply this principle to some extent. Wrap the data structure in a struct (or, very common in C, using "handles", that is, pointers to incomplete type - this idiom will be explained later in the answer).

让我们假设您将矩阵实现为double的锯齿状数组.与连续的2D数组相比,它们在遍历它们时会更糟(因为它们不属于单个连续的内存块),但允许使用数组表示法进行访问,并且每行的大小可以不同.

Let's suppose that you implemented the matrices as jagged arrays of double. Compared to contiguous 2D arrays, they are worse when iterating over them (as they don't belong to a single block of contiguous memory) but allow for accessing with array notation and each row can have different size.

所以现在的问题是,由于指针的使用已硬连接到用户代码上,因此您现在不能更改表示形式,而现在您只能执行较差的实现.

So now the problem is you can't change representations now, as the usage of pointers is hard-wired over user code, and now you're stuck with inferior implementation.

如果将其封装在结构中,这甚至不是问题.

This wouldn't be even a problem if you encapsulated it in a struct.

typedef struct Matrix_
{
    double** data;
} Matrix;

double get_element(Matrix* m, int i, int j)
{
    return m->data[i][j];
}

只需更改为

typedef struct Matrix_
{
    int width;
    double data[]; //C99 flexible array member
} Matrix;

double get_element(Matrix* m, int i, int j)
{
    return m->data[i*m->width+j];
}

句柄技术的工作方式如下:在头文件中,您声明一个不完整的struct以及在指向该struct的指针上起作用的所有函数:

The handle technique works like this: in the header file, you declare a incomplete struct and all the functions that work on the pointer to the struct:

// struct declaration with no body. 
struct Matrix_;
// optional: allow people to declare the matrix with Matrix* instead of struct Matrix*
typedef struct Matrix_ Matrix;

Matrix* create_matrix(int w, int h);
void destroy_matrix(Matrix* m);
double get_element(Matrix* m, int i, int j);
double set_element(Matrix* m, double value, int i, int j);

在源文件中,声明实际的结构并定义所有功能:

in the source file you declare the actual struct and define all the functions:

typedef struct Matrix_
{
    int width;
    double data[]; //C99 flexible array member
} Matrix;

double get_element(Matrix* m, int i, int j)
{
    return m->data[i*m->width+j];
}

/* definition of the rest of the functions */

世界其他地方不知道struct Matrix_包含什么内容,也不知道它的大小.这意味着用户不能直接声明值,而只能使用指向Matrixcreate_matrix函数的指针.但是,用户不知道大小这一事实意味着用户不依赖于大小-这意味着我们可以随意删除成员或将成员添加到struct Matrix_.

The rest of the world doesn't know what does the struct Matrix_ contain and it doesn't know the size of it. This means users can't declare the values directly, but only by using pointer to Matrix and the create_matrix function. However, the fact that the user doesn't know the size means the user doesn't depend on it - which means we can remove or add members to struct Matrix_ at will.

这篇关于C语言中的三重指针:这是样式问题吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆