如何区分不同指针的含义?

Posted

技术标签:

【中文标题】如何区分不同指针的含义?【英文标题】:How to distinguish different pointer's meaning? 【发布时间】:2016-01-31 09:34:40 【问题描述】:

指针对很多事情都很有用,以至于有时无法理解它们在特定代码行中的含义。 例如,有时您使用指针来表示一系列元素:

char* char_array = "abcd";
int* int_array = malloc(5 * sizeof(*int_array));

有时您使用指针在堆上分配单个对象或使一个元素指向另一个元素:

int a = 5;
int* int_ptr = &a;
struct item* an_item = malloc(sizeof(*an_item));

当两者都使用碰撞时,连续的指针变得不可读:

    struct cell** board;
 // Does this represent a succession of cell allocated on the heap,
 // a succession of pointers to uniques cells (like an array),
 // a succession of pointers to multiples cells (like a two dimensional array)?

 // Of course the more you add pointers the more it becomes confusing.
    struct cell*** board;

我考虑过使用typedef 或宏来创建一个表示指针的类型,该指针用作引用或已被malloc 编辑过的东西。 这可能是双刃剑,因为在某些情况下我会获得可读性,但它也会混淆代码。您有什么建议来编写更容易理解指针含义的代码?

【问题讨论】:

***.com/q/16709946/1606345 我真的不明白这个问题。如果您是初学者,指针可能会令人困惑,并且您建议的内容可能很有用,但是在习惯它之后,这没什么大不了的。指针总是以类似的模式使用,过一段时间你就会学会它们。 使用变量命名约定,以及描述其属性的指针声明上方的代码cmets(即,它是否将拥有它所指向的内容,以及它是否可能指向数组的第一个) 三重间接是令人困惑的,没有办法解决这个问题。尽量避免三重间接。 【参考方案1】:

您有什么建议来编写更容易理解指针含义的代码?

确实,对于代码的局外人来说,指针的含义可能是不清楚的。我建议在变量名称前加上前缀以赋予它们更多含义。

见:https://en.wikipedia.org/wiki/Hungarian_notation#Examples

当然,您不必详细遵循此示例。您可以找到多种方式来添加前缀或组成自己的前缀。只要你在某个地方解释它就可以了。

【讨论】:

【参考方案2】:

指针的含义总是一样的。它实际上总是只指向一个对象。因此,指针是指向内存中单个位置的变量


至于你的不同例子

当你做类似的事情时

char* char_array = "abcd";
int* int_array = malloc(5 * sizeof(*int_array));

同样,指针char_array 指向单个char,即整个字符串"abcd" 中的a。碰巧的是,由于它的初始化方式(字符串文字),有字符存储在下一个内存位置。


上面例子中的指针其实和下面的char_ptr是一样的
char* char_array = "abcd";
char* char_ptr = char_array;

如果你喜欢这样

printf(" %c", char_ptr);

它将打印a

如果你这样做

printf(" %s", char_ptr);

它将打印整个字符串"abcd"

在这里您可以看到char_ptr 的作用也与char_arrayprintf() 语句中的作用相同,

【讨论】:

我不认为这是一个非常有用的回应;指针通常指向一个对象,该对象是一系列对象(又名数组)中的第一个对象,并且 OP 询问我们如何知道这种情况是否正在发生。例如。当char_ptr 可能被声明为char x; char *char_ptr = &x; 时,你怎么知道printf("%s", char_ptr); 是否安全 @MM,好的。我觉得OP被问到如何知道它们在理论上是否不同。我发帖说它们在理论上没有什么不同。 你是对的,指针的 nature 是这样定义的,但是 OP 对可以归因于的不同 roles 更感兴趣指针。以此类推,所有人都是一样的,但我们有不同的工作。 虽然它们在理论上是不同的,指向 1 个对象的情况只需要不同的代码处理与可能指向 1 个对象的情况(这是系列中的第一个对象) @M.M,在 C 标准的情况下,理论上没有什么不同。所有的指针都只是指向一个对象。【参考方案3】:

这与代码风格有关,因此可能会有不同的答案,而且它们都可能是正确的,但如果您愿意,可以呈现不同的风格或观点。

我的建议是永远不要超过两个 *.如果我记得我的 C 编码,我只使用了两个 * 来表示 void ** 类型。

在所有其他情况下,使用 typedef(不是宏!)并为您的对象构建良好的结构。

使用 typedef,为每个级别创建名称。因此,如果您从 CELL 类型开始,并且想要这些数组,请调用它,例如CELL_LIST,它将是一个(指向)CELL 的数组。您想要 CELL_LIST 数组吗?例如,将其命名为 BOARD。

所以 CELL_LIST 是指向 CELL 的指针。 BOARD 是指向 CELL_LIST 的指针(也可以命名为 ROW)。需要另一个维度?称它为 BOARD_LIST 或 BOARD_3D ...

【讨论】:

我的建议是永远不要使用指针类型定义;读者必须建立一个准确的内存布局心智模型,并且 * 被遮盖会干扰这一点

以上是关于如何区分不同指针的含义?的主要内容,如果未能解决你的问题,请参考以下文章

《C专家编程》数组和指针并不同--多维数组

《C专家编程》数组和指针并不同--多维数组

悬空指针的含义[重复]

flutter web中如何区分手指触摸手势和鼠标指针手势?

函数指针三种定义与使用方式

函数指针三种定义与使用方式