Существует ли сокращенная байтовая нотация в C / C ?

#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
 

Конечно, вам нужно создавать новый макрос каждый раз, когда вы хотите создать «генератор» с разным количеством повторений.