2015-08-21 208 views
1

當我嘗試從函數返回類型爲verylongint的值時,出現錯誤。什麼是正確的方式返回? verylongint是long long類型的數組,在第5行中定義。 返回verylongint的函數應該是string2verylongint(char * n)。編譯器的輸出低於源代碼。如何從函數返回一個定義的類型(數組)?

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#define SIZE 63 

typedef long long verylongint[63]; 

char* verylongint2string(verylongint n); 
verylongint string2verylongint(char* n); 

main(){ 
    verylongint n; 
    int i; 
    for(i=0; i<SIZE; i++)n[i]=0; //initialize 
    n[0]= 999999999999999999; 
    n[1]= 999999999999999999; 
    n[2]= 2323232311; 
    printf("%s\n", verylongint2string(n)); 

    verylongint m; 
    m = string2verylongint("123999999999999999999999999999999999999999999999999999999"); 

    printf("%s\n", verylongint2string(m)); 
} 

verylongint string2verylongint(char* n){ 
    char m[18]; // first long long element, which is not zero, as string 
    sscanf(n, "%[^9]", m); 
    long long n1; // as long long 
    sscanf(m, "%lld", &n1); 
    int length= strlen(n)-strlen(m); // length of string without the first element 
    int i; 
    verylongint k; //return value 
    for(i=0; i<SIZE; i++)k[i]=0; //initialize 
    for(i=0; i<length/18; i++){ // length/18 is the number of elements (without 1st) 
     k[i]=999999999999999999; 
    } 
    k[i] = n1; 

    printf("%s\n", verylongint2string(k)); 

    return k; 
} 

char* verylongint2string(verylongint n){ 
    char* string = (char*) malloc(18*63*sizeof(char));//18 is the length of the biggest number 
          //63 is the length of the long-array 
    int i=SIZE; 
    while(n[--i]==0); 
    //string=n[i]; 
    sprintf(string, "%lld", n[i]); //first number, which is not zero 
    while(--i>=0){ //adding the biggest number 
     strcat(string,"999999999999999999"); //the biggest number(one char smaller than lld) 
    } 

    return string; 
} 

輸出:

[email protected]:~/Documents$ gcc verylongint.c -o vli 
verylongint.c:9:13: error: ‘string2verylongint’ declared as function returning an array 
verylongint string2verylongint(char* n); 
      ^
verylongint.c: In function ‘main’: 
verylongint.c:21:4: error: incompatible types when assigning to type ‘verylongint’ from type ‘int’ 
    m = string2verylongint("123999999999999999999999999999999999999999999999999999999"); 
    ^
