Type casting boolean to int externally - casting

when internally the storage of boolean variable is in the form of an int variable,then why does it happen that when we try to type cast the boolean into int ,compilation error comes,
for example,
boolean a=true; // when this line executes the compiler then it internally converts the a vaiable to int type and it holds the value =1
so if i write
int rd=(int)a; // then why is this error??
that is when internally automatically boolean is converted as an int type variable then why externally we are not allowed to do type casting

Related

Can you assign a default enum value for failed casts in c++?

I'm wondering if it's possible to assign a default value to an enum in C++? That is to say, if we try to convert a value to this specific enum, and the value does not exist, have it return a default enum value...
enum ExampleEnum : int
{
DefaultValue = 0,
Value1 = 1,
Value2 = 2;
};
// I want this to return 0 (DefaultValue) as the value (3) is not defined in ExampleEnum.
const ExampleEnum invalid_enum = static_cast<ExampleEnum>(3);
No, there is no such built-in feature and you can't affect what the static_cast<ExampleEnum> will do. Of course you can just write yourself a function that will perform the cast with a prior check of the value and use that instead of static_cast.
But also note that the cast static_cast<ExampleEnum>(3) is valid and that 3 is an allowed value of your enumeration type. An enumeration with a fixed underlying type (e.g. the one which has a type explicitly specified as you did) has all the values of its underlying type as valid values.
The named enumerators in the enumeration definition are just aliases for a subset of the values. They don't affect the range of possible values in this case.
(Beware though that this is different for enumerations without fixed underlying type.)

Is it safe to assign bool or float to int32_t?

I have a c++ project that have a struct with int32_t member data type and i want to assign bool and float variables to it, will that ruin the value of the variable? If yes, what should i do other than changing the struct member data type?
Whenever the compiler has to use a value of a type in a context where another type is expected, an implicit conversion is performed.
The rules for implicit conversions are numerous, but under Floating–integral conversions, there is the following paragraph:
A prvalue of floating-point type can be converted to a prvalue of any
integer type. The fractional part is truncated, that is, the
fractional part is discarded. If the value cannot fit into the
destination type, the behavior is undefined (even when the destination
type is unsigned, modulo arithmetic does not apply). If the
destination type is bool, this is a boolean conversion (see below).
So, you can safely assign a floating point type (e.g. float or double) to an integer. Provided that the value can fit, the decimal part will be truncated. This implies a loss of data, and might be a source of bugs, or might be done on purpose in certain applications. Note that the floating point types have a larger range than int32_t, and if the value cannot be stored, it is undefined behaviour as per the standard.
Bools, on the other hand, can be safely assigned to integer types under all circumstances:
If the source type is bool, the value false is converted to zero and
the value true is converted to the value one of the destination type
(note that if the destination type is int, this is an integer
promotion, not an integer conversion).
The value you assign will be converted to int32_t. The bool value will not lose anything. The float value will be truncated. Only the integral part of it will be stored.
If yes, what should i do other than changing the struct member data type?
That depends on whether the type of the values you want to store are determined at runtime or compile-time. If it's determined at runtime, you can use an std::any instead of an int32_t:
#include <any>
struct MyStruct {
std::any val;
};
// ...
MyStruct s;
s.val = true; // val now contains a bool
s.val = 3.1415; // val now contains a double
s.val = 3.1415f; // val now contains a float
s.val = 42; // val now contains an int
If the type is determined at compile-time, you can make a struct template:
template <typename T>
struct MyStruct {
T val;
};
// ...
MyStruct<bool> s1;
s1 = false;
MyStruct<float> s2;
s2 = 3.1415;

How do I correctly pass, as argument, a literal integer as a void pointer, using its address as the integer’s actual value

