2012-05-07 3 views
0

Есть ли разница между двумя приведенными ниже функциями, в обоих случаях не возвращается адрес локальной переменной, но использование f1() fn возвращает правильное значение 4, но не f2(). Также в третьем случае я прав, что строковая константа не хранится в стеке, поэтому, когда мы возвращаем указатель, она будет работать нормально. Также тогда, где хранятся строковые константы?Строковое постоянное хранилище

int* f1() 
{ 
    int* a=(int*)4; 
    return a; 
} 

int* f2() 
{ 
    int a=4; 
    return &a; 
} 

char* f3() 
{ 
    char* p="abcd"; 
    return p; 
} 
+0

Есть ли разница между двумя функциями - и вы дали три функции! :) – tuxuday

+1

Для записи вам не следует возвращать указатели на такие переменные стека. Эта память, скорее всего, будет использована для чего-то еще после выхода функции. –

+0

Не нужно было комментировать комментарий «это домашнее задание» на данный момент lol – UNECS

ответ

6

Существуют различия между всеми из них:

  1. первом возвращает int * со значением 4, обратите внимание, что он не указывает на переменную со значением 4, но по адресу 4.
  2. Вторая возвращает указатель на переменную, которая содержит 4, но на самом деле этот указатель недопустим, поскольку он указывает на локальную переменную уже возвращенной функции, и любое ее использование приведет к неопределенному поведению.
  3. Третий возвращает указатель на char (по определению), но на самом деле это указатель на строковый литерал (по реализации). Проблема с ним заключается в том, что при возврате функции char *, а не в const char *, можно попытаться изменить буфер возврата, который снова приведет к неопределенному поведению.
+0

вы, ребята, слишком быстр ... – UmNyobe

+0

Я знаю, что даже не начал набирать ответ – UNECS

+0

В f3() где находится Строковый литерал фактически хранится (а не в стек справа?), поскольку мы можем получить доступ даже после возвращения функции. Также почему строковый литерал const char * - это просто языковая конструкция или что-то еще ??? – grv

1
  • f1 бросает значение 4 на адрес, в сущности, указывая где-то в памяти.
  • f2 Возвращает адрес локальной переменной. Выделение этого указателя будет неопределенным поведением.
  • f3 - указатель на строковый литерал. Это действительный указатель, поскольку время жизни строкового литерала совпадает с временем жизни программы (статической продолжительности хранения). Где именно этот литерал хранится, определяется реализацией. Манипулирование содержимым строкового литерала является неопределенным поведением.
+0

Не указывает f1 на адрес 0x4 (а не «где-то в памяти»)? –

+0

@ScottWilson Исправить. Учитывая виртуальную память, я считаю, что это «где-то» :). Каждый указатель, который вы не получаете безопасным способом или хардкорным знанием лежащей в основе машины, настолько бесполезен, что его ценность не имеет большого значения. – pmr

+0

Так что все строковые литералы имеют статическое хранилище? Также почему строковый литерал, определенный как const char *, - это просто языковая конструкция или есть какая-то причина ?? – grv

0
  • В f1 вы явно указать адрес 4 и возвратил же, а не значение по этому адресу.
  • Локальные переменные выделяются в стеке, поэтому в f2, где вы вернули &a, вы возвращаете адрес в стеке, а не 4, который присутствует по этому адресу в памяти. Де-ссылка на этот адрес приводит к неопределенному поведению, поскольку функция сбрасывается со стека.
  • Строковые литералы выделяются на только для чтения секции данных и обратите внимание на разницу между

    char arr[]="abcd"; и char *ptr="abcd";

    Первый представляет собой массив символов и выделяется в стеке, а второй является указателем на строку literal, который (буквальный не указатель) выделяется в разделе данных только для чтения.

PS: Я предположил GCC/x86 здесь.

+0

В 'f2' нет' can'. Выражение разыменования этого указателя является UB, независимо от того, что было очищено или нет. – pmr

+0

согласен и отредактирован :) – toofast1227

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