verylongint.c: At top level: 
verylongint.c:26:13: error: ‘string2verylongint’ declared as function returning an array 
verylongint string2verylongint(char* n){ 
      ^
verylongint.c: In function ‘string2verylongint’: 
verylongint.c:42:2: warning: return makes integer from pointer without a cast [enabled by default] 
    return k; 
^
verylongint.c:42:2: warning: function returns address of local variable [-Wreturn-local-addr] 
+6

C函數不能按值返回數組。把它放到一個結構體中。 –

+2

或決定誰(調用者或被調用者)將分配內存並使用指針 –

+0

您需要學習使用C編程的第一件事是,99%的時間,調用者需要提供容器來展示結果,而不是返回容器與被調用者提供的結果。 – user3528438

回答

0

作爲評價所提到的,數組不能是一個函數的返回值。您需要傳入數組作爲參數。由於數組傳入函數會衰減爲指向第一個元素的指針,因此函數中數組的更改將反映在調用者中。

此外,verylongint2string爲其結果分配一個緩衝區,但永遠不會釋放任何地方,導致內存泄漏。鑑於您如何使用它,您可以改爲使用固定長度的靜態變量,儘管這意味着您不能在同一語句中調用它兩次,或者在多線程應用程序中使用它,而不會調用未定義的行爲。

0

C語言向數組公開了一個非常奇怪的行爲。 你可以找到大量關於數組腐敗的指針,以指針爲例,特殊行爲是一些情況等等。這些評論來自閱讀(並且在某些情況下誤解標準),從一開始就沒有開發過C語言20世紀70年代。 C誕生於彙編程序和高級語言之間的中介語言,用於對OS代碼塊進行編程,其中與複雜的數據結構並排排列,它也被要求訪問硬件寄存器,處理硬件I/O和喜歡。

當時預留一個內存區保存一些相同類型的變量被稱爲數組。那麼如何使用這些數據呢?很簡單,您可以使用內存區域基址訪問所有陣列數據。 但這是偶然的數組的第一個元素的地址。從那時起,我們用來說,對陣列名稱的任何引用都等同於對其第一個元素地址的引用:

array => &array[0];

這背後的真正原因是,通過在彙編,編譯器生成的代碼(低電平)側將是這樣的:

array db 10 dup (0) 

對於取其參考在代碼陣列:

lea eax, array 

它是數組的基地址。

不止一種語言規範,它是將數組名稱與其第一個元素的地址相關聯的實用規則。

而且還有一個指針變量包含地址,所以如果我們得到一個地址,它應該來自一個數組或從一個指針,我們可以應用同樣的方式訪問數據:

movsx eax, byte ptr [eax+4] //read in eax, extendid the sign, the 5th element of the array pointed by eax 

只是有發射代碼中的一個小差異。假設我們有:

int a[10]; 
int *p = a; 
foo(a[3], p[3]); 

將編譯到:

a DW 10 DUP(?) //An array of 10 ints uninitialized 
p DW a   //a pointer initialized to a address 
.... 
lea eax, p //Get the address of the pointer 
mov eax, DWORD PTR [eax] //Get the base address of array memory 
mov eax, DWORD PTR [eax+0xC] //0xC is the offset of the 3rd element (3 * 4bytes) 
push eax  //Push second parameter 
lea eax, a //Get the address of the array 
mov eax, DWORD PTR [eax+0xC] //0xC is the offset of the 3rd element (3 * 4bytes) 
push eax  //Push first parameter (C pushes parameters right to left) 
call foo 

正如你所看到的唯一區別是,使用指針,我們必須從中讀取數組基址,同時用數組彙編程序給我們正確的數據地址。

然後訪問數據是完全一樣的。這是因爲C中的指針和數組在大多數情況下的行爲幾乎相同。再次實際規則成爲一種語言規則...

當時,當記憶被計入ķ國際勞工組織 ytes(不GB!)左右的內存塊移動是無稽之談。從這裏出現另一條規則:只能通過引用將數組傳遞給函數,並且此作業由編譯器自動完成。 最後函數永遠不會返回數組

現在回到你的代碼有2個錯誤:你不能從一個函數返回一個數組,你沒有返回局部變量,因爲他們只在結束函數返回時的功能範圍存在回饋垃圾和UB(未定義行爲)。

但是你可以創建使用指針從動態內存中的數組,並返回這個指針:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#define SIZE 63 

typedef long long verylongint[63]; 

char *verylongint2string(verylongint *n); 
verylongint *string2verylongint(char *n); 

int main(int argc, char *argv[]) 
{ 
    verylongint n; 
    int i; 
    for (i = 0; i < SIZE; i++) 
     n[i] = 0; //initialize 
    n[0] = 999999999999999999; 
    n[1] = 999999999999999999; 
    n[2] = 2323232311; 
    printf("%s\n", verylongint2string(&n)); 

    verylongint *m; //m now is a pointer to the array 
    m = string2verylongint("123999999999999999999999999999999999999999999999999999999"); 

    printf("%s\n", verylongint2string(m)); 
} 

verylongint *string2verylongint(char *n) 
{ 
    char m[18]; // first long long element, which is not zero, as string 
    sscanf(n, "%[^9]", m); 
    long long n1; // as long long 
    sscanf(m, "%lld", &n1); 
    int length = strlen(n) - strlen(m); // length of string without the first element 
    int i; 
    verylongint *k = malloc(sizeof(verylongint)); //return value 
    for (i = 0; i < SIZE; i++) 
     (*k)[i] = 0; //initialize 
    for (i = 0; i < length/18; i++) 
    { // length/18 is the number of elements (without 1st) 
     (*k)[i] = 999999999999999999; 
    } 
    (*k)[i] = n1; 

    printf("%s\n", verylongint2string(k)); 

    return k; 
} 

char *verylongint2string(verylongint *n) 
{ 
    char *string = (char *)malloc(18 * 63 * sizeof(char)); //18 is the length of the biggest number 
    //63 is the length of the long-array 
    int i = SIZE; 
    while (n[--i] == 0) ; 
    //string=n[i]; 
    sprintf(string, "%lld", (*n)[i]); //first number, which is not zero 
    while (--i >= 0) 
    { //adding the biggest number 
     strcat(string, "999999999999999999"); //the biggest number(one char smaller than lld) 
    } 

    return string; 
} 

享受。

相關問題