Weird hex values from std::cout.

Started by
12 comments, last by MarkS_ 7 years, 3 months ago
I'm testing a cryptographic random number generator library based on Blum Blum Shub. The library I found seems to work, but the test program I wrote does not.

Here is the test program code:
#include <iostream>
#include <iomanip>

#include <mpir.h>
#include <gmpbbs.h>

int main()
{
	long		i;
	rndbbs_t	*test_random;
	char		*rand_val;

	//Excuse the mix of C and C++. The RNG library is written in C. Soon to be remedied...

	test_random = rndbbs_new();

	rndbbs_gen_blumint(test_random,2048);
	rndbbs_gen_x(test_random);

	rand_val = new char[16];
	for (i = 0; i < 16; ++i)
		rand_val[i] = (char)0;

	rand_val = rndbbs_randbytes(test_random,16);

	std::cout.setf(std::ios::hex,std::ios::basefield);
	std::cout.setf(std::ios::uppercase);
	for(i = 0;i < 16;++i)
		std::cout << std::setfill('0') << std::setw(2) << static_cast<unsigned int>(rand_val[i]) << " ";

	delete [] rand_val;
	rndbbs_destroy(test_random);

	while(1);
	return 0;
}
This is the output:

error.jpg

The leading "FFFFFF" on several of the printed bytes are not generated by the RNG.

The output should read: "47 0F 8E 9F 33 1A B0 A9 EB 79 E4 BC 8A 25 94 9A".

I have never seen this before and cannot find any solutions through Google. Any idea why this is happening?
Advertisement
The problem is that `char' seems to be signed in your compiler. This is allowed by the C++ standard. You can fix the problem by first casting to `unsigned char' and then to `unsigned int'.

There is nothing weird about the behaviour, it's completely expected. Try making rand_val an unsigned char and get rid of the integer promotion in the output statement.

Stephen M. Webb
Professional Free Software Developer

Never mind. I fixed it.

Changing this:

std::cout << std::setfill('0') << std::setw(2) << static_cast<unsigned int>(rand_val) << " ";

to this:

std::cout << std::setfill('0') << std::setw(2) << static_cast<unsigned char>(rand_val) + 0 << " ";

did the trick.

[edit] Posted before I refreshed the page. Thanks guys!

std::cout << std::setfill('0') << std::setw(2) << static_cast<unsigned char>(rand_val) + 0 << " ";

By adding a signed in constant you're implicitly converting the sign-extended explictly-cast unsigned int implicitly widened from a (maybe signed, maybe not, it depends) char value in your array into a signed int, which exceeds the range of the int and invokes undefined behaviour.

I'd still recommend you use the right data type in the first place (unsigned char to hold a byte) rather than simply plaster some undefined behaviour into your program in the hopes that it will not simply reformat your hard drive.

I mean, it's just a thought, but I'd steer away from undefined behaviour if I were you.

Stephen M. Webb
Professional Free Software Developer

Bregma, are you saying that casting a char to unsigned char can invoke undefined behavior?

Section "4.7 Integral conversions" of the C++14 standard says:

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source
integer (modulo 2^n where n is the number of bits used to represent the unsigned type).



This sounds to me like the conversion is just dandy. But I find the language in the standard pretty confusing, so perhaps I am missing something?

Bregma, are you saying that casting a char to unsigned char can invoke undefined behavior?

Ah, I'm wrong. It's implementation-defined behaviour. He's converting it from char to unsigned char and then widening it to (signed) int. It's well-defined, just not reliable behaviour. The difference is that undefined behaviour can do anything at all, whereas implementation-defined behaviour is restricted to given some valid integral result (which depends on the vendor and hardware architecture) or crashing.

I still stand by my statement that if he had used unsigned char to store unsigned bytes, there would have been no problem and no need for casting about.

Stephen M. Webb
Professional Free Software Developer

I'd still recommend you use the right data type in the first place (unsigned char to hold a byte) rather than simply plaster some undefined behaviour into your program in the hopes that it will not simply reformat your hard drive.


The library's function returns a char array, so that's not entirely up to me. I am rewriting the library to remove the dependency on C and use C++, so that can and will change.

Any reason not to use std::random_device? Are you working with machines that don't have randomness generators?

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

Any reason not to use std::random_device? Are you working with machines that don't have randomness generators?


I'm working on a test bed for an application that will eventually run on an embedded microcontroller. Everything must be hand rolled.

This topic is closed to new replies.

Advertisement