Print a GUID variable
Asked Answered
V

13

50

I have a GUID variable and I want to write inside a text file its value. GUID definition is:

typedef struct _GUID {          // size is 16
    DWORD Data1;
    WORD   Data2;
    WORD   Data3;
    BYTE  Data4[8];
} GUID;

But I want to write its value like:

CA04046D-0000-0000-0000-504944564944

I observed that:

  • Data1 holds the decimal value for CA04046D
  • Data2 holds the decimal value for 0
  • Data3 holds the decimal value for next 0

But what about the others?

I have to interpret myself this values in order to get that output or is there a more direct method to print such a variable?

Villar answered 4/11, 2009 at 9:43 Comment(1)
Variables hold values, and values do not have a base. It may be displayed as decimal, hexidecimal, binary, or any other base as part of the "printing" function, but the value itself has no base and so is not "decimal".Mars
S
67

Use the StringFromCLSID function to convert it to a string

e.g.:

GUID guid;
CoCreateGuid(&guid);

OLECHAR* guidString;
StringFromCLSID(guid, &guidString);

// use guidString...

// ensure memory is freed
::CoTaskMemFree(guidString);

Also see the MSDN definition of a GUID for a description of data4, which is an array containing the last 8 bytes of the GUID

Sinuation answered 4/11, 2009 at 9:47 Comment(4)
using bstr as the prefix here is misleading as BSTR is a type and it is freed with SysFreeString(), not CoTaskMemFree(). I'd rename this to guidString, or guidStringCoTaskMemAlloc to be really explicit. OLECHAR is a vestige from 16 bit days, use wchar_t or WCHAR instead, better yet PWSTR as that includes the SAL annotation for "null terminated"Catching
StringFromGUID2() can be used to avoid the allocation, it puts its result in a caller specified buffer. this avoids the possibility of failure and the need to free the result.Catching
The link you gave says that Data4 contains values, not a pointer to an array as you say in the comment.Neille
@SergeRogatch I think I wrote that because C++ treats array types similar to a pointer to a single element... I'll change the wording to make it less confusingSinuation
S
61

Sometimes its useful to roll your own. I liked fdioff's answer but its not quite right. There are 11 elements of different sizes.

printf("Guid = {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", 
  guid.Data1, guid.Data2, guid.Data3, 
  guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
  guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);

Output: "Guid = {44332211-1234-ABCD-EFEF-001122334455}"

Refer to Guiddef.h for the GUID layout.

Same, as a method:

