Как получить доступ к данным другой переменной, указав на слабый байт в структуре? - PullRequest
0 голосов
/ 28 сентября 2019
#include <stdio.h>
#include <stdlib.h>

struct someStruct {
    int ivar;
    char cvar;
    float fvar;
};

main(argc,argv)
const char** argv;
{
    struct someStruct someObj;
    someObj.ivar = 1;
    someObj.fvar = 2.3;
    someObj.cvar = 'r';
    printf("%u\n",&someObj.fvar);
    printf("%u\n",(&someObj.cvar + 4));
    printf("%f\n",*((&someObj.cvar) + 4));
    printf("%f\n",someObj.fvar);
}

Это программа, которую я написал, которая пытается получить доступ к адресу fvar, добавив 4 к адресу char.Я знаю концепцию вялого байта.Я пытался получить доступ к этой памяти, и вот!он напечатал адрес правильно.

printf("%u\n",&someObj.fvar);
printf("%u\n",(&someObj.cvar + 4));

Оба печатают один и тот же адрес.

Затем я попытался получить доступ к fvar следующим образом:

printf("%f\n",*((&someObj.cvar) + 4));
printf("%f\n",someObj.fvar);

и

0.000000
2.300000

были моими результатами.

Затем я понял, что char * и float * интерпретируются по-разному.

Итак, я попробовал все виды типов: от char * до float * до float, а также от char до float * до floatи это также во всех возможных точках, таких как, например, typecasting the returned address to float, с использованием 4.0 вместо 4 (который, как я понял, не должен был работать ... и не работал) и т. д.

Он почему-то просто не печатает 2.300000 и продолжает печатать 0.000000

Где я пропускаю концепцию?

Обратите внимание, что у меня есть 64-bit MinGW и добавляется slack-byte(Я знаю, что некоторые нет), который я уже подтвердил:

printf("%u",sizeof(someObj.ivar));
printf("%u",sizeof(someObj.fvar));
printf("%u",sizeof(someObj.cvar));
printf("%u",sizeof(someObj));

, что дает 4, 4, 1 и 12 ....(sizeof(char) + 3) соответственно.

PS Я знаю, что это ужасная идея, но именно так я обычно изучаю концепции XD

1 Ответ

0 голосов
/ 28 сентября 2019

Предполагая, что верно следующее:

 &someObj.cvar + 4 == &someObj.fvar

вы можете привести значение указателя к правильному типу:

printf("%f\n", *(float*)((&someObj.cvar) + 4));

(&someObj.cvar) - указатель на char,так что *(&someObj.cvar) это char.Спецификатор %f printf ожидает double или float, передача char недопустима.Примечание: float при передаче в функциях с переменными числами в качестве одного из аргументов в параметре многоточия неявно преобразуется в double, см. Пример. cppreference неявных преобразований .Вы должны передать double или float %f, а не char.

Примечания:

main(argc,argv)
const char** argv;
{

Не использовать неявное int объявлениеи старый, устаревший, устаревший стиль объявления функций.Используйте обычный стиль:

int main(int argc, char **argv) {
  • printf("%u\n",&someObj.fvar); - неопределенное поведение.%u ожидает unsigned char, а не float *.Вы можете напечатать указатель void*, используя спецификатор %p: printf("%p\n", (void*)&someObj.fvar); или привести его к unsinged int: printf("%u\n", (unsigned int)(uintptr_t)(void*)&someObj.fvar);

  • C имеет макрос offsetof, объявленный в stddef.h для доступа к количеству "свободных байтов" (мне больше нравится название "отступающие байты").Вы можете: printf("%f", *(float*)((char*)&someObj + offsetof(struct someStruct, fvar)));

...