2012-10-25 152 views
2

早些時候,我問了一個關於我寫的帕斯卡三角形程序的問題,並且解決了我最初的問題。我現在有新的問題,我已經嘗試用gmp做這個!我對這門語言很陌生,所以請和我一起裸照。這裏c與gmp的帕斯卡三角形

/* 
    This code is just to see exactly how much faster C is than python 
    at doing numerically stuff. It should calculate the nth row of 
    pascals triangle. 
    The way you use it is by calling the executable with the row 
    you wish to compute as the only argument. For example if you 
    are on an *nix system: 
    ./pascal 6 

    Or in a windows command prompt: 
    pascal.exe 6 
*/ 

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

/* 
    I decided to use a struct here because I thought it was ugly 
    to have to pass around the length of my arrays in function 
    calls. 
*/ 

typedef struct{ 
    int length; //length of the array 
    int numbits; //number of bits allocated per val in vals 
    mpz_t* vals; //pointer to start of array 
} CoolArray; 

//initArray allocates memory for the CoolArray. 
void initArray(CoolArray* array, int length, int numbits); 

//destroyArray frees allocated memory in the struct. 
void destroyArray(CoolArray* array); 

//printArray prints the contents of the array. 
void printArray(CoolArray* array); 

//pascal computes the nth row of pascal's 
//triangle, with n being array->length, 
//and stores the values in the array. 
void pascal(CoolArray* array); 

//setArray takes two CoolArrays of the same length 
//and sets the values in the first to the values 
//in the second. 
void setArray(CoolArray* array1, CoolArray* array2); 

int main(int argc, char** argv){ 
    int length = atoi(argv[1]); 
    CoolArray array1; 
    initArray(&array1, length, 800); //giving every int 800 bits of memory 
    printf("Calculating the %dth row of pascals triangle...\n", length); 
    pascal(&array1); 
    printArray(&array1); 
    destroyArray(&array1); 
    return 0; 
} 

void initArray(CoolArray* array, int length, int numbits){ 
    assert(length>=1); //don't make arrays with a length <=0!!! 
    array->length = length; 
    array->vals = (mpz_t*) calloc(length, sizeof(mpz_t)); //first I allocate memory for vals... 
    mpz_array_init(array->vals, length, numbits); //then I allocate memory for each val in vals 
    return; 
} 

void destroyArray(CoolArray* array){ 
    int i=0; 
    for(; i < array->length; ++i){ //first I go through the array and 
    mpz_clear(array->vals[i]); //clear the memory used for each val 
    } 
    free(array->vals); //then use free on the entire array 
    return; 
} 

void pascal(CoolArray* array){ 
    assert(array->length >= 1);//making sure the length wasn't fiddled with... 

    if(array->length == 1){ 
    mpz_set_ui(array->vals[0], (unsigned long int)1); 
    return; 
    } 
    int row; 
    int index; 
    mpz_set_ui(array->vals[0], (unsigned long int)1); //if we aren't looking for the first row 
    mpz_set_ui(array->vals[1], (unsigned long int)1);//then i'll start with the second row 
    CoolArray current; 
    initArray(&current, array->length, array->numbits); //current is a helper array 
    for(row = 2; row < array->length; ++row){ 
    mpz_set_ui(current.vals[0], (unsigned long int)1); //set the first val to 1 
    for(index = 1; index < row; ++index){ 
     mpz_add(current.vals[index], //set the value of this... 
      array->vals[index], //to this... 
      array->vals[index-1]); //plus this. 
    } 
    mpz_set_ui(current.vals[row], (unsigned long int)1); //make the last number 1 
    //printArray(&current); 
    setArray(array, &current); //put every value in current into array 
    } 
    destroyArray(&current); //get rid of current 
    return; 
} 

void setArray(CoolArray* array1, CoolArray* array2){ 
    assert(array1->length==array2->length);//making sure they are the same length 
    int i=0; 
    for(; i < array2->length; ++i){ 
    mpz_set(array1->vals[i], array2->vals[i]); //array1 is the array whose values are being set 
    } 
    return; 
} 

void printArray(CoolArray* array){ 
    int i=0; 
    printf("["); 
    for(; i < array->length; ++i){ 
    mpz_out_str(stdout, 10, array->vals[i]); 
    if(i < (array->length - 1)) printf(", "); 
    else printf("]\n"); 
    } 
    return; 
} 

我得到正確的輸出,sorta。值打印是正確的,但我也越來越一堆線條像這樣在終端與預期輸出一起:

gmpascal(80974) malloc: *** error for object 0x1008001a0: Non-aligned pointer being freed (2) 
*** set a breakpoint in malloc_error_break to debug 

我在我的功能destroyArray錯誤地釋放內存?如果是這樣,我可以做些什麼來修復它,因爲據我所知(從檢查gmp手冊)我正確地做到了這一點。或者是我的gmp安裝有問題?

編輯:好吧,我以爲我發現的主要問題,當我意識到我是一個指針傳遞給我的mpz_t陣列的每個元素mpz_clear,當我剛剛路過的mpz_t本身。當我運行該程序時,仍然可以獲得上述輸出。但我仍然有這樣的編譯器警告:

gmpascal.c: In function ‘initArray’: 
gmpascal.c:62: warning: passing argument 1 of ‘__gmpz_array_init’ from incompatible pointer type 

是這樣的:

從這個
mpz_t array[length]; //length is an int 
mpz_array_init(array, length, numbits); //and so is numbits 

不同:

mpz_t* array; 
array = (mpz_t*) calloc(length, sizeof(mpz_t)); 
mpz_array_init(array, length, numbits); 

第一個是直接來自手冊的例子,第二個是我在代碼中寫的。我認爲這可能是問題,但我不知道爲什麼兩者會有所不同。

回答

0

sizeof(mpz_t)的類型爲size_t。在許多現代系統上,size_t未定義爲int。你應該聲明struct字段爲size_t numbits

+0

謝謝,這固定了編譯器警告過我的一件事,但我仍然遇到了大量出現malloc錯誤的東西。我想我知道問題是什麼。 – Broseph