C++ typecasting with bitwise assignement operation - c++

I haven't found a way to typecast where bitwise assignment operation (e.g. x |= y &z;) is involved.
Example:
#include <stdio.h>
typedef enum type1{
AA = 0,
BB = 1
} type1_e;
int main()
{
type1_e x,y;
y = type1_e(y | x); //working
y |= (type1_e)(y|x); //ERROR: as.cc:15: error: invalid conversion from ‘int’ to ‘type1_e’
}

operator | yields an int result
type1_e(y | x)
y | x is an int. You're explicitly casting that int to type1_e.
y |= (type1_e)(y|x);
is equivalent to
y = y | type1_e(y | x);
You are using operator | which yields an int result, then trying to assign that to y which is type1_e. You can't do that without casting.
To overcome that, you could do this:
y = type1_e(y | type1_e(y | x));
which is the same as:
y = type1_e(y | y | x);
which is the same as:
y = type1_e(y | x);
or:
y = static_cast<type1_e>(y | x);

You can write an overload for bitwise OR (|) that works for your enum.
You will have to use static_cast as well for proper conversion.
#include<iostream>
using namespace std;
typedef enum type1{
AA = 0,
BB = 1
} type1_e;
type1_e operator |=(type1_e& x, type1_e y)
{
return x=static_cast<type1_e>(static_cast<int>(x) | static_cast<int>(y));
}
int main()
{
type1_e x = AA, y = BB;
y = type1_e(y | x); //working
std::cout << y << '\n';
x = AA, y = AA;
y |= static_cast<type1_e>(y|x); //also works
std::cout << y << '\n';
}
See demo.

Related

Cast from int to char

I'd like to know how this cast works :
int value = 100;
auto f = [&value] (int x, int y) -> char { return x + y + value; };
printf("%d\n", f(10, 20));
value = 200;
printf("%d\n", f(10, 20));
return 0;
It prints -126 and -30 but i don't understand how is it possible to print a negative integer.
The numerical range for char is -128..127. 10 + 20 + 100 is 130 and outside of that range, so it wraps around when expressed as char.
To fix you need to use a data type that can contain values large enough:
auto f = [&value] (int x, int y) -> int { return x + y + value; };
Or use values < 127.

