繁体   English   中英

如何在C中将指针重新分配给较小的数组?

[英]How to reassign pointer to smaller array in C?

有没有一种方法可以在C中重新分配一个指向数组的指针,使其指向更小的数组? 例如,如果我有一个指针ptr最初指向大小为3的数组s ,并且还存在一个大小为2的数组s1 ,我可以重新分配ptr使其指向s并因此指向一个较小的数组吗?

我尝试了以下代码:

void changePtr(double* ptr);

int main()
{
    double *ptr;
    ptr = (double*)malloc(sizeof(double)*3);
    double s[3]={1,2,3};
    ptr=s;
    changePtr(ptr);

    return 0;
}

void changePtr(double* ptr) {

    double s1[2]={4,5};
    free(ptr);
    ptr = (double*)malloc(sizeof(double)*2);
    ptr=s1;
}

但是,当我在VIsual Studio中运行它时,在free(ptr)出现错误,该错误表明Debug Assertion failed! Expression: _CrtIsValidHeapPointer(block) Debug Assertion failed! Expression: _CrtIsValidHeapPointer(block)

为什么是这样?

编辑

新代码是:

void changePtr(double* ptr);

int main()
{
    double *ptr;
    ptr = (double*)malloc(sizeof(double)*3);
    double *s;
    s = (double*)malloc(sizeof(double)*3);
    s[0]=1; s[1]=2; s[0]=3; 
    for (int i=0; i<3; i++){
        ptr[i]=s[i];
    }

    changePtr(ptr);

    for (int i=0; i<2; i++){
        printf("%f\t", ptr[i]);
    }


    free(ptr);
    free(s);

    return 0;
}

void changePtr(double* ptr) {
    free(ptr);
    double *s1;
    s1 = (double*)malloc(sizeof(double)*2);
    s1[0]=11; s1[1]=12;

    ptr = (double*)malloc(sizeof(double)*2);

    for (int i=0; i<2; i++){
        ptr[i]=s1[i];
    }
}

但是当我在调用changePtr之后打印出ptr的值时,得到了像-1456815990147....1这样的垃圾值。 为什么是这样?

编辑1

对您的原始问题:

简短答案:是的,您可以将指针重新分配给C中的一个较小数组。

长答案:短答案是误导的。 数组也只是C语言中的指针。为了更好地理解这个概念,您可能需要阅读此线程 ,尤其是看看这个答案


问题是您尝试取消分配stack上的内存。

每当您创建局部变量àla int a = 5 ,它就会被压入堆栈,也就是说,该变量将在堆栈上分配内存,并且在函数调用( main() )结束后,内存将被取消分配-所有这些自动发生!

在您的情况下,将发生以下情况:

// memory is allocated automatically on stack for the local variable "s"
double s[3]={1,2,3};

// assign the stack address of "s" to "ptr"
ptr = s;

// de-allocate the managed stack address of "s", which is NOT allowed!
free(ptr);

另一方面,例如通过malloc创建动态内存发生在需要由程序员管理的heap内存中,即分配( malloc() )和取消分配( free() )内存是允许的,并且必须非常小心。

因此,在您的程序中,当它到达此行时free(ptr); ,则断言失败,因为目标内存地址不满足要求-> IsValidHeapPointer :没有ptr不是有效的堆指针,因为那IsValidHeapPointer它持有s变量的堆栈地址。 :)


编辑2

当我在调用changePtr之后打印出ptr的值时,得到了像-1456815990147 .... 1这样的垃圾值。 为什么是这样?

这是因为,你释放的内存ptrchangePtr(ptr)第一,也就是内容ptr与一些“垃圾”值写入。

然后在这里分配新的内存,并将其分配给ptr

ptr = (double *) malloc(sizeof(double) * 2); 

此后,您通过ptr所做的更改(即ptr[i] = 12 )对ptr持有的先前地址没有影响。 因此,只需删除free(ptr)和上面的行,就不需要它们。


编辑3

那么ptr现在只包含2个值了吗? 在删除您提到的那一行之后,然后打印出ptr中的值之后,它将显示ptr [0]和ptr [1]的正确值,然后显示ptr [2]的垃圾值。

正确。 ptr[2]之前已被释放,因此,除非您为该地址分配新值,否则它将仍然是垃圾。 释放堆内存后也要小心。 您不应使用指针访问内存或为其分配新值。 在您对其free调用之后,考虑指针“ void”。

当我尝试使用printf(“%d”,sizeof(ptr))打印它的大小时,它显示为8,而printf(“%d”,sizeof(ptr)/ sizeof(ptr [0])显示为1。

ptr是一个指针。 sizeof(ptr)返回8个字节,这是系统中指针所保存的地址大小。 因此,这不是数组的大小...此外,在编程时无法确定运行时期间指针的大小(指向数组并作为引用传递给函数,就像您执行changePtr(ptr) ),如果要执行一些循环操作,则必须将数组大小显式传递给函数。

好吧,当你这样做

double s[3]={1,2,3};

该内存不是由您管理的,因此您无法释放它。 仅当使用malloc或calloc分配内存(即动态分配的内存)时,才可以使用free。 此外,那里有内存泄漏,因为

ptr=(double*)malloc(sizeof(double)*3); // here you allocate memory 
...
ptr = s; // here you change the pointer address but allocated memory is never freed

一种解决方案是使用for循环将值从s复制到ptr,并在changePtr中执行相同的操作以将值从s1复制到ptr。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM