|
-
July 26th, 2005, 07:04 AM
#1
conversion
hello,
does someone can tell me how do i convert string with hex values to it's ascii values?
thanks in advance.
-
July 26th, 2005, 07:38 AM
#2
Re: conversion
Code:
char hex_string[] = "0xAA";
char ascii;
sscanf(hex_string, "0x%X", &ascii);
-
July 26th, 2005, 07:47 AM
#3
Re: conversion
 Originally Posted by SunCore
does someone can tell me how do i convert string with hex values to it's ascii values?
Can you be more specific?
Do you mean converting "413F2042" to "A? B", or converting "hello \x2F\x41" to "hello ?A"
Or converting "0xFF" to "255", letting "255" be converted (just copied) to "255"
Or do you mean converting "FF" to "255"
-
July 26th, 2005, 07:51 AM
#4
Re: conversion
 Originally Posted by Kheun
Code:
char hex_string[] = "0xAA";
char ascii;
sscanf(hex_string, "0x%X", &ascii);
Even if this code works with little-endian machines with 4 bytes stack alignment, it is preferable (and ISO compliant) to use unsigned int pointers.
Code:
char hex_string[] = "0xAA";
unsigned uascii;
char ascii;
sscanf(hex_string, "0x%X", &uascii);
ascii=static_cast<char>(uascii);
-
July 26th, 2005, 07:42 PM
#5
Re: conversion
Well, my understanding is that the OP is asking for a way to convert heximal string representation into an ascii character. Since it is only a character, I don't see any reason why endianness is only to affect it. Anyway, the C standard library function like printf() and scanf() interpret the string in human readable form. So we don't ready have to worry about it.
I don't understand why it is preferrable to use unsigned char for this case. Since the resulting value will be the same, why you need to add an extra step in the conversion? Please explain.
-
July 27th, 2005, 08:41 AM
#6
Re: conversion
 Originally Posted by Kheun
I don't understand why it is preferrable to use unsigned char for this case. Since the resulting value will be the same, why you need to add an extra step in the conversion? Please explain.
sscanf don't do RTTI, it just interprets the pointer passed to the function, as a pointer to an unsigned long value, so with one or more mov assembly instructions, it modifies the four bytes pointed by the pointer passed as its argument.
But if you take address of a char, we can just assume that there is only one valid byte of pointed data, no more.
So, sscanf may theorically crash if we pass the address of a char.
In fact, with x86 processors, the data on the stack is aligned on 4 bytes boundaries (some compilers may regroup some variables).
For example, consider this stack frame:
Code:
// local variable declarations
int a=1;
short b=2;
char c=3;
// we use addresses of these variables, so they are put on the stack.
The assembly code frame may be (i tried with BC++):
Code:
push ebp
mov ebp,esp
add esp,-7
mov dword ptr [ebp-4],1
mov word ptr [ebp-6],2
mov byte ptr [ebp-7],3
Now suppose that we write 4 bytes at address ebp-7, it will override the value of b, and even a.
If we are very lucky, the compiler may not regroup variables, so the asm code could look like that:
Code:
push ebp
mov ebp,esp
add esp,-12
mov dword ptr [ebp-4],1
mov word ptr [ebp-8],2
mov byte ptr [ebp-12],3
In that case, it will work correctly, but i suppose that only very old compilers may produce this code.
As an example, i tried to compile this code with BC++:
Code:
#include <cstdio>
void f(void *)
{}
int main()
{
int i=0;
f(&i); // make sure that i is not optimized.
char c;
std::sscanf("FFFFFFFF","%X",&c); // very bad!
std::printf("%08X",i);
return 0;
}
The output is "00FFFFFF"
I also compiled it with GCC, and the output is identical : "00FFFFFF"
I tried with Watcom C++, and the output is finally "0" with this compiler.
Last edited by SuperKoko; July 27th, 2005 at 08:49 AM.
-
July 27th, 2005, 08:00 PM
#7
Re: conversion
Thank you very much for being thorough and highlighting the potential buffer overflow problem. I would be very lucky that the program runs without crashing. Anyway, rechecking the MSDN for format specification field, the appropriate variable type should be unsigned interger instead.
As for RTTI, it is normally turned off by default. Even if we are writing C++ code using STL, it is not being used at all. It is only used when we write some code that does a downcasting from base pointer to derived pointer. It is also being used for retrieving the class type. Since it is vendor specific and varies from compiler to compiler, it is normally not preferrable. In fact, IMO, using RTTI is against the very essence of OOP. This is because using polymorphism helps us to avoid writing code with switch-case statement that determine the appropriate action based on class type while when RTTI and dynamic_cast is used, you have to do that.
-
July 28th, 2005, 04:13 AM
#8
Re: conversion
Code:
#include <sstream>
#include <iomanip>
int main()
{
std::string hexstr("239a3c");
std::istringstream iss(hexstr);
int value;
iss >> std::setbase(16) >> value;
std::cout << "value is " << value << std::endl;
}
value is 2333244
-
July 28th, 2005, 04:22 AM
#9
Re: conversion
When i said that sscanf don't do RTTI, i was not thinking of the RTTI of OOP, but the run time type identification in general, which is physically impossible with the _cdecl calling convention (and others calling conventions), because a raw pointer to raw data is passed on the stack.
In C++ RTTI can only exists for classes designed to be RTTI classes (generally, they have a VTable pointer). Moreover, you can do RTTI with a pointer to a base RTTI class, but even if objects support RTTI, you cannot do RTTI with a void* pointer to such objects.
note that, i agree that RTTI is evil (especially with switch statements), except when used smartly.
dynamic_cast has a main application : allowing horizontal cast in a class hierarchy with multiple inheritance, allowing to add the notion of interfaces in C++.
dynamic_cast can also be used in debug versions of a project to check a conversion from parent-class pointer to child-class pointer which can be done with a static_cast. This usage is useless for release versions (except if you suspect that your project is highly buggy, and you want detailed report bugs from the users).
-
July 28th, 2005, 05:31 AM
#10
Re: conversion
RTTI is generally evil, although exception handling uses it.
streaming uses compile-time operator overloading though, not RTTI.
scanf() and its family of functions do no type-safety checking at all, you just pass them an address and they write into it.
dynamic_cast should be used for one purpose only: loading symbols from a dynamic library, then checking they are of the type you want. In order to do that you have to know that the symbols are derived from a known base class.
For example, maybe you have a generic type called "factory". Now if you load a symbol with dlsym / GetProcAddress and cast it to "factory *", you might want to then check it is of the factory type to your object. (Note that can be a problem if you use templates, as Factory<Derived> is not derived from Factory<Base>).
-
July 28th, 2005, 09:54 AM
#11
Re: conversion
 Originally Posted by NMTop40
