2016-11-25 5 views
4

Я пытаюсь перенести некоторый код C на Java, однако я изо всех сил пытался выяснить, что делают эти строки кода.char * (Array) cast to unsigned long + 1?

Примечание: rawEntry имеет тип char* и, кажется, в 12 байт, выделенные в качестве такого

char *rawEntry = (char*)malloc(0x000c); 

unsigned long *l; 
unsigned long offset; 

// ... 

l = (unsigned long*) rawEntry + 1; 
offset = ntohl(*l); 

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

offset = (rawEntry[0] << 24) + 
     (rawEntry[1] << 16) + 
     (rawEntry[2] << 8) + 
     (rawEntry[3]) + 
     1; 

Когда представлены следующим массиве,

1 0 0 0 0 0 0 0 0 0 11 -38 

С код выхода 3034 в качестве смещения
кода выходов Мои Java 16777217, или 1, если перевернуть обратный порядок байт

+0

'rawEntry' может быть' 'символ * или массив' char', но не оба. Различие может не иметь значения для вашей конкретной задачи, но опять же, возможно. Нам трудно сказать, потому что вы на самом деле не дали нам много работы. –

+0

'char * rawEntry = (char *) malloc (0x000c);' - так выделяется 'rawEntry' @JohnBollinger – CraftedCart

ответ

5

Это выражение

l = (unsigned long*) rawEntry + 1; 

отливки rawEntry - указатель на тип, размер 8 байт в вашей системе. После этого, добавление 1 означает добавление 8 байт, поэтому фактическое преобразование выглядит следующим образом:

offset = (Byte.toUnsignedInt(rawEntry[ 8]) << 24) + 
     (Byte.toUnsignedInt(rawEntry[ 9]) << 16) + 
     (Byte.toUnsignedInt(rawEntry[10]) << 8) + 
     (Byte.toUnsignedInt(rawEntry[11]) << 0); 

следующие четыре байта интерпретируются как 3034:

0 0 11 -38 

Вы должны быть в состоянии упростить это далее используя ByteBuffer:

int offset = ByteBuffer.wrap(rawEntry, 8, 4).getInt(); 
+0

Затем он считывает 8 нулей. –

+0

Yea ... Просто получите 0 ... – CraftedCart

+0

Напротив, операторы литья имеют более высокий приоритет, чем добавление. Выражаемое выражение эквивалентно '((unsigned long *) rawEntry) + 1'. И, конечно, нужно помнить о семантике добавления указателя. –

2

Прежде чем идти дальше, важно отметить, что этот код зависит от фактического величина long на вашей платформе. На 64-битных платформах longs составляют 64 бита, то есть long занимает до 8 байтов. С другой стороны, ntohl преобразует «длинную сеть» длиной 32 бита (4 байта).

Предполагая rawEntry является {1,0,0,0,0,0,0,0,0,0,0xB,0xDA,…} (0xB является базой 16 эквивалент 11, 0xDA является базой 16 (шестнадцатеричное) unsigned значение, которое соответствует -38)

l = (unsigned long*) rawEntry + 1; 

на самом деле означает, что l относится ко второму unsigned long , Это пропускает первые 8 байт от rawEntry и l, затем указывает на часть {0,0,0xB,0xDA,…}. Теперь *l - это unsigned long, представленный байтовой последовательностью {0,0,0xB,0xDA,…}, и это зависит от вашей архитектуры. Если вы находитесь на маленькой конечной машине, которая будет 0x ... DA0B0000 (эллипсис, потому что конец массива не показан, это неопределенное поведение). И теперь ntohl просто сохранит последние 32 бита и инвертирует порядок байтов, приводящий к 0x00000BDA или 3034 в базе 10.

Самый простой способ, чтобы написать это в Java будет

offset = (rawEntry[8] << 24) + 
     (rawEntry[9] << 16) + 
     (rawEntry[10] << 8) + 
     (rawEntry[11]);