为什么这个程序的输出是垃圾?

时间:2018-01-22 00:45:52

标签: c pointers

我想知道为什么输出是垃圾?我该如何解决这个问题?

#include<stdio.h>

char *Func(void);
int main()
{
    char *string1;

    string1 = Func();
    puts(string1);

    return 0;
}

char *Func(void)
{
    char string2[10]="medo";
    return string2;
}

2 个答案:

答案 0 :(得分:2)

因为string2仅在Func范围内有效。

将数组分配给指针,将其传递给函数或在函数返回指针时与return一起使用时,数组会衰减为指针。

衰减为指针的数组意味着它被转换为指针并且指针指向数组的第一个元素。

使用这样的数组:

int arr[] = { 1, 2, 3 };

这些是等价的:

int *p1 = arr;
int *p2 = &arr[0];

Func的问题在于它返回的指针指向仅在Func运行时有效的内存位置。一旦Func返回,它就不再有效,程序流可能会立即替换这些值。

main功能中,您将此指针传递给printf,因为string1所指向的位置在main中无效(仅限Funcmain中有效,你会得到垃圾。实际上这是未定义的行为,并且 medo 也可以打印出来。

如何修复它:在Func中声明一个数组,将其传递给Func,让#include<stdio.h> #include<string.h> Func(char* string2); int main() { char string1[20]; Func(string1); puts(string1); return 0; } void Func(char *string2) { strcpy(string2, "medo"); } 使用 传递数组并返回:

<RadDataForm *ngFor="let item of menus" tkExampleTitle tkToggleNavButton [source]="item">
    <TKEntityProperty tkDataFormProperty name="name" [isReadOnly]="isReadOnly" displayName="Name" index="0"></TKEntityProperty>
    <TKEntityProperty tkDataFormProperty name="price" [isReadOnly]="isReadOnly" displayName="Price" index="1"></TKEntityProperty>
    <TKEntityProperty tkDataFormProperty name="image" [isReadOnly]="isReadOnly" displayName="Image" index="2"></TKEntityProperty>
    <TKEntityProperty tkDataFormProperty name="quantity" displayName="Quantity" index="3">
        <TKPropertyEditor tkEntityPropertyEditor type="Stepper"></TKPropertyEditor>
    </TKEntityProperty>
</RadDataForm>

答案 1 :(得分:1)

因为打印时字符串的生命周期已经结束。

局部变量,例如string2中的Func,通常存储在堆栈中,这是一个非常动态的结构,每次调用或返回函数时都会更改。 (程序堆栈的实际行为有点太复杂了,不能在这里详细说明,但请记住,堆栈中的东西不能存放在那里的函数。)

当函数返回时,不再需要string2,因此可能会被垃圾数据覆盖。然而,Func返回指向string2的指针(记住数组的名称是指向其内容的指针) - 因此返回指向堆栈分配的字符串的指针,该字符串被垃圾数据覆盖。打印此指针引用的数据(在main中,通过string1)只打印该垃圾。

有两种方法可以解决这个问题。一种是让调用者处理内存分配,并将分配的区域传递给被调用者,如下所示:

#include <stdio.h>
#include <string.h>

void Func(char *);

int main (void) {
  char string[10];
  Func(string);
  puts(string);
  return 0;
}

void Func (char * string) {
  strcpy(string, "test");
}

...另一种方法是让被调用者处理分配,但记住调用者必须释放它,如下所示:

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

char * Func(void);

int main (void) {
  char * string = Func();
  puts(string);
  free(string);
  return 0;
}

char * Func (void) {
  char * string = malloc(10);
  strcpy(string, "test");
  return string;
}

无论哪种方式都可以解决您的问题,您选择的是设计问题。