Добавить 0 отступов к адресу указателя - PullRequest
0 голосов
/ 15 февраля 2020

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

Но я не получаю его запустить, как я считаю, мой адрес усекается, т. е. 0 в адресе удаляются.

Есть ли какой-нибудь способ, которым я могу поддерживать 0, или есть способ, которым я могу напечатать приведение моего адреса, хранящегося в buff, к указателю?

#include <stdio.h>
#include <stdint.h>

int main(int argc, char *argv[]) {
    int address = 200000000;
    char buff[80];
    sprintf(buff, "0x%012x", address);
    printf("%s\n", buff);

    uint32_t * const Value = (uint32_t *)(uintptr_t)buff;
    // *Value = 10;

    printf("%p\n", Value); // Value is now storing the value of the variable buff, I dont want this

    uint32_t *const Value2 = (uint32_t *)(uintptr_t)0x00000bebc200;

    printf("%p\n", Value2); // my address gets truncated, dont want the address to be truncated
}

Ответы [ 2 ]

0 голосов
/ 15 февраля 2020

Если %p представляет только 8 шестнадцатеричных цифр для адреса, то это потому, что указатель на вашей платформе составляет только 32 бита, и в этом случае начальные нули не имеют смысла, так как нет линий шины адреса от A32 до A40 до установить на ноль. Биты не «усечены», их нет на первом месте.

Если по какой-то странной причине вам нужно sh представить адрес в виде 48 бит (12 шестнадцатеричных цифр) на платформе, где 32 битов тогда достаточно:

uintptr_t address = 200000000u ;
uint32_t* const Value = (uint32_t *)address ;
printf( "0x%12.12lX\n", (uintptr_t)Value ) ;

Выходы:

0x00000BEBC200 

Но это только вопрос представления, значения в address и Value неизменны и остаются 32 битами .

0 голосов
/ 15 февраля 2020

Нет необходимости предотвращать усечение вашего указателя.

При компиляции для 64-битного указатель будет иметь 64-битный размер. Это означает, что он содержит число типа 0x0123456789ABCDEF.

Тем не менее, выходной форматер %p отбрасывает любые начальные 0, поскольку они не изменяют поведение вашей программы. Это похоже на сравнение 0x42==0x0042.


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

Компьютер сохраняет ваш адрес в двоичном формате , В памяти ваш адрес 200000000 будет сохранен как 0b1011111010111100001000000000.

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

Компьютер не заботится, если вы вводите десятичные, шестнадцатеричные или двоичные числа, в памяти он всегда будет работать с двоичным представлением.

Это означает, что вы можете напрямую следовать совету вашего связанного ответа

#include <inttypes.h> // defines PRIxPTR, see comments of @chqrlie and @JonathanLeffler

uintptr_t address= 200000000; // compiler makes sure to convert this to binary for the pc
uint32_t *Pointer = (uint32_t*) address;

printf("0x%" PRIxPTR " address\n", address); // if the ptr size is known, e.g. %lx can be used
printf("%p pointer\n", Pointer);

sprintf преобразует ваше число в Строка ASCII и сохраняет это в бафф. Это означает, что вы не можете разыграть содержимое баффа, чтобы вернуть число. Вам необходимо преобразовать строку в int или строку в шестнадцатеричное ранее.


Edit:

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

 printf("%d\n", address == 200000000); // output true
 printf("%d\n", address == 0xbebc200); // output true
 printf("%d\n", address == 0x00000bebc200); // output true
 printf("%d\n", address == 0b1011111010111100001000000000); // output true
...