Этот вопрос состоит из двух частей. Во-первых, как вы маскируете два 32-разрядных целых числа в 64-разрядное длинное целое число?
Как уже говорили другие, допустим, у меня есть функция, которая принимает координаты X и Y и возвращает longint, представляющий линейное значение этой точки. Я склонен называть это линеаризацией двумерных данных:
public long asLong(int x, int y) {
return ( ((long)x) << 32 ) | y;
}
public int getX(long location) {
return (int)((location >> 32) & 0xFFFFFFFF);
}
public int getY(long location) {
return (int)(location & 0xFFFFFFFF);
}
Простите, если я параноидален по поводу порядка операций, иногда другие операции более жадные, чем <<, что заставляет вещи перемещаться дальше, чем они должны. </p>
Почему это работает? Когда это может потерпеть неудачу?
Удобно, что целые числа имеют тенденцию быть точно половиной размера longints. Что мы делаем, это приводим x к long, сдвигаем его влево до тех пор, пока он полностью не окажется слева от y, а затем выполняем операцию объединения (OR), чтобы объединить биты обоих.
Давайте представим, что это 4-разрядные числа, объединяемые в 8-разрядное число:
x = 14 : 1110
y = 5 : 0101
x = x << 4 : 1110 0000
p = x | y : 1110 0000
OR 0101
---------
1110 0101
Между тем обратное:
p = 229 : 1110 0101
x = p >> 4 : 1111 1110 //depending on your language and data type, sign extension
//can cause the bits to smear on the left side as they're
//shifted, as shown here. Doesn't happen in unsigned types
x = x & 0xF:
1111 1110
AND 0000 1111
-------------
0000 1110 //AND selects only the bits we have in common
y = p & 0xF:
1110 0101
AND 0000 1111
-------------
0000 0101 //AND strikes again
Такой подход появился очень давно, в средах, в которых нужно было выжать каждый бит из пространства хранения или передачи. Если вы не находитесь во встроенной системе или не сразу упаковываете эти данные для передачи по сети, практичность всей этой процедуры начинает очень быстро снижаться:
- Это слишком много работы только для упаковки возвращаемого значения, которое почти всегда нужно немедленно распаковывать и читать вызывающей стороне. Это все равно, что вырыть дыру и заполнить ее.
- Это значительно снижает читабельность вашего кода. "Какой тип возвращается?" Э-э ... инт ... и еще один инт ... в длинном.
- Это может привести к появлению трудно отслеживаемых ошибок. Например, если вы используете неподписанные типы и игнорируете расширение знака, то позже переходите на платформу, которая заставляет эти типы дополнять два. Если вы сэкономите longint и попытаетесь прочитать его позже в другой части вашего кода, вы можете столкнуться с ошибкой off-by-one в битовом сдвиге и потратить час на отладку вашей функции только для того, чтобы узнать, что это неправильный параметр.
Если это так плохо, каковы альтернативы?
Вот почему люди спрашивают вас о вашем языке. В идеале, если вы находитесь в C или C ++, лучше сказать
struct Point { int x; int y; };
public Point getPosition() {
struct Point result = { 14,5 };
return result;
}
В противном случае в HLL, таких как Java, вы можете использовать внутренний класс для достижения той же функциональности:
public class Example {
public class Point {
public int x;
public int y;
public Point(int x, int y) { this.x=x; this.y=y; }
}
public Point getPosition() {
return new Point(14,5);
}
}
В этом случае getPosition возвращает Example.Point - если вы продолжаете часто использовать Point, продвигайте его до полного собственного класса. На самом деле, в java.awt уже есть несколько классов Point, включая Point и Point.Float
Наконец, многие современные языки теперь имеют синтаксический сахар для упаковки нескольких значений в кортежи или непосредственного возврата нескольких значений из функции. Это своего рода последнее средство. По моему опыту, всякий раз, когда вы притворяетесь, что данные не такие, как , равны , вы сталкиваетесь с проблемами в будущем. Но если ваш метод обязательно должен вернуть два числа, которые на самом деле не являются частью одних и тех же данных , то для этого лучше использовать кортежи или массивы.
Ссылку на кортеж c ++ stdlib можно найти по адресу
http://www.cplusplus.com/reference/std/tuple/