Гуру, усли такие есть, поделитесь как сбить размер указателя на архитектуре x86-64 с 8 до 4 байт? компилим g++, опция -m32 под фряхой некатит совсем, другие методы есть?
Это никак не получится. Если есть 64-битное адресное пространство, то указатели будут 8 байтов, никуда от этого не деться. Можно только скомпилить в 32-битном режиме.
А ручками? моно? нет это не порт это просто быдло-гиганский сеточный массив для задач моделирования. Они там на соседей указывают и от этого не спрятаться не дется...
Используй в качестве указателя номер элемента массива, например. Или (как в ДОСе бывало), смещение относительно базы. Или еще что придумай -- простор для творчества необычайный! -- у меня, если память экономить надо, указатели по 2-4 бита бывают...
Это вообщето динамический массив, и не квадратный (в смысле прямоугольный), так что там указатели на соседей посуществу, ибо их надо нати быстро (а то перебирать односвязанный спивок 9000000 раз грустно). вот и выходит что из 48 байтов объекта 32 это указатели, однако если сделать антинаучную вещь - упаковать значения указателей в разности ( между значением указателя на соседа и указателя на себя) и учтя что левый и правый соседи всегда рядом (они всегда создаются последовательно) то размер моно ужать до 28 байт :) - выигрыш в 20 байт. Скажете смешно оно, однако когда объектов 100000000 а память не резиновая, ну сэкономили скажем 3000р на памяти. Всем спс.
> и учтя что левый и правый соседи всегда рядом (они всегда создаются последовательно)
В этом случае совершенно непонятно, на кой хрен тебе связный список с указателями.
Положи их в массив, и будет щастье. Вообще любые структуры так или иначе позволяют упаковать себя в "плотный" либо разреженный массив (в конце концов, они ж в памяти лежат? ;-).
Попробуй сделать базовый адрес массива, тогда адрес элемента будет
база+смещение, на базовый 8 байт, а смещение может быть любой длины.
Даже может много переделывать не придётся
А что массивы динамической длинны уже придумали? Я априори понятия не имею какое количество элементов в каждой строке будет да и само количество строк на этапе компиляции неивестно... так что увы счастья не будет.
1. список используют, если нужно быстрое добавление/удаление элементов в/из середину/ы, когда как время поиска не важно. т.е. в тех случаях, если у тебя количество операций добавления/удаления на порядок больше, чем операций поиска элемента.
2. массивы используют, когда надо обеспечить быстрый и эффективный доступ, в то время как время добавления и удаления не имеет значения. т.е. если у тебя количество операций добавления/удаления на порядок меньше, чем операций поиска элемента.
Вообще-то если включить мозг то структуру двойного двусвязанного списка (ну на левый правый верхний и нижний соседей) можно написать так что размеры той части которая содержит указатели можно ужать до 1 - 2 байтов. При этом сохранится удобство самой структуры (в голом массиве очень некомфортно искать элементы) с точки зрения адресации соседей. Как? Ну тут товарищь на правильном пути - хранить не указатели а разности между целевым объектом и собой, а дальше обратить внимание что если объекты создаются подряд то и разности будут все почти одинаковые (почти это про фряху, на ней они прыгают между дискретным набором значений, что увы придется учесть если намерены под ней запускаться, под лигью все разности как правило одинаковы (этого никто не гарантирует но я отклонений не встречал).
ЗЫ: юзать malloc и прочее если пишешь не на С а на С++ и имеешь четкую объектную модель отражающую задачу и некрасиво а следовательно неправильно, тем более можно сокрыть низкоуровневый код с разностями и пр в реализации базового класса.
> А что массивы динамической длинны уже придумали? Я априори понятия не
> имею какое количество элементов в каждой строке будет да и само
> количество строк на этапе компиляции неивестно... так что увы счастья
> не будет.
псёудокод:
size_t len = START_LEN;
size_t used = 0;
array = alloc(START_LEN);
while(newone = fetch_item()) {
if (used >= len) {
len *= 1.5; //choose anything from 1.2 to 2
array = realloc(len);
}
array[++used] = newone;
}
Как тут товарищь уже писал как вы это предлагаете впихнуть в объектную модель на С++ - т. е. элементами выступают объекты классов, они создаются при помощи оператора new, который вызывает конструктор а внем вкусности, как просто предлагается применять классы и malloc?? что перегружать new? Это вот уже совсем меня не втыкает, расеости зарелизить проще...
>> Как тут товарищь уже писал как вы это предлагаете впихнуть в
>> объектную модель на С++ - т. е. элементами выступают объекты
>> классов, они создаются при помощи оператора new, который вызывает
>> конструктор а внем вкусности, как просто предлагается применять
>> классы и malloc?? что перегружать new? Это вот уже совсем меня не
>> втыкает, расеости зарелизить проще...
Стандартный new можно вызывать на уже выделенной памяти.
#include <iostream>
#include <cstdlib>
#include <ctime>
class Foo
{
private:
int i;
public:
Foo(): i(std::rand()) {}
void doSomething() { std::cout << i << std::endl; }
};
int main()
{
char buf[sizeof(Foo)];
Foo *foo;
std::srand(std::time(NULL));
foo = new(buf) Foo;
foo->doSomething();
foo->~Foo();
return 0;
}
И где при этом гарантии что последовательно создавая объекты они будут распологаться в этой выделенной памяти последовательно? Спрашиваю в силу полной неочевидности для меня этого факта.
>>И где при этом гарантии что последовательно создавая объекты они будут распологаться в этой выделенной памяти последовательно? Спрашиваю в силу полной неочевидности для меня этого факта.
Объект будет создаваться по тому указателю, который передан в new и занимать ровно sizeof(Foo) байт. Т.е. можешь размещять объекты внутри заранее выделенного пула памяти как хочешь.
насколько я понимаю тут ошибка. Только malloc дает память гарантированно выровненную для любого типа. Автоматический массив чаров на стеке не будет гарантированно выровненным для любого типа.
>> насколько я понимаю тут ошибка. Только malloc дает память гарантированно выровненную для любого типа. Автоматический массив чаров на стеке не будет гарантированно выровненным для любого типа.
Хм... Помоему с точки зрения C++ выравнивание блоков памяти не имеет никакого значения. Это зависит только от конкретных архитектур процессоров, если они не умеют оперировать с переменными по невыровненным адресам. x86 и amd64 нормально работают с любыми адресами, просто с невыровненными медленнее. В любом случае, автор пул для объектов явно не на стеке будет выделять =).