ставит () указатель на C - PullRequest
0 голосов
/ 26 марта 2010

У меня есть функция:

char *make_text(void)
{       
        char txt[MAXLEN];
        //make something
        return txt;
}

Вот моя основная программа:

int main(void)
{
        char *s = make_text();
        puts(s);
        getch();
        return 0;
}

puts(s) возвращает 0 и ничего не печатается. Что произошло?

Ответы [ 7 ]

3 голосов
/ 26 марта 2010

Память, выделенная вами в функции make_text, была освобождена в конце make_text. Таким образом, вы не должны пытаться получить к нему доступ.

Вы можете выделить память, используя malloc или calloc, чтобы она не освобождалась автоматически.

1 голос
/ 26 марта 2010

make_text возвращает txt, который выделяется в локальном хранилище в функции make_text. Когда возвращается make_text, все вещи в локальном хранилище этой функции очищаются. Для этого вам нужно использовать динамическое хранилище с malloc():

char *make_text(void)
{
    char *txt = malloc(MAXLEN);
    // do stuff
    return txt;
}

Память, выделенная с помощью malloc(), не исчезает при возврате функции. Это означает, что C не знает, когда именно безопасно освободить, поэтому, когда вы закончите с этим, вы должны вызвать free() на txt, чтобы вручную освободить память. В противном случае у вас будет утечка памяти.

1 голос
/ 26 марта 2010

Возвращение указателя на значение в стеке - плохая идея, и, вероятно, не сработает.

0 голосов
/ 27 марта 2010

Вы можете вернуть указатель на статическую переменную, например:

char *make_text(void)
{       
        static char txt[MAXLEN];
        //make something
        return txt;
}

(Конечно, приведенный выше код не является потокобезопасным).

0 голосов
/ 27 марта 2010

Автоматические переменные (локальные переменные и параметры для вызываемых функций) должны храниться где-то. Это где-то в стеке (или в регистрах, но это сейчас не важно). Вот небольшая упрощенная аннотация стека о том, как работает ваша программа:

int main(void) 
{ 
// [_start+0x040 ]
// This is just the address of some code just after the code that called main.
// You immediatly call make_text, so lets go there.
   char *make_text(void) 
   {
// [_start+0x040, main+0x004] 
// this is the address within main that make_text returns to
      char txt[MAXLEN];
// [_start+0x040, main+0x004, txt[MAXLEN-1], ..., txt[0]  ]
      return txt;
// This empties this function's data and pops the return address into
// the instruction pointer.
   } 
   char *s = make_text(); 
// [_start+0x040, &txt[0] ]
// Now, back in main we have an address to something that is not on the stack
// anymore.
// Random things happen to memory that used to be part of the stack.
        puts(s); 
// [_start+0x040, &txt[0], main+0x008 ]
// puts() here tries to print a string containing random data which also happens
// to be the same memory that puts is trying to use as its local variables.
        getch();
// getch() is the only part that probably worked   
0 голосов
/ 26 марта 2010

Вы возвращаете переменную txt из make_text, которая является локальной для функции. Результаты этого не определены, так как txt выйдет из области видимости, когда функция вернется.

Вместо этого вы можете передать txt в качестве аргумента:

void make_text(char * txt)
{       
        //make something
        sprintf(txt,"%s","Something!");

}

А главное:

int main(void)
{
        char s[MAXLEN];
        make_text(s);
        puts(s);
        getch();
        return 0;
}
0 голосов
/ 26 марта 2010

когда вы объявляете char txt [MAXLEN]; внутри области видимости, в этом случае функция make_text, вектор txt символа char будет действителен только в течение времени жизни make_text.

Вам нужно будет использовать динамическое распределение.

char *make_text(void)
{       
        char *txt = (char *) malloc(sizeof(char) *MAXLEN);
        //make something
        return txt;
}

Тогда вам придется освободить память после того, как текст был использован:

char *s = make_text();

free(s);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...