Assignment EOF of int to char behavior on ARM vs x86_64 - casting

I am running this snippet of code both on ARM (iMX6) and intel 64 bits:
#include <stdio.h>
int main()
{
int i = EOF;
char d = i;
printf("i = %d, d = %d\n", i, d);
if (i == EOF)
printf ("i is EOF\n");
if (d == EOF)
printf ("d is EOF\n");
return 0;
}
In both cases, I compiled it with gcc 5.4:
ARM: gcc (Ubuntu/Linaro 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
x86_64: gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
However, the results are very different:
ARM:
i = -1, d = 255
i is EOF
x86_64:
i = -1, d = -1
i is EOF
d is EOF
Why does this happen?

It is implementation-defined if char is signed (i.e. ranges from -128 to 127) or is unsigned (ranges from 0 to 255).
In your combination of ARM and gcc, it's obviously unsigned.
Therefore -1 is converted to 255.
In your combination of x86_64 and gcc, it's signed. Therefore, -1 is
retained.

Related

bitset not working with some numbers

i am trying to convert 8 Byte wide number to bit strings .
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <bitset>
void getAsString(int64_t mask )
{
printf("mask = %lld\n", mask);
std::string test = std::bitset< 64 >( mask ).to_string();
printf("test = %s \n", test.c_str() );
}
int main()
{
int64_t allowedBits[4] = { 0x0000000000000001L, 0x0000000000010000L, 0x0000000100000000L, 0x0001000000000000L };
for (int i = 0; i < 4; ++i)
{
getAsString(allowedBits[i]);
}
}
Below is the output on Linux Machine
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04 LTS
Release: 16.04
Codename: xenial
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
mask = 1
test = 0000000000000000000000000000000000000000000000000000000000000001
mask = 65536
test = 0000000000000000000000000000000000000000000000010000000000000000
mask = 4294967296
test = 0000000000000000000000000000000100000000000000000000000000000000
mask = 281474976710656
test = 0000000000000001000000000000000000000000000000000000000000000000
Same code this machine .
Distributor ID: CentOS
Description: CentOS release 6.8 (Final)
Release: 6.8
Codename: Final
g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-17)
Give the below output
mask = 1
test = 0000000000000000000000000000000000000000000000000000000000000001
mask = 65536
test = 0000000000000000000000000000000000000000000000010000000000000000
mask = 4294967296
test = 0000000000000000000000000000000000000000000000000000000000000000
mask = 281474976710656
test = 0000000000000000000000000000000000000000000000000000000000000000
I have checked the width of the int64_t . it is 8 in both machines.
For mask 4294967296 and 281474976710656 the string is zero .
Any help here would be really appreciated .
Based on the version of your compiler (gcc-4.4.7) the code is probably using a library which isn't updated to deal with C++11. The pre-C++11 specification of the std::bitset<N> constructor taking an integer used unsigned long. For a 32 bit build unsigned long uses 32 bits. As a result the argument will be truncated before passed to std::bitset<N>'s constructor.
I verified that libstdc++ shipping with gcc-4.4.7 does use unsigned long as the type in the constructor.

Why gcc and clang compiles to different "const" result for my program?

I was testing the behavior of "const" keyword under .c and .cpp, using gcc and clang.
#include<stdio.h>
int main(){
const int i=1;
int *pi = (int *)(&i);
*pi = 2;
printf("i = %d *pi = %d\n",i,*pi);
const int j=i;
printf("j = %d\n", j);
return 0;
}
Using different compilers leads to different results:
$gcc testConst.c && ./a.out
i = 2 *pi = 2
j = 2
$clang testConst.c && ./a.out
i = 1 *pi = 2
j = 1
If I change the file from .c to .cpp, and use g++ to compile and run it, then the result is same as clang version
$g++ testConst.cpp && ./a.out
i = 1 *pi = 2
j = 1
I wish to know:
The meaning of 'const' in C and C++ are a bit different, so the result of same compiler gcc, could leads to different result?
Compiling the same .c file, gcc and clang have different result, which is correct, or this is undefined behavior? Any C/C++ standard statements that could explain this?
It is undefined behavior to modify a const variable. It could even be that this:
*pi = 2;
Sets your integer to 9999. Or crashes the program.
Even once you've compiled the program, if you run it four times and get four different results, you will have no standing to complain. That's the beauty of undefined behavior.

sin(<minus zero>) does not return the expected result on Visual Studio 2013 64bit

