Click to Rate and Give Feedback
Related Articles

This month we explain how pseudo variables and format specifiers provide a wealth of information for use in debugging.

Kenny Kerr

MSDN Magazine December 2008

...

Read more!

We use the new Asynchronous Agents Library in Visual C++ 2010 to solve the classic Dining Philosophers concurrency problem.

Rick Molloy

MSDN Magazine June 2009

...

Read more!

This month's column explains how to use Windows HTTP Services, or WinHTTP, the new, powerful API for implementing HTTP clients.

Kenny Kerr

MSDN Magazine August 2008

...

Read more!

This month begins the design of the actual mouse class for EEK!

Stanley B. Lippman

MSDN Magazine December 2007

...

Read more!

This column crafts an XML document to hold the mouse environment simulation data and shows how to incorporate an XML file into the program using a DataSet.

Stanley B. Lippman

MSDN Magazine October 2007

...

Read more!

Also by this Author

Paul DiLascia

MSDN Magazine June 2005

...

Read more!

Paul DiLascia

MSDN Magazine April 2006

...

Read more!

Paul DiLascia

MSDN Magazine December 2005

...

Read more!

Paul DiLascia

MSDN Magazine November 2005

...

Read more!

This month: CWebVersion revisited using HTTP instead of FTP, and adding sounds to an MFC-based app.

Paul DiLascia

MSDN Magazine May 2006

...

Read more!

Popular Articles

The MVP pattern helps you separate your logic and keep your UI layer free of clutter. This month learn how.

Jean-Paul Boodhoo

MSDN Magazine August 2006

...

Read more!

Ray Djajadinata

MSDN Magazine May 2007

...

Read more!

Now you can perform efficient, sophisticated text analysis using regular expressions in SQL Server 2005.

David Banister

MSDN Magazine February 2007

...

Read more!

C# allows developers to embed XML comments into their source files-a useful facility, especially when more than one programmer is working on the same code. The C# parser can expand these XML tags to provide additional information and export them to an external document for further processing. This article shows how to use XML comments and explains the relevant tags. The author demonstrates how to set up your project to export your XML comments into convenient documentation for the benefit of other developers. He also shows how to use comments ...

Read more!

Jeff Prosise explains when it's better to use UpdatePanel and when it's better to use asynchronous calls to WebMethods or page methods instead.

Jeff Prosise

MSDN Magazine June 2007

...

Read more!

From the June 2002 issue of MSDN Magazine.
MSDN Magazine
Commas, Pseudocode, Operator =, and More
Download the code for this article: C0206.exe (56KB)
S
hrewd readers will notice that starting this month, I'm serving C# along with the usual fare. Those of you who love C/C++ needn't fret; I'll go on answering the same sorts of questions I always have. But .NET and C# really are cool in a lot of ways, so it behooves me to broaden my scope. In particular, I want to illustrate the relative merits of each system by showing how things are done both ways. That should minimize the pain of entering the new C# world, for those of you who care to. And if you're a diehard, that's fine too—you should still enjoy the column. Personally, I try to avoid ideology. I'd rather use whatever tool gets the job done quickest, and my job is to help you do the same. So—C's the day!

Q What are the priority and associativity of the , (comma) operator? Some books state that it's right to left and others left to right. Which one is correct? How will the following statements execute?
a=10,20,30;
a=(10,20,30);
Lakshmikumar Allampati

A First of all, let me say that when in doubt, use parentheses. It's really not worth the two minutes it takes to look up something like this (except to satisfy your curiosity). Parens not only ensure correctness, they make your code more readable. Why leave any doubt? That said, expressions separated by commas are always evaluated left to right. So the value of an expression
(expr1, expr2, expr3)
is always the value of the last expression. Thus, in your second example, the result of the right-hand side is 30, so a is set to 30. But because assignment (=) takes precedence over comma (,) your first example is equivalent to
(a=10),20,30;
So the compiler-generated code first sets a to 10, then evaluates the expressions 20 and 30, which evaluate to themselves and disappear into primal nothingness since they have no side effects. In fact, a clever compiler might even omit them from the generated code. Keep in mind that while a statement like
20;
doesn't do anything, it is nevertheless a valid C statement. Figure 1 is a short program that illustrates your example in real code. If you don't believe what I'm saying, just compile and run it. (What, you don't trust me?)
      The comma operator is rather esoteric, the kind of thing C pundits ponder in their beddy-bye and, frankly, not terribly useful. Perhaps that's why it doesn't appear in C#. I only mention the comma here because, while most programmers don't use it or even know it exists, it does crop up from time to time. Most often you'll see the little guy in for loops
