Проблема выражения оператора GCC - PullRequest
3 голосов
/ 15 января 2012

Я только что прочитал о расширении выражений операторов в GCC и обнаружил неожиданное поведение при его использовании.

Пожалуйста, обратите внимание на этот пример:

#include <stdio.h>

int main(void)
{

    char* res1 = ({
                        char arr[] ={'h', 'e', '\0'}; // was char *arr[]
                        arr[0] = 'x';
                        char* ptr = arr;
                        ptr;
                 });


    char* res2 = ({
                        char arr[] ={'h', 'e', '\0'}; // was char *arr[]
                        arr[0] = 'X';
                        char* ptr = arr;
                        ptr;
                 });

    printf ("%s %p\n", res1, res1);
    printf ("%s %p\n", res2, res2);

    return 0;
}

Вывод:

X 0x7fff93098160
X 0x7fff93098160

Я заметил, что переменные arr в первом блоке и arr во втором блоке занимают один и тот же адрес памяти.

Почему это происходит ??

Ответы [ 3 ]

3 голосов
/ 15 января 2012

Насколько я понимаю, область действия переменных, определенных в выражениях операторов, - это просто сами выражения операторов. То есть, когда res1 инициализируется, массив уже находится вне области видимости, и указатель указывает на нераспределенную память. Массив во втором выражении оператора занимает одну и ту же память. Это на самом деле мало чем отличается от следующего кода:

char* res1;
{
  char arr[] ={'h', 'e', '\0'};
  arr[0] = 'x';
  char* ptr = arr;
  res1 = ptr;
}

char* res2;
{
  char arr[] ={'h', 'e', '\0'};
  arr[0] = 'X';
  char* ptr = arr;
  res2 = ptr;
}

printf ("%s %p\n", res1, res1);
printf ("%s %p\n", res2, res2);
2 голосов
/ 15 января 2012

Оба вхождения arr являются объектами массива с автоматической продолжительностью хранения;они локальны по отношению к включающему блоку { ... } в выражении оператора.

Каждое выражение оператора захватывает адрес этой локальной переменной;этот адрес сохраняется в res1 и res2 and used *after* the end of the block, when the object arr` больше не существует .

Это та же проблема, что и функция, возвращающая адрес локальной переменной.Адрес становится недействительным, когда переменная перестает существовать, а поведение программы не определено.

Так что не делайте этого.

2 голосов
/ 15 января 2012

Оба массива являются локальными для выражений операторов, и память, которую они занимают, может быть повторно использована после окончания выражения.В этом случае он используется повторно.

Если бы вы обращались к этим значениям указателя или использовали их, вы бы вызывали неопределенное поведение, поэтому их равенство не имеет значения.

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