C:指针算术和 malloc() - 不行?

C: Pointer arithmetic and malloc() - NO GO?

为了熟悉指针,我遇到了使用 malloc() 和 free() 进行动态内存分配的部分。我想确认或更正我对这个话题的理解。

到现在为止,我了解到指针的两大好处:

  1. 通过引用调用(即可以使用指针访问和更改函数外部的变量,而无需变量是全局变量)。
  2. 使用指针运算,这是一种非常方便且代码高效的方式来遍历数组(例如,作为字符串的 char 数组)、访问和操作数据。

谈到 malloc(),我觉得如果指针地址不被重置,指针运算会变得相当危险。在下面的示例中,我使用 malloc() 创建了两个指针 ptr 和 ptr1。 我知道这两个 malloc() 函数分配了两个内存块,每个内存块都和 size*sizeof(int) 一样大,所以这是保留内存,这两个块的第一个元素的地址给了 ptr 和 ptr1.

使用第一个 for 循环,我使用指针将值分配到内存位置。 ptr 使用指针算法,ptr1 使用数组算法(如果我可以这样称呼它的话)。

for循环结束时,ptr没有指向保留内存块的首元素地址,必须重新设置回来才能指向首元素地址。

第二个for循环打印两个内存块中的数据。在那里,我没有重置 ptr 以指向内存中第一个元素的地址。

现在是大问题: 使用 free(ptr),free() 接收一个指向某个地址的指针(除了被保留的内存块的起始地址)。我是否正确理解写 free(ptr),我现在将释放一个不同的 size*sizeof(int) 内存块,我可能会释放一些不应该释放的敏感数据?

这样理解对吗?如果是这样,在使用与 malloc() 相关的指针时是否始终使用数组运算是否明智?

谢谢, 亚历克斯

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

int main()
{
int size = 0;
printf("Enter the array size: ");
scanf("%d",&size);

int * ptr = (int *)malloc(size*sizeof(int));
int * ptr1 = (int *)malloc(size*sizeof(int));

int i = 0;
// First for loop
for( ; i<size;i++)
{
    *ptr = i;
    ++ptr;
    *(&ptr1[i]) = i;
}

ptr = ptr-size; // Resetting to the start address

// Second for loop
for(i = 0; i<size;i++)
{
    printf("%d\t\t",*ptr);
    ptr++;
    printf("%d\n",*(&ptr1[i]));
}

free(ptr);  // Is the correct memory block now freed?
free(ptr1);
return 0;
}

您的程序有未定义的行为。传递给 free() 的指针值必须 完全等于 malloc()calloc()realloc() 获得的值。来自 cppreference.com:

The behavior is undefined if the value of ptr does not equal a value returned earlier by malloc(), calloc(), realloc(), or aligned_alloc() (since C11).

因此,保留一个指向您的分配的纯指针以传递给 free(),并使用一个副本进行指针运算。

对于初学者来说,这些语句中使用了冗余运算符

*(&ptr1[i]) = i;

printf("%d\n",*(&ptr1[i]));

它们相当于

ptr1[i] = i;

printf("%d\n", ptr1[i] );

如果指针的值与调用 malloc 返回的值不同,则为此类指针调用 free 会导致未定义的行为。

注意这个循环中的那个

for( ; i<size;i++)
{
    *ptr = i;
    ++ptr;
    *(&ptr1[i]) = i;
}

你可以像

那样对指针 ptr 显式使用指针算法
for( ; i<size;i++)
{
    *( ptr + i ) = i;
    *(&ptr1[i]) = i;
}

在这种情况下,指针 ptr 本身的值不会改变。