How To: Represent Numbers in Dec, Hex, and Oct

Introduction

In C and C++, you can have 3 ways of write a number:

  • Using Decimal (base-10) notation
    Very nice for general numbers. It’s easy to read and maintain. Read about decimal notation here.
  • Using Hexadecimal (base-16) notation
    Very efficient for flags especially if you need to see how bits are organized. Plus, it is very popular in C and C++. Read about hexadecimal notation here.
  • Using Octal (base-8) notation
    Not very friendly for most developers and for team mates of course. Read about octal notation here.

Unfortunately, you cannot write a binary number directly in your code. Convert it to any of the three notations first. Read about binary notation here.

Decimal Representation

Just as you write number on papers, you can write it in your code.

	int i = 100;

And you can use the format specifier %d to display the number as decimal using the printf function and its €œsisters€ (e.g. wsprinf in Windows).

	printf("%d", i);

Hexadecimal Representation

Just convert the number to hex and write it prefixed with 0x.

	int i = 0x64;

And you can use the format specifier %x to display the number as hexadecimal as small letters. And %X to display it as capital letters.

	printf("0x%x", i);

Octal Representation

Convert the number to oct and write it prefixed with 0.

	int i = 0144;

Of course, you can use printf to display octal numbers. And this is done through the %o format specifier.

	printf("%o", i);

Beware while reading octal numbers. Octal representation is very similar to decimal. 0144 equals to 100 in decimal notation and 0x64 in hexadecimal.

Unfortunately, you can’t use printf to display numbers in binary notation. You can make your own routine that accomplishes that.

Converting Colors to Gray Shades

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Contents

Contents of this article:

  • Contents
  • Introduction
  • Colors in Grayscale
  • Detecting Print Preview Mode
  • Detecting Black-and-White Printers
  • Mixing all Together

Introduction

This article discusses how you can display the page in print preview as grayscale if the printer is black-and-white. It discusses first how you can convert colors to grayscale. After that is discusses how to detect whether you are in print preview or not and whether the current printer is color or black-and-white printer. Let’s go€¦

Colors in Grayscale

If your application offers printing capability to the user, it should be aware of whether the user has a black-and-white or color printer while previewing the page. Of course, the user won’t be happy at all if he previewed his page in full-colors and printed it in black-and-white.

To solve this dilemma, you should render your print preview in grayscale if the user has a black-and-white printer and in full-colors if the user has a color printer.

The formula that converts a color to gray shade is very easy:

R/G/B = (red * 0.30) + (green * 0.59) + (blue * 0.11)

Set all the red, green, and blue to the sum of 30% of the red value, 59% of the green, and 11% of the blue.

For example, we can convert the color Magenta (0xFF, 0x00, 0xFF) to grayscale using the following steps:

-> 255 * 0.30 = 76
-> 0 * 0.59 = 0
-> 255 * 0.11 = 28
-> 76 + 0 + 28 = 104
-> R/G/B = 76

Thus, Magenta in grayscale equals to the RGB values 76, 76, 76.

The following function converts the color to grayscale:

COLORREF GetGrayscale(COLORREF cr)
{
	BYTE byColor;

	byColor =
		( GetRValue(cr) * 0.30 ) +
		( GetGValue(cr) * 0.59 ) +
		( GetBValue(cr) * 0.11 );

	return
		RGB( byColor, byColor, byColor );
}

Detecting Print Preview Mode

If you have a CPrintInfo you can detect whether you are “print-previewing” or printing by checking the m_bPreview flag. If you don’t have a CPrintInfo (i.e. you are in the context of the OnDraw function) you can detect print preview mode by comparing CDC’s m_hDC and m_hAttribDC members.

MFC does some magic using m_hDC and m_hAttribDC. It uses m_hDC for output, while it uses m_hAttribDC for queries about DC attributes. How this helps?

If you are printing to the screen or to the printer, both m_hDC and m_hAttribDC will refer to the same HDC that’s used for drawing and retrieving attributes. On the other hand, while in print preview, MFC sets m_hDC to the window DC and sets m_hAttribDC to the HDC of the current printer. The results are unimaginable. If you are drawing, the calls are carried out to the screen. If you are querying about attributes (i.e. calling GetDeviceCaps,) the calls are carried out to the printer.

Therefore, you can detect print preview mode using a single line of code:

BOOL bPreview = (pDC->m_hDC != pDC->m_hAttribDC);

Or you can use the following code if you have a CPrintInfo:

BOOL bPreview = pInfo->m_bPreview;

Detecting Black-and-White Printers

Another point of interest is detecting whether the current printer is monochrome (black-and-white) or color printer.

This can be done through the GetDeviceCaps function with the NUMCOLORS item specified. It returns the number of colors if the device has a color depth of 8 bits per pixel or less. It’s not limited to printer DCs only. It can be used with display DCs too.

The following code detects if the device is monochrome:

BOOL bMono = (pDC->GetDeviceCaps(NUMCOLORS) == 2);

Mixing all Together

