为了账号安全,请及时绑定邮箱和手机立即绑定

为什么需要使用type **指向type *?

为什么需要使用type **指向type *?

C
侃侃尔雅 2019-12-16 13:12:39
我已经读了几天《学习C的艰难方法》,但这是我要真正理解的东西。作者Zed写道这char **是为了“指向(指向char的指针)的指针”,并说这是必需的,因为我正试图指向二维的东西。这是网页上的确切内容一个char *已经是“指向char的指针”,因此这只是一个字符串。但是,您需要2个级别,因为名称是二维的,这意味着您需要char **作为“指向(指向char的指针)”类型的指针。这是否意味着我必须使用一个可以指向二维事物的变量,这就是为什么我需要二维变量的原因**?只需稍作跟踪,这是否也适用于n维?这是相关的代码char *names[] = { "Alan", "Frank", "Mary", "John", "Lisa" };char **cur_name = names;
查看完整描述

3 回答

?
慕村9548890

TA贡献1884条经验 获得超4个赞

不,该教程的质量值得怀疑。我不建议继续阅读它。


A char**是指针到指针。它不是二维数组。它不是指向数组的指针。它不是指向2D数组的指针。


本教程的作者可能会感到困惑,因为存在广泛的错误和错误做法,说您应该分配动态2D数组,如下所示:


// BAD! Do not do like this!

int** heap_fiasco;

heap_fiasco = malloc(X * sizeof(int*));

for(int x=0; x<X; x++)

{

  heap_fiasco[x] = malloc(Y * sizeof(int));

}

但是,这不是2D数组,它是一个缓慢的,碎片化的查找表,分配给整个堆。访问查找表中一项的语法heap_fiasco[x][y]类似于数组索引语法,因此许多人出于某种原因认为这是分配2D数组的方式。


动态分配2D数组的正确方法是:


// correct

int (*array2d)[Y] = malloc(sizeof(int[X][Y]));

您可以说第一个不是数组,因为如果这样做memcpy(heap_fiasco, heap_fiasco2, sizeof(int[X][Y])),代码将崩溃并燃烧。这些项目未分配在相邻的存储器中。


同样memcpy(heap_fiasco, heap_fiasco2, sizeof(*heap_fiasco))也会崩溃和烧毁,但是由于其他原因:您得到的是指针的大小而不是数组的大小。


虽然memcpy(array2d, array2d_2, sizeof(*array2d))会起作用,因为它是2D数组。


查看完整回答
反对 回复 2019-12-17
?
心有法竹

TA贡献1866条经验 获得超5个赞

指针花了我一段时间来理解。我强烈建议绘制图表。


请阅读并理解C ++教程的这一部分(至少在指针方面,图表确实对我有所帮助)。


告诉您对于二维数组,您需要一个指向char的指针是一个谎言。您不需要它,但这是实现它的一种方法。


内存是顺序的。如果您想像单词hello那样连续放置5个字符(字母),则可以定义5个变量,并始终记住使用它们的顺序,但是如果要保存6个字母的单词会怎样呢?您是否定义更多变量?如果只按顺序将它们存储在内存中会不会更容易?


因此,您要做的就是向操作系统请求5个字符(每个字符恰好是一个字节),然后系统将向您返回一个内存地址,该地址开始您的5个字符的序列。您使用此地址并将其存储在变量中,我们将其称为指针,因为它指向您的内存。


指针的问题在于它们只是地址。您怎么知道该地址存储了什么?是5个字符还是8个字节的大二进制数字?还是它是您加载的文件的一部分?你怎么知道的?


这是像C这样的编程语言试图通过提供类型来帮助您的地方。类型告诉您变量存储的内容,而指针也具有类型,但是其类型告诉您指针指向的内容。因此,char *是指向存储位置的指针,该存储位置包含单个char或一系列chars。可悲char的是,您需要记住自己有关多少个数字的部分。通常,您将这些信息存储在一个变量中,以提醒您有多少个字符。


那么,当您想要拥有二维数据结构时,该如何表示呢?


最好用一个例子来解释。让我们做一个矩阵:


1  2  3  4

5  6  7  8

9 10 11 12

它具有4列和3行。我们如何存储它?


好吧,我们可以制作3个序列,每个序列有4个数字。第一个序列为1  2  3  4,第二个序列为,5  6  7  8第三个和最后一个序列为9 10 11 12。因此,如果我们要存储4个数字,我们将要求系统为我们保留4个数字并为它们提供一个指针。这些将是指向数字的指针。但是,由于我们需要3个指针,因此我们将要求系统给3个指针指向指针编号。


这就是您最终得到建议的解决方案的方式...


另一种方法是认识到您需要4乘3的数字,然后要求系统按顺序存储12个数字。但是,您如何访问第2行和第3列中的数字?这是数学的用武之地,但让我们在示例中进行尝试:


1  2  3  4

5  6  7  8

9 10 11 12

如果我们将它们彼此相邻存储,它们将如下所示:


offset from start:  0  1  2  3    4  5  6  7    8   9  10  11   

numbers in memory: [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]

所以我们的映射是这样的:


row | column | offset | value

 1  |   1    |   0    |   1

 1  |   2    |   1    |   2

 1  |   3    |   2    |   3

 1  |   4    |   3    |   4

 2  |   1    |   4    |   5

 2  |   2    |   5    |   6

 2  |   3    |   6    |   7

 2  |   4    |   7    |   8

 3  |   1    |   8    |   9

 3  |   2    |   9    |  10

 3  |   3    |  10    |  11

 3  |   4    |  11    |  12

现在,我们需要制定一个简单易行的公式,将行和列转换为偏移量……如果我有更多时间,我会回到它的位置上……现在我需要回家(抱歉)。 ..


编辑:我有点晚了,但让我继续。要查找行和列中每个数字的偏移量,可以使用以下公式:


offset = (row - 1) * 4 + (column - 1)

如果您注意到-1这里的两个数字,您会发现这是因为我们的行号和列号以1开头,所以我们必须这样做,这就是计算机科学家偏爱基于零的偏移量的原因(由于该公式) )。但是,对于C语言中的指针,当您使用多维数组时,语言本身会为您应用此公式。因此,这是另一种方式。



查看完整回答
反对 回复 2019-12-17
?
烙印99

TA贡献1829条经验 获得超13个赞

从您的问题中,我了解的是您在问为什么要为声明为* names []的变量使用char **。因此,答案是当您只写names []时,它就是array的语法,而array本质上是一个指针。


因此,当您编写* names []时,这意味着您要指向一个数组。而且因为数组基本上是一个指针,所以这意味着您有一个指向指针的指针,这就是为什么如果您编写的话编译器不会抱怨的原因


char ** cur_name =名称;


在上面的代码行中,您声明了一个指向字符指针的指针,然后使用指向数组的指针初始化它(记住数组也是指针)。



查看完整回答
反对 回复 2019-12-17
  • 3 回答
  • 0 关注
  • 311 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信