Может ли кто-нибудь объяснить это за пределами доступа к массиву в стандартной библиотеке MSVC++?

В Visual Studio реализация type_info, обычно расположенная в C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\typeinfo:

class type_info {
    /* ... */

    _CRTIMP_PURE bool __CLR_OR_THIS_CALL operator==(const type_info& _Rhs) const;

    /* ... */

private:
    void *_M_data;
    char _M_d_name[1];
    __CLR_OR_THIS_CALL type_info(const type_info& _Rhs);

   /* ... */

};

Я заметил, что реализация оператора равенства == использует указатель символа _M_d_name + 1. Может ли кто-нибудь объяснить мне, как это «работает», потому что кажется, что это выходит за пределы массива?

Реализация, C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\crt\src\ti_inst.cpp:

ASSERT_UNMANAGED_CODE_ATTRIBUTE
SECURITYSAFECRITICAL_ATTRIBUTE
bool type_info::operator==(const type_info& rhs) const
{
        return (strcmp((rhs._M_d_name)+1, (_M_d_name)+1)?0:1);
}

Спасибо!


person trev    schedule 25.11.2014    source источник
comment
Это в основном способ написать структуру переменной длины.   -  person T.C.    schedule 25.11.2014
comment
Имейте в виду, что это является частью реализации, которая также включает в себя компилятор и т. д., поэтому они могут делать все, что им нравится, в том числе использовать неопределенное поведение... определенное.   -  person Ben Hymers    schedule 25.11.2014
comment
@Т.С. Спасибо за ваш комментарий. Есть ли шанс, что вы могли бы немного уточнить?   -  person trev    schedule 25.11.2014
comment
@BenHymers Ничто не может определить это поведение в терминах C ++; просто в контексте реализации они знают, что это будет делать на практике.   -  person Lightness Races in Orbit    schedule 25.11.2014
comment
@LightnessRacesinOrbit: это уже его точка зрения: достаточно, чтобы поведение было определено в VC++. Его не необходимо определять в стандартном C++.   -  person MSalters    schedule 25.11.2014
comment
@MSalters: я знаю; Я просто хотел сделать это абсолютно ясным для других читателей.   -  person Lightness Races in Orbit    schedule 25.11.2014


Ответы (1)


Этот трюк предназначен для гибкого элемента массива. Он выделит память для class type_info и строки имени, поэтому (rhs._M_d_name)+1 находится именно там, где находится строка имени. Вот диаграмма, чтобы описать это:

        +------------+ --+           
        |            |   |           
        +------------+               
        |            |   |           
        |            |    ->type_info
        +------------+   |           
+-------+  _M_d_name |   |           
|       +------------+ --+           
+------->            |               
        |            |               
        |            |               
        +------------+               

На самом деле c99 поддерживает эту функцию, а расширение Microsoft позволяет использовать последний элемент C или C++. структура или класс должны быть массивом переменного размера

person jfly    schedule 25.11.2014