RTTI is generally evil, although exception handling uses it.
Please explain further. I've seen Andrei Alexandrescu do some pretty amazing things with RTTI that don't have to do with exception handling. I'm curious why you say it is generally evil.
Kevin Hall
-
July 28th, 2005, 11:06 AM
#12
Re: conversion
I've always thought that switching on RTTI is an admission of defeat. Wanting to know the run-time type of something implies that you have a polymorphic object, but that the interface you have (the base class) is not specified well enough to let you do the job. That, or the function takes an argument that's too high up the hierarchy and should really take a more specialised type. Once you start downcasting, then you're exposing yourself to maintenance problems, since you're coupling your code to specific derivatives and thus lessening your ability to modify those derivatives or to add new ones.
I don't recall Alexandrescu doing that much with RTTI - do you have some specific examples?
Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
-- Sutter and Alexandrescu, C++ Coding Standards
Programs must be written for people to read, and only incidentally for machines to execute.
-- Harold Abelson and Gerald Jay Sussman
The cheapest, fastest and most reliable components of a computer system are those that aren't there.
-- Gordon Bell
-
July 28th, 2005, 11:19 AM
#13
Re: conversion
In his "Modern C++ Design" book, he used RTTI to do some multiple type-switch capabilities. I believe he also did some factory or visitor pattern using RTTI, but I can't recall off the top of my head.
I admitt that RTTI is not perfect, and should be used carefully, but they sometimes do solve problems not easily solvable in other ways. I've just have never heard anyone come out and declare RTTI evil before.
Kevin Hall
-
July 28th, 2005, 11:25 AM
#14
Re: conversion
So RTTI in many situations may be an admission of defeat. But is that evil?
Macro functions have been declared evil since template functions (a) provide true functional behavior and (b) provide type safety.
Exception specifications are evil because it easily leads to situations where teminate() can be called unexpectedly. It also prevents optimizations (and frequently downgrades performance). Many believe that if the consequences of exception specifications were known in 1998, the standards comittee would have omitted them from the standard.
So, what is it about RTTI that is evil? If C++ were designed again, why would RTTI be omitted?
Kevin Hall
-
July 28th, 2005, 11:32 AM
#15
Re: conversion
I virtually never use throw() specifications apart from the empty one (guaranteeing no throw) and then I only use that sparingly (it's more of a comment).
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|