#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:
Интересная небольшая проблема. То, что рано или поздно должно произойти с каждым программистом, либо из любопытства, либо из-за ругани.
По сути, четыре части.
- Выразите нужный адрес в виде целого числа соответствующего размера.
- Преобразуйте целое число в указатель на некоторый тип.
- Разыменуйте указатель, чтобы получить значение этого типа.
- Выведите значение.
- [при желании увеличьте адрес и повторите.]
Для простоты я буду использовать адрес 0x1000 и целочисленное содержимое.
int address = 0x1000;
int* pcontent = (int*)address;
int content = *pcontent;
printf ("Address %p: content xn", pcontent, content);
Следует сделать два замечания.
- Это неопределенное поведение, но оно неизбежно, если вы хотите получить результат.
- Выбранный мной адрес может быть допустимой памятью или может вызвать ошибку 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 байт в строке.