печатать биты пустого указателя

Если я создам пустой указатель и выделю участок памяти для этого пустого указателя, как я могу распечатать отдельные биты, которые я только что выделил?

Например:

void * p;
p = malloc(24);
printf("0x%x\n", (int *)p);

Я хотел бы, чтобы приведенное выше напечатало 24 бита, которые я только что выделил.


person kubiej21    schedule 01.02.2013    source источник
comment
На самом деле вы выделили 24 байта. (Строго говоря, вы выделили место для хранения 24 символов.)   -  person David Schwartz    schedule 02.02.2013


Ответы (6)


size_t size = 24;
void *p = malloc(size);

for (int i = 0; i < size; i++) {
  printf("%02x", ((unsigned char *) p) [i]);
}

Конечно, это вызывает неопределенное поведение (значение объекта, выделенного malloc, имеет неопределенное значение).

person ouah    schedule 01.02.2013
comment
+1, но, возможно, вы могли бы пропустить этот комментарий о неопределенном поведении. Это уже подразумевается в вопросе. ОП хочет знать, как выглядит память сразу после malloc. - person s.bandara; 02.02.2013
comment
@s.bandara Почему это неявно? ОП, кажется, даже не знает об этом. - person ; 02.02.2013
comment
@s.bandara Мне это нужно, иначе кто-то понизит этот ответ, потому что он вызывает неопределенное поведение;) - person ouah; 02.02.2013
comment
Вот что я подумал, это похоже на приговор CYA, и я думаю, что это должно уйти. @ H2CO3, если цель состоит в том, чтобы проверить память, выделенную malloc, это даже не неопределенное поведение в этом смысле. Скорее, результат будет неопределенным, но таково, например, поведение scanf. - person s.bandara; 02.02.2013
comment
Неопределенное значение не означает неопределенное поведение. Имеет ли это? Конечно, вы можете читать что угодно, но это не заставит вашу программу сойти с ума. - person zch; 02.02.2013
comment
@s.bandara Эй, нет. Это неопределенное поведение. Я знаю разницу между неопределенным поведением и неопределенным [поведением | результат | значение | порядок оценивания]. И этот предназначен для вызова UB. - person ; 02.02.2013
comment
Чтение @s.bandara неопределенного значения вызывает неопределенное поведение: неопределенное поведение: поведение при использовании непереносимой или ошибочной программной конструкции ошибочных данных или объекта с неопределенным значением - person ouah; 02.02.2013
comment
Ребята, все, что я должен сказать, это то, что вы должны применять это определение в данном конкретном контексте. Вы можете посмотреть память перед инициализацией с помощью отладчика, который делает то же самое, ну и что? поведение undefined не имеет смысла в таком контексте. - person s.bandara; 02.02.2013
comment
@ s.bandara, но отладчик не является реализацией C, поэтому неопределенное поведение не применяется к отладчику. - person ouah; 02.02.2013
comment
Строго говоря, доступ к неопределенным значениям не всегда является неопределенным поведением (и приведенный выше пример не является UB). C99 определяет неопределенное значение либо как неопределенное значение, либо как представление ловушки. Поскольку доступ к памяти через символьный тип не может привести к представлению ловушки, доступ к неопределенному значению через символьный тип не является неопределенным поведением — вы просто читаете неуказанные значения. - person Michael Burr; 02.02.2013
comment
@MichaelBurr, строго говоря, чтение неопределенного значения всегда является UB (поэтому, даже если вы читаете объект unsigned char, и мы знаем, что unsigned char objecst не имеет представлений-ловушек). См. DR#338 http:// open-std. org/jtc1/sc22/wg14/www/docs/dr_338.htm - person ouah; 02.02.2013
comment
@ouah: так что я вижу, что C11 (из-за этого DR) добавил поведение UB для чтения через тип символа в определенных ситуациях, однако «новый» UB применяется только к доступу к автоматическому, адрес которого никогда не был взят. Блок с malloc() не попадает в эту категорию. Так что думаю, что ваш пример все-таки не УБ. - person Michael Burr; 02.02.2013

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

void *buf = malloc(24);
unsigned char *ptr = buf;
for (int i = 0; i < 24; i++) {
    printf("%02x ", (int)ptr[i]);
}

free(buf);
printf("\n");
person Community    schedule 01.02.2013

void print_memory(void *ptr, int size)
{ // Print 'size' bytes starting from 'ptr'
    unsigned char *c = (unsigned char *)ptr;
    int i = 0;

    while(i != size)
        printf("%02x ", c[i++]);           
}

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

print_memory(p, 24);
person Nik Bougalis    schedule 01.02.2013
comment
Без увеличения i это никогда не вернется. - person Gary; 02.02.2013

void* p = malloc(24); выделяет 24 байта и сохраняет адрес первого байта в p. Если вы попытаетесь напечатать значение p, вы на самом деле напечатаете адрес. Чтобы напечатать значение, на которое указывает ваш указатель, вам нужно разыменовать его, используя *. Также старайтесь избегать указателей void, если это возможно:

unsigned char *p = malloc(24);
// store something to the memory where p points to...
for(int i = 0; i < 24; ++i)
    printf("%02X", *(p + i));

И не забудьте free память, выделенную malloc :)

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

person LihO    schedule 01.02.2013

malloc размещает в байтах, а не в битах. И что бы это ни было, ваш printf пытается напечатать адрес в памяти.

person sr01853    schedule 01.02.2013

malloc выделяет байты.

 for (i = 0; i < 24; ++i) printf("%02xh ", p[i]);

напечатает 24 байта. Но если привести к int, вам нужно будет настроить цикл:

 for (i = 0; i < 24; i += sizeof(int)) printf("%xh", *(int *)&p[i]);

Но тогда, если вы знаете, что вам нужен int, почему бы просто не объявить его как int?

person Gary    schedule 01.02.2013
comment
Я признаю, что нет, я не понимаю арифметику указателей. Мне нужно использовать указатель void из-за спецификаций более крупного задания. - person kubiej21; 02.02.2013
comment
@ kubiej21 kubiej21 Я отправлял это автору этого ответа. - person ; 02.02.2013
comment
Итак, опечатка получает ехидное замечание? Вы уверены, что понимаете взаимодействие с людьми? - person Gary; 05.02.2013