Определить указатель на адрес памяти и распечатать содержимое C

#c #pointers

#c #указатели

Вопрос:

Я хочу распечатать данные с заданных адресов памяти.

Используя этот код, я могу определить переменную, определить указатель на нее и распечатать ее содержимое с помощью указателя.

 char buf[100];
void *p = buf;

strcpy(p, "Test string");

printf("Address: %Xn", amp;buf);
printf("Contents: %cn", p);
 

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

Комментарии:

1. Печать содержимого случайного (не являющегося частью того, что вы выделили) адреса памяти, является неопределенным поведением.

2. @chris; Память выделена, но спецификация формата неверна.

3. @крис, ну и что? он экспериментирует с неопределенным поведением…

4. @haccks, я предположил, что последняя часть больше намекала на другую память.

5. Спасибо вам за ВСЕ ваши ответы, мне было трудно выбрать что-то конкретное. Я выбрал самого напористого из них. Я еще не закончил свою проблему, она неправильно перебирает адреса памяти, но что-то печатает.

Ответ №1:

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

По сути, четыре части.

  1. Выразите нужный адрес в виде целого числа соответствующего размера.
  2. Преобразуйте целое число в указатель на некоторый тип.
  3. Разыменуйте указатель, чтобы получить значение этого типа.
  4. Выведите значение.
  5. [при желании увеличьте адрес и повторите.]

Для простоты я буду использовать адрес 0x1000 и целочисленное содержимое.

 int address = 0x1000;
int* pcontent = (int*)address;
int content = *pcontent;
printf ("Address %p: content xn", pcontent, content);
 

Следует сделать два замечания.

  1. Это неопределенное поведение, но оно неизбежно, если вы хотите получить результат.
  2. Выбранный мной адрес может быть допустимой памятью или может вызвать ошибку trap, или он может делать что угодно. Вам придется поэкспериментировать с разными адресами, чтобы выяснить, какие.

[Много лет назад я использовал эту стратегию для распечатки всего содержимого памяти на компьютере с объемом памяти всего 96 КБ, что привело к некоторым интересным возможностям взлома. Но я отвлекся.]

Ответ №2:

Вы используете неправильный спецификатор для печати адреса. Используйте %p и приведите аргумент к void * .

 printf("Address: %pn", (void*)buf);  
 

и для печати строки

 printf("Contents: %sn", p);
 

Комментарии:

1. Поскольку buf это массив, buf и amp;buf равны. Это не делает ваш ответ неправильным или что-то в этом роде, но, возможно, вам следует это объяснить.

Ответ №3:

Вы должны определить указатель p как

 char *p = buf;
 

или использовать приведение с последующим увеличением p. Например

 p = ( char *)p   n;
 

Например

 printf( "%sn", ( char *)p   5 );
 

Вы не можете увеличивать / уменьшать указатели типа void * , потому void что в неполном типе.

Также спецификаторы формата в этих вызовах

 printf("Address: %Xn", amp;buf);
printf("Contents: %cn", p);
 

ошибаются.

Если вы хотите распечатать строку , которую вы должны указать %s . если вы хотите напечатать только один символ, то вам следует написать

 char *p = buf;
printf("Contents: %cn", p[0]);
 

или

 void *p = buf;
printf("Contents: %cn", ( ( char *)p )[0]);
 

Ответ №4:

Вы используете %c вместо этого используйте %s для печати строки printf("Contents: %sn", p);

Ответ №5:

Если бы мы хотели печатать случайные байты из памяти, мы бы хотели использовать:

 char *p = buf;

printf("Address:  %pn", p);
printf("Contents: 0xxn", *p);
 

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

Ответ №6:

Вы могли бы попробовать что-то вроде этого:

 void printMemory(void* mem, int bytes){
    char* p = (char*) mem;
    for(int i=0;i<bytes;i  ){
        printf("%x ",p[i] amp; 0xff);
        if(i%8 == 7)
            printf("n");
    }
}
 

Это приведет к печати 8 байт в строке.