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

查看:39
本文介绍了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);

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

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?

推荐答案

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

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 中,您也可以在某种程度上应用此原则.将数据结构包装在一个结构体中(或者,在 C 中很常见,使用句柄",即指向不完整类型的指针 - 这个习语将在后面的答案中解释).

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];
}

句柄技术是这样工作的:在头文件中,你声明了一个不完整的结构体和所有作用于结构体指针的函数:

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_ 包含什么,也不知道它的大小.这意味着用户不能直接声明值,而只能使用指向Matrix 的指针和create_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天全站免登陆