As an experiment:
I have hypothetical function with signature: void func(void *), where I have to pass an integer value, literally in the code: func(42). It must be done with a literal integer.
Is there a “right” way to pass a integer value, say, “hacked” as an address in a pointer (to address 0x2A for example), and the somehow convert it back to an integer (42 for the 0x2A example). All of this without unexpected behavior?
In short: being able to convert a pointer address into an integer which will hold the number of the address.
Both C and C++ standards explicitly allow for such conversion.
C99 6.3.2.3.5:
An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation.
C++11 5.2.10.5
A value of integral type or enumeration type can be explicitly converted to a pointer.
Therefore, your call of func((void*)42) should work with all standard-compliant compilers.
What is the, say, most correct way to pass a literal integer to an argument expecting a void pointer, and having the integer untouched in the function?
This way of passing a literal integer as an argument to a function expecting a void* guarantees that the original integer would be untouched in the function, because the argument is passed by value.
It shouldn't be done this way.
You can allocate the value on the stack and then call the function.
Example in C:
int i = 42;
func((void*) (&i));
Example in C++:
int i = 42;
func(reinterpret_cast<void*> (&i));
Otherwise, if you are not sure about the life time of the variable, it can be allocated on the heap using malloc()/free() or new/delete.

What happens if you pass an int to a byte parameter in C?

