Power Programming Languages

Power Programming Languages

IBM Power, including the AIX, IBM i, and Linux operating systems, support a wide range of programming languages, catering to both traditional enterprise applications and modern development needs.


#Power


#Servers
#Programminglanguages
 View Only

C/C++ things: data conversion fall-trap

By Archive User posted 08/08/13 02:08 AM

  

Originally posted by: Ka_Lin


Question: d=1, -d==?

Let's see what the answer is. What is the output of the following code?

int main() {
  char  dt = '\1';
  long tdt;
  tdt = -dt;
  printf("%ld\n", tdt);
}

The first option in my mind is that the output should be "-1". I think you would agree with me. However, how about the output on the 64-bit system? We expect the same output -1 and let's see if this is the case. Let's test it:

#xlc -q64 a.c  -qlanglvl=extended
#./a.out
4294967295

Here the output is "4294967295" rather than "-1". How that comes?

Don't worry, maybe we missed sth? Let's see the following code before we can answer the question:

"char  dt = '\1'; -dt;"

For this code block, we need to verify whether the variable "dt" is signed or unsigned. Let's see how the C language standard says:

"The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char."

That is to say, the standard does not define signed or unsigned for type char. Let's see how the XL compiler documentation says:

http://publib.boulder.ibm.com /infocenter/comphelp/v111v131/topic/com.ibm.xlc111.aix.doc/language_ref/ch.html)

"By default, char behaves like an unsigned char. To change this default, you can use the -qchars option or the #pragma chars directive. See -qchars for more information."

From this, we know that in XL compilers, the type char is unsigned by default. We can use the -qchars option to change the default behavior. Let's test it:

#xlc -q64 a.c  -qlanglvl=extended -qchar=signed
#./a.out
-1

Great! That explains the above behavior and get the point, I think.

Wait a minute... let's hold on. Do you really understand it? Maybe not. Let's look at another question. Regardless of whether we use -qchars, we can still get "-1" if we do not specify -qlanglvl=extended. Why?

#xlc -q64 a.c
#./a.out
-1

And, the following code prints "-1" as well, even -qlanglvl=extended is used.

int main() {
  unsigned char  dt = '\1';
  long tdt =dt;
  tdt = -tdt;
  printf("%ld\n", tdt);
}
#xlc -q64 a.c  -qlanglvl=extended ;./a.out
-1

Why the following code prints "4294967295" back?

int main() {
  unsigned  dt = '\1';
  long tdt;
  tdt = -dt;
  printf("%ld\n", tdt);
}

There seems to be sth deeper that needs to be investigated. Let's look into the following points:

  • The behavior of the minus operator
  • The rules of integral promotion
  • Type cast


Let's see them one by one.

1. For the behavior of the minus operator, the ISO C++ standard says:

"The result of the unary - operator is the negative of its (promoted) operand.  The integer promotions are performed on the operand, and the result has the promoted type."

The result type of the - operator relies on the type of the promoted operand. Similar information can be found in the XL compiler documentation:

http://publib.boulder.ibm.com/infocenter/comphelp/v111v131/topic/com.ibm.xlc111.aix.doc/language_ref/artnege.html

"Unary minus operator - :The result has the same type as the operand after integral promotion."

2. The rules of integral promotion

We can see the following information in our XL compiler doc:

http://publib.boulder.ibm.com/infocenter/comphelp/v111v131/topic/com.ibm.xlcpp111.aix.doc/language_ref/integer_float_promotion.html

"If an integer type other than wchar_t, bit field, and Boolean can be represented by the int type and its rank is lower than the rank of int, the integer type can be converted to the int type. Otherwise, the integer type can be converted to the unsigned int type."

Meanwhile, let's pay attention to the notes below:

-qupconv (C only)

Specifies whether the unsigned specification is preserved when integral promotions are performed.

Defaults
-qnoupconv for all language levels except classic or extended
-qupconv when the classic or extended language levels are in effect


We can see that the -qupconv (-qlanglvl=extended)option impacts the unsigned specification processing during integral promotion. When -qlanglvl=extended or -qupconv is in effect, unsigned specification is preserved.


3. We all know that the unsigned specification is determined by the target type when the type cast is performed. So, back to the preceding code:

int main() {
  unsigned char  dt = '\1';
  long tdt =dt;         // Type cast to tdt
  tdt = -tdt;          //The result type is still long, so the result is -1
  printf("%ld\n", tdt);
}

For the following code,

int main() {
  unsigned  dt = '\1';
  long tdt;
  tdt = -dt;    //Equivalent to (long)( (unsigned int) (-((unsigned int)u)) )
  printf("%ld\n", tdt);
}

the type of dt is unsigned int. According to #2 above, no need to be promoted, so the type of "-dt" is unsigned int as well. As a result, the value of -dt is 0xFFFFFFFF in binary. It is then cast to type long and assigned to dt, so the result of 0x00000000FFFFFFFF is 4294967295.  

For the following code,

int main() {
  unsigned char  dt = '\1';
  long tdt;
  tdt = -dt; 
  printf("%ld\n", tdt);
}

tdt = -dt. Unsigned char needs to be promoted to unsigned int when -qupconv or -qlanglvl=extended is in effect; otherwise, promoted to int.

When -qupconv or -qlanglvl=extended is effect, "tdt=-dt" is equivalent to "(long)( (unsigned int) (-((unsigned int)td)) )" and the result is 4294967295. Whereas when -qnoupconv (with other langlvl) is in effect, "tdt=-dt" is equivalent to "(long)( ( int) (-(( int)dt)) )" and the result is -1.


At this point, we can finally answer "d=1,-d==?". The result relies on operand type, possible type conversion, and the compiler options.

 

Author: Jiu Fu Guo (Jeff)


#C/C++andFortran
#C/C++-compilers-for-AIX
0 comments
0 views

Permalink