for (i=0,n=1; ...) {
  •••
}
which feels fine and natural; but occasionally you'll encounter something awkward like
c = (a++, b++, a+b);
which increments both a and b, then assigns the sum to c. One can only surmise that the person writing such code has an abnormally severe propensity for terseness or else is desperate to seem clever. Much preferable is the more mundane
a++;      // another apple. sigh.
b++;      // another banana—I like bananas!
c = a+b;  // count = sum. Addition is cool
which consumes two more lines but makes your code more comprehensible at 3:00 in the morning and even gives you a chance to express your feelings about each operation. If you want to show off, write code that's well-designed and reliable.

Q I am learning to be a programmer, and my teacher keeps saying, "You must use pseudocode before you do any programming." I know programmers who have been programming for many years and they never use it. Why do you think my teacher insists on it?
Michael Hodo

A I'm glad you're learning to become a programmer—welcome! Today must be my day for weird questions. First the comma operator, which I haven't considered in years, and now this. Not that your question is so weird, only that I should answer it here. Usually I stick to more practical queries, not programming philosophy. Nevertheless, I frequently get "what's the best way ..." questions, so why not?
      Different programmers and different programs require different design techniques. There's nothing vital about pseudocode per se. What is important is that you have a design. What form your design takes depends on the task at hand. If you're developing algorithms or business logic, then pseudocode, flowcharts, or even mathematics may offer the most concise expression because pseudocode is inherently procedural and thus good for expressing procedural operations. But if you're building a user interface or Web site, pseudocode is too linear. You need to draw some screens and menus on a big sheet of paper or whiteboard. Even a napkin will do. Or some vaporware with commands that don't do anything. If you're designing a database, you'd draw object diagrams with tables and data structures, with relationship lines and pointers connecting them. The point is you need a design, but how you express your design depends on what you're trying to do. There's no single right way to go about writing any program.
      That said, if you're really sure you know what you're doing—and many talented programmers are—then by all means, jump right in! But I can't emphasize enough the importance of having a design. Even experienced programmers, including yours truly, have been known to botch things by being cocky. You wouldn't trek into an unknown jungle without a map, or build a skyscraper without a blueprint, would you? The design is your blueprint, both for yourself and others. It's the proof that you really do understand what you're about to do.
      "But how much time should I spend designing?" A good rule of thumb is to spend half your time on design and half implementing. Keep in mind implementation doesn't follow design in perfect succession. Usually, there's an initial design followed by the implementation. Then as soon as you get your hands dirty, you discover important details and situations your design doesn't consider. So it's back to the whiteboard.
      Design is almost always an iterative process. That's why I've never liked the organizational approach where one person or group designs and another implements. It can work if everyone stays on the same page, but the implementers need to understand the design at least well enough to recognize when some difficulty they encounter represents a design flaw, not a limitation in their coding ability. Better software is usually produced when the relationship between designer/implementer resembles that of mentor/apprentice rather than commander/footsoldier. Or better yet, when you can divide the project so each person has responsibility for both design and implementation of some piece of the overall system. Unfortunately, this isn't always possible.

Q I have a base class with an overloaded = operator and a class derived from this base class that also has an overloaded = operator. My question is, how do I call the base class = operator from the derived class = operator?
Robert M. Larson

A This question typically arises because operator= is not inherited when you derive a new class. For example, MFC's CString has an assignment operator for LPCSTRs:
class CString {
public
   const CString& operator=(LPCSTR p) { ... };
};
which lets you write
CString s;
s = "Where do you want to go today?";
      Now suppose you derive a new class that is called CBetterString. Your better string doesn't automatically inherit the assignment operator from CString:
CBetterString bs;
bs = "To the supermarket.";  // NOT!
This won't compile because CBetterString does not inherit operator=(LPCSTR) from CString. If you want to assign from LPCSTRs, you have to explicitly write the assignment operator even if all it does is call the base class version. Suppose you do. What's the syntax? You might try casting as shown here:
CBetterString& CBetterString:operator=(LPCSTR lp)
{
   *((CString*)this) = lp; // call base class operator=
   return *this;
}
That works, but it's too cryptic. Who can read all those parentheses? Here's a better way:
   CBetterString&     
   CBetterString:operator=(LPCTSTR lp)
   {
      CString::operator=(lp);
      return *this;
   }
With this, there's no need even to document the call because it's obvious what you're doing. In general, you can always call any operator directly using the syntax classname::operatorX(...) where X is whatever operator you want (=, *, ++, whatever), and the ellipsis is whatever parameters the operator requires. An operator is just a function with the special name "operator" followed by a special character or two.

Q How can I use C++ to get the IP address of a machine?
Abdul Ghaffar

