Supressing sign extension

D

Dave

I'm working on a program that will be parsing a protocol. My basic storage
element type is an array of characters or char*. The reason I am using
char* is because many of the socket and stream functions I'll be using take
char* as a parameter.

What I am seeing with my program is that when bit 7 is true, my integers are
being sign extended. Below is a program that should demonstrate my
problem. I am encountering this problem in a checksum loop that is adding
unsigned bytes together. As soon as bit7 is set my numbers become huge
because something is sign extending the high-byte. I think this may be a
processor related issue, but how can I overcome it.

I th

=============== Example
#include <iostream>

int main () {
// Define some constants
char ch[10] = { 0x01, 0x05, 0x07, 0x08, 0xFF,
0x0E, 0x0F, 0x10, 0x17, 0x18 };

// Observe sign extension
for (int i=0; i < 10; i++) {
std::cout << std::dec << "The value of ch[" << i << "] is "
<< std::hex << static_cast<unsigned short>(ch)
<< std::endl;
}
return 0;
}

============= a.out
The value of ch[0] is 1
The value of ch[1] is 5
The value of ch[2] is 7
The value of ch[3] is 8
The value of ch[4] is ffff
The value of ch[5] is e
The value of ch[6] is f
The value of ch[7] is 10
The value of ch[8] is 17
The value of ch[9] is 18
 
G

Gianni Mariani

Dave said:
I'm working on a program that will be parsing a protocol. My basic storage
element type is an array of characters or char*. The reason I am using
char* is because many of the socket and stream functions I'll be using take
char* as a parameter.

What I am seeing with my program is that when bit 7 is true, my integers are
being sign extended. Below is a program that should demonstrate my
problem. I am encountering this problem in a checksum loop that is adding
unsigned bytes together. As soon as bit7 is set my numbers become huge
because something is sign extending the high-byte. I think this may be a
processor related issue, but how can I overcome it.

I th

=============== Example
#include <iostream>

int main () {
// Define some constants
char ch[10] = { 0x01, 0x05, 0x07, 0x08, 0xFF,
0x0E, 0x0F, 0x10, 0x17, 0x18 };

// Observe sign extension
for (int i=0; i < 10; i++) {
std::cout << std::dec << "The value of ch[" << i << "] is "
<< std::hex << static_cast<unsigned short>(ch)


probably not portable in 1's complement:

<< std::hex << (reinterpret_cast<unsigned char *>(ch))

or perhaps better :

<< std::hex << static_cast<unsigned char>(ch)


<< std::endl;
}
return 0;
}

============= a.out
The value of ch[0] is 1
The value of ch[1] is 5
The value of ch[2] is 7
The value of ch[3] is 8
The value of ch[4] is ffff
The value of ch[5] is e
The value of ch[6] is f
The value of ch[7] is 10
The value of ch[8] is 17
The value of ch[9] is 18
 
A

Alf P. Steinbach

* Dave:
I'm working on a program that will be parsing a protocol. My basic storage
element type is an array of characters or char*. The reason I am using
char* is because many of the socket and stream functions I'll be using take
char* as a parameter.

What I am seeing with my program is that when bit 7 is true, my integers are
being sign extended. Below is a program that should demonstrate my
problem. I am encountering this problem in a checksum loop that is adding
unsigned bytes together. As soon as bit7 is set my numbers become huge
because something is sign extending the high-byte. I think this may be a
processor related issue, but how can I overcome it.

I th

=============== Example
#include <iostream>

int main () {
// Define some constants
char ch[10] = { 0x01, 0x05, 0x07, 0x08, 0xFF,
0x0E, 0x0F, 0x10, 0x17, 0x18 };

// Observe sign extension
for (int i=0; i < 10; i++) {
std::cout << std::dec << "The value of ch[" << i << "] is "
<< std::hex << static_cast<unsigned short>(ch)


Here you should either cast to a signed integer type such as 'int'
(which may produce apparently negative values, but values which can be
safely casted back to 'char' or 'unsigned char' or 'signed char'), or
you should use 'unsigned char' in the first place, or you should first
cast to 'unsigned char'.
 
D

Dave

I managed to solve the problem in a way similar to this:

int main () {
char ch[10] = { 0x01, 0x05, 0x07, 0x08, 0xFF,
0xFE, 0x0F, 0x7F, 0x80, 0x18 };
unsigned char* puc;
// Pretend the char* is really an unsigned char*
puc = reinterpret_cast<unsigned char*>(ch);

// Casting from a uchar to uint doesn't sign extend.
for (int i=0; i < 10; i++) {
std::cout << std::dec << "The value of puc[" << i << "] is "
<< std::hex << static_cast<unsigned int>(puc)
<< std::endl;
return 0;
}

but it seems highly non-portable - comments?.

The most portable way I can think of would be to manually calculate the
checksum in two character array. The problem I am working on is summing up
the bytes of a char* string to create a two byte checksum. But at present,
sign extension is messing things up.

If I use the 2 char array approach I could tackle the problem much like an
assembly language problem. I would look for a carry and increment the high
byte of the check sum. But the problem then becomes detecting the carry.
In assembly it is easy...just look for the 'C' flag to change. But how can
I do that in C++ efficiently. I don't know of any portable interface into
the processor registers. Is there a guru's trick using shifts or basic
logic operations?
 
A

Alf P. Steinbach

* Dave:
I managed to solve the problem in a way similar to this:

int main () {
char ch[10] = { 0x01, 0x05, 0x07, 0x08, 0xFF,
0xFE, 0x0F, 0x7F, 0x80, 0x18 };
unsigned char* puc;
// Pretend the char* is really an unsigned char*
puc = reinterpret_cast<unsigned char*>(ch);

The need for reinterpret_cast (or a C cast) should be a a very large,
waving, flashing and noisily flapping red flag telling you that this
approach is UnGood (TM).


// Casting from a uchar to uint doesn't sign extend.
for (int i=0; i < 10; i++) {
std::cout << std::dec << "The value of puc[" << i << "] is "
<< std::hex << static_cast<unsigned int>(puc)
<< std::endl;
return 0;
}

but it seems highly non-portable - comments?.


I pointed out three better solutions in a previous posting.

The most portable way I can think of would be to manually calculate the
checksum in two character array. The problem I am working on is summing up
the bytes of a char* string to create a two byte checksum. But at present,
sign extension is messing things up.

Post code.

If I use the 2 char array approach I could tackle the problem much like an
assembly language problem. I would look for a carry and increment the high
byte of the check sum. But the problem then becomes detecting the carry.
In assembly it is easy...just look for the 'C' flag to change. But how can
I do that in C++ efficiently. I don't know of any portable interface into
the processor registers. Is there a guru's trick using shifts or basic
logic operations?

Gurus are not telepaths -- you should first describe what you're trying
to achieve (a bit of code would help).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,832
Latest member
GlennSmall

Latest Threads

Top