【问题标题】:New to pointers in CC 中指针的新手
【发布时间】:2020-08-12 21:45:14
【问题描述】:

在下面的代码中,我想更好地理解 int *z = malloc(sizeof(int); 发生了什么

对我来说,它创建了一个指向 int 的指针。然后*z得到x指向的值(2)和y指向的值(4)之和。

现在 *z = 6。这是否意味着 *z 不指向任何东西?它只存储一个int?我以为 *z 是指针,指针是地址?感谢您的帮助理解。

int *add(int *x, int *y)
{
    int *z = malloc(sizeof(int));
    *z = (*x) + (*y);
    return z;
}

int main(void)
{
    int a = 2;
    int b = 4;
    int *ptr = add(&a, &b);
    printf("sum = %i\n", *ptr);
    
}

【问题讨论】:

  • *z derefences 允许您读取/写入指向的内存位置的指针。不要忘记在mainfree(ptr) 来释放你malloc'd 的内存。此外,这个例子是非常人为的。 IRL,您只需在没有指针的情况下完成所有这些操作,堆栈分配所有内容并直接使用整数返回值,所以也许这不是您需要指针的一个很好的动机。
  • 可能是一个微妙的点,但z = malloc( sizeof (int)) 不会创建指针。它分配(“创建”不准确,但我想会通俗地使用)内存并将分配内存的地址分配给z*z 不是指针。 z 是一个指针。 *z 是存储在z 指向的地址的值。指针不是地址;它是一个保存地址的变量。

标签: c pointers


【解决方案1】:

现在 *z = 6。这是否意味着 *z 不指向任何东西?它只存储一个int?我以为 *z 是指针,指针是地址?感谢您的帮助理解。

*z = 6 是正确的,但你对这种情况的发生方式是错误的。

z 是一个指针,因此它指向内存中的某个位置。在您的程序的早期,您使用 int *z = malloc(sizeof(int)); 分配了z 指向的空间。

然后,当您执行*z = (*x) + (*y); 时,您基本上已经将加法的结果放入了分配的空间中。

z 仍然指向那个空间(因为它是一个指针)。 *z 称为解引用,意思是直接到达指针指向的值。

换句话说:6 存储在z 指向的位置,*z 是获取该值的一种方式。

【讨论】:

    【解决方案2】:

    *z = 66 分配给ptr指向的位置。这就是指针的作用,它指向事物,但是为了将值放在它指向的位置而不是更改指针,您需要使用 * 运算符取消引用。1

    从概念上讲,将您的记忆想象为多个字节,每个字节都有一个数字。指向int 的指针表示内存中的特定位置,假定该位置保存int 或4 字节的数据。

    *z = 6 的意思是“在z 描述的内存位置放入一个整数值 6”,翻译成的机器指令大致相同。

    z 绝对不会“存储一个 int”,它存储一个位置。该位置可能存在,或者可能是NULL,或者可能无效。除非您仔细检查代码以确保指针有效,否则无法保证。这是你作为程序员的责任。

    这也是为什么指针会变得棘手和令人沮丧的原因。他们在您的代码中引入了间接


    1 在 C 中,指针在很大程度上也可以与数组互换,因此您可以使用 z[0] = 6,尽管由于 z 仅指向单个 int,因此除 0 之外的任何索引都是无效的。

    【讨论】:

    • 所以z存储了6所在的地址..然后*ptr得到z..所以现在*ptr =(6所在的地址)。 *z 会发生什么?它不再指向任何东西了吗?
    • 如果您想深入挖掘,那就太好了。尝试在编译时查看该代码的assembly language 输出。理解 CPU 的指令有助于理解为什么 C 是这样设计的。有一条指令有效地说“将这个值放在这个内存位置”,还有一条指令说“从这个内存位置读取”。 z 本身不被消耗。它总是在那里。你可以像*z += 2 一样轻松地做int a = *z
    • @Dylan No. *ptr = 6 将值 6 存储在 ptr 引用的位置。 ptr 仍然指向同一个位置。
    • z 视为“间接整数”,因为您需要取消对它的引用才能获得一个。 z + 6 正在做指针数学。 *z + 6 正在做整数数学运算。
    • 记住,从概念上讲,C 中的所有东西都有一个内存地址,优化除外,所以int z 也是一个内存位置,你总是可以做int* zptr = &z 然后你有一个指针可以操纵该值,不需要malloc
    【解决方案3】:
    int *z = malloc(sizeof(int));
    

    这将引发系统调用以在堆上分配一个整数。 z 是从 malloc 返回的这个整数的地址(如果 malloc 分配失败 z 将为 null)

    z 是指向在堆上分配的缓冲区的指针(如果 malloc 成功)。在你的情况下,这个缓冲区保存一个整数,所以它是一个指向这个整数的指针。

    参见手册页中的 malloc 描述。 malloc_man_pages

    *z = (*x) + (*y);
    

    你是对的。您正在将地址 x 中设置的值和地址 y 中设置的值分配给 z 指向的位置。

    您不检查 malloc 的返回值,这是一件非常糟糕的事情。始终检查 malloc 是否成功!见下文。也许您需要检查在 x 和 y 中获得的指针?! (这取决于你,但我建议检查)。

    int* add(int *x, int *y)
    {
        int *z = NULL; 
        
        if(x && y)
        {
            z = malloc(sizeof(int));
            if(z)
            {
                *z = (*x) + (*y);
            }
        }
    
        return z;
    }
    

    【讨论】:

      猜你喜欢
      • 2010-10-13
      • 2013-04-22
      • 1970-01-01
      • 1970-01-01
      • 2021-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多