A First, you need to realize a machine can have more than one IP address. Many people, myself included, have computers with more than one Internet adapter card. On my machine, one adapter talks to the cable modem and the other talks to my home network. This is a typical setup for people with broadband connections.
      That said, getting the IP addresses for the local machine is straightforward, once you know the proper voodoo. It requires delving into the low-level world of Winsock, aka the Windows® Sockets API. Figure 2 shows a simple console app I wrote (called getip1) that displays the IP addresses. Figure 3 shows the output from getip1 (with fictitious data).

Figure 3 getip1 Output
Figure 3 getip1 Output

      To use Winsock, you first have to call WSAStartup to say hello. Don't forget to call WSACleanup when you're finished. To get the IP addresses, you need the machine's host name, which you get by calling—what else?—gethostname. Once you have the name, you can call gethostbyname to get more information about the host, including its IP addresses. Gethostbyname returns a pointer to a hostent structure:
// from winsock.h
struct  hostent {
  char* h_name;      /* official name of host */
  char* h_aliases;   /* alias list */
  short h_addrtype;  /* host address type */
  short h_length;    /* length of address */
  char* h_addr_list; /* list of addresses */
};
As is typically the case with low-level APIs, the actual layout of this structure is a bit confusing. The hostent is actually a variable-length structure where h_addr_list is the start of a null-terminated array of addresses. Each address is h_length bytes. In the example in Figure 3, the host name (h_name) is "mars.microsoft.net." There are no aliases. The address type (or address family as it's sometimes called) is two (AF_INET = internet; see winsock.h for others). As mentioned, h_length is four since the length of an IP address is four bytes; each x.y.z.w number occupies one byte. Finally, h_addr_list is the start of the IP addresses themselves. Each one follows the other, with a null at the end. So the entire hostent structure in memory looks something like Figure 4. To format the IP addresses nicely in x.y.z.w form, you have to copy them first into something called a sockaddr, then call a special function, inet_ntoa. Hey, be thankful you don't have to read op codes!

Figure 4 Hostent Struct
Figure 4 Hostent Struct

      Just for fun, what would getip look like in C#? The .NET common runtime has a namespace, System.Net, with classes that take the pain out of network programming. In particular, there's a class called Dns with static methods to get the host name and IP addresses. Figure 5 shows the details. As you can see, getip2 is a lot simpler than the C version. Dns wraps the same basic underlying winsock functions and structures: there's Dns.GetHostName to get the host name and Dns.GetHostByName to get an IPHostEntry object. The .NET classes hide initialization and termination, hide the ugly hostent structure, wrap the addresses in an array, and even know how to format an IP address without thinking. The C# version of getip has 19 code lines, versus 53 for C. Granted, getip1 displays a bit more stuff, but C# is still the hands-down brevity winner. No need to mention it runs with a little hiccup the first time .NET loads.

Q In your February 2002 column, I read how to pass the derived class name to the base class constructor. I'm trying to solve the same problem using C# in .NET. I ended up putting the class name as a constant being passed down to the base constructor, like this:
Private Const DERIVED_CLASS_NAME = "DerivedClass";
public DerivedClass() : base(DERIVED_CLASS_NAME)
{
   •••
}
I don't like this solution because it relies on someone typing the name correctly. Can your C++ solution be ported to C#?
Craig Roffers

A There's no need to port my solution to C# since C# doesn't have the same problem. In C#, an object is what it is, forever and always, period. Figure 6 is a little program that demonstrates what I mean. It has two classes, MyBase and MyDerived, each with its own constructor. Each constructor calls GetType and displays the result.

Figure 7 Csclass Output
Figure 7 Csclass Output

As you can see from the output in Figure 7, GetType returns the same class from both constructors: namely, MyDerived, the derived type. In C#, the type of a class instance is whatever type the object really is: the most derived class. This is true even inside base class constructors, unlike C++. In C++, because each base class ctor initializes its own vtable, objects don't "become" what they are (they don't achieve selfhood) until all the base class constructors have completed. The opposite happens during destruction. This often leads to unexpected behavior if you call a C++ virtual function from a constructor or destructor. Control goes to the base class function, not the derived one. But as Figure 7 shows, in C#, the most derived virtual function gets called, even if you call it from a base class constructor. By the way, Csclass also shows how to walk the entire derivation tree of an object using Type.BaseType in a simple loop:
Type type = d.GetType();
while (type!=null) {
   Console.WriteLine(type);
   type = type.BaseType;
}
      Of course, the real csclass.cs has extra code to print the indention—what do you think I am, a lazy slouch? Happy programming—whether it's C, C++, or C#!

Send questions and comments for Paul to cppqa@microsoft.com.
Paul DiLascia is a freelance writer, consultant, and Web/UI designer-at-large. He is the author of Windows++: Writing Reusable Windows Code in C++(Addison-Wesley, 1992). Paul can be reached at askpd@pobox.com or http://www.dilascia.com.

Page view tracker