void printf_guid(GUID guid) {
    printf("Guid = {%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", 
      guid.Data1, guid.Data2, guid.Data3, 
      guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
      guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}

you can also pass a CLSID to this method.

Separatrix answered 7/8, 2013 at 21:22 Comment(3)
worked like a champ! I'm messing with some BLE structures that have UUID aka GUID. I set: GUID *guid = &pCharBuffer->CharacteristicUuid.Value.LongUuid; and used the printf above. thanks for sharing!Bard
I had to change each %02hhX into %02hX for it to work.Admeasurement
Due to integer promotion, h and hh modifier can be omitted.Vincenty
M
17

You can eliminate the need for special string allocations/deallocations by using StringFromGUID2()

GUID guid = <some-guid>;
// note that OLECHAR is a typedef'd wchar_t
wchar_t szGUID[64] = {0};
StringFromGUID2(&guid, szGUID, 64);
Memphis answered 12/11, 2013 at 22:44 Comment(3)
these are not BSTRs, those are freed with SysFreeString(), StringFromCLSID result is freed with CoTaskMemAllocCatching
Well, the advantage of using StringFromGUID2() is that you don't have to do any COM or BSTR string deallocations. You pass it plain ol' memory, and it writes characters there. An OLECHAR is just a typedef'd wchar_t.Memphis
It should be enough to allocate 36 + 2 + 1 wide characters, as the string contains GUID, enclosing braces and null terminator.Smtih
D
14

In case you prefer C++ way

std::ostream& operator<<(std::ostream& os, REFGUID guid){

    os << std::uppercase;
    os.width(8);
    os << std::hex << guid.Data1 << '-';

    os.width(4);
    os << std::hex << guid.Data2 << '-';

    os.width(4);
    os << std::hex << guid.Data3 << '-';

    os.width(2);
    os << std::hex
        << static_cast<short>(guid.Data4[0])
        << static_cast<short>(guid.Data4[1])
        << '-'
        << static_cast<short>(guid.Data4[2])
        << static_cast<short>(guid.Data4[3])
        << static_cast<short>(guid.Data4[4])
        << static_cast<short>(guid.Data4[5])
        << static_cast<short>(guid.Data4[6])
        << static_cast<short>(guid.Data4[7]);
    os << std::nouppercase;
    return os;
}

Usage:

static const GUID guid = 
{ 0xf54f83c5, 0x9724, 0x41ba, { 0xbb, 0xdb, 0x69, 0x26, 0xf7, 0xbd, 0x68, 0x13 } };

std::cout << guid << std::endl;

Output:

F54F83C5-9724-41BA-BBDB-6926F7BD6813

Disqualification answered 7/11, 2014 at 16:1 Comment(2)
I'm assuming those std::cout.width()'s should be os.width() ?Likable
You need os.fill('0') at the start, and the width needs to be repeated for every byte of Data4.Chiropractic
D
12

In case when your code uses ATL/MFC you also could use CComBSTR::CComBSTR(REFGUID guid) from atlbase.h:

GUID guid = ...;
const CComBSTR guidBstr(guid);  // Converts from binary GUID to BSTR
const CString guidStr(guidBstr); // Converts from BSTR to appropriate string, ANSI or Wide

It will make conversion & memory cleanup automatically.

Downtime answered 17/10, 2012 at 12:46 Comment(0)
C
8

Courtesy of google's breakpad project:

std::string ToString(GUID *guid) {
    char guid_string[37]; // 32 hex chars + 4 hyphens + null terminator
    snprintf(
          guid_string, sizeof(guid_string),
          "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
          guid->Data1, guid->Data2, guid->Data3,
          guid->Data4[0], guid->Data4[1], guid->Data4[2],
          guid->Data4[3], guid->Data4[4], guid->Data4[5],
          guid->Data4[6], guid->Data4[7]);
    return guid_string;
}

UUID guid = {0};
UuidCreate(&guid);
std::cout << ToString(&guid);
Cecilla answered 3/4, 2014 at 20:29 Comment(0)
F
8

Inspired by JustinB's answer

#define GUID_FORMAT "%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX"
#define GUID_ARG(guid) (guid).Data1, (guid).Data2, (guid).Data3, (guid).Data4[0], (guid).Data4[1], (guid).Data4[2], (guid).Data4[3], (guid).Data4[4], (guid).Data4[5], (guid).Data4[6], (guid).Data4[7]

and then

printf("Int = %d, string = %s, GUID = {" GUID_FORMAT "}\n", myInt, myString, GUID_ARG(myGuid));
Footed answered 30/10, 2014 at 3:53 Comment(0)
S
2

I know the question is quite old, but would this work maybe?

inline std::ostream& operator <<(std::ostream& ss,GUID const& item) {
  OLECHAR* bstrGuid;
  ::StringFromCLSID(item, &bstrGuid);
  ss << bstrGuid;
  ::CoTaskMemFree(bstrGuid);
  return ss;
}
Sabayon answered 26/7, 2011 at 14:52 Comment(0)
D
2

Use UuidToString function to convert GUID to string. The function accepts UUID type which is typedef of GUID.

Diondione answered 12/1, 2016 at 11:56 Comment(0)
B
1
std::string
GuidToString(const GUID& guid, bool lower = false)
{
    const char* hexChars = lower ? "0123456789abcdef" : "0123456789ABCDEF";

    auto f = [hexChars](char* p, unsigned char v)
    {
        p[0] = hexChars[v >> 4];
        p[1] = hexChars[v & 0xf];
    };

    char s[36];
    f(s, static_cast<unsigned char>(guid.Data1 >> 24));
    f(s + 2, static_cast<unsigned char>(guid.Data1 >> 16));
    f(s + 4, static_cast<unsigned char>(guid.Data1 >> 8));
    f(s + 6, static_cast<unsigned char>(guid.Data1));
    s[8] = '-';
    f(s + 9, static_cast<unsigned char>(guid.Data2 >> 8));
    f(s + 11, static_cast<unsigned char>(guid.Data2));
    s[13] = '-';
    f(s + 14, static_cast<unsigned char>(guid.Data3 >> 8));
    f(s + 16, static_cast<unsigned char>(guid.Data3));
    s[18] = '-';
    f(s + 19, guid.Data4[0]);
    f(s + 21, guid.Data4[1]);
    s[23] = '-';
    f(s + 24, guid.Data4[2]);
    f(s + 26, guid.Data4[3]);
    f(s + 28, guid.Data4[4]);
    f(s + 30, guid.Data4[5]);
    f(s + 32, guid.Data4[6]);
    f(s + 34, guid.Data4[7]);

    return std::string(s, 36);
}
Bustamante answered 10/12, 2018 at 23:35 Comment(0)
T
0

For those using C++20 formatting library, or {fmt}, here's a quick implementation of std::formatter made from the answers above:

struct std::formatter<GUID> : std::formatter<std::string>
{
    auto format(const GUID& guid, format_context& ctx) const
    {
        auto it = ctx.out();
        it = std::format_to(it, "{:08X}", guid.Data1);
        it = std::format_to(it, "-{:04X}", guid.Data2);
        it = std::format_to(it, "-{:04X}", guid.Data3);
        it = std::format_to(it, "-{:02X}{:02X}", guid.Data4[0], guid.Data4[1]);
        it = std::format_to(it, "-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}",
            guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
        return it;
    }
};
Tantalizing answered 18/9, 2023 at 19:37 Comment(0)
C
0

If you cannot use StringFromCLSID or StringFromGUID2, you can directly format the GUID using C++20 std::format.

To convert a GUID to string:

std::string StringFromGUID(const GUID& guid) {
    return std::format("{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}

Or for just printing, you can directly overload the stream insertion operator:

std::ostream& operator<<(std::ostream& os, const GUID& guid) {
    return os << std::format("{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
}
Cemetery answered 12/6, 2024 at 18:31 Comment(0)
D
-2
printf(%X-%X-%X-%X-%X", guid.Data1, guid.Data2, guid.Data3, &guid.Data4);
Dunton answered 13/6, 2013 at 10:56 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.