C:指针算术和 malloc() - 不行?
C: Pointer arithmetic and malloc() - NO GO?
为了熟悉指针,我遇到了使用 malloc() 和 free() 进行动态内存分配的部分。我想确认或更正我对这个话题的理解。
到现在为止,我了解到指针的两大好处:
- 通过引用调用(即可以使用指针访问和更改函数外部的变量,而无需变量是全局变量)。
- 使用指针运算,这是一种非常方便且代码高效的方式来遍历数组(例如,作为字符串的 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 本身的值不会改变。
为了熟悉指针,我遇到了使用 malloc() 和 free() 进行动态内存分配的部分。我想确认或更正我对这个话题的理解。
到现在为止,我了解到指针的两大好处:
- 通过引用调用(即可以使用指针访问和更改函数外部的变量,而无需变量是全局变量)。
- 使用指针运算,这是一种非常方便且代码高效的方式来遍历数组(例如,作为字符串的 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 本身的值不会改变。