From: Rune Allnor on 23 Nov 2009 04:44 Hi all. I need to inspect the bit patterns in a buffer. In order to do that, I want to print the values of each character to screen as numerical values on hex format. Below is an example program that shows a number of more or less successful attempts to achieve this. The buffer c is initialized with the hexadecimal numbers 0x30, 0x31, 0x32 and 0x33, which happens to be the ASCII values of the characters '0', '1', '2' and '3'. In attempt a) I just pipe the ASCII values to std::cout along with a hint that I want the hex values to be printed. The attempt is clearly unsuccessful, as the characters, not the hex values, are printed. In attempt b) I type cast the values of the buffer from uchar to uint. This has the desired effect, at the expense of using a C-style type cast, which is something I want to avoid, if at all possible. Attempt c), where I achieve the desired result by assigning the uchar value to be printed to the temporary uint variable d is a bit clumsy, since it involves a temporary variable that is not strictly necessary, either from a semantic or algorithmic point of view. So the question is if it is possible to achieve the desired result by using a reinterpret_cast<> or static_cast<> directly on the uchar values inside the buffer c? I can't see any obvious way to achieve this, since chars have a different memory footprint than any of the int types I am aware of, that otherwise would suit the purpose. Are there any data types with the same memory footprint as chars, that are interpreted by the IO library as numeric integer values, as opposed to text glyphs? Rune --------------- Output ---------------- a) Naive output: 0 1 2 3 b) C-style type cast: 30 31 32 33 c) Type cast by variable assignment: 30 31 32 33 --------------------------------------- ///////////////////////////////////////////////////////////////////////////// #include <iomanip> #include <iostream> int main() { // Hex values of digits: 0 1 2 3 unsigned char c[] = {0x30,0x31,0x32,0x33}; std::cout << "a) Naive output:" << std::endl; for (size_t n = 0; n != 4; ++n) { std::cout << std::hex << c[n] << " "; } std::cout << std::endl << std::endl; std::cout << "b) C-style type cast:" << std::endl; for (size_t n = 0; n != 4; ++n) { std::cout << std::hex << (unsigned int) c[n] << " "; } std::cout << std::endl << std::endl; std::cout << "c) Type cast by variable assignment:" << std::endl; for (size_t n = 0; n != 4; ++n) { size_t d = c[n]; std::cout << std::hex << d << " "; } std::cout << std::endl; return 0; } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Neil Butterworth on 23 Nov 2009 12:36 Rune Allnor wrote: > Hi all. > > I need to inspect the bit patterns in a buffer. In order to do that, I > want > to print the values of each character to screen as numerical values > on > hex format. > > Below is an example program that shows a number of more or less > successful attempts to achieve this. The buffer c is initialized with > the > hexadecimal numbers 0x30, 0x31, 0x32 and 0x33, which happens > to be the ASCII values of the characters '0', '1', '2' and '3'. > > In attempt a) I just pipe the ASCII values to std::cout along with a > hint that I want the hex values to be printed. The attempt is clearly > unsuccessful, as the characters, not the hex values, are printed. > > In attempt b) I type cast the values of the buffer from uchar to > uint. This has the desired effect, at the expense of using a > C-style type cast, which is something I want to avoid, if at all > possible. > > Attempt c), where I achieve the desired result by assigning the > uchar value to be printed to the temporary uint variable d is a bit > clumsy, since it involves a temporary variable that is not strictly > necessary, either from a semantic or algorithmic point of view. > > So the question is if it is possible to achieve the desired result > by using a reinterpret_cast<> or static_cast<> directly on the uchar > values inside the buffer c? > > I can't see any obvious way to achieve this, since chars > have a different memory footprint than any of the int types > I am aware of, that otherwise would suit the purpose. > > Are there any data types with the same memory footprint as > chars, that are interpreted by the IO library as numeric integer > values, as opposed to text glyphs? > > Rune > > --------------- Output ---------------- > a) Naive output: > 0 1 2 3 > > b) C-style type cast: > 30 31 32 33 > > c) Type cast by variable assignment: > 30 31 32 33 > --------------------------------------- > > ///////////////////////////////////////////////////////////////////////////// > #include <iomanip> > #include <iostream> > > int main() > { > // Hex values of digits: 0 1 2 3 > unsigned char c[] = {0x30,0x31,0x32,0x33}; > std::cout << "a) Naive output:" << std::endl; > for (size_t n = 0; n != 4; ++n) > { > std::cout << std::hex << c[n] << " "; > } > std::cout << std::endl << std::endl; > > std::cout << "b) C-style type cast:" << std::endl; > for (size_t n = 0; n != 4; ++n) > { > std::cout << std::hex << (unsigned int) c[n] << " "; > } > std::cout << std::endl << std::endl; > > std::cout << "c) Type cast by variable assignment:" << std::endl; > for (size_t n = 0; n != 4; ++n) > { > size_t d = c[n]; > std::cout << std::hex << d << " "; > } > std::cout << std::endl; > return 0; > } I can't see what is wrong with the obvious: std::cout << std::hex << static_cast<unsigned int>(c[n]) << " "; And I don't see why you think having a "different memory footprint" precludes a cast - a cast creates a new value which may have a completely different "footprint" from the thing the cast is applied to. Neil Butterworth -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Daniel Krügler on 23 Nov 2009 12:50 On 23 Nov., 22:44, Rune Allnor <all...(a)tele.ntnu.no> wrote: > Hi all. > > I need to inspect the bit patterns in a buffer. In order to do that, I > want > to print the values of each character to screen as numerical values > on > hex format. > > Below is an example program that shows a number of more or less > successful attempts to achieve this. The buffer c is initialized with > the > hexadecimal numbers 0x30, 0x31, 0x32 and 0x33, which happens > to be the ASCII values of the characters '0', '1', '2' and '3'. > > In attempt a) I just pipe the ASCII values to std::cout along with a > hint that I want the hex values to be printed. The attempt is clearly > unsuccessful, as the characters, not the hex values, are printed. Yes, this is intended behavior. > In attempt b) I type cast the values of the buffer from uchar to > uint. This has the desired effect, at the expense of using a > C-style type cast, which is something I want to avoid, if at all > possible. So, why not using a static_cast then? > Attempt c), where I achieve the desired result by assigning the > uchar value to be printed to the temporary uint variable d is a bit > clumsy, since it involves a temporary variable that is not strictly > necessary, either from a semantic or algorithmic point of view. > > So the question is if it is possible to achieve the desired result > by using a reinterpret_cast<> or static_cast<> directly on the uchar > values inside the buffer c? No. What is your hesitation about a static_cast? You could also simply rely on implicit conversion with a very tiny helper function: inline int to_int(char c) { return c; } You could also easily define your own IO manipulator, which performs this for you and would perform the to-hex conversion in one step: struct char_as_hex_t { int c; char_as_hex_t(char c) : c(c) {} }; inline char_as_hex_t as_hex(char c) { return char_as_hex_t(c); } template <typename Ch, typename Tr> inline std::basic_ostream<Ch, Tr>& operator<<( std::basic_ostream<Ch, Tr>& os, char_as_hex_t manip) { os << std::hex << manip.c; return os; } and use it like this: std::cout << as_hex('a') << std::endl; If you are really cool, you define char_as_hex_t as a template, which is specialized for all integral types with special handling for the character types. In this case I would rename it to "as_hex" or so. > I can't see any obvious way to achieve this, since chars > have a different memory footprint than any of the int types > I am aware of, that otherwise would suit the purpose. > > Are there any data types with the same memory footprint as > chars, that are interpreted by the IO library as numeric integer > values, as opposed to text glyphs? This depends on which sizeof ratios the fundamental types have ;-) On some machines you may find sizeof(char) == sizeof(long double). IMO your search for "same memory footprint" in this kind of example is premature optimization of the worst kind: For most machines an int function argument is much more advantageous than a (1-octet) char, because the registers need to be unpacked again, while int typically has already the proper register size. You could use unsigned short, but I would never do this in this example - just stay with int. HTH & Greetings from Bremen, Daniel Kr�gler -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Francis Glassborow on 23 Nov 2009 12:53 Rune Allnor wrote: > Hi all. > > I need to inspect the bit patterns in a buffer. In order to do that, I > want > to print the values of each character to screen as numerical values > on > hex format. > > Below is an example program that shows a number of more or less > successful attempts to achieve this. The buffer c is initialized with > the > hexadecimal numbers 0x30, 0x31, 0x32 and 0x33, which happens > to be the ASCII values of the characters '0', '1', '2' and '3'. > > In attempt a) I just pipe the ASCII values to std::cout along with a > hint that I want the hex values to be printed. The attempt is clearly > unsuccessful, as the characters, not the hex values, are printed. > > In attempt b) I type cast the values of the buffer from uchar to > uint. This has the desired effect, at the expense of using a > C-style type cast, which is something I want to avoid, if at all > possible. > > Attempt c), where I achieve the desired result by assigning the > uchar value to be printed to the temporary uint variable d is a bit > clumsy, since it involves a temporary variable that is not strictly > necessary, either from a semantic or algorithmic point of view. > > So the question is if it is possible to achieve the desired result > by using a reinterpret_cast<> or static_cast<> directly on the uchar > values inside the buffer c? > > I can't see any obvious way to achieve this, since chars > have a different memory footprint than any of the int types > I am aware of, that otherwise would suit the purpose. > > Are there any data types with the same memory footprint as > chars, that are interpreted by the IO library as numeric integer > values, as opposed to text glyphs? What has memory footprint got to do with static_cast<> ? int main() { // Hex values of digits: 0 1 2 3 unsigned char c[] = {0x30,0x31,0x32,0x33}; std::cout << "Using static_cast<> " << std::endl; for (size_t n = 0; n != 4; ++n) { std::cout << std::hex << static_cast<unsigned int> (c[n]) << " "; } std::cout << std::endl << std::endl; return 0; } Note that casts are generally about values not about storage types. In C++ problems can arise if you cast to a reference type but that is not the case here. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Rune Allnor on 23 Nov 2009 12:51 Hm. Wrote the code and the post in parallel, so I lost the point first time around. In the code below is the test using reinterpret_cast<> added, along with the corresponding added output. As can be seen, each char value is preceeded by a number of leading zeros that I am unable to get rid of. I assume this has something to do with memory footprints and/or byte ordering (I am using VS2008 on a PC, which, according to http://en.wikipedia.org/wiki/Endianness means that the internal byte organization is little-endian). Rune > --------------- Output ---------------- > a) Naive output: > 0 1 2 3 > > b) C-style type cast: > 30 31 32 33 > > c) Type cast by variable assignment: > 30 31 32 33 d) reinterpret_cast: 00000030 00000031 00000032 00000033 > --------------------------------------- > > ///////////////////////////////////////////////////////////////////////////�// > #include <iomanip> > #include <iostream> > > int main() > { > // Hex values of digits: 0 1 2 3 > unsigned char c[] = {0x30,0x31,0x32,0x33}; > std::cout << "a) Naive output:" << std::endl; > for (size_t n = 0; n != 4; ++n) > { > std::cout << std::hex << c[n] << " "; > } > std::cout << std::endl << std::endl; > > std::cout << "b) C-style type cast:" << std::endl; > for (size_t n = 0; n != 4; ++n) > { > std::cout << std::hex << (unsigned int) c[n] << " "; > } > std::cout << std::endl << std::endl; > > std::cout << "c) Type cast by variable assignment:" << std::endl; > for (size_t n = 0; n != 4; ++n) > { > size_t d = c[n]; > std::cout << std::hex << d << " "; > } > std::cout << std::endl; /////////////////////////////////////////////////// std::cout << "d) reinterpret_cast:" << std::endl; for (size_t n = 0; n != 4; ++n) { std::cout << std::hex << reinterpret_cast<int*> (c[n]) << " "; } std::cout << std::endl << std::endl; /////////////////////////////////////////////////// > return 0; > > } -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
|
Next
|
Last
Pages: 1 2 Prev: Article: On Iteration Next: inlining of functions returning an unwindable object |