2011-02-21 2 views
1

Для распаковки сложных двоичных строк со смешанными удвоениями и целыми числами с использованием Ruby's String.unpack Мне нужно определить смещения внутри двоичной строки. Обычно удваивается 8 байтов, а целые - 4 байта, но для того, чтобы сделать мой код не зависящим от машины, я хотел бы запросить эти размеры из моего кода Ruby.Самый простой способ определить sizeof (double) и sizeof (int) из Ruby?

Каков самый простой способ определить размер целых чисел и удваивается из Ruby, то есть запросить ответ запроса на метод C?

+1

Откуда берутся данные? скрипт Ruby обязательно запускается на архитектуре, которая создает значения? – Christoph

+0

Вы уверены, что это то, что вы хотите сделать? Как указывает @Cristoph, размер зависит от программы и платформы, которые генерируют двоичные строки, а не рубиновую программу и платформу, потребляющую их. Любая спецификация двоичного интерфейса должна иметь явно заданный макет (размер элемента, сущность, заполнение и т. Д.). – AShelly

+0

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

ответ

2

я нашел приемлемое решение, используя Array#pack, обратный метод String#unpack. По упаковкам строки 1 целого числа или 1 двойной, можно определить размер целых чисел и удваивает внутри самого рубина, который дает те же результаты, используя sizeof(int) или sizeof(double) (из-за реализацией Array#pack в C):

[1.to_i].pack("i").size # 4 
[1.to_f].pack("d").size # 8 
0

Мое текущее решение иметь небольшую программу на С, sizeofdouble.c:

#include <stdio.h> 
int main() { 
    printf("%lu", sizeof(double)); 
} 

, которые при компиляции в sizeofdouble исполняемый файл может быть вызван из рубина с

sizeofdouble = `./sizeofdouble`.to_i 

но это уродливое хак , а не чистое решение этой проблемы.

+0

ваша программа C не переносима, так как 'sizeof (long) == sizeof (size_t)' не обязательно истинно; либо использовать модификатор длины 'z' (который не поддерживается повсеместно), либо отбрасывать' unsigned' (нет необходимости в 'unsigned long') – Christoph

1

Я не знаком с языком Ruby или его системой сборки/распределения. Тем не менее, существование Rake предполагает, что можно создавать пользовательские файлы установки пакета - например, конфигурационный файл, который экспортирует результат из следующих команд как рубин констант:

echo __SIZEOF_INT__ | gcc -E -P - 
echo __SIZEOF_DOUBLE__ | gcc -E -P - 
+0

Я не могу получить это, чтобы вывести что-нибудь еще, кроме буквального/оригинального' __SIZEOF_INT__' или '__SIZEOF_DOUBLE__' (с использованием gcc 4.2.1 на mac или gcc 4.1.2 в окне linux с или без' -c'). –

+0

согласно моему google-fu, дата патча с 2007 года; не знаю, когда он был впервые включен в релиз, но я могу подтвердить, что он находится в 4.3.4 ... – Christoph

2

Это настолько очевидно, что я, вероятно, отсутствует пункт:

puts 1.size #=> 4 
puts (256**10 - 1).size #=> 12 
+0

Хех? Размер int (с уверенностью с 'puts 1.to_i.size') приводит к 8 на моей машине (MBP, ruby ​​1.8,7), а не 4, что является' sizeof (int) 'в C. –

+1

I ' Предположим, у вас 64-битный процессор, у меня 32 бит. Я понятия не имею, как C справляется с этим. – steenslag