How does C/C++ deal if you pass an int as a parameter into a method that takes in a byte (a char)? Does the int get truncated? Or something else?
For example:
void method1()
{
int i = //some int;
method2(i);
}
void method2(byte b)
{
//Do something
}
How does the int get "cast" to a byte (a char)? Does it get truncated?
If byte stands for char type, the behavior will depend on whether char is signed or unsigned on your platform.
If char is unsigned, the original int value is reduced to the unsigned char range modulo UCHAR_MAX+1. Values in [0, UCHAR_MAX] range are preserved. C language specification describes this process as
... the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
If char type is signed, then values within [SCHAR_MIN, SCHAR_MAX] range are preserved, while any values outside this range are converted in some implementation-defined way. (C language additionally explicitly allows an implementation-defined signal to be raised in such situations.) I.e. there's no universal answer. Consult your platform's documentation. Or, better, write code that does not rely on any specific conversion behavior.
Just truncated AS bit pattern (byte is in general unsigned char, however, you have to check)
int i = -1;
becomes
byte b = 255; when byte = unsigned char
byte b = -1; when byte = signed char
i = 0; b = 0;
i = 1024; b = 0;
i = 1040; b = 16;
Quoting the C++ 2003 standard:
Clause 5.2.2 paragrah 4: When a function is called, each parameter (8.3.5) shall be initialized (8.5, 12.8, 12.1) with its corresponding
argument.
So, b is initialized with i. What does that mean?
8.5/14 the initial value of the object being initialized is the (possibly converted) value of the initializer
expression. Standard conversions (clause 4) will be used, if necessary, to convert the initializer
expression to the … destination type; no user-defined conversions are considered
Oh, i is converted, using the standard conversions. What does that mean? Among many other standard conversions are these:
4.7/2 If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source
integer (modulo 2n where n is the number of bits used to represent the unsigned type).
4.7/3 If the destination type is signed, the value is unchanged if it can be represented in the destination type (and
bit-field width); otherwise, the value is implementation-defined.
Oh, so if char is unsigned, the value is truncated to the number of bits in a char (or computed modulo UCHAR_MAX+1, whichever way you want to think about it.)
And if char is signed, then the value is unchanged, if it fits; implementation-defined otherwise.
In practice, on the computers and compilers you care about, the value is always truncated to fit in 8 bits, regardless of whether chars are signed or unsigned.
You don't tell what a byte is, but if you pass a parameter that is convertible to the parameter type, the value will be converted.
If the types have different value ranges there is a risk that the value is outside the range of the parameter type, and then it will not work. If it is within the range, it will be safe.
Here's an example:
1) Code:
#include <stdio.h>
void
method1 (unsigned char b)
{
int a = 10;
printf ("a=%d, b=%d...\n", a, b);
}
void
method2 (unsigned char * b)
{
int a = 10;
printf ("a=%d, b=%d...\n", a, *b);
}
int
main (int argc, char *argv[])
{
int i=3;
method1 (i);
method2 (i);
return 0;
}
2) Compile (with warning):
$ gcc -o x -Wall -pedantic x.c
x.c: In function `main':
x.c:22: warning: passing arg 1 of `method2' makes pointer from integer without a cast
3) Execute (with crash):
$ ./x
a=10, b=3...
Segmentation fault (core dumped)
'Hope that helps - both with your original question, and with related issues.
There are two cases to worry about:
// Your input "int i" gets truncated
void method2(byte b)
{
...
// Your "method2()" stack gets overwritten
void method2(byte * b)
{
...
It will be cast to a byte the same as if you casted it explicitly as (byte)i.
Your sample code above might be a different case though, unless you have a forward declaration for method2 that is not shown. Because method2 is not yet declared at the time it is called, the compiler doesn't know the type of its first parameter. In C, functions should be declared (or defined) before they are called. What happens in this case is that the compiler assumes (as an implicit declaration) that method2's first parameter is an int and method2 receives an int. Officially that results in undefined behaviour, but on most architectures, both int and byte would be passed in the same size register anyway and it will happen to work.

Type Conversion/Casting Confusion in C++

What is Type Conversion and what is Type Casting?
When should I use each of them?
Detail: Sorry if this is an obvious question; I'm new to C++, coming from a ruby background and being used to to_s and to_i and the like.
Conversion is when a value is, um, converted to a different type. The result is a value of the target type, and there are rules for what output value results from what input (of the source type).
For example:
int i = 3;
unsigned int j;
j = i; // the value of "i" is converted to "unsigned int".
The result is the unsigned int value that is equal to i modulo UINT_MAX+1, and this rule is part of the language. So, in this case the value (in English) is still "3", but it's an unsigned int value of 3, which is subtly different from a signed int value of 3.
Note that conversion happened automatically, we just used a signed int value in a position where an unsigned int value is required, and the language defines what that means without us actually saying that we're converting. That's called an "implicit conversion".
"Casting" is an explicit conversion.
For example:
unsigned int k = (unsigned int)i;
long l = long(i);
unsigned int m = static_cast<unsigned int>(i);
are all casts. Specifically, according to 5.4/2 of the standard, k uses a cast-expression, and according to 5.2.3/1, l uses an equivalent thing (except that I've used a different type). m uses a "type conversion operator" (static_cast), but other parts of the standard refer to those as "casts" too.
User-defined types can define "conversion functions" which provide specific rules for converting your type to another type, and single-arg constructors are used in conversions too:
struct Foo {
int a;
Foo(int b) : a(b) {} // single-arg constructor
Foo(int b, int c) : a(b+c) {} // two-arg constructor
operator float () { return float(a); } // conversion function
};
Foo f(3,4); // two-arg constructor
f = static_cast<Foo>(4); // conversion: single-arg constructor is called
float g = f; // conversion: conversion function is called
Classic casting (something like (Bar)foo in C, used in C++ with reinterpret_cast<>) is when the actual memory contents of a variable are assumed to be a variable of a different type. Type conversion (ie. Boost's lexical_cast<> or other user-defined functions which convert types) is when some logic is performed to actually convert a variable from one type to another, like integer to a string, where some code runs to logically form a string out of a given integer.
There is also static and dynamic casting, which are used in inheritance, for instance, to force usage of a parent's member functions on a child's type (dynamic_cast<>), or vice-versa (static_cast<>). Static casting also allows you to perform the typical "implicit" type conversion that occurs when you do something like:
float f = 3.14;
int i = f; //float converted to int by dropping the fraction
which can be rewritten as:
float f = 3.14;
int i = static_cast<int>(f); //same thing
In C++, any expression has a type. when you use an expression of one type (say type S) in a context where a value of another type is required (say type D), the compiler tries to convert the expression from type S to type D. If such an implicit conversion doesn't exist, this results in an error. The word type cast is not standard but is the same as conversion.
E.G.
void f(int x){}
char c;
f(c); //c is converted from char to int.
The conversions are ranked and you can google for promotions vs. conversions for more details.
There are 5 explicit cast operators in C++ static_cast, const_cast, reinterpret_cast and dynamic_cast, and also the C-style cast
Type conversion is when you actually convert a type in another type, for example a string into an integer and vice-versa, a type casting is when the actual content of the memory isn't changed, but the compiler interpret it in a different way.
Type casting indicates you are treating a block of memory differently.
int i = 10;
int* ip = &i;
char* cp = reinterpret_cast<char*>(ip);
if ( *cp == 10 ) // Here, you are treating memory that was declared
{ // as int to be char.
}
Type conversion indicates that you are converting a value from one type to another.
char c = 'A';
int i = c; // This coverts a char to an int.
// Memory used for c is independent of memory
// used for i.