Почему (const char *) ptr не считается lvalue - PullRequest
0 голосов
/ 03 июня 2019

У меня есть следующий код (только код ключа) и минимальный пример кода , но он недопустим из-за строки OFFSET_PTR(pFileBothDirInfo->NextEntryOffset, pFileBothDirInfo); (ошибка IDE: выражение должно быть изменяемым значение. Компиляция: ошибка C2106: '=': левый операнд должен иметь значение l.)

char packet_bytes[9] = {0};

int main(int argc, char* argv[]) {
    printf("(int)sizeof(smb2_query_directory_response_t) = %d\n", (int)sizeof(smb2_query_directory_response_t));
    printf("(int)sizeof(smb2_FileBothDirectoryInformation_t) = %d\n", (int)sizeof(smb2_FileBothDirectoryInformation_t));

    const smb2_query_directory_response_t*  pSMB2QueryDirectoryResponse = (smb2_query_directory_response_t*)packet_bytes;
    const smb2_FileBothDirectoryInformation_t *pFileBothDirInfo = pSMB2QueryDirectoryResponse->OutputBufferLength ? REINTERPRET_CAST(const smb2_FileBothDirectoryInformation_t*, pSMB2QueryDirectoryResponse->Buffer) : NULL;
    while (pFileBothDirInfo)
    {
        // ideone runs on linux with a compiler who consider wchar_t 4 bytes?
        // https://stackoverflow.com/questions/16944750/c-unicode-characters-printing
        //wprintf(L"%.*s|%.*s\n", pFileBothDirInfo->FileNameLength/2, pFileBothDirInfo->FileName, pFileBothDirInfo->ShortNameLength/2, pFileBothDirInfo->ShortName);
        if (pFileBothDirInfo->NextEntryOffset)
        {
            offset_ptr(pFileBothDirInfo->NextEntryOffset, pFileBothDirInfo);

            const unsigned char *ptrTemp;
            ptrTemp = ((const unsigned char*)pFileBothDirInfo + 10);
            //be equivalent to 
            //((const unsigned char*)pFileBothDirInfo) = ( (const unsigned char*)pFileBothDirInfo + 10 );
            OFFSET_PTR(pFileBothDirInfo->NextEntryOffset, pFileBothDirInfo);
            *((int *)10) = 100;
            printf("ptrTemp = %p", ptrTemp);
        } 
        else
        {
            break;
        }
    }
    return 0;
}

Я также ссылался на выражения L-значения и R-значения

У lvalue есть адрес, к которому ваша программа может получить доступ. Примеры выражений lvalue включают имена переменных, включая const переменные, элементы массива, вызовы функций, которые возвращают ссылку на lvalue, битовые поля, объединения и члены класса.

и Выражения L-Value и R-Value , в которых указано, что следующий код допустим, но IDE VS2015 и его компилятор выдавали ошибку.

char *p;
short i;
long l;

(long *)p = &l;     /* Legal cast   */
(long)i = l;        /* Illegal cast */

Похожая ошибка при использовании ideone компилятора:

Compilation error   #stdin compilation error #stdout 0s 15232KB
prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:259:33: error: lvalue required as left operand of assignment
    OFFSET_PTR(pFileBothDirInfo->NextEntryOffset, pFileBothDirInfo);
                                 ^
prog.cpp:235:107: note: in definition of macro ‘OFFSET_PTR’
 #define OFFSET_PTR(byte_offset, ref_ptr) ((const unsigned char*)ref_ptr = (const unsigned char*)ref_ptr + byte_offset)

Я думаю, (const unsigned char*)pFileBothDirInfo имеет адрес, но почему он не считается lvalue?

Ссылки

Ответы [ 2 ]

2 голосов
/ 03 июня 2019

Я думаю, (const unsigned char*)pFileBothDirInfo имеет адрес, но почему он не считается lvalue?

Вы ошибаетесь.

Результат выражения (T) cast-выражение имеет тип T. Результатом является lvalue, если T является [тип ссылки lvalue или ссылка rvalue на тип функции], и xvalue, если T - это [стандартная ссылка на тип объекта]; в противном случае результат является prvalue.

[expr.cast] ([] скобки добавлены к групповым предложениям)

const unsigned char* не является каким-либо ссылочным типом, поэтому результат является prvalue.

Вы создаете значение типа const unsigned char*. Почему это связано с хранением объекта типа const smb2_FileBothDirectoryInformation_t *?

MSVC допускает (long *)p = &l; в качестве расширения.

1 голос
/ 03 июня 2019

OFFSET_PTR не работает.

Да, pFileBothDirInfo имеет адрес, но (const unsigned char*)pFileBothDirInfo является временным.Значение.Вот что происходит, когда вы выполняете приведение к типу значения!Вы получаете свежий объект нового типа.

Другая проблема заключается в том, что это const.Вы не можете изменить const вещи.Вот что это значит.

...