We have seen how to convert the color to grayscale, how to detect print preview mode, and how to detect a black-and white printer. Now, let’s mix them all together.

In OnDraw and OnPrint, we can solve the dilemma of black-and-white print-previewing by a simple change in the code. The following code segment sets the color based on the type of printer (it works fine too even if we are painting to the screen.)

BOOL bMono =
	(pDC->GetDeviceCaps (NUMCOLORS) == 2) &&
	(pDC->m_hDC != pDC->m_hAttribDC);

CBrush brush	(bMono ?
	GetGrayscale(RGB (255, 0, 255)) :
	RGB (255, 0, 255));

bMono is set to TRUE only if we are in print preview mode and the current printer is black-and-white printer.

Marshaling Unions

Before You Start

If this is your first time you hear about unions or you need to know more about them, please refer to our article “A short speech about Unions” first.

How to Marshal a Union

You can marshal a union the same way you marshal structures. However, because of the way that unions laid-out into memory, you will need to explicitly set variable positions inside the type.

You can marshal a union in few steps:

  1. Create your marshaling type, no matter whether your marshaling type is a managed structure or class. However, you should consider the passing mechanism when working with reference types like classes.
  2. Decorate the type with the StructLayoutAttribute attribute specifying LayoutKind.Explicit to control exactly the memory location of every member inside the type.
  3. Add your required fields only. Because we are controlling the memory layout explicitly, order of fields is no important.
  4. Decorate every field with FieldOffsetAttribute attribute specifying the absolute position -in bytes- of the member from the start of the structure.

Example

Consider the following union:

union SOME_CHARACTER {
	int iCode;
	char cChar;
};

Now, it’s the time for the meat of our lesson. The following code snippets defines the marshaling type of our union:

    [StructLayout(LayoutKind.Explicit)]
    public struct SOME_CHARACTER
    {
        // Both members located on the same
        // position in the beginning of the union

        // This is the continer. it is 4 bytes
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.I4)]
        public int iCode;

        // This is only 1 byte.
        [FieldOffset(0)]
        public char cChar;
    }

    static void Main()
    {
        SOME_CHARACTER character = new SOME_CHARACTER();

        // The code for letter 'A'
        character.dwCode = 65;
        // Should prints 'A'
        Console.WriteLine("wcChar = {0}", character.wcChar);

        character.wcChar = 'B';
        // Should prints 66
        Console.WriteLine("Code = {0}", character.dwCode);
    }

From the previous code, we learn that€¦

  • Unions marshaled like structures, they can be marshaled as either managed structures or classes.
  • Setting StructLayoutAttribute.LayoutKind to LayoutKind.Explicit allows us to exactly control the memory location of the members.
  • We use the FieldOffsetAttribute to specify the starting location in bytes of the field into the type in memory.
  • To create the union between the fields, we set both the fields to the same memory location.
  • In the example, iCode begins from byte 0 to byte 4. And cChar begins from byte 0 to byte 1.
  • If we do not need to take advantage of the union, we can emit cChar because it is contained inside the range of iCode. But, we cannot emit iCode because it is the container.
  • When we change either one of the union variables, the other variable changes too because they share the same memory address. Notice that in our example, int is 4-bytes and char is only 1 byte. Therefore, iCode interprets the whole value, while cChar interprets only the first byte (8 bits) of the value.

Unions with Arrays

Now, consider the following union:

union UNION_WITH_ARRAY
{
    int nValue;
    char str[10];
};

This union must be marshaled in a special way because managed code does not permit value types and reference types to overlap.

As a refresher, a value-type is the type stored into the stack memory; it inherits from System.ValueType. Value-types represented in all primitive data types, structures, and enumerations. On the other hand, reference-types are types stored in the memory heap; they inherit from System.Object. Most types in .NET are reference-types (except System.ValueType of course.)

As a result, we cannot union both members of our example, because whether marshaling the second variable str as an array, a System.Text.StringBuilder, or a System.String, it is still a reference-type. Therefore, we have to leave the advantage of unions, and marshal only a single member. For our example, we will create two marshaling types for our union, one with the first member marshaled, and the other with the other member.

As we know, the layout and size of the type inside the memory is the most crucial. Therefore, we must preserve the layout and size of our union. This union has a 10-bytes array as a container and only one member contained, and this member is only 4-bytes. Therefore, we have two choices, to marshal the union with the container member, or to marshal it with the contained member but to extend it enough to be as large as the container. In this example, we will take the two approaches.

The following are two code segments. The first demonstrates how to marshal only the second member which is the container, while the second demonstrates how to marshal the first member.

    // Setting StructLayoutAttribute.CharSet
    // ensures the correct encoding for all
    // string members of the union in our example
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public struct UNION_WITH_ARRAY_1
    {
        // As we know, character arrays can be marshaled
        // as either an array or as a string

        // Setting MarshalAsAttribute is required
        // for the array and the string

        // That is another way:
        //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
        //public char[] charArray;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string charArray;
    }

    // StructLayoutAttribute.Size determines
    // the size -in bytes- of the type.
    // If the size specified is larger than
    // members' size, the last member will be extended
    // Because this is only a single
    // member, we laid it out sequentially.
    [StructLayout(LayoutKind.Sequential, Size = 128)]
    public struct UNION_WITH_ARRAY_2
    {
        [MarshalAs(UnmanagedType.I2)]
        public short number;
    }

