32 bit signed integer

Hi.

I have get_massege function which needs to return 32 bit integer.
So i thought about using u32. Then i realized i have some ERROR CODEs
which need to be negative (to distinguish them from 32 bit value).
they are numerous: -1,-2,-3,-4,-5
so basically i need 33 bits integer :/

What datatype should i use for that?
std::int32_t -- 32-bit signed integer
std::int64_t -- 64-bit signed integer

https://en.cppreference.com/w/cpp/header/cstdint
Another way would be to use a std::variant
https://en.cppreference.com/w/cpp/utility/variant

eg as a simple example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <variant>

struct Value {
	unsigned value;
};

struct Error {
	short code;
};

using Var = std::variant<Value, Error>;

void display(Var var) {
	if (std::holds_alternative<Value>(var))
		std::cout << "Has value " << std::get<Value>(var).value << '\n';
	else
		std::cout << "Has error code " << std::get<Error>(var).code << '\n';
}

int main() {
	Var var;

	var = Value(45);
	display(var);

	var = Error(-5);
	display(var);
}



Has value 45
Has error code -5


There's also std::visit which can be very useful:
https://en.cppreference.com/w/cpp/utility/variant/visit
Last edited on
Instead of
int getMessage(args); // returns a value or an error code
do
1
2
3
// Get the message. Returns 0 on success and a negative value on error.
// On success, set "result" to the integer result.
int getMessage(args, int &result);
I liked the above for a long time, but recently its been a neverending source of frustration.
I keep having to do this:

int unnecessary;
getMessage(arg, unnecessary);
if(unnecessary == value)
...

instead of
if(getMessage(arg) == value)

with at times 5 or so variables who only exist because of the reference parameter design.
When I do it new these days I will return a tuple or pair or something, anything, to avoid this aggravation. Is that just me?
> its been a never ending source of frustration.

It is frustrating because it introduces more verbiage; becomes even more frustrating when it sabotages using const proactively. As a minor irritant, it may also be slightly less efficient.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <string>
#include <utility>

enum errc { OK, ERR_INVALID_ARG = -1, ERR_XYZ = -2, /* etc. */ };
using result_t = std::string ;

namespace A
{
    int foo( int arg, result_t& result )
    {
        if( arg == 0 )
        {
            result = {} ;
            return ERR_INVALID_ARG ;
        }

        else
        {
            result = std::to_string(arg+arg) ;
            return OK ;
        }
    }
}

namespace B
{
    std::pair<result_t,errc> foo( int arg )
    {
        if( arg == 0 ) return { {}, ERR_INVALID_ARG } ;
        else return { std::to_string(arg+arg), OK } ;
    }
}

int main()
{
    {
        /* const */ result_t result {} ;
        if( auto ec = A::foo( 100, result ) ; ec != OK ) std::cerr << "*** error *** " << ec << '\n' ;
        else std::cout << result << '\n' ;
    }

    {
        const auto [ result, ec] = B::foo(100) ;
        if( ec != OK ) std::cerr << "*** error *** " << ec << '\n' ;
        else std::cout << result << '\n' ;
    }
}
dhayden,

Why what you suggest is better option then this ?
int getMessage(args, int *result);


(if i am working in c for example)
Last edited on
Yes, that would be the C-equivalent of what he suggested.
Jonnin,

You still have to check for an error before you use the result:
1
2
3
int unnecessary;
getMessage(arg, unnecessary);
if(unnecessary == value) // "unnecessary" may be uninitialized if getMessage had an error 


JLBorges makes good points.

Perhaps the best way to handle errors in a case like this (where you want to use the result in an expression) is to throw an exception for errors.
(if i am working in c for example)


As for the 'c' way, there's always union...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

struct Var {
	bool isError = 0;
	union {
		unsigned value;
		short code;
	} uvar;
};

void display(Var var) {
	if (!var.isError)
		std::cout << "Has value " << var.uvar.value << '\n';
	else
		std::cout << "Has error code " << var.uvar.code << '\n';
}

int main() {
	Var var {};

	var.uvar.value = 45;
	display(var);

	var.isError = true;
	var.uvar.code = -5;
	display(var);
}

Last edited on
Yes, you do have to deal with errors:

if( foo(something)->result ) //what to do if foo failed somehow?

every attempt to make that happen without bloat is a struggle.
about the smallest I have to offer generally is factoring it out if it makes sense:
if(!condition_that_makes_foo_fail && foo(something)->result)
{}
else
{throw/complain/whatever}

and where possible, handling it inside of foo() so that foo can't give a bad result that goes forward, which makes the straight up call safe again.
there are many, many other ways as well. Error handling is a chore, but we certainly have loads of ways to manage it.

What do you mean error handling? This is my function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int Get_Msg (int ch, int* result){

	u8 IS_FIFO_Empty;
	u32 fifo_stat;
	u32 data;

	if ((ch<0)||(ch>Rx_num-1))
		return CH_PARAM_ERROR;

	if 	(Rx_Channels[ch].IsReady == 0)
		return IDLE_CHANNEL;

	fifo_stat = Xil_In32(XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+0X204+(0x10)*ch);

	IS_FIFO_Empty = (fifo_stat>>24) & 0x1; // 1 if fifo is empty

	if (IS_FIFO_Empty==0){
		*result = Xil_In32(XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR+0X208 (0x10)*ch);
		return SUCCESS;
	}
	else
		return FIFO_EMPTY;

}


What i am doing is if i have any error the function return negative value, otherwise it returns 0 . in main i just check:

1
2
3
4
5
6
7
stat = Get_Msg (Channel,&result);
		if (stat<0)	{
			xil_printf("Parameters error\n\r");
			xil_printf("Status %d\n\r",stat);
			break;
		}
else data = result; // in this point i know i get viable result 
error handing is both a concept and a tool in c++.
what you have above is conceptual error handling: you have an error, detect it, and handle it. This is fine.

c++ provides tools as well, which is the try/throw/catch keywords and syntax. you try to do some block of code, if there is a problem you throw an error, and after that you catch the error and handle it (else, if you do not, the program will crash with an unhandled exception code).
** the try/etc is more correctly called exception handling, if you want a better keyword to search on how to use them.

the exception handling tools are very powerful and flexible, and prone to temptation to abuse them. Beware using them as an alternative condition block, and keep them for real errors. They do not perform well as conditions or goto like constructs, and the code becomes difficult to understand what is an error and what is not.
Last edited on
Thanks :))
Topic archived. No new replies allowed.