In the engineering application that I develop for, I stumbled over a difference in the result of sin(-0) between 32bit and 64bit. Due to the nature of the computations, this propagates into some phase differences.
We are developing on Windows with MSVC 2013.
Apparently the floating point standard specifies that sin(-0) returns the argument unchanged - according to cppreference/sin at least.
I've done some investigation and these are some other results I got:
// Visual Studio 2013 32 bit on Win7 - default arguments
std::sin( -0 ) = -0
std::sin( 0 ) = 0
// Visual Studio 2013 64 bit on Win7 - default arguments
std::sin( -0 ) = 0 // the faulty one
std::sin( 0 ) = 0
// g++ (GCC) 5.1.0 : g++ -std=c++11 -O2 -Wall -pedantic -mfpmath=387 -m64 main.cpp && ./a.out
std::sin( -0 ) = -0
std::sin( 0 ) = 0
// g++ (GCC) 5.1.0 : g++ -std=c++11 -O2 -Wall -pedantic -mfpmath=sse -m64 main.cpp && ./a.out
std::sin( -0 ) = -0
std::sin( 0 ) = 0
I also know that the Intel math libraries (libm*.dll) also return sin(-0)=-0.
Looking into the disassembly, the implementation of std::sin directs into msvcr120d.dll.
The questions:
is this an error in Microsoft's sin routine implementation on 64bit?
should I have used some specific compiler argument that I do not know about?
The code to use for the above output:
#include <cmath>
#include <iostream>
void printSin( const double dfPh )
{
const auto dfSinPh = std::sin( dfPh );
std::cout.precision( 16 );
std::cout << "std::sin( " << dfPh << " ) = " << dfSinPh << std::endl;
}
int main()
{
printSin( -0.00000000000000000000 );
printSin( +0.00000000000000000000 );
return 0;
}
In the end I resorted to a poor man's solution. I specifically check for -0 using std::signbit and closeness to zero, and consider sin(-0) = -0.
Slow? Perhaps, but correct for our needs.

Illegal instruction (core dumped) upon compiling with SSE and -O3 options using latest g++ with a custom alignment allocator implementation

When using g++ (GCC) 4.8.3 20140911 (Red Hat 4.8.3-7) to compile the following piece of code using the compiling command "g++ -g -fno-omit-frame-pointer -msse2 -mssse3 -O3 Memory.cpp", the executable raises "Illegal instruction (core dumped)" upon execution.
It compiles and runs without problems using the same exact compiler flags using an older g++ version. It also compiles and runs without problems when the compiler flags "-mssse3 -O3" is dropped or is replaced with a lower optimization level such as "-O2".
If usage with both the old and the newer g++ compiler, having the compiler flags "-msse2 -mssse3 -O3", and having a portable aligned memory allocator is a requirement, what options exist? Is there a simple mistake in the following piece of code that could be easily fixed? Finally, why did this error exist?
When using gdb, the line that triggers this error is: "memory[i] = (unsigned char)i;".
Thanks much in advance.
#include <iostream>
using std::cerr;
using std::cout;
using std::endl;
using std::flush;
#include <stdlib.h>
void *aligned_alloc(int alignment, int size){
const int pointer_size = sizeof(unsigned char *);
const int requested_size = size + alignment - 1 + pointer_size;
unsigned char *base = (unsigned char *)malloc(requested_size);
if (base == NULL) return NULL;
unsigned char *start = base + pointer_size;
const int trim_offset = (int)(((unsigned long long)(start+alignment-1)) & (alignment-1));
unsigned char *aligned = start + alignment - 1 - trim_offset;
*(unsigned char **)(aligned-pointer_size) = base;
return aligned;
}
void aligned_free(void **aligned){
if (*aligned == NULL) return;
unsigned char *base = *(unsigned char **)((unsigned char *)(*aligned) - sizeof(unsigned char *));
free(base);
*aligned = NULL;
}
int main(){
unsigned char *memory = (unsigned char *)aligned_alloc(16, 120);
if (memory == NULL){
cout<<"ERROR: Unable to allocate memory."<<endl;
exit(1);
}
for (int i=0; i<120; i++){
memory[i] = (unsigned char)i;
}
aligned_free((void **)&memory);
return 0;
}
This was caused by a CPU that didn't support the SSSE3 (Supplemental Streaming SIMD Extensions 3) instruction subset (in particular, a 3GHZ P4 of some flavor) trying to run code compiled for CPUs that support that instruction subset; simply dropping the -mssse3 flag from the GCC command line should be enough to cause the offending instructions to go away.

