2015-08-21 164 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; 
} 

享受。

相关问题