2011-12-15 4 views
5

Рассмотрим следующий код:C - возвращает указатель обугленного без таНос

char* pointerTesting(void) { 

    char* test = "hello"; 
    return test; 
} 

int main() { 

    char* string = pointerTesting(); 
    printf("string: %s\n", string); 
} 

Это не имеет никаких проблем компиляции и запуска. Однако, по моему мнению, это не должно работать, поскольку память, выделенная указателю test, находится в стеке и уничтожается при возврате на главную.

Итак, вопрос в том, как это удается работать без malloc в функции pointerTesting()?

+3

См. Http://stackoverflow.com/questions/2589949/c-string-literals-where-do-they-go и множество похожих вопросов по этой теме в stackoverflow. – jman

+0

* указатель * выделяется в стеке (для типичных реализаций), но вы не возвращаете указатель, а только копию, если его значение. Это похоже на 'int n = 42; return n; '. Это распределение того, что указывает на это. –

ответ

13

В этом случае строка "hello" хранится в глобальной памяти *. Так вот уже выделено.

Поэтому он по-прежнему действует, когда вы возвращаетесь из функции.

Однако, если вы сделали это:

char test[] = "hello"; 
return test; 

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

* Хотя обычно это так, стандарт не говорит, что он должен храниться в глобальной памяти.
Но важная часть состоит в том, что время жизни строкового литерала - это продолжительность всей программы. (см. комментарии)

+0

Я был бы счастливее, если бы в вашем ответе упоминалось, что «привет» 'находится в глобальной памяти из-за несчастного случая реализации и _not_ из-за запрещенного поведения в любом стандарте. – sarnold

+0

@sarnold Согласен, должен ли я изменить его на «* обычно * хранится в глобальной памяти»? Или я должен сказать: «хранится * в другом месте»? – Mysticial

+0

Мне нравится звездочка, которую у вас есть. :) Благодаря! – sarnold

2

Фокус в том, что память, на которую ссылается тест, не находится в стеке, как вы ожидаете. См. String literals: Where do they go? для некоторых объяснений.

5

Вы вернув значение из test, который является адрес первого символа в строке буквальным "hello" (который, как и все строковые литералы, хранится в виде массива char таким образом, что он доступен на время жизни программы). Если вы пытались вернуть адрес из test для последующего использования, то да, у вас возникнут проблемы.

Теперь следующий фрагмент кода будет не работы:

char *pointerTesting(void) 
{ 
    char test[] = "hello"; 
    return test; 
} 

В этом случае, вы пытаетесь вернуть адрес первого элемента в объекте массива, который является локальным для функции, которая будет быть недействительным после выхода из функции. Помните, что в большинстве контекстов выражение типа «N-element array of T» будет заменено выражением типа «указатель на T», значением которого является адрес первого элемента в массиве.

Смежные вопросы