#c #c
#c #c
Вопрос:
Прошло некоторое время с тех пор, как я программировал на C / C . Ни за что на свете я не могу вспомнить (или найти в Google), как выполнить следующую работу. Я думал, что существует сокращенный способ записи повторяющейся строки байтов, например:
0x00 => 0x00000000
0xFF => 0xFFFFFFFF
0xCD => 0xCDCDCDCD
Например, если бы я должен был объявить
int x = 0xCD;
printf("%d", x);
он будет печатать 3452816845
, а не 205
.
Я схожу с ума?
Возможно ли это без выполнения битовых сдвигов во время выполнения (например, путем обработки препроцессором)?
Комментарии:
1. Ничего подобного не существует.
2. @Justin: Один из нас сходит с ума, и я не думаю, что это я! 🙂 Как вы думаете, что это может быть за сокращение? Преобразование формата? Коэффициент повторения в объявлении? Подразумеваемый цикл?
3. Трудно представить такую функцию в C или C хотя бы потому, что не так много мест, где это было бы полезно.
4. Я просто хочу написать целочисленные константы, которые имеют одинаковые два байта, повторяющиеся для всего целого числа.
5. @Mark Ransom Я мог бы поклясться, что использовал их для создания масок, когда я выполнял упражнение по скручиванию в колледже. Может быть, мы работали с короткими записями?
Ответ №1:
Самый простой способ:
0x1010101u * x
Я не могу придумать ни одного синтаксиса, который мог бы быть проще или понятнее…
Редактировать: я вижу, вы хотите, чтобы это работало для произвольных типов. Поскольку это имеет смысл только для неподписанных типов, я предполагаю, что вы используете неподписанный тип. Затем попробуйте
#define REPB(t, x) ((t)-1/255 * (x))
Ответ №2:
В C. по умолчанию ничего подобного нет. В CSS есть что-то похожее (цвет #123
расширяется до #112233
), но это совершенно другое. 🙂
Вы могли бы написать макрос, который сделает это за вас, например:
#define REPEAT_BYTE(x) ((x) | ((x) << 8) | ((x) << 16) | ((x) << 24))
...
int x = REPEAT_BYTE(0xcd);
Ответ №3:
Если вы не напишете свой собственный макрос, это невозможно. Как он узнает, как долго повторять? 0xAB
может означать 0xABABABABABABABABABABAB
все, что он знает (используя предложенную идею).
Комментарии:
1. Он будет повторять это в зависимости от типа.
2. Если это необходимо, используйте макрос, предложенный мной и duskwuff.
3. @Justin: Нет, это не так. C и C не инициализируются таким образом. Существует тип инициализатора и тип переменной, а также способы преобразования из одного в другой. Тип переменной не влияет на значение и тип инициализатора. Вы уверены, что имеете в виду C или C ?
Ответ №4:
Такой сокращенной записи нет. 0x00 совпадает с 0. 0xFF совпадает с 0x000000FF.
Комментарии:
1. …хотя
0x00
является шестнадцатеричным и0
восьмеричным. 🙂
Ответ №5:
Вы могли бы использовать некоторые шаблонные хитрости:
#include <iostream>
#include <climits>
using namespace std;
template<typename T, unsigned char Pattern, unsigned int N=sizeof(T)>
struct FillInt
{
static const T Value=((T)Pattern)<<((N-1)*CHAR_BIT) | FillInt<T, Pattern, N-1>::Value;
};
template<typename T, unsigned char Pattern>
struct FillInt<T, Pattern, 0>
{
static const T Value=0;
};
int main()
{
cout<<hex<<FillInt<unsigned int, 0xdc>::Value<<endl; // outputs dcdcdcdc on 32 bit machines
}
которая автоматически адаптируется к целочисленному типу, переданному в качестве первого аргумента, и полностью разрешается во время компиляции, но это просто для развлечения, я не думаю, что я бы использовал такую вещь в реальном коде.
Комментарии:
1. Почему бы вам не использовать такую вещь в реальном коде? Только сегодня я был укушен
0xFFFF
тем, что для u16 была записана константа (и концептуально это было «байт0xFF
повторяется N раз»), но затем тип переключился на u32, и константа стала неправильной.
Ответ №6:
Нет. Но вы можете использовать memset:
int x;
memset(amp;x, 0xCD, sizeof(x));
И вы могли бы сделать из этого макрос:
#define INITVAR(var, value) memset(amp;(var), (int)(value), sizeof(var))
int x;
INITVAR(x, 0xCD);
Ответ №7:
Вы можете использовать конкатенацию токенов препроцессора:
#include <stdio.h>
#define multi4(a) (0x##a##a##a##a)
int main()
{
int a = multi4(cd);
printf("0x%xn", a);
return 0;
}
Результат:
0xcdcdcdcd
Конечно, вам нужно создавать новый макрос каждый раз, когда вы хотите создать «генератор» с разным количеством повторений.