REPEAT_BYTE(x) macro - c

I was looking the code in kernel.h header file in /usr/src/linux-headers-3.11-.../include/linux/, I stumbled upon this macro (line 47) :
#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
After running this example I made:
#include <stdio.h>
#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
int main(void)
{
long z = 12;
fprintf(stderr, "\tz = %ldd (0x%lX)\n"
"\tREPEAT_BYTE(%ldd) = %ldd (0x%lX)\n",
z, z, z, REPEAT_BYTE(z), REPEAT_BYTE(z));
return 0;
}
I've figured out what it does: It receives an int between 0 and 255(including them), so any one-byte long int, and it repeats that byte. This is obvious (except macro's name) when looking at the output:
z = 12d (0xC)
REPEAT_BYTE(12d) = 868082074056920076d (0xC0C0C0C0C0C0C0C)
However, I still can't understand how does this expression work: ((~0ul / 0xff) * (x)), I could use some help with it.
Thanks a lot in advance!

On a 64-bit machine, ~0ul is 0xffffffffffffffff. Divide that by 0xff and you get 0x0101010101010101. Multiply by an 8-bit value and you get that 8-bit value repeated 8 times.

Related

Assigning an integer value as binary to a variable in C

how can I assign an integer value like 111 to an other integer value but considering 111 as a binary?
For example I want to do that:
int x = 0b111; // x has the value 7
but I have the "111" saved as an integer;
what I tried to do is something like that:
int value = 111;
int x = 0bvalue;
obviously that doesn't work. So how should I do it?
One way is converting the value to string and converting back to integer specifying radix.
int value = 111;
char buffer[1024];
snprintf(buffer, sizeof(buffer), "%d", value);
int x = strtol(buffer, NULL, 2);
Another way is converting integer without converting to string.
int value = 111;
int x = 0;
for (int delta = 1, value2 = value; value2 > 0; value2 /= 10, delta *= 2) {
x += (value2 % 10) * delta;
}
The best solution is to use hex. It is safe to assume that anyone reading your code is a programmer and therefore knows hex. Binary is however a very cumbersome format, particularly so beyond 8 bits, which is why the standard doesn't provide it - 0b is a non-standard compiler extension.
You know for example that you are dealing with a gravely incompetent programmer when you see something like this for written for a 32 bit MCU:
SPICR = 0b10001111001100101010111001001111; // see manual page 666
People have trashed their keyboards for less.
If you still need binary compile time constants for some reason, you can either use non-standard compiler extensions that allows 0b prefix or cook up a macro in standard C. The latter can be done as described below:
Given a preprocessor token such as 00001111, we can convert this to a string in the pre-processor by using the # "stringify" operator. Suppose we have a macro like #define BIN(n) #n.
From there on, we end up with a string literal "00001111" which we can access like an array. So (#n)[0] would give us the first '0' digit, now in ASCII format.
This way we can grab each individual digit. (#n)[0] - '0' will give value 0 or 1 instead of ASCII strings.
If we shift this value depending on string position, we get the binary value of that digit. For example ((#n)[0] - '0') << 7 gives value 128.
If we do this for all digits and sum the result, we get the value.
The complete macro might look like this:
#define TO_BIN(x) ((x)-'0')
#define BINARIFY(val, n) (TO_BIN(val) << n)
#define BIN8(n) ( \
BINARIFY((#n)[0], 7) + \
BINARIFY((#n)[1], 6) + \
BINARIFY((#n)[2], 5) + \
BINARIFY((#n)[3], 4) + \
BINARIFY((#n)[4], 3) + \
BINARIFY((#n)[5], 2) + \
BINARIFY((#n)[6], 1) + \
BINARIFY((#n)[7], 0) )
This can be made more flexible yet, but for now lets just add some defensive programming to ensure 8 digits integers are always used and that the macro input isn't complete garbage:
#define BIN(n) _Generic((n), int: sizeof(#n)==9 ? BIN8(#n) : 0 )
(There are still some ways to trick that macro - it isn't fool-proof but better than nothing)
Complete example:
#include <stdio.h>
#define TO_BIN(x) ((x)-'0')
#define BINARIFY(val, n) (TO_BIN(val) << n)
#define BIN8(n) ( \
BINARIFY(n[0], 7) + \
BINARIFY(n[1], 6) + \
BINARIFY(n[2], 5) + \
BINARIFY(n[3], 4) + \
BINARIFY(n[4], 3) + \
BINARIFY(n[5], 2) + \
BINARIFY(n[6], 1) + \
BINARIFY(n[7], 0) )
#define BIN(n) _Generic((n), int: sizeof(#n)==9 ? BIN8(#n) : 0 )
int main (void)
{
printf("%d\n", BIN(00001111)); // 15
printf("%d\n", BIN(10000000)); // 128
printf("%d\n", BIN(10101011)); // 171
}
Note that this is pure real-time and the binary calculations cost no performance or memory, unlike sprintf or strtoul calls that happen in run-time. For example x86 assembly gives
mov esi, 15
...
mov esi, 128
...
mov esi, 171
So the decimal values are hard-coded into the binary just as if we'd used a binary literal. And since it is compile-time calculation, we can get read-only constants just fine:
const int x = BIN(10101011);

How to printf("%0x") with the number of digits determined from the type?

I can specify the number of digits like printf("%08x", ...). But I'd like to automatically adjust the number of digits according to the data type, (e.g, long (64 bits) should automatically have 64/4=16 digits). Is there a way to do so? Thanks.
How to printf(“%0x”) with the number of digits determined from the type?
1) Find the bit width
Use sizeof, CHAR_BIT to find the bit width sizeof(x)*CHAR_BIT1 or see below alternative.
2) Find the nibble width
(bit_width + 3)/4 for the nibble width - number of hexadecimal characters.
3) Pass the width
Use "*" to pass in the width and print using the widest type, uintmax_t.
#include <float.h>
#include <limits.h>
#include <stdio.h>
#define PRINTF_XW(x) printf("%0*jx\n", (int)(sizeof(x)*CHAR_BIT+3)/4, (uintmax_t) (x))
int main(void) {
unsigned char uc = 1;
unsigned short us = 2;
unsigned u = 3;
unsigned long ul = 4;
unsigned long long ull = 5;
uintmax_t uj = 6;
PRINTF_XW(uc);
PRINTF_XW(us);
PRINTF_XW(u);
PRINTF_XW(ul);
PRINTF_XW(ull);
PRINTF_XW(uj);
return 0;
}
Sample output, may differ amongst platforms.
01
0002
00000003
0000000000000004
0000000000000005
0000000000000006
Alternative
Another approach would use _Generic - tis a bit more work - and more rewards.
See unsigned long long uf:42; example below.
#include <float.h>
#include <limits.h>
#include <stdint.h>
int hexwidth(uintmax_t u) {
int count = 3;
while (u) {
u >>= 1;
count++;
}
return count/4;
}
// Default case useful for other unsigned types wider than `unsigned`
#define HEXWIDTH(s) _Generic((s), \
unsigned char: hexwidth(UCHAR_MAX), \
unsigned short: hexwidth(USHRT_MAX), \
unsigned : hexwidth(UINT_MAX), \
unsigned long: hexwidth(ULONG_MAX), \
unsigned long long: hexwidth(ULLONG_MAX), \
default: hexwidth((s)*0u - 1u) \
)
#define PRINTF_XW(x) printf("%0*jx\n", HEXWIDTH(x), (uintmax_t) (x))
With language extensions that allow wider than unsigned fields - works nicely too.
int main(void) {
struct {
unsigned long long uf:42;
} s1 = {7};
struct {
unsigned long long uf:51;
} s2 = {8};
PRINTF_XW(s1.uf);
PRINTF_XW(s2.uf);
}
Output
00000000007 <-- 11 digits
0000000000008 <-- 13 digits
Macro-magic could replace hexwidth(uintmax_t u) as follows with a compile time calculation:
#define NW3(x) (((x) > 0xFu) ? 2 : 1)
#define NW4(x) (((x) > 0xFFu) ? NW3((x)>>8)+2 : NW3(x))
#define NW5(x) (((x) > 0xFFFFu) ? NW4((x)>>16)+4 : NW4(x))
#define NW6(x) (((x) > 0xFFFFFFFFu) ? NW5((x)>>32)+8 : NW5(x))
#define NW(x) (((x) > 0xFFFFFFFFFFFFFFFFu) ? NW6((((x)+0llu)>>32)>>32)+16 : NW6((x)+0llu))
// Default case useful for all unsigned types as wide/wider than `unsigned`
#define HEXWIDTH(s) _Generic((s), \
unsigned char: NW(UCHAR_MAX), \
unsigned short: NW(USHRT_MAX), \
default: NW((s)*0u - 1u) \
)
1 This works well when there is no padding in the type - common amongst standard unsigned integer types.
You should probably look into C's <inttypes.h>
#include <inttypes.h>
unit8_t value = 0x34;
printf("The value formatted for 8 bits is %" PRIx8 ".", value);
Note the PRIx8 is a string, which correctly will format for "printf" "hexadecimal" "eight bits".
Note that the lack of commas between the strings are not a mistake. This is a formatting technique that uses a feature in C called "automatic string concatenation", such that the three strings will get slapped together. The PRIx8 is just a convenience which means the correct formatting for an 8 bit hexadecimal value.
To get the similar output formatted for 32 bits, you would use PRIx32.
For a brief overview of the inttypes.h output formats, you can look at Good introduction to <inttypes.h>

Preprocessor giving compilation while declaring unsigned int x and initializing with a binary constant [duplicate]

I need to work with a binary number.
I tried writing:
const char x = 00010000;
But it didn't work.
I know that I can use a hexadecimal number that has the same value as 00010000, but I want to know if there is a type in C++ for binary numbers, and if there isn't, is there another solution for my problem?
If you are using GCC then you can use a GCC extension (which is included in the C++14 standard) for this:
int x = 0b00010000;
You can use binary literals. They are standardized in C++14. For example,
int x = 0b11000;
Support in GCC
Support in GCC began in GCC 4.3 (see https://gcc.gnu.org/gcc-4.3/changes.html) as extensions to the C language family (see https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions), but since GCC 4.9 it is now recognized as either a C++14 feature or an extension (see Difference between GCC binary literals and C++14 ones?)
Support in Visual Studio
Support in Visual Studio started in Visual Studio 2015 Preview (see https://www.visualstudio.com/news/vs2015-preview-vs#C++).
template<unsigned long N>
struct bin {
enum { value = (N%10)+2*bin<N/10>::value };
} ;
template<>
struct bin<0> {
enum { value = 0 };
} ;
// ...
std::cout << bin<1000>::value << '\n';
The leftmost digit of the literal still has to be 1, but nonetheless.
You can use BOOST_BINARY while waiting for C++0x. :) BOOST_BINARY arguably has an advantage over template implementation insofar as it can be used in C programs as well (it is 100% preprocessor-driven.)
To do the converse (i.e. print out a number in binary form), you can use the non-portable itoa function, or implement your own.
Unfortunately you cannot do base 2 formatting with STL streams (since setbase will only honour bases 8, 10 and 16), but you can use either a std::string version of itoa, or (the more concise, yet marginally less efficient) std::bitset.
#include <boost/utility/binary.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <bitset>
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
unsigned short b = BOOST_BINARY( 10010 );
char buf[sizeof(b)*8+1];
printf("hex: %04x, dec: %u, oct: %06o, bin: %16s\n", b, b, b, itoa(b, buf, 2));
cout << setfill('0') <<
"hex: " << hex << setw(4) << b << ", " <<
"dec: " << dec << b << ", " <<
"oct: " << oct << setw(6) << b << ", " <<
"bin: " << bitset< 16 >(b) << endl;
return 0;
}
produces:
hex: 0012, dec: 18, oct: 000022, bin: 10010
hex: 0012, dec: 18, oct: 000022, bin: 0000000000010010
Also read Herb Sutter's The String Formatters of Manor Farm for an interesting discussion.
A few compilers (usually the ones for microcontrollers) has a special feature implemented within recognizing literal binary numbers by prefix "0b..." preceding the number, although most compilers (C/C++ standards) don't have such feature and if it is the case, here it is my alternative solution:
#define B_0000 0
#define B_0001 1
#define B_0010 2
#define B_0011 3
#define B_0100 4
#define B_0101 5
#define B_0110 6
#define B_0111 7
#define B_1000 8
#define B_1001 9
#define B_1010 a
#define B_1011 b
#define B_1100 c
#define B_1101 d
#define B_1110 e
#define B_1111 f
#define _B2H(bits) B_##bits
#define B2H(bits) _B2H(bits)
#define _HEX(n) 0x##n
#define HEX(n) _HEX(n)
#define _CCAT(a,b) a##b
#define CCAT(a,b) _CCAT(a,b)
#define BYTE(a,b) HEX( CCAT(B2H(a),B2H(b)) )
#define WORD(a,b,c,d) HEX( CCAT(CCAT(B2H(a),B2H(b)),CCAT(B2H(c),B2H(d))) )
#define DWORD(a,b,c,d,e,f,g,h) HEX( CCAT(CCAT(CCAT(B2H(a),B2H(b)),CCAT(B2H(c),B2H(d))),CCAT(CCAT(B2H(e),B2H(f)),CCAT(B2H(g),B2H(h)))) )
// Using example
char b = BYTE(0100,0001); // Equivalent to b = 65; or b = 'A'; or b = 0x41;
unsigned int w = WORD(1101,1111,0100,0011); // Equivalent to w = 57155; or w = 0xdf43;
unsigned long int dw = DWORD(1101,1111,0100,0011,1111,1101,0010,1000); //Equivalent to dw = 3745774888; or dw = 0xdf43fd28;
Disadvantages (it's not such a big ones):
The binary numbers have to be grouped 4 by 4;
The binary literals have to be only unsigned integer numbers;
Advantages:
Total preprocessor driven, not spending processor time in pointless operations (like "?.. :..", "<<", "+") to the executable program (it may be performed hundred of times in the final application);
It works "mainly in C" compilers and C++ as well (template+enum solution works only in C++ compilers);
It has only the limitation of "longness" for expressing "literal constant" values. There would have been earlyish longness limitation (usually 8 bits: 0-255) if one had expressed constant values by parsing resolve of "enum solution" (usually 255 = reach enum definition limit), differently, "literal constant" limitations, in the compiler allows greater numbers;
Some other solutions demand exaggerated number of constant definitions (too many defines in my opinion) including long or several header files (in most cases not easily readable and understandable, and make the project become unnecessarily confused and extended, like that using "BOOST_BINARY()");
Simplicity of the solution: easily readable, understandable and adjustable for other cases (could be extended for grouping 8 by 8 too);
This thread may help.
/* Helper macros */
#define HEX__(n) 0x##n##LU
#define B8__(x) ((x&0x0000000FLU)?1:0) \
+((x&0x000000F0LU)?2:0) \
+((x&0x00000F00LU)?4:0) \
+((x&0x0000F000LU)?8:0) \
+((x&0x000F0000LU)?16:0) \
+((x&0x00F00000LU)?32:0) \
+((x&0x0F000000LU)?64:0) \
+((x&0xF0000000LU)?128:0)
/* User macros */
#define B8(d) ((unsigned char)B8__(HEX__(d)))
#define B16(dmsb,dlsb) (((unsigned short)B8(dmsb)<<8) \
+ B8(dlsb))
#define B32(dmsb,db2,db3,dlsb) (((unsigned long)B8(dmsb)<<24) \
+ ((unsigned long)B8(db2)<<16) \
+ ((unsigned long)B8(db3)<<8) \
+ B8(dlsb))
#include <stdio.h>
int main(void)
{
// 261, evaluated at compile-time
unsigned const number = B16(00000001,00000101);
printf("%d \n", number);
return 0;
}
It works! (All the credits go to Tom Torfs.)
The C++ over-engineering mindset is already well accounted for in the other answers here. Here's my attempt at doing it with a C, keep-it-simple-ffs mindset:
unsigned char x = 0xF; // binary: 00001111
As already answered, the C standards have no way to directly write binary numbers. There are compiler extensions, however, and apparently C++14 includes the 0b prefix for binary. (Note that this answer was originally posted in 2010.)
One popular workaround is to include a header file with helper macros. One easy option is also to generate a file that includes macro definitions for all 8-bit patterns, e.g.:
#define B00000000 0
#define B00000001 1
#define B00000010 2
…
This results in only 256 #defines, and if larger than 8-bit binary constants are needed, these definitions can be combined with shifts and ORs, possibly with helper macros (e.g., BIN16(B00000001,B00001010)). (Having individual macros for every 16-bit, let alone 32-bit, value is not plausible.)
Of course the downside is that this syntax requires writing all the leading zeroes, but this may also make it clearer for uses like setting bit flags and contents of hardware registers. For a function-like macro resulting in a syntax without this property, see bithacks.h linked above.
C does not have native notation for pure binary numbers. Your best bet here would be either octal (e.g. 07777) of hexadecimal (e.g. 0xfff).
You can use the function found in this question to get up to 22 bits in C++. Here's the code from the link, suitably edited:
template< unsigned long long N >
struct binary
{
enum { value = (N % 8) + 2 * binary< N / 8 > :: value } ;
};
template<>
struct binary< 0 >
{
enum { value = 0 } ;
};
So you can do something like binary<0101011011>::value.
The smallest unit you can work with is a byte (which is of char type). You can work with bits though by using bitwise operators.
As for integer literals, you can only work with decimal (base 10), octal (base 8) or hexadecimal (base 16) numbers. There are no binary (base 2) literals in C nor C++.
Octal numbers are prefixed with 0 and hexadecimal numbers are prefixed with 0x. Decimal numbers have no prefix.
In C++0x you'll be able to do what you want by the way via user defined literals.
Based on some other answers, but this one will reject programs with illegal binary literals. Leading zeroes are optional.
template<bool> struct BinaryLiteralDigit;
template<> struct BinaryLiteralDigit<true> {
static bool const value = true;
};
template<unsigned long long int OCT, unsigned long long int HEX>
struct BinaryLiteral {
enum {
value = (BinaryLiteralDigit<(OCT%8 < 2)>::value && BinaryLiteralDigit<(HEX >= 0)>::value
? (OCT%8) + (BinaryLiteral<OCT/8, 0>::value << 1)
: -1)
};
};
template<>
struct BinaryLiteral<0, 0> {
enum {
value = 0
};
};
#define BINARY_LITERAL(n) BinaryLiteral<0##n##LU, 0x##n##LU>::value
Example:
#define B BINARY_LITERAL
#define COMPILE_ERRORS 0
int main (int argc, char ** argv) {
int _0s[] = { 0, B(0), B(00), B(000) };
int _1s[] = { 1, B(1), B(01), B(001) };
int _2s[] = { 2, B(10), B(010), B(0010) };
int _3s[] = { 3, B(11), B(011), B(0011) };
int _4s[] = { 4, B(100), B(0100), B(00100) };
int neg8s[] = { -8, -B(1000) };
#if COMPILE_ERRORS
int errors[] = { B(-1), B(2), B(9), B(1234567) };
#endif
return 0;
}
You can also use inline assembly like this:
int i;
__asm {
mov eax, 00000000000000000000000000000000b
mov i, eax
}
std::cout << i;
Okay, it might be somewhat overkill, but it works.
The "type" of a binary number is the same as any decimal, hex or octal number: int (or even char, short, long long).
When you assign a constant, you can't assign it with 11011011 (curiously and unfortunately), but you can use hex. Hex is a little easier to mentally translate. Chunk in nibbles (4 bits) and translate to a character in [0-9a-f].
From C++14 you can use Binary Literals, now they are part of the language:
unsigned char a = 0b00110011;
You can use a bitset
bitset<8> b(string("00010000"));
int i = (int)(bs.to_ulong());
cout<<i;
I extended the good answer given by #renato-chandelier by ensuring the support of:
_NIBBLE_(…) – 4 bits, 1 nibble as argument
_BYTE_(…) – 8 bits, 2 nibbles as arguments
_SLAB_(…) – 12 bits, 3 nibbles as arguments
_WORD_(…) – 16 bits, 4 nibbles as arguments
_QUINTIBBLE_(…) – 20 bits, 5 nibbles as arguments
_DSLAB_(…) – 24 bits, 6 nibbles as arguments
_SEPTIBBLE_(…) – 28 bits, 7 nibbles as arguments
_DWORD_(…) – 32 bits, 8 nibbles as arguments
I am actually not so sure about the terms “quintibble” and “septibble”. If anyone knows any alternative please let me know.
Here is the macro rewritten:
#define __CAT__(A, B) A##B
#define _CAT_(A, B) __CAT__(A, B)
#define __HEX_0000 0
#define __HEX_0001 1
#define __HEX_0010 2
#define __HEX_0011 3
#define __HEX_0100 4
#define __HEX_0101 5
#define __HEX_0110 6
#define __HEX_0111 7
#define __HEX_1000 8
#define __HEX_1001 9
#define __HEX_1010 a
#define __HEX_1011 b
#define __HEX_1100 c
#define __HEX_1101 d
#define __HEX_1110 e
#define __HEX_1111 f
#define _NIBBLE_(N1) _CAT_(0x, _CAT_(__HEX_, N1))
#define _BYTE_(N1, N2) _CAT_(_NIBBLE_(N1), _CAT_(__HEX_, N2))
#define _SLAB_(N1, N2, N3) _CAT_(_BYTE_(N1, N2), _CAT_(__HEX_, N3))
#define _WORD_(N1, N2, N3, N4) _CAT_(_SLAB_(N1, N2, N3), _CAT_(__HEX_, N4))
#define _QUINTIBBLE_(N1, N2, N3, N4, N5) _CAT_(_WORD_(N1, N2, N3, N4), _CAT_(__HEX_, N5))
#define _DSLAB_(N1, N2, N3, N4, N5, N6) _CAT_(_QUINTIBBLE_(N1, N2, N3, N4, N5), _CAT_(__HEX_, N6))
#define _SEPTIBBLE_(N1, N2, N3, N4, N5, N6, N7) _CAT_(_DSLAB_(N1, N2, N3, N4, N5, N6), _CAT_(__HEX_, N7))
#define _DWORD_(N1, N2, N3, N4, N5, N6, N7, N8) _CAT_(_SEPTIBBLE_(N1, N2, N3, N4, N5, N6, N7), _CAT_(__HEX_, N8))
And here is Renato's using example:
char b = _BYTE_(0100, 0001); /* equivalent to b = 65; or b = 'A'; or b = 0x41; */
unsigned int w = _WORD_(1101, 1111, 0100, 0011); /* equivalent to w = 57155; or w = 0xdf43; */
unsigned long int dw = _DWORD_(1101, 1111, 0100, 0011, 1111, 1101, 0010, 1000); /* Equivalent to dw = 3745774888; or dw = 0xdf43fd28; */
Just use the standard library in C++:
#include <bitset>
You need a variable of type std::bitset:
std::bitset<8ul> x;
x = std::bitset<8>(10);
for (int i = x.size() - 1; i >= 0; i--) {
std::cout << x[i];
}
In this example, I stored the binary form of 10 in x.
8ul defines the size of your bits, so 7ul means seven bits and so on.
Here is my function without adding Boost library :
usage : BOOST_BINARY(00010001);
int BOOST_BINARY(int a){
int b = 0;
for (int i = 0;i < 8;i++){
b += a % 10 << i;
a = a / 10;
}
return b;
}
I nominate my solution:
#define B(x) \
((((x) >> 0) & 0x01) \
| (((x) >> 2) & 0x02) \
| (((x) >> 4) & 0x04) \
| (((x) >> 6) & 0x08) \
| (((x) >> 8) & 0x10) \
| (((x) >> 10) & 0x20) \
| (((x) >> 12) & 0x40) \
| (((x) >> 14) & 0x80))
const uint8 font6[] = {
B(00001110), //[00]
B(00010001),
B(00000001),
B(00000010),
B(00000100),
B(00000000),
B(00000100),
B(00000000),
I define 8-bit fonts and graphics this way, but could work with wider fonts as well. The macro B can be defined to produce the 0b format, if supported by the compiler.
Operation: the binary numbers are interpreted in octal, and then the bits are masked and shifted together. The intermediate value is limited by the largest integer the compiler can work with, I guess 64 bits should be OK.
It's entirely processed by the compiler, no code needed runtime.
Binary constants are to be standardised in C23. As of writing, 6.4.4.1/4 of the latest C2x draft standard says of the proposed notation:
[...] A binary constant consists of the prefix 0b or 0B followed by a sequence of the digits 0 or 1.
C++ provides a standard template named std::bitset. Try it if you like.
usage : BINARY(00010001);
int BINARY(int a){
int b = 0;
for (int i = 0;i < 8;i++){
b += a % 10 << i;
a = a / 10;
}
return b;
}
You could try using an array of bool:
bool i[8] = {0,0,1,1,0,1,0,1}

Shift operator on integers

I have the following function:
#include<stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <inttypes.h>
uint64_t dtally(uint64_t x)
{
uint64_t t = 0;
while (x){ t += 1 << ((x%10) * 6), x /= 10;
return t;
}
int main(int argc, char *argv[])
{
printf("%" PRIu64 "\n", dtally(39));
return 0;
}
when I pass a number as 39 i understand should return the following value
18014398509481984
but it returns this value:
4456448
because returns this value and not what you expected?
There are two problem with your code (in fact it is the same problem twice).
First, t is an int, which is usually a 32 bit integer (and at least 16 bits). So 2^54, will not fit there. You have to use a 64 bit type for t. But your problem will persist.
The second problem is trickier: 1 << ((x % 10) * 6) perform a shift operation on the literal 1. But 1 is an int. So 1 << 54 will return 0 (the one is shifted out of the 32 bits of memory, then added to t). To solve this, you can cast the literal 1 to int64_t or use the literal 1LL (type long long) instead.
So you should have something like this:
int count(int x)
{
int64_t t = 0;
while (x) t += 1LL << ((x % 10) * 6), x /= 10;
return t;
}
18014398509481984 is probably too big for an int on your platform.
Check this by testing sizeof(int). If that's 4 then the largest number you can represent is a little over 2 billion. It might even be only 2 (in which case the largest int would be 32767).
You could use int64_t instead which is 64 bits (and available since C99; although a platform is not compelled to support it).
Don't forget to suffix any literals with LL which denotes a 64 bit type.

Defining smallest possible sized macro in C

I want to define a boolean macro in C that uses less than 4 bytes. I have looked into this, and maybe it is possible to define an asm macro, with gcc, that could be less. It is important that the definition will be small because I will have tens of thousands of matrices which hold these boolean values, and it is important that they can be as memory efficient as possible. Ideally, I want to define a 4-bit, or 8-bit macro that represents true and false, and will evaluate as such in an if-statement.
Edit:
When I define a macro
#define True 0
#define False !True
and then print the size, it returns a size of 4 bytes, which is very inefficient.
Edit2:
I just read up on bitpacking, and however little bits I could have for a boolean would be best. I'm just not too sure how to bitpack a struck that has the size of a few bits.
Edit3:
#include <stdio.h>
#include <string.h>
#define false (unsigned char(0))
#define true (!false)
int main() {
if (true) {
printf("The size of true is %d\n", sizeof(true));
}
}
gives the following output
test.c: In function ‘main’:
test.c:8:9: error: expected ‘)’ before numeric constant
test.c:9:51: error: expected ‘)’ before numeric constant
Try this instead for your macros:
#define false ((unsigned char) 0)
#define true (!false)
This won't fix your space needs though. For more efficient storage, you need to use bits:
void SetBoolValue(int bitOffset, unsigned char *array, bool value)
{
int index = bitOffset >> 3;
int mask = 1 << (bitOffset & 0x07);
if (value)
array[index] |= mask;
else
array[index] &= ~mask;
}
bool GetBoolValue(int bitOffset, unsigned char *array)
{
int index = bitOffset >> 3;
int mask = 1 << (bitOffset & 0x07);
return array[index] & mask;
}
Where each value of "array" can hold 8 bools. On modern systems, it can be faster to use a U32 or U64 as the array, but it can take up more space for smaller amounts of data.
To pack larger amounts of data:
void SetMultipleBoolValues(int bitOffset, unsigned char *array, int value, int numBitsInValue)
{
for(int i=0; i<numBitsInValue; i++)
{
SetBoolValue(bitOffset + i, array, (value & (1 << i)));
}
}
And here would be a driver:
int main(void)
{
static char array[32]; // Static so it starts 0'd.
int value = 1234; // An 11-bit value to pack
for(int i=0; i<4; i++)
SetMultipleBoolValues(i * 11, array, value, 11); // 11 = 11-bits of data - do it 4 times
for(int i=0; i<32; i++)
printf("%c", array[i]);
return 0;
}
If you are using this in a structure, then you will want to use a bit field.
struct {
unsigned flag : 1;
/* other fields */
};
If you are wanting an array of boolean values, you should implement a bit vector (I was about to implement one, but Michael Dorgan's already done it).
First of all, there's no storage associated with your macros; they expand to the integer constants 0 and 1. The sizeof evaluates to 4 because the expressions have integer type. You can certainly assign those values to objects of smaller type (short or char).
For me, life got a lot simpler when I stopped using TRUE and FALSE macros1. Remember that in C, a zero-valued integral expression evaluates to false, and all non-zero-valued integral expressions evaluate to true.
If you want to store values into something smaller than 8 bits, then you're going to have to do your own bit packing, something like
#define TEST(x,bit) ((x) & (1 << (bit)))
#define SET(x,bit) ((x) |= (1 << (bit)))
#define CLEAR(x,bit) ((x) &= ~(1 << (bit)))
The smallest useful type for this is unsigned char. So if you need to store N single-bit values, you need an array of N/CHAR_BIT+1 elements. For example, to store 10 single-bit boolean values, you need 2 eight-bit array elements. Bits 0 through 7 will be stored in element 0, and bits 8 through 10 will be stored in element 1.
So, something like
#define MAX_BITS 24
unsigned char bits[MAX_BITS / CHAR_BIT + 1];
int bit = ...;
SET(bits[bit/CHAR_BIT], bit % CHAR_BIT);
if ( TEST(bits[bit/CHAR_BIT], bit % CHAR_BIT) )
{
// do something if bit is set
}
CLEAR(bits[bit/CHAR_BIT], bit % CHAR_BIT);
No warranties express or implied; I don't do a lot of bit twiddling. But hopefully this at least points you in the right direction.
1. The precipitating event was someone dropping a header where TRUE == FALSE. Not the most productive afternoon.
You should probably just use an unsigned char, it will be the smallest individually addressable type:
typedef unsigned char smallBool;
smallBool boolMatrix[M][N];
The above will use M * N bytes for the matrix.
Of course, wasting CHAR_BIT - 1 bits to store a single bit is ... wasteful. Consider bit-packing the boolean values.

Resources