|
|||
|
Angelo wrote:
> I have a signed Hex value in a string that needs to be converted to a > signed int. Here's my code: > > #include "stdafx.h" > #include <sstream> > #include <iostream> > > int main(int argc, char* argv[]) > { > long Val; > // -998 hex value, 2's compliment > std::string strVal = "FFFFFC1A"; That is: "4294966298" in decimal. > std::istringstream strIn( strVal ); > strIn >> std::hex >> Val; > if ( strIn.fail() ) > std::cout << "conversion failed\n"; > else > std::cout << "converted value: " << static_cast<long>(Val) << > std::endl; > return 0; > } > if I use this code, I get conversion failed, however, if I > change Val from long to unsigned long, my output is -998 like > I would expect. 2 questions here: > 1. why does the conversion fail if Val is a signed long? Because you have overflow. Technically, undefined behavior, but any good implementation will simply fail. 0xFFFFFC1A is a positive value, equal to 4294966298 in decimal. If long's are only 32 bits on your machine, this value doesn't fit, so you have overflow. -998 in hex would be -3E6. There is some confusion here, I imagine, because you cannot in fact output a long in hex format; for some strange reason, the long will be converted into unsigned long, and output as an unsigned long. > 2. Is there any problems with using unsigned long for Val and > casting to signed long? Officially, yes. The value in the unsigned long is out of the range of a long (supposing 32 bit long's), so the results are implementation defined, and may cause program termination. (Note that implementation defined means that a conforming implementation is required to document what they do. If you find such documentation, let us know -- I think it will be a first.) Practically, no. There are several classic cases where you more or less have to -- assigning the results of istream::get() or fgetc() to a char, for example, if char is signed. The result is that almost all programs count on it, and any implementation which didn't make it work as expected would break too much code for the implementation to be viable. (Presumably, an implementation could make a special case of converting an int to a char, but I have never heard of an implementation which does so.) > Note: Im using VC++6.0 You really should upgrade. VC++ was an excellent compiler when it first came out, but that was a long, long time ago, and the world has moved on since then. -- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|
||||
|
||||
|
|
|
|||
|
try this:
#include <iostream> int main() { long int mylong = 0xFFFFFC1A; std::cout << "mylong: " << mylong << std::endl; return 0; } if a long is 32bits then this will print out -998. 0xFFFFFC1A is -998 in binary 2's complement format, I dont beleive it's represented as -3E6 internally. if you change the long int to an unsigned long int then it will output as 4294966298. I think this is correct but please correct me if I'm wrong. Thanks Angelo [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Also, I agree that we need to upgrade vc++ ;-) I beleive that we will
be upgrading vc++ soon. All of our software depends on mfc, is it even possible to use a different compiler for that? At home, I use g++ with eclipse and it seems to run pretty well. Being free is a bonus. Thanks Angelo [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Angelo wrote:
> try this: > #include <iostream> > int main() > { > long int mylong = 0xFFFFFC1A; > std::cout << "mylong: " << mylong << std::endl; > return 0; > } > if a long is 32bits then this will print out -998. Technically, you have implementation defined behavior, which may in fact trap. The value of 0xFFFFFC1A is 4294966298. If long is only 32 bits, it doesn't fit, so the results of the conversion are implementation defined. In practice, you are probably right for most, if not all, two's complement machines (and the only modern machine I know of which isn't two's complement has 36 bit longs). > 0xFFFFFC1A is -998 No. At least, not in any math I know of. 0xFFFFFC1A is 4294966298. The results of converting the unsigned long with the value 4294966298 to a long may be -998, but that's the result of an implementation defined conversion, which changes the value. > in binary 2's complement format, I dont beleive it's > represented as -3E6 internally. I'm not sure what that means. On my Sparc, in 32 bit mode, the internal representation does have the sign bit set, which means that the value is negative. And the definition of the representation of negative values says that when all of the bits are taken together, the value is -998. Or -0x36E, if you prefer. If you are talking about the bit pattern, then the bit pattern used to represent -998 is 11111111111111111111110000011010. In C++, you can access the bit pattern using the & operator and masks, but it really isn't relevant to much of anything. > if you change the long int to an unsigned long int then it > will output as 4294966298. > I think this is correct but please correct me if I'm wrong. It's the usual implementation defined behavior on a 32 bit machine. But the fact remains that it is the result of implementation defined conversions. The original problem is due to the fact that the C++ standard defines all hexidecimal input and output as if taking place on unsigned values. On output, it converts a long to unsigned long. On input, it will read the value as an unsigned long, then convert it to a signed long. With the caveat that if the value is not representable, it is undefined behavior, not the implementation defined conversion you get normally. Most quality implementations will treat it as an error, and set failbit. And of course, the conversion of a negative signed long to unsigned long on output results in a value that is not representable as a long. So you get the error on input. -- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Ohhhh, I think I understand now. I thought that a negative number
could be represented via hex in c++ (via 2's complement, not using a '-' sign). So, in c++, there is no guarantee that assigning a signed long to 0xFFFFFC1A would come up with -998(base10). Question: If I assigned a signed long with 11111111111111111111110000011010(base2), is there any guarantee that it'll come out with -998 base10 for 32 bit longs? Thanks for the help Angelo [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Also, just so you know that my problem isnt contrived, I am trying to
do this for a project. I have a serial temp sensor which returns the temperatures as a 32 bit signed value(negatives in 2's compliment), but the values are given in base 16. So if it returns something like FFFFFC1A, then I am supposed to interpret it as -998. I am trying to figure out an error free way to convert this string into a signed long. Angelo [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
In article <1130277523.046616.125840@o13g2000cwo.googlegroups .com>,
Angelo <kereszte@msu.edu> writes >Ohhhh, I think I understand now. I thought that a negative number >could be represented via hex in c++ (via 2's complement, not using a >'-' sign). > >So, in c++, there is no guarantee that assigning a signed long to >0xFFFFFC1A would come up with -998(base10). > >Question: If I assigned a signed long with >11111111111111111111110000011010(base2), is there any guarantee that >it'll come out with -998 base10 for 32 bit longs? You are assuming that negative numbers are necessarily represented using 2's complement. The C++ Standard (as does the C Standard) allows the use of 1's complement as well as sign and magnitude. Most current systems use 2's complement but that is not required. So in answer to your final question, the C++ Standard does not guarantee that the bit pattern quoted represent -998. -- Francis Glassborow ACCU Author of 'You Can Do It!' see http://www.spellen.org/youcandoit For project ideas and contributions: http://www.spellen.org/youcandoit/projects [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Angelo wrote:
> Also, I agree that we need to upgrade vc++ ;-) I beleive that we will > be upgrading vc++ soon. All of our software depends on mfc, is it even > possible to use a different compiler for that? Just upgrade to VC7.1. It is just that VC6 is pre standard and buggy (compared the modern compilers). For example, in some cases it does not call destructors for temporary objects on the stack. And there are plenty of compile time problems. -- Valentin Samko - http://val.samko.info [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
In article <1130335267.739246.22200@o13g2000cwo.googlegroups. com>,
Angelo <kereszte@msu.edu> writes >Also, just so you know that my problem isnt contrived, I am trying to >do this for a project. I have a serial temp sensor which returns the >temperatures as a 32 bit signed value(negatives in 2's compliment), but >the values are given in base 16. > >So if it returns something like FFFFFC1A, then I am supposed to >interpret it as -998. I am trying to figure out an error free way to >convert this string into a signed long. Why didn't you ask the question to start with instead of worrying about representations. 1) Check your implementation uses 2's complement (it probably does) 2) Use std::strol() from <cstdlib> -- Francis Glassborow ACCU Author of 'You Can Do It!' see http://www.spellen.org/youcandoit For project ideas and contributions: http://www.spellen.org/youcandoit/projects [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Francis Glassborow wrote:
> In article > <1130335267.739246.22200@o13g2000cwo.googlegroups. com>, Angelo > <kereszte@msu.edu> writes > >Also, just so you know that my problem isnt contrived, I am > >trying to do this for a project. I have a serial temp sensor > >which returns the temperatures as a 32 bit signed > >value(negatives in 2's compliment), but the values are given > >in base 16. > >So if it returns something like FFFFFC1A, then I am supposed > >to interpret it as -998. I am trying to figure out an error > >free way to convert this string into a signed long. > Why didn't you ask the question to start with instead of > worrying about representations. Well, his problem is one of representation. (Supposing that the FFFFFC1A is text.) > 1) Check your implementation uses 2's complement (it probably does) > 2) Use std::strol() from <cstdlib> According to the C standard, if the correct value is outside the range of representable values, LONG_MIN or LONG_MAX will be returned, according to the sign of the value. Any way you cut it, the correct value of the string FFFFFC1A is 4294966298. If longs are 32 bits on his machine, stdtol should return 2147483648 (and store ERANGE in errno); if they are longer, strtol should return 4294966298. The only way strtol can return a negative value is if it is given a negative value to convert. The problem is that his data source converts negative values to the equivalent unsigned value, and outputs that as a string. If (as is highly likely), his machine and that data source use the same format, and his machine makes conversions along the lines unsigned->int->unsigned an identity function, then the correct solution is to read the value in as an unsigned long, and then convert the unsigned long to long. If this doesn't work, he has a bit more work on his hands, but I would still start by getting the value that was output, as an unsigned long. -- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Angelo wrote:
> Ohhhh, I think I understand now. I thought that a negative > number could be represented via hex in c++ (via 2's > complement, not using a '-' sign). Attention: don't confuse external representation (in text format) with internal. > So, in c++, there is no guarantee that assigning a signed long > to 0xFFFFFC1A would come up with -998(base10). No. On my machine (in 64 bit mode), it doesn't. More generally, conversions of signed to unsigned are well defined, but only for a given length (and the length of long may be anything greater than or equal to 32 -- as a minimum, 32, 36, 48 and 64 have existed), conversions in the other direction are "implementation defined". In practice, assigning an unsigned long which has the value 0xFFFFFC1A to a long will result in -998 on most modern machines where long is 32 bits. But you've got to get that unsigned long first; a text string is NOT an unsigned long, and the standard speaks of what happens when the correctly converted value is not representable. The correctly converted value is only negative if there is a - sign. > Question: If I assigned a signed long with > 11111111111111111111110000011010(base2), is there any > guarantee that it'll come out with -998 base10 for 32 bit > longs? Not from the standard. Probably from your implementation (again, supposing 32 bit longs). If you have control of both sides, pass the value as a decimal value. It's a lot simpler, and more robust. (But one might legitimately ask why C++ doesn't allow outputting signed values as hexadecimal.) -- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Very interessting! I must check the output of the temp sensor and see
if it supports outputing in regular decimal format. why doesnt c++ allow outputting signed values as hex? Thanks for all your help. It's definitely helped me, and I have learned quite a bit. Angelo [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|||
|
Angelo wrote:
[...] > why doesnt c++ allow outputting signed values as hex? Good question. A simple answer for the standard streams would be that formatted output is defined in terms of C's printf format specifiers, and there isn't a format specifier for hex for signed int's. (Remember that a printf format specifier must also indicate the type -- there is a different format specifier for decimal signed int and decimal unsigned int, and it is the format specifier, and not the actual type passed, that determines how the value is interpreted.) But that's just part of it. I just checked, and the classical iostream's didn't support it either. I suspect that the main reason is simply that most of the time, when you output in hex format, it's because you want to see the bit pattern, and signedness is irrelevant. It probably never occurred to anyone that you *are* outputting a value, not just a bit pattern, and that someone might want to read the value back in "as a value". But I'm really just guessing about it. -- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Converting date to String | Ramchandra | Newsgroup comp.soft-sys.sas | 1 | 08-16-2006 12:34 PM |
| Re: Converting from string to numeric (keeping decimal) in SQL | David L Cassell | Newsgroup comp.soft-sys.sas | 0 | 10-13-2005 06:35 PM |
| Re: preserve case using CALL PRXCHANGE | Guido T | Newsgroup comp.soft-sys.sas | 0 | 07-29-2005 10:42 AM |
| Re: preserve case using CALL PRXCHANGE | Chang Chung | Newsgroup comp.soft-sys.sas | 0 | 07-28-2005 11:35 PM |
| Re: preserve case using CALL PRXCHANGE | Venky Chakravarthy | Newsgroup comp.soft-sys.sas | 0 | 07-28-2005 11:10 PM |