C++ Convert XOR Implementation To 8 Bit (Processor Doesn't Support XOR)

This function is used to calculate the XOR of a 32 bit integer
int xor32int(int x, int y)
{
int res = 0; // Initialize result
// Assuming 32-bit Integer
for (int i = 31; i >= 0; i--)
{
// Find current bits in x and y
bool b1 = x & (1 << i);
bool b2 = y & (1 << i);
// If both are 1 then 0 else xor is same as OR
bool xoredBit = (b1 & b2) ? 0 : (b1 | b2);
// Update result
res <<= 1;
res |= xoredBit;
}
return res;
}
This works fine when XOR'ing 8 bit values, but they first need to be casted to int, i.e.
char byte1 = 0x23, byte2 = 0x34;
int result = xor32int((int)byte1, (int)byte2);
And being that xor32int() assumes input to be 32 bit integers it runs a loop 32 times, so even if value is only 8 bit it runs extra loops when unnecessary resulting in a major decrease in performance.
How would I go about converting the xor32int() function so it only works with 8 bit values so it doesn't need to loop 32 times?
If you are wondering why don't I simply use the XOR operator, it is because I am working with an old machine that uses a processor that doesn't support XOR.
Is there a reason you can't use (x | y) & ~(x & y)? That's one definition of xor. You can write it as a function:
char xor8(char x, char y) {
return (x | y) & ~(x & y);
}
You can even write it as a function template:
template<typename T>
T xorT(T x, T y) {
return (x | y) & ~(x & y);
}
In case you can't use that for some reason, I'm pretty sure you can replace int with char, and 31 with 7:
char xor8char(char x, char y)
{
char res = 0;
for (int i = 7; i >= 0; i--)
{
bool b1 = x & (1 << i);
bool b2 = y & (1 << i);
bool xoredBit = (b1 & b2) ? 0 : (b1 | b2);
res <<= 1;
res |= xoredBit;
}
return res;
}
All of that, live on Coliru.

error: not assignable in macro function

I'm trying to write a function into a macro, but it is giving me a 'not assignable error'. My macro is this:
#define swapmacro(t, x, y) {t temp = x; x = y; y = temp;}
This is the code where I called it
int x = 4;
int y = 5;
swapmacro(int, 4, 5);
Then it gave me this error message:
stack.c:23:3: error: expression is not assignable
swapmacro(int, 4, 5);
^ ~
stack.c:7:43: note: expanded from macro 'swapmacro'
#define swapmacro(t, x, y) {t temp = x; x = y; y = temp;}
^
stack.c:23:3: error: expression is not assignable
swapmacro(int, 4, 5);
^ ~
stack.c:7:50: note: expanded from macro 'swapmacro'
#define swapmacro(t, x, y) {t temp = x; x = y; y = temp;}
^
swapmacro(int, 4, 5);
expands to this:
{int temp = 4; 4 = 5; 5 = temp;};
Neither 4 = 5 nor 5 = temp are valid expressions. Integer literals cannot be lvalues. Perhaps you meant to do this:
swapmacro(int, x, y);
Why not resort to something that uses a macros?
See swap
So the code could be
std::swap(x,y);
with type safety etc.

Returning and outputting 2 integers from 1 function

i have to write a code that has a function that takes two integers and returns x as (a + b) and y as (a * b) and when i run it, it only outputs y. Why doesnt it output (or return) x?
#include <iostream>
using namespace std;
int math (int a, int b) {
int x, y;
x = a + b;
y = a * b;
return x, y;
}
int main() {
cout << math (5,3);
getchar();
getchar();
return 0;
}
The return type of math is int, so this is what it returns (a single integer).
The expression x, y uses the comma operator. The comma operator evaluates x, discards its value, and then evaluates and returns y. In other words, return x, y is equivalent to return y.
You could use std::pair<int,int> to return a pair of integers.
The line
return x, y;
does not do what you expect. The comma operator returns only the value after the last comma - in this case, y. To return multiple values, you should use a struct or class containing both.
You can only return one thing. You can put those in a struct, and return it. Simpler example.
struct xy {
int x;
int y;
};
xy math(int a, int b) {
xy pair;
int x, y;
pair.x = a + b;
pair.y = a * b;
return pair;
}
There are two ways to make a function return more than one value. The
first is to use out parameters, either references or pointers:
void
math( int a, int b, int& sum, int& product )
{
sum = a + b;
product = a * b;
}
int
main()
{
int s;
int p;
math(5, 3, s, p);
std::cout << s << ' ' << p << std::endl;
return 0;
}
The other is to define a class to contain the two values:
struct MathResults
{
int sum;
int product;
};
MathResults
math( int a, int b )
{
return MathResults{ a + b, a * b };
}
std::ostream&
operator<<( std::ostream& dest, MathResults const& value )
{
dest << value.sum << ' ' << value.product;
}
int
main()
{
std::cout << math( 5, 3 ) << std::endl;
return 0;
}
In most cases, the second solution is to be preferred.

How to store a 64 bit integer in two 32 bit integers and convert back again

I'm pretty sure its just a matter of some bitwise operations, I'm just not entirely sure of exactly what I should be doing, and all searches return back "64 bit vs 32 bit".
pack:
u32 x, y;
u64 v = ((u64)x) << 32 | y;
unpack:
x = (u32)((v & 0xFFFFFFFF00000000LL) >> 32);
y = (u32)(v & 0xFFFFFFFFLL);
Or this, if you're not interested in what the two 32-bits numbers mean:
u32 x[2];
u64 z;
memcpy(x,&z,sizeof(z));
memcpy(&z,x,sizeof(z));
Use a union and get rid of the bit-operations:
<stdint.h> // for int32_t, int64_t
union {
int64_t big;
struct {
int32_t x;
int32_t y;
};
};
assert(&y == &x + sizeof(x));
simple as that. big consists of both x and y.
I don't know if this is any better than the union or memcpy solutions, but I had to unpack/pack signed 64bit integers and didn't really want to mask or shift anything, so I ended up simply treating the 64bit value as two 32bit values and assign them directly like so:
#include <stdio.h>
#include <stdint.h>
void repack(int64_t in)
{
int32_t a, b;
printf("input: %016llx\n", (long long int) in);
a = ((int32_t *) &in)[0];
b = ((int32_t *) &in)[1];
printf("unpacked: %08x %08x\n", b, a);
((int32_t *) &in)[0] = a;
((int32_t *) &in)[1] = b;
printf("repacked: %016llx\n\n", (long long int) in);
}
The basic method is as follows:
uint64_t int64;
uint32_t int32_1, int32_2;
int32_1 = int64 & 0xFFFFFFFF;
int32_2 = (int64 & (0xFFFFFFFF << 32) ) >> 32;
// ...
int64 = int32_1 | (int32_2 << 32);
Note that your integers must be unsigned; or the operations are undefined.
long x = 0xFEDCBA9876543210;
cout << hex << "0x" << x << endl;
int a = x ;
cout << hex << "0x" << a << endl;
int b = (x >> 32);
cout << hex << "0x" << b << endl;
Not sure if this way of doing is good for portability or others but I use...
#include <stdio.h>
#include <stdint.h>
typedef enum {false, true} bool;
#ifndef UINT32_WIDTH
#define UINT32_WIDTH 32 // defined in stdint.h, but compiler error ??
#endif
typedef struct{
struct{ // anonymous struct
uint32_t x;
uint32_t y;
};}ts_point;
typedef struct{
struct{ // anonymous struct
uint32_t line;
uint32_t column;
};}ts_position;
bool is_little_endian()
{
uint8_t n = 1;
return *(char *)&n == 1;
}
int main(void)
{
uint32_t x, y;
uint64_t packed;
ts_point *point; // struct offers a "mask" to retreive data
ts_position *position; // in an ordered and comprehensive way.
x = -12;
y = -23;
printf("at start: x = %i | y = %i\n", x, y);
if (is_little_endian()){
packed = (uint64_t)y << UINT32_WIDTH | (uint64_t)x;
}else{
packed = (uint64_t)x << UINT32_WIDTH | (uint64_t)y;
}
printf("packed: position = %llu\n", packed);
point = (ts_point*)&packed;
printf("unpacked: x = %i | y = %i\n", point->x, point->y); // access via pointer
position = (ts_position*)&packed;
printf("unpacked: line = %i | column = %i\n", position->line, position->column);
return 0;
}
I like the way I do as it's offer lots of readiness and can be applied in manay ways ie. 02x32, 04x16, 08x08, etc.
I'm new at C so feel free to critic my code and way of doing... thanks