Try it out!

If you are brave enough, you might try to marshal DEVMODE structure; that is one of the most complex structures in the Windows API. If you are interested you can refer to the MSDN library for the documentation of DEVMODE structure. Don’t be shocked when you first see that structure. (My advice is to pray for God before you think about marshaling DEVMODE structure.)

BOOL or BOOLEAN?

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Windows comes with two types that represent a Boolean variable (TRUE or FALSE.) Both represent FALSE if 0 and TRUE if non-zero.

The big difference you need to care when working with that two Booleans is that BOOL defined as int which is 32 bits (4 bytes) on 32-bit environments and 16 bits (2 bytes) on 16-bit environments. BOOLEAN on the other hand, defined as BYTE, which in turn defined as unsigned char. Thus, BOOLEAN only occupies 8 bits (1 byte) from memory.

Although you can convert between them easily, BOOL is much common than BOOLEAN and it is very popular in the Windows API.

Now, the decision is yours!

A Short Speech about Unions

هذه المقالة متوفرة أيضا باللغة العربية، اقرأها هنا.

Contents

Contents of this article:

  • Contents
  • Definition
  • Unions and Structures
  • Example
  • Results
  • Unions Usefulness
  • Unions and the API

Definition

A union is a memory location that is shared by two or more different types of variables. A union provides a way for interpreting the same bit pattern in two or more different ways (or forms.)

Unions and Structures

In fact, unions share structures lots of characteristics, like the way they defined and marshaled. It might be helpful to know that, like structures, unions can be defined inside a structure or even as a single entity. In addition, unions can define complex types inside, like structures too.

Example

To understand unions, we will take a simple example. Consider the following union:

typedef union CHARACTER
{
	int i;
	char c;
};

This was a simple union defines a character. It declared two members, i and c, it defined them in the same memory location. Thus, it provides two ways for accessing the character, by its code (int) and by its value (char). For this to work it allocates enough memory storage for holding the largest member of the union and that member is called container. Other members will overlap with the container. In our case, the container is i because it is 4 bytes (on Win32, 16 on Win16), while c is only 1 byte. Figure 1 shows how the memory is allocated for the union.

Figure 1 - CHARACTER union into memory

Results

Because the two members are sharing the same memory location, when you change one member the other is changed too. Consider the following example:

int main()
{
	union CHARACTER ch;

	ch.i = 65;				// 65 for A
	printf("c = %c", ch.c);	// prints 'A'
	printf("n");

	ch.c += 32;				// 97 for a
	printf("i = %d", ch.i);	// prints '97'
	printf("n");

	return 0;
}

When you change any of the members of the union, other members change too because they are all same the same memory address.

Now consider the same example but with values that won’t fit into the char member:

int main()
{
	union CHARACTER ch;

	ch.i = 330;
	printf("c = %c", ch.c);	// prints 'J'
	printf("n");		// Ops!

	ch.c += 32;
	printf("i = %d", ch.i);	// prints '362'
	printf("n");

	return 0;
}

What’s happened? Because char is 1 bye wide, it interprets only the first 8 bits of the union that are equal to 32.

The same rule applies if you add another member to the union. See the following example. Notice that order of member declarations doesn’t matter.

int main()
{
	union {
		int i;
		char c;
		short n;
	} ch;

	ch.i = 2774186;

	printf("i = %d", ch.i);
	printf("n");
	printf("c = %i",
		(unsigned char)ch.c);
	printf("n");
	printf("n = %d", ch.n);
	printf("n");

	return 0;
}

Now, i, the container, interprets the 32 bits. c, interprets the first 8 bits (notice that we converted it to unsigned char to not to show the negative value.) n, interprets the first high word (16 bits.)

Unions Usefulness

You might ask: Why I need unions at all? I could easily use the cast operator to convert between data types!

The answer is very easy. Unions come very efficient when casting between types require much overhead. Consider the following example: You are about to write an integer to a file. Unfortunately, there’s no function in the C standard library that allow you to write an int to a file, and to using fwrite function requires excessive overhead. The perfect solution is to define a union that contains an integer and a character array to allow it to be interpreted as an integer and as a character array when you need to pass it to fwrite for example. See the following code snippet:

union myval{
	int i;
	char str[4];
};

In addition, unions offer you more performance than casts. Moreover, your code will be more readable and efficient when you use unions.

Unions and the API

Unions exist throughout the API, however, they are usually declared inside structures and not as a single unit. A good example is the DEVMODE structure.

Why is it preferred using unions inside structures? It doesn’t make much sense if they were a single unit. For our example, you could easily convert the integer to a character rather than creating a union. However, the efficiency of unions comes when they are declared inside structures. In addition, you gain more performance (and scalability of course) when you work with unions.