- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
void array_random_input(int *array, unsigned int *array_size)
{
unsigned register int i, j;
for(i=0; i<(*array_size); i++)
for(j=0; j<(*array_size); j++)
*(array + (*array_size) * i + j) = rand()%100;
}
void array_recombination(int *array, unsigned int *array_size)
{
unsigned register int i, j, tmp;
for(i=0; i<(*array_size)/2; i++)
for(j=0; j<(*array_size)/2; j++)
{
tmp = *(array + (*array_size) * i + j);
*(array + (*array_size) * i + j) = *(array + (*array_size) * ((*array_size)/2 + i) + ((*array_size)/2 + j));
*(array + (*array_size) * ((*array_size)/2 + i) + ((*array_size)/2 + j)) = tmp;
}
for(i=0; i<(*array_size)/2; i++)
for(j=(*array_size)/2; j<(*array_size); j++)
{
tmp = *(array + (*array_size) * i + j);
*(array + (*array_size) * i + j) = *(array + (*array_size) * ((*array_size)/2 + i) + (j - (*array_size)/2));
*(array + (*array_size) * ((*array_size)/2 + i) + (j - (*array_size)/2)) = tmp;
}
}
//ardent greetings to my teacher F.S.V.! :)
Условие задачи: необходимо создать динамический двумерный массив размерностью 2n и сделать перестановку крест накрест его четвертей. В качестве параметров все функции принимают указатели. Для пущего brainfuck'а доступ к элементам массива осуществлялся с использованием одномерной адресации (по другому никак не получалось :)
Для сокращения привожу только функции наполнения массива случайными значениями и перестановки элементов.
TheCalligrapher 23.12.2010 01:10 # 0
P.S. Или для пущей суровости размер массива у вас из другого потока прямо на лету меняться может? :)))
mr_visor 23.12.2010 01:18 # 0
TheCalligrapher 23.12.2010 01:22 # −1
mr_visor 23.12.2010 01:52 # −1
Если же будем в качестве аргументов передавать переменные, то внутри функций мы создаём копии этих переменных (вот тот самый момент с памятью!), проводим над ними манипуляции и в конце возвращаем их значение.
Уже получается, что в коде не функции, а процедуры :)
guest 23.12.2010 01:58 # 0
absolut 23.12.2010 02:30 # 0
Раз уж речь об оптимизации зашла - к чему два цикла в функции по i, j ? Массив-то непрерывный с точки зрения размещения в памяти. Понимаю еще если бы какая-то логика была от i,j, так там обычный рандом.
interested 23.12.2010 09:06 # 0
Это называется ссылка. Указатель -- это тип данных, который хранит адрес, а не предоставляет значение по адресу. Для получения значения его следует разимеровать (звездонуть *ptr).
Кроме того. Указатель всегда, кроме может быть критических случаев, имеет туже длину, что и int. На всякие unsigned int нужно больше уделить внимания, потому что они могут оказать 4х байтными, когда система 8и байтная. Тогда вы ещё и потеряете в памяти, создав внутри функции автоматический указатель.
guest 23.12.2010 09:18 # 0
Таковым случаем являются указатели на члены классов (правда в с++, а не в си).
На 64хбитных архитектурах указатель может быть больше int.
Зато с size_t или с ptrdiff_t - указатель совпадает по размеру.
Ваш К.О.
guest 23.12.2010 09:33 # 0
На 32хразрядных платформах до 16 байт.
Могу предположить, что на 64х разрядных - до 32 байт на 1 указатель.
rat4 23.12.2010 09:45 # 0
Можно пример?
guest 23.12.2010 09:48 # +1
Ну подробная статья на эту тему + реализазация костыля для испрвления этой ситуации.
interested 23.12.2010 10:12 # 0
А из таблицы получается, что вопрос не соответствия длины указателя длине int является, помимо прочего ещё и вопросом компилятора.
guest 23.12.2010 10:17 # 0
Сказано лишь, что:
char<=short<=int<=long<=long long
Всё. Тоесть зависят размеры как от платформы, так и от компилятора.
interested 23.12.2010 10:25 # 0
Я так понимаю это высказывание, что int -- всегда равен длине процессорного слова, которое, в общем случае, есть длина указателя на память.
Хотя, это, несомненно, домысливание стандарта.
И не найду я сейчас утверждения о независимости аппаратной long int (а может unsigned int)... Но оно точно где-то есть.
И при всём при этом они действительно должны вкладываться одни в другой. Достаточно жозенькие условия...
guest 23.12.2010 12:49 # 0
rat4 23.12.2010 14:18 # 0
guest 23.12.2010 17:24 # +1
int может быть как 64 бита, так и 32.
Анонимус 23.12.2010 17:39 # +4
interested 24.12.2010 09:39 # 0
Обращая внимание на эти слова, я, как оговорил выше, для себя додумываю стандарт. И не утверждаю, что так есть наверняка.
Сталкивался с длинными int на высокопроизводительных машинах.
Про современные, входящие в строй, 64x битные машины общие -- не знаю. Думаю, стоит попробовать на них ставить писаный для них Unix и пользоваться компилятором оттуда, тогда всё будет срастаться со стандартом.
Это моё предположение.
rat4 24.12.2010 10:00 # 0
GCC 4.5.1
sizeof(int) == 4
interested 24.12.2010 10:30 # +1
Боюсь, вы держите в руках именно такой компилятор.
bugmenot 24.12.2010 10:34 # 0
bugmenot 23.12.2010 16:27 # 0
interested 24.12.2010 09:42 # 0
И в статье хорошо об этом написано.
TheCalligrapher 26.12.2010 16:28 # 0
Никакого совпадения по размеру с типами `size_t` и `ptrdiff_t` нет. Язык ничего подобного никогда не гарантировал. Да и нет никаких предпосылок для такого совпадения. Это какое-то странное заблуждение, родившееся в эпоху flat memory model.
Несложно вспомнить 16-битные сегментные платформы, на которых `size_t` был меньше указателя в некоторых моделях памяти. Платформы с "маленьким" `size_t` прекрасно существюит и сейчас (какие-то компиляторы С для IBM, кажется).
guest 26.12.2010 16:34 # 0
guest 26.12.2010 16:36 # 0
TheCalligrapher 26.12.2010 22:10 # +2
Более того, тип `ptrdiff_t` по определению - тип знаковый. Чтобы он "всегда работал" для вычисления разности двух указателей, этот тип обязан быть как минимум на один бит длиннее, чем тип `size_t`. Вы видели хоть одну платформу, где `ptrdiff_t` длиннее, чем `size_t`? В рельности они практически всегда имеют один им тот же размер, что говорит о том, что вышеупомянутая проблема с `ptrdiff_t`- соверешенно реальна. Тип `ptrdiff_t` очень легко переполнить.
guest 26.12.2010 22:12 # 0
guest 26.12.2010 16:38 # 0
size_t действительно раньше был не совпадающем по размеру с указателем. Но сейчас стандарт новый и проживёт это ещё долго.
guest 26.12.2010 16:40 # 0
Или Вы предлагаете, что стоит писать кросплатформенный код, который можно отправлять на машине времени в прошлое без необходимости переписывать его?
TheCalligrapher 26.12.2010 22:18 # +2
TheCalligrapher 26.12.2010 22:16 # +4
В эпоху flat memory model откуда то появилось наивное заблуждение о том, что максимальный размер объекта должен быть равен полному объему адресного пространства программы - отсюда и это странное верование о том, что размер `size_t` должен быть равен размеру указателя. На самом же деле это не так.
Еще раз: целочисленные типы, равные по размеру указателю, это типы `intptr_t` и `unintptr_t`. Именно для этого они и были введены в стандарот C99. А `size_t` к размеру указателя никакого отношения не имеет вообще.
guest 26.12.2010 22:24 # 0
Например, хранить размер адресного пространства, а значит, по меньшей мере, должен совпадать по размеру с указателем или быть больше.
Впрочем, соглашусь, что, когда последний раз читал стандарт, инфы о совпадении размера size_t c указателем не видел, но по всем сайтикам почему то кричат, особенно в рекламе анализатора 64х битного кода Viva64, что sizeof(size_t)==sizeof(void*).
guest 26.12.2010 22:27 # +1
Я полностью согласен. :)
guest 26.12.2010 22:28 # 0
guest 26.12.2010 22:30 # 0
Только опечатка:
`intptr_t` и `uintptr_t`
Но это ничего не меняет.
MAKAKA 11.09.2020 02:18 # 0
Если вы искали способ открыть шкатулка Лемаршана, то вот он ^^
gost 11.09.2020 06:49 # +1
Доброго ня, MAKAKA ^_^.
TOPT 11.09.2020 07:18 # 0
TheCalligrapher 26.12.2010 09:39 # 0
guest 26.12.2010 14:27 # 0
Там же вроде массив, а не 1 unsigned.
TheCalligrapher 26.12.2010 15:50 # 0
guest 26.12.2010 15:54 # 0
gegMOPO4 23.12.2010 17:05 # 0
Ещё один вариант -- все функции должны иметь одинаковую сигнатуру, а некоторые из них могут изменять размер.
Понятно, что даже в этом случае первым же делом следует ради читаемости и эффективности разыменовать указатель в локальную переменную.
interested 24.12.2010 09:43 # 0
Да, с таким аргументом я могу согласиться.
Но, правильно замечено, что всё же:
>первым же делом следует <...> разыменовать указатель в локальную переменную
Pizurok 23.12.2010 22:25 # 0
guest8 11.09.2020 05:43 # −999