跨函数的“动态(指针)数组”

时间:2013-12-20 10:46:03

标签: c arrays pointers math memory

我希望创建一个函数,它返回一个数字可以除以的所有可能数字。另外,我希望在另一个函数中使用这些返回的结果,这些函数查找这些结果中的所有素数,然后返回那些。

长话短说,我希望能够返回“动态数组”并在另一个函数中再次使用它们。

到目前为止我所拥有的:

int *division (long a) {
    int i;
    int *divResult = malloc(a * sizeof(long)); //Ultimately I want to allocate space dynamically instead of reserving too much space

    if (naturalNumber(a)) { //What it basically does is "fmod(a, 1)" (returns boolean)
    divLength = 0; //A global int set to trace the length of division()
        for (i = 0; i < a + 1; i++) {
            if (divisor(i, a)) { //Checks wether the division of a by i returns a whole number (returns boolean)
                //divResult = realloc(divResult, sizeof(long)); //This gives seg faults and errors durning runtime; To be clear I am not exactly using it like this. What I do is I adjust the "malloc(a*sizeof(long))" to "malloc(sizeof(long))"
                divResult[i] = i; //If i is a divisor add it to the pointer
                divLength += 1; //track how long the current division is
            }
        }
    }

    free(divResult); //I was hoping this to remove the divResult from the memory, sadly it is still there and doesnt give me an error of me trying to return a NULL value
    //printf("Mem: %p\n", (void *)divResult);
    return divResult; //Return a "dynamic array" so that another function can use it
}

正如您所看到的,我知道我必须使用指针而不是真正的数组,因为这些指针无法返回。 我知道这有效并且已经恢复了真正的价值。

此外,我希望此函数使用division()函数来查看数字的除数并将它们放在数组中:

int *primes (long a) { //I'm trying to reuse the same tactic as before:
    int i;
    int *primeResult = malloc(a * sizeof(long)); //Allocating it again...

    if (naturalNumber(a)) { //See previous codeblock
        for (i = 0; i < a + 1; i++) {
            division(i); //Calling the function here to divide each number from 1 to "a" so I am able to see which one is of size 2 (in other words the division of number *1 to a* and check wether it is a prime number (it has in total only 2 divisors))
            printf("len = %d\n", divLength); //prints the current length of division()
            if (divLength == 2) { //If the division() "length" is 2
                primeResult[i] = i; //add i to primes
            }
        }
    }

    free(primeResult); //Same as above
    return primeResult;
}

你可能猜到我没有得到预期的结果。

使用:

int *div;
div = division(a) + 1;
for (i = 0; i < a; i++) {
    if (*(div + i) != 0)
        printf("*(div + %d) : %d\n", i, *(div + i));
}

int *prime;
prime = primes(a) + 1;
for (i = 0; i < a; i++) {
    if (*(prime + i) != 0)
        printf("*(prime + %d) : %d\n", i, *(prime + i));
}

我明白了:

len = 6
len = 1
len = 2
len = 2
len = 3
len = 2
len = 4
len = 2
len = 4
len = 3
len = 4
len = 2
len = 6
*(prime + 1) : 2
*(prime + 2) : 3
*(prime + 3) : 4
*(prime + 4) : 5
*(prime + 5) : 6
*(prime + 6) : 7
*(prime + 10) : 11
*(prime + 11) : 12

我可以向你保证,如果我注释掉除除了()和调用primes()之外的所有痕迹,我仍然可以得到结果:

*(div + 1) : 2
*(div + 2) : 3
*(div + 3) : 4
*(div + 5) : 6
*(div + 11) : 12
len = 0
len = 0
len = 0
len = 0
len = 0
len = 0
len = 0
len = 0
len = 0
len = 0
len = 0
len = 0
len = 0
*(prime + 1) : 2
*(prime + 2) : 3
*(prime + 3) : 4
*(prime + 5) : 6
*(prime + 11) : 12

所以,我知道我的代码很糟糕;这就是为什么我现在要问(我还在学习),我问你:

  • 为什么它仍然会返回division()的值,即使我已经“释放”了divResult的内存?
  • 如何让realloc()工作?
  • 单独的函数中有没有更简单的方法来完成所有这些?

最后但并非最不重要的是:有没有人真正理解我在问什么?

