C中返回的数组不包含相同的值

时间:2015-02-27 02:25:06

标签: c arrays pointers

我正在教自己C和我错误地导致了以下问题:当我在方法中创建一个数组并将其作为指针返回时调用函数,没有任何内容是正确的。我已将此问题归结为以下示例:

char * makeArr(void){
    char stuff[4];
    stuff[0]='a';
    stuff[1]='b';
    stuff[2]='c';
    stuff[3]='d';
    printf("location of stuff:%p\n",stuff);
    int i;

    for(i = 0; i < 4; i++){
       printf("%c\n",stuff[i]);
    }

    return stuff;
}

int main(void){
    char* myarr;
    myarr = makeArr();
    int i;
    printf("\n");
    printf("location of myarr:%p\n", myarr);
    for(i = 0; i < 4; i++){
        printf("%c\n",myarr[i]);
    }
}

输出返回以下内容:

location of stuff:0028FF08
a
b
c
d

location of myarr:0028FF08
Ä
ÿ
(
(a null character)

所以我已经验证了两个值之间的位置是相同的,但值不同。我想我错过了一些关键的C警告;我可以推测它与数组衰减成指针或变量范围的问题有关,但是任何可以解决这个问题的灯都会非常感激。

3 个答案:

答案 0 :(得分:4)

你要做的是返回一个局部变量的地址,一个在函数退出时超出范围的变量,与:

没有区别
char *fn(void) {
    char xyzzy = '7';
    return &xyzzy;
}

这是因为,除了某些有限的情况,数组会衰减成指向该数组的第一个元素的指针。

虽然你可以从技术上返回那个指针(它本身并不是无效的),你不能做的是之后取消引用它:

char *plugh = fn();
putchar (*plugh);

这样做是未定义的行为,按照C11 6.5.3.2 Address and indirection operators /4(我的粗体):

  

如果为指针指定了无效值,则一元*运算符的行为未定义。

     

由一元*运算符解除引用指针的无效值包括空指针,不正确地对齐指向的对象类型的地址,以及结束后对象的地址它的一生。

说明问题之后,至少有两种方法可以解决它。

首先,您可以在函数外部创建数组(扩展其范围),并将其地址传递给要填充的函数。

void makeArr (char *stuff) {
    stuff[0]='a';
    stuff[1]='b';
    stuff[2]='c';
    stuff[3]='d';
}

int main(void) {
    char myarr[4];
    makeArr (myarr);
    // Use myarr here
}

其次,您可以在函数内动态分配数组并将其传回。当函数退出时,在堆上创建的项 not 超出范围,但是在尝试使用它之前应该确保分配成功,并且在完成时释放内存它

char *makeArr (void) {
    char *stuff = malloc (4);
    if (stuff != NULL) {
        stuff[0]='a';
        stuff[1]='b';
        stuff[2]='c';
        stuff[3]='d';
    }
    return stuff;
}

int main(void) {
    char *myarr;
    myarr = makeArr();
    if (myarr != NULL) {
        // Use myarr here
        free (myarr);
    }
}

答案 1 :(得分:2)

stuff[]仅在函数调用期间存在于堆栈中,它在返回后被写入。如果你想让它保持值,则声明它static并且它会做你想要的。

然而,整个想法从根本上是蹩脚的,不要在现实生活中这样做。如果你想要一个函数初始化数组,在函数外部声明一个数组,将一个指向这个数组的指针作为参数传递给函数,然后通过该指针初始化一个数组。您可能还希望将数组的大小作为第二个参数传递。

由于您正在学习,故意省略示例代码。

答案 2 :(得分:1)

您的数组stuff在本地定义为函数makeArr。你不应该指望它能够超越那个功能的生命。

char * makeArr(void){
  char stuff[4];

相反,试试这个:

char * makeArr(void){
  char *stuff=(char*)calloc(4, sizeof(char));

这会动态创建一个数组,直到你free()为止。