Is there a shorthand byte notation in C/C++?

6

It’s been awhile since I programmed in C/C++. For the life of me, I cannot remember (or find in Google) how to make the following work. I thought there was a shorthand way of writing a repeating string of bytes, like these:

0x00 => 0x00000000
0xFF => 0xFFFFFFFF
0xCD => 0xCDCDCDCD

For example, if I was to declare

int x = 0xCD;
printf("%d", x);

it would print 3452816845, not 205.

Am I going crazy?

Is it possible without doing runtime bit shifts (e.g., by making the preprocessor handle it)?

c++
c
asked on Stack Overflow Nov 1, 2011 by Jay • edited Jan 26, 2021 by ib.

7 Answers

13

The simplest way is:

0x1010101u * x

I can't think of any syntax that could possibly be simpler or more self-explanatory...

Edit: I see you want it to work for arbitrary types. Since it only makes sense for unsigned types, I'm going to assume you're using an unsigned type. Then try

#define REPB(t, x) ((t)-1/255 * (x))
answered on Stack Overflow Nov 1, 2011 by R.. GitHub STOP HELPING ICE • edited Jan 26, 2021 by R.. GitHub STOP HELPING ICE
8

There's nothing like that by default in C. There's something similar in CSS (the color #123 is expanded to #112233), but that's completely different. :)

You could write a macro to do it for you, though, like:

#define REPEAT_BYTE(x) ((x) | ((x) << 8) | ((x) << 16) | ((x) << 24))
...
int x = REPEAT_BYTE(0xcd);
2

Unless you write your own macro, this is impossible. How would it know how long to repeat? 0xAB could mean 0xABABABABABABABABABABAB for all it knows (using the proposed idea).

answered on Stack Overflow Nov 1, 2011 by jli
2

There is no such shorthand. 0x00 is the same as 0. 0xFF is the same as 0x000000FF.

answered on Stack Overflow Nov 1, 2011 by David Schwartz
2

You could use some template trickery:

#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
}

which adapts automatically to the integral type passed as first argument and is completely resolved at compile-time, but this is just for fun, I don't think I'd use such a thing in real code.

answered on Stack Overflow Nov 1, 2011 by Matteo Italia
2

Nope. But you can use memset:

int x;
memset(&x, 0xCD, sizeof(x));

And you could make a macro of that:

#define INITVAR(var, value) memset(&(var), (int)(value), sizeof(var))
int x;
INITVAR(x, 0xCD);
answered on Stack Overflow Nov 1, 2011 by Andrew Cottrell
1

You can use the preprocessor token concatenation:

#include <stdio.h>
#define multi4(a) (0x##a##a##a##a)

int main()
{
    int a = multi4(cd);
    printf("0x%x\n", a);
    return 0;
}

Result:

0xcdcdcdcd

Of course, you have to create a new macro each time you want to create a "generator" with a different number of repetitions.

answered on Stack Overflow Nov 1, 2011 by Grimflo

User contributions licensed under CC BY-SA 3.0