3 个答案:

答案 0 :(得分:3)

释放指针时,分配给它的内存会发生什么变化是未定义的。它不会被清除,可能会重复使用,内存的内容可能会被覆盖......或者可能没有。

在你的情况下,从你释放它的那一刻到你打印它的那一刻之间,内存似乎保持不变,但在每次执行你的程序或每个操作系统时都可能不是这样。

void* realloc (void* ptr, size_t size)将复制在ptr分配的内存,并将其复制到大小为size的新内存区域。但是你用realloc来实现什么呢?

  

有没有更简单的方法在单独的功能中完成所有这些?   你能更具体一点吗?

更新(评论时): 你可以重构你的两个函数来拥有相同类型的接口,但是可以在不同的上下文中使用以下原型:

// the functions take as a parameter an array of integers, an a pointer to an integer. It returns an array of transformed data and through the second parameter, the length of the output.
int* findDividers(int input, int* output_length) {
    int* dividers = malloc(input * sizeof(int));
    int found_dividers = 0;
    // do things
    int* tmp = realloc(dividers, found_dividers);
    free(dividers);

    *output_length = found_dividers;
    return tmp;
}

int* primeFilter(int* input, int input_length, int* output_length) { /* same structure as before */ }

// you can then use it as follow
int integer_to_process = 0xdeadbeef;

int dividers_count = 0;
int* dividers = findDividers(integer_to_process, &dividers_count);

int primes_count = 0;
int* primes = primeFilter(dividers, dividers_count, &prime_count);

// now feel free to use the two arrays, with a minimal length, as you want.

答案 1 :(得分:2)

  • 为什么它仍然会返回division()的值,即使我已经“释放”了divResult的内存?访问释放的内存块的内容是未定义的行为,任何事情都可能发生。在大多数实现中,如果内存未被重用于其他任何内容,您将能够看到旧值。但是你不能依赖它,因为你不知道什么时候会重新分配内存。

  • 如何让realloc()工作?如果仍然需要,请不要释放内存。只要分配了内存,就可以使用realloc()缩小或扩展内存。但请确保更新所有指向内存的指针,因为realloc()可以移动内存。

  • 有没有更简单的方法在单独的功能中完成所有这些?这是一个非常广泛的问题。

答案 2 :(得分:1)

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

long *division(long n){
    int i, len = 1;//for 1
    long *result;

    if(n < 1) return NULL;
    result = malloc(n * sizeof(long));
    if(result){
        for (i = 2; i <= n; ++i)//skip 1
            if(n % i == 0)
                result[len++] = i;
        result[0] = len;//put a length instead of 1
        result=realloc(result, len*sizeof(long));
    }
    return result;
}

long *factor(long n){
    int i=2, sqi=4, len = 1;
    long *result;

    if(n < 1) return NULL;
    result = malloc((n/2+1)*sizeof(long));
    if(result){
        while(sqi <= n){
            int flag = 0;
            while(n % i == 0 && (flag = 1))
                n /= i;
            if(flag)
                result[len++] = i;
            sqi += 2*(i++) + 1;
        }
        if(n != 1)result[len++] = n;
        result[0] = len;
        result=realloc(result, len*sizeof(long));
    }
    return result;
}

long *primes(long n) {Quite verbose
    int i, len = 1;
    long *result;

    if(n < 1) return NULL;
    result = malloc((n/2+2) * sizeof(long));
    if(result){
        for (i = 2; i <= n; ++i) {
            long *div=factor(i);
            if(div[1] == i) {
                result[len++] = i;
            }
            free(div);
        }
        result[0] = len;
        result=realloc(result, len*sizeof(long));
    }
    return result;
}

int main(){
    long *div = division(1234);
    int i, len = div[0];
    for(i=1;i<len;++i){
        printf("%ld\n", div[i]);
    }
    free(div);
    printf("\n");
    long *fact = factor(123456);
    len = fact[0];
    for(i=1;i<len;++i){
        printf("%ld\n", fact[i]);
    }
    free(fact);
    printf("\n");
    long *prime = primes(123);
    len = prime[0];
    for(i=1;i<len;++i){
        printf("%ld ", prime[i]);
    }
    free(prime);
    printf("\n");
    return 0;
}