GCC problem with raw double type comparisons

I have the following bit of code, however when compiling it with GCC 4.4 with various optimization flags I get some unexpected results when its run.
#include <iostream>
int main()
{
const unsigned int cnt = 10;
double lst[cnt] = { 0.0 };
const double v[4] = { 131.313, 737.373, 979.797, 731.137 };
for(unsigned int i = 0; i < cnt; ++i) {
lst[i] = v[i % 4] * i;
}
for(unsigned int i = 0; i < cnt; ++i) {
double d = v[i % 4] * i;
if(lst[i] != d) {
std::cout << "error # : " << i << std::endl;
return 1;
}
}
return 0;
}
when compiled with: "g++ -pedantic -Wall -Werror -O1 -o test test.cpp" I get the following output: "error # : 3"
when compiled with: "g++ -pedantic -Wall -Werror -O2 -o test test.cpp" I get the following output: "error # : 3"
when compiled with: "g++ -pedantic -Wall -Werror -O3 -o test test.cpp" I get no errors
when compiled with: "g++ -pedantic -Wall -Werror -o test test.cpp" I get no errors
I do not believe this to be an issue related to rounding, or epsilon difference in the comparison. I've tried this with Intel v10 and MSVC 9.0 and they all seem to work as expected. I believe this should be nothing more than a bitwise compare.
If I replace the if-statement with the following: if (static_cast<long long int>(lst[i]) != static_cast<long long int>(d)), and add "-Wno-long-long" I get no errors in any of the optimization modes when run.
If I add std::cout << d << std::endl; before the "return 1", I get no errors in any of the optimization modes when run.
Is this a bug in my code, or is there something wrong with GCC and the way it handles the double type?
Note: I've just tried this with gcc versions 4.3 and 3.3, the error is not exhibited.
Resolution: Mike Dinsdale noted the following bug report: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 It seems the GCC team are not completely sure about nature of problem.
As suggested in the bug report a possible resolution is to use the ffloat-store option. I've tried this and it works, however the results from a performance point of view are not that great, though ymmv.
The fact that the result depends on the optimization settings suggests it might be the x87 extended precision messing with things (as Michael Burr says).
Here's some code I use (with gcc on x86 processors) to switch the extended precision off:
static const unsigned int PRECISION_BIT_MASK = 0x300;
///< bitmask to mask out all non-precision bits in the fpu control word \cite{INTEL}.
static const unsigned int EXTENDED_PRECISION_BITS = 0x300;
///< add to the fpu control word (after zeroing precision bits) to turn on extended precision \cite{INTEL}.
static const unsigned int STANDARD_PRECISION_BITS = 0x200;
///< add to the fpu control word (after zeroing precision bits) to turn off extended precision \cite{INTEL}.
void set_fpu_control_word(unsigned int mode)
{
asm ("fldcw %0" : : "m" (*&mode));
}
unsigned int get_fpu_control_word()
{
volatile unsigned int mode = 0;
asm ("fstcw %0" : "=m" (*&mode));
return mode;
}
bool fpu_set_extended_precision_is_on(bool state)
{
unsigned int old_cw = get_fpu_control_word();
unsigned int masked = old_cw & ~PRECISION_BIT_MASK;
unsigned int new_cw;
if(state)
new_cw = masked + EXTENDED_PRECISION_BITS;
else
new_cw = masked + STANDARD_PRECISION_BITS;
set_fpu_control_word(new_cw);
return true;
}
bool fpu_get_extended_precision_is_on()
{
unsigned int old_cw = get_fpu_control_word();
return ((old_cw & PRECISION_BIT_MASK) == 0x300);
}
Or you can just run your code with valgrind, which doesn't simulate the 80-bit registers, and is probably easier for a short program like this!
The problem is likely the result of losing some precision when storing the result of an expression vs. the compiler not doing so in a local as an optimization:
double d = v[i % 4] * i; // the result, `d`, might be kept in a register
// instead of storing it in a memory location,
// keeping full precision
if(lst[i] != d) { // the value stored in lst[i] may have lost some
// precision since it had to be stored in memory,
// which might not be able to hold the full
// precision that the expression generated
The C99 standard says in 6.3.1.8/2 "Usual arithmetic conversions":
The values of floating operands and of the results of floating expressions may be
represented in greater precision and range than that required by the type; the types are not
changed thereby.
The width of the floating point registers in x86 is different from the width of the double in RAM. Therefore comparisons may succeed or fail depending entirely on how the compiler decides to optimize the loads of floating point values.