C指针:指向固定大小的数组(C pointers : pointing to an array of fixed size)

编程入门 行业动态 更新时间:2024-10-28 06:30:32
C指针:指向固定大小的数组(C pointers : pointing to an array of fixed size)

这个问题出在这里的C大师:

在C中,可以如下声明一个指针:

char (* p)[10];

..它基本上指出这个指针指向一个10个字符的数组。 关于声明这样的指针的整洁的事情是,如果您尝试将不同大小的数组的指针分配给p,那么您将收到编译时错误。 如果您尝试将一个简单的char指针的值分配给p,它也会给您一个编译时错误。 我尝试使用gcc,它似乎与ANSI,C89和C99一起使用。

看起来像我这样声明一个像这样的指针是非常有用的 - 特别是当传递一个指针到一个函数。 通常人们会写这样一个函数的原型:

void foo(char * p, int plen);

如果你期望一个特定大小的缓冲区,那么你只需要测试一下你们的价值。 但是,您不能保证将p传递给您的人将真正给予该缓冲区中有效的内存位置。 你必须相信这个叫做这个功能的人正在做正确的事情。 另一方面:

void foo(char (*p)[10]);

..强制调用者给你一个指定大小的缓冲区。

这似乎非常有用,但是我从来没有看到在任何代码中曾经遇到过这样的指针。

我的问题是:有没有什么理由,人们不会声明这样的指针? 我没有看到一些明显的陷阱吗?

This question goes out to the C gurus out there:

In C, it is possible to declare a pointer as follows:

char (* p)[10];

.. which basically states that this pointer points to an array of 10 chars. The neat thing about declaring a pointer like this is that you will get a compile time error if you try to assign a pointer of an array of different size to p. It will also give you a compile time error if you try to assign the value of a simple char pointer to p. I tried this with gcc and it seems to work with ANSI, C89 and C99.

It looks to me like declaring a pointer like this would be very useful - particularly, when passing a pointer to a function. Usually, people would write the prototype of such a function like this:

void foo(char * p, int plen);

If you were expecting a buffer of an specific size, you would simply test the value of plen. However, you cannot be guaranteed that the person who passes p to you will really give you plen valid memory locations in that buffer. You have to trust that the person who called this function is doing the right thing. On the other hand:

void foo(char (*p)[10]);

..would force the caller to give you a buffer of the specified size.

This seems very useful but I have never seen a pointer declared like this in any code I have ever ran across.

My question is: Is there any reason why people do not declare pointers like this? Am I not seeing some obvious pitfall?

最满意答案

你在发表什么是绝对正确的。 我会说每个C开发人员到达完全一样的发现,并得出完全相同的结论,当(如果)他们达到一定程度的熟练使用C语言。

当您的应用程序区域的细节调用特定固定大小的数组(数组大小是编译时常量)时,将这样的数组传递给函数的唯一正确方法是使用指针到数组参数

void foo(char (*p)[10]);

(在C ++语言中,这也是用引用来完成的

void foo(char (&p)[10]);

)。

这将启用语言级类型检查,这将确保提供正确大小的数组作为参数。 实际上,在许多情况下,人们隐含地使用这种技术,甚至没有意识到这一点,将数组类型隐藏在typedef名称后面

typedef int Vector3d[3]; void transform(Vector3d *vector); /* equivalent to `void transform(int (*vector)[3])` */ ... Vector3d vec; ... transform(&vec);

另外注意上面的代码是与Vector3d类型相关的数组或struct是不变的。 您可以随时将数组的定义从数组切换到struct然后返回,而不用更改函数声明。 在这两种情况下,函数将通过引用接收聚合对象(这里有例外,但是在这个讨论的上下文中,这是真的)。

然而,您不会看到这种数组传递的方法明确地使用,只是因为太多的人被一个相当复杂的语法所困惑,并且对于C语言的这些功能来说恰当地使用它们根本不够舒适。 因此,在平均现实生活中,将数组作为指针传递到其第一个元素是更受欢迎的方法。 它只是看起来“更简单”。

但实际上,使用指向第一个元素进行数组传递的指针是一个非常小巧的技巧,这个技巧是一个非常具体的用途:它的唯一目的是为了方便传递不同大小的数组(即运行时大小) 。 如果您真的需要处理运行时大小的数组,那么传递这样一个数组的正确方式是指向其第一个元素的指针,具体尺寸由附加参数提供

void foo(char p[], unsigned plen);

实际上,在许多情况下,能够处理运行时大小的数组是非常有用的,这也有助于该方法的普及。 许多C开发人员从来没有遇到(或从来不认识)需要处理固定大小的数组,因此仍然不知道适当的固定大小的技术。

然而,如果数组大小是固定的,则将其作为指向元素的指针传递

void foo(char p[])

这是一个主要的技术层面的错误,不幸的是这些日子相当广泛。 在这种情况下,指针对阵列技术是一个更好的方法。

可能阻碍采用固定大小的数组传递技术的另一个原因是动态分配的数组类型的天真方法的主导地位。 例如,如果程序调用类型为char[10]固定数组(如您的示例),则平均开发人员将将这样的数组malloc

char *p = malloc(10 * sizeof *p);

该数组不能传递给声明为的函数

void foo(char (*p)[10]);

这混淆了平均开发人员,使他们放弃了固定大小的参数声明,而没有进一步思考。 实际上,问题的根源在于天真的malloc方法。 上面显示的malloc格式应该保留用于运行时大小的数组。 如果数组类型具有编译时大小,那么malloc的更好的方法如下

char (*p)[10] = malloc(sizeof *p);

这当然可以很容易地传递给上面声明的foo

foo(p);

编译器将执行正确的类型检查。 但是再一次,这对于一个没有准备的C开发人员来说过于混乱,这就是为什么你不会经常在“典型的”平均日常代码中看到它。

I would like to add to AndreyT's answer (in case anyone stumbles upon this page looking for more info on this topic):

As I begin to play more with these declarations, I realize that there is major handicap associated with them in C (apparently not in C++). It is fairly common to have a situation where you would like to give a caller a const pointer to a buffer you have written into. Unfortunately, this is not possible when declaring a pointer like this in C. In other words, the C standard (6.7.3 - Paragraph 8) is at odds with something like this:

int array[9]; const int (* p2)[9] = &array; /* Not legal unless array is const as well */

This constraint does not seem to be present in C++, making these type of declarations far more useful. But in the case of C, it is necessary to fall back to a regular pointer declaration whenever you want a const pointer to the fixed size buffer (unless the buffer itself was declared const to begin with). You can find more info in this mail thread: link text

This is a severe constraint in my opinion and it could be one of the main reasons why people do not usually declare pointers like this in C. The other being the fact that most people do not even know that you can declare a pointer like this as AndreyT has pointed out.

更多推荐

本文发布于:2023-08-05 15:42:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1434765.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:数组   指针   大小   pointers   size

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!