#c
Вопрос:
У меня есть программа, которая принимает unsigned char ctr[24]
. Это будет использоваться много раз, и я хотел бы иметь новое ctr
для каждой операции. Поэтому мне нужно было бы либо генерировать случайное значение каждый раз, либо я мог бы инициализировать его до 0 и увеличивать. Я стремлюсь к производительности, поэтому генерирование нового значения каждый раз, вероятно, будет медленным по сравнению с простым увеличением. Можно ли увеличить массив символов без знака?
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Увеличьте его на единицу…
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01
и т.д..
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x02
Комментарии:
1. Вы хотите обработать
ctr
значение a24*8
bit?2. Для меня этот вопрос неясен… что вы подразумеваете под
Is it possible to increment a unsigned char array?
увеличением каждого элемента? или…?3. Да, его можно увеличить, как и любое другое число, и это также быстрее.
4.
int n = 24; while (n-- amp;amp; ctr[n] == 0);
5. @TedLyngmo Или микро-оптимизация с помощью
int n = 24; while ( ctr[--n] == 0 amp;amp; n);
Ответ №1:
Рассматривая unsigned char ctr[24] = {0};
как счетчик, инициализированный 0, 24 элемента можно рассматривать как цифры базового UCHAR_MAX 1
числа. Исходя из вопроса, цифра «единицы измерения» должна храниться в ctr[23]
, цифра «база 1«, цифра ctr[22]
«база 2» ctr[21]
и т. Д. Когда цифра со значением UCHAR_MAX
увеличивается, она становится 0, и к следующей позиции цифры необходимо добавить значение «бит переноса», равное 1.
void increment(unsigned char ctr[static 24])
{
unsigned int pos = 24;
while (pos-- amp;amp; ctr[pos] == 0)
;
}
Вышеуказанная функция увеличивает unsigned char[24]
значение на месте. Сначала он увеличивается ctr[23]
, и если он обернулся вокруг 0 , увеличивается ctr[22]
и так далее, пока одна из цифр не обернется вокруг 0 или все цифры не обернутся вокруг 0.
Комментарии:
1. Может потребоваться некоторое время
pos--
, чтобы быть ложным. 😉2. @chux-переустановка. Я могу подождать. 🙂
Ответ №2:
Маловероятно, что вам это действительно понадобится…. Я имею в виду, что если бы вы просто взяли первые 8 байтов и обработали их как uint64_t, это заняло бы много-много времени, прежде чем обернуться.
Мне кажется, что некоторые вещи с указателем, и это работа, выполненная для любого вероятного варианта использования.
Обратите внимание, что вам, возможно, потребуется использовать несколько байтов в середине ваших 24, чтобы убедиться, что ваша память выровнена соответствующим образом для 64-разрядного доступа, но это мелочь.
Комментарии:
1. Это ответ — но просто используйте an
unsigned long long
.2. «некоторые вещи, связанные с указателем, и это работа» , Пахнут как нарушение строгого сглаживания.
3. @user694733 В C подход, основанный на объединении, не является UB. У него все еще болит голова от выравнивания.
4. @DanMills в этом даже нет необходимости
union
. Просто используйте auint64_t
напрямую. Это хорошо примерно для столетия времени выполнения с шагом в 3 000 000 000 операций в секунду. Я сомневаюсь, что ОПЕРАЦИЯ нуждается в определенных значениях так быстро и надолго…5. @AndrewHenle Союз должен обойти ограничения на ввод типа в стандарте C, не беспокоясь о том, что увеличение uint64_t может произойти в ближайшее время.
Ответ №3:
void *inc(void *buff, size_t size)
{
unsigned char *cbuff = buff;
for(size_t index = 0; index < size; index )
{
if(cbuff[index] == 255)
{
cbuff[index] = 0;
}
else
{
cbuff[index] ;
break;
}
}
return buff;
}
Ответ №4:
У меня есть программа, которая принимает беззнаковый символ ctr[24]. Это будет использоваться много раз, и я хотел бы иметь новый ctr для каждой операции. Поэтому мне нужно было бы либо генерировать случайное значение каждый раз, либо я мог бы инициализировать его до 0 и увеличивать. Я стремлюсь к производительности, поэтому генерирование нового значения каждый раз, вероятно, будет медленным по сравнению с простым увеличением. Можно ли увеличить массив символов без знака?
Просто не надо.
Используйте простое unsigned long long
. Он более чем достаточно велик.
При 3 миллиардах операций приращения в секунду для перехода на 64-разрядное значение потребуется 97 лет.
unsigned long long
достаточно большой.
Ответ №5:
Что-то вроде этого? непроверенный
void add1_recur(unsigned char *x, int lo) {
if (lo < 0) /* 192 bit overflow! */ exit(EXIT_FAILURE);
if (x[lo] == 255) {
x[lo] = 0;
add1_recur(x, lo - 1;)
} else {
x[lo] = 1;
}
}
// add 1 to x; assume x[0] is high order bit
void add1_inplace(unsigned char x[static 24]) {
add1_recur(x, 23);
}
Ответ №6:
Насколько я понимаю, вам просто каждый раз нужен новый шаблон. Не обязательно счетчик.
Так что бы сделал профсоюз?
Нравится:
typedef union
{
uint64_t d64[3];
unsigned char d8[24];
} ctr_t;
void p(unsigned char ca[])
{
for (int i=0; i<24; i) printf("0xX ", ca[i]);
puts("");
}
void change(ctr_t* ctr)
{
// Do some change to each of the three uint64
ctr->d64[0];
--ctr->d64[1];
ctr->d64[2];
}
int main(void) {
ctr_t ctr = {{0, 0, 0xff00ff00ff}}; // Just some initialization
p(ctr.d8);
change(amp;ctr);
p(ctr.d8);
change(amp;ctr);
p(ctr.d8);
change(amp;ctr);
p(ctr.d8);
return 0;
}
Выход
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xFF 0x00 0xFF 0x00 0xFF 0x00 0x00 0x00
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x00 0x01 0xFF 0x00 0xFF 0x00 0x00 0x00
0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xFE 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x01 0x01 0xFF 0x00 0xFF 0x00 0x00 0x00
0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xFD 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x02 0x01 0xFF 0x00 0xFF 0x00 0x00 0x00