如何区分不同指针的含义?
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_array
在printf()
语句中的作用相同,
【讨论】:
我不认为这是一个非常有用的回应;指针通常指向一个对象,该对象是一系列对象(又名数组)中的第一个对象,并且 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 ...
【讨论】:
我的建议是永远不要使用指针类型定义;读者必须建立一个准确的内存布局心智模型,并且*
被遮盖会干扰这一点以上是关于如何区分不同指针的含义?的主要内容,如果未能解决你的问题,请参考以下文章