c - 使用 malloc 和 free 理解指针

标签 c arrays pointers malloc free

指针在 C 中是一个非常棘手的东西。对于很多人来说很难理解它,所以为了更好地理解我写了以下代码:

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    int *p; // pointer -> will be dynamic allocated
    int *a; // array -> will be dynamic allocated

    // print before allocate memory (1)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: %d\n", &a, a, *a);
    printf("\n");

    // allocate memory (2)
    p = (int *)malloc(sizeof(int));
    a = (int *)malloc(sizeof(int) * 10);

    // print after allocate, but before give a value to poinetrs (3)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: %d\n", &a, a, *a);
    printf("\n");

    // give a value to poinetrs (4)
    *p = 1;
    for (int i = 0; i < 10; i++) { a[i] = i; }

    // print after we gave a value to pointers (5)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: ", &a, a);
    // because a is an array we must use a loop for print 
    for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }
    printf("\n");
    printf("\n");

    // free pointers (6)
    free(p);
    free(a);

    // print pointers after free (7)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: ", &a, a);
    // because a is an array we must use a loop for print 
    for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }
    printf("\n");
    printf("\n");

    // try to change values after free (8)
    *p = 12;
    for (int i = 0; i < 10; i++) { a[i] = 3; }

    // print after (8)
    printf("&p: %p\tp: %p\t*p: %d\n", &p, p, *p);
    printf("&a: %p\ta: %p\t*a: ", &a, a);
    // because a is an array we must use a loop for print 
    for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }
    printf("\n");
    printf("\n");

    return 0;
}

输出:

&p: 0xbfe5db64  p: 0xbfe5dc24   *p: -1075452506
&a: 0xbfe5db68  a: 0xbfe5dc2c   *a: -1075452502

&p: 0xbfe5db64  p: 0x8716008    *p: 0
&a: 0xbfe5db68  a: 0x8716018    *a: 0

&p: 0xbfe5db64  p: 0x8716008    *p: 1
&a: 0xbfe5db68  a: 0x8716018    *a: 0 1 2 3 4 5 6 7 8 9 

&p: 0xbfe5db64  p: 0x8716008    *p: 0
&a: 0xbfe5db68  a: 0x8716018    *a: 0 1 2 3 4 5 6 7 8 9 

&p: 0xbfe5db64  p: 0x8716008    *p: 12
&a: 0xbfe5db68  a: 0x8716018    *a: 3 3 3 3 3 3 3 3 3 3 

现在,问题和观察:

  1. 当我在为它分配内存之前打印指针时,为什么指针有一个随机值和一个随机地址指向它,为什么它不是 NULL?

  2. 我们使用malloc后,可以看到指针指向的地址变了,它的值为NULL,那么malloc到底是做什么的呢?

  3. 在我们给它一个值并打印它之后,我们释放它并再次打印它,但是值和地址与后面的数组相同,但整数却不同,为什么?那么免费的真正作用是什么?

  4. 释放空间后,我们可以继续改变数组和整数的值,为什么在释放空间后可以这样呢?我们不需要重用 malloc 吗?

最佳答案

  1. 因为语言规范是这么说的。指针的值(即它指向的地址)是不确定的。它可以指向任何地方,就像 int 可以保存任何值一样。读取这些值(就像您在第一个 printf 中使用 *p*a 所做的那样)实际上是未定义的行为.

  2. 如果你的意思是它指向的数据是0,那是偶然的。分配的内存不必清零。例如,它可能是先前使用 malloc 分配的 block 的一部分,然后是 freed(free 不会将内存清零,请参阅下面第 3 点。)

  3. 那也是机缘巧合。当您释放 内存时,它不会清零,也不必立即使用。它可以一直存储旧值,直到它被用于其他用途(例如,被另一次分配)

  4. 这也是未定义的行为。你正在写你不再拥有的内存。任何事情都可能发生。该程序可能已经崩溃。偶然地,您似乎可以成功写入数组,这可能是因为内存仍未被其他任何会导致更明显的运行时错误的东西使用。

关于c - 使用 malloc 和 free 理解指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25802322/

相关文章:

c++指向整数的指针在减去时给出不同的答案

c - 如何修复链表段错误 C

c++ - std::shared_ptr operator [] 等效访问

javascript - 如何从对象数组中获取特定数据并将其存储在js(vue js)中的新数组中

javascript - 随机比较数组中的每个元素

c++ - 编译器显示错误消息 "makes pointer from integer without cast"(反转数组)。我该如何解决这个问题?

c - "assert I' m 保持此互斥锁是否可行?

c - 以字符串和整数为键的哈希表的哈希函数

c - 如何正确释放一个 erlang 术语

c - 头文件中的数组声明