Monday, November 21, 2016

C Storage Classes -- Where Do You Store Your Foo?

In investigating the proper means to declare a global variable, I found myself reviewing some C documentation that I had long forgotten, concerning the Storage Class.

To briefly review, each variable declaration consists of 3 elements: the storage class, the type, and the variable name. For example:


auto int x;
static int y;


The storage class can take the form of auto, extern, static, or register. If not specified, the implicit storage class is that of auto.

The auto storage class is the most frequently used of the classes, primarily because it is the implicit default. Local variables take this form, where the storage is not allocated until the block in which the variable is defined is entered.

The extern storage class specified simply a reference to a variable that is defined elsewhere. Space is therefore not allocated upon encountering this reference, since the storage is allocated elsewhere. This as you may recall is the means to declare a global variable.

The static storage class specifies that the variable cannot be access by functions outside the translation unit in which it was defined. A common error is declaration of a static variable in a header file, which is imported by more than one translation unit not understand that each translation unit essentially created independent copies of the variable. A common practice of declaring a static constant in a header, used by multiple translation units results in multiple copies of the constant, in each translation unit. However, if the static variable simply defines a constant....generally, no-harm-no-foul. It is however worth understanding that it is not a shared reference.

The last storage class is that of register, which notifies the compiler to make the variable as efficient as possible. Ideally, the variable will retain it's location in a cpu register for optimal performance.

Tuesday, November 8, 2016

Singular and Plural Output -- One Lump Or Two

This particular blog post teeters on that fine line of ridiculously obvious and pure genius.

It's not too uncommon to provide output of a particular data structure that can take the form of singular or plural content.  Because we're often in a rush, we sometimes sacrifice a more thoroughly thought out implementation for speed of implementation, sloppy but fast.



The result, duplicating assignment of output assignments like this:
  if ( list.size() <= 1)
  {
    printf("(%s:%d) found %ld identifier %s\n",__FILE__,__LINE__,list.size(),oss.str().c_str());
  }
  else
  {
    printf("(%s:%d) found %ld identifiers %s\n",__FILE__,__LINE__,list.size(),oss.str().c_str());
  }

Copy-n-pasted statements are notorious for falling out of sync and can complicate the intended usage (e.g. say overlooking one of the cases when searching through the logs).

Or perhaps worse, simply ignoring or manipulating grammar to fit for both the plural and singular content.
    printf("(%s:%d) found identifier list: %s\n",__FILE__,__LINE__,oss.str().c_str());

But if you take a breath you can satisfy both plural and singularity output, which often is simply accomplished by adding an 's' to a word in the string, like this:
  printf("(%s:%d) found %ld identifier%s %s\n",__FILE__,__LINE__,list.size(),list.size()<=1 ? "": "s", oss.str().c_str());


Full source code example follows.  I've taken some liberties mixing C & C++ syntax for convenience and to demonstrate the principle rather than using solid coding practices.  The same principle can be applies to pure-C or pure-C++ implementations.

#include <stdio.h>
#include <vector>
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <iterator>

typedef std::vector<int> List;
typedef std::ostringstream ListString;

void log(const List& list)
{
  ListString oss;
  std::copy(list.begin(), list.end(), std::ostream_iterator<int>(oss, " "));

  if ( list.size() <= 1)
  {
    printf("(%s:%d) found %ld identifier %s\n",__FILE__,__LINE__,list.size(),oss.str().c_str());
  }
  else
  {
    printf("(%s:%d) found %ld identifiers %s\n",__FILE__,__LINE__,list.size(),oss.str().c_str());
  }
}

void log2(const List& list)
{
  ListString oss;
  std::copy(list.begin(), list.end(), std::ostream_iterator<int>(oss, " "));
  printf("(%s:%d) found %ld identifier%s %s\n",__FILE__,__LINE__,list.size(),list.size()<=1 ? "": "s", oss.str().c_str());
}

int main(int argc, char* argv[])
{
  printf("(%s:%d) main process initializing\n",__FILE__,__LINE__);
  static const int arr[] = {1,1,2,3,5,8,13,21,34};
  static int arrSize=sizeof(arr)/sizeof(arr[0]);

  List list1(arr,arr+1);
  List list2(arr,arr+arrSize);

  log(list1);
  log(list2);

  log2(list1);
  log2(list2);
  printf("(%s:%d) main process terminating\n",__FILE__,__LINE__);
}

Friday, November 4, 2016

Unix Find Command -- Where'd I Put My Keys

I'll be the first to admit, I'm a bit of a dinosaur with respect to usage of IDEs.  While I'm well versed in Eclipse and other IDE's, I still find myself more efficient when using a multi-window environment, specifically 3-4 editor sessions along side debugging and execution windows.  In my native habitat, you'll find me running Linux with 3-4 terminals each with specific source files open (I'm not a tabbed session window man myself), one terminal tail'ing a redirected output file, and one where I run the application redirecting to the output file.  Certainly this depends on what I'm working on, but that's a pretty reasonable representation of how I roll.

So what?  Well, because I don't use IDEs I don't have the luxury of 'Open Declaration' style features isn't my jam.  In the absence of IntelliSense style functionality, I rely on the Unix find command to locate my next source code victim.  Despite that, I've had a poor understanding on how to properly use the find command, especially for more sophisticated commands.

For years, I had zero understanding of the ACTIONS options.  Casual observation of co-workers over the years seems to imply that many don't, resulting in clumsy, half-azzed usage of it.  Few understand the ramifications, specifically whenever you misuse the find command, it causes a puppy to cry.  So take heed my tech warrior and prevent the crying of puppies.


So let's set the stage for some find commands.
$ echo "hello" > hello.txt
$ echo "hello world" > helloworld.txt
$ mkdir subdir

$ echo "hello\nworld" > subdir/helloworld2.txt


So as an example of a clumsy misuse of find, for years if I wanted to display the contents of all these text files I'd do something like this:
$ more `find . -name "*.txt"`
::::::::::::::
./subdir/helloworld2.txt
::::::::::::::
hello\nworld
::::::::::::::
./helloworld.txt
::::::::::::::
hello world
::::::::::::::
./hello.txt
::::::::::::::
hello


Similarly, if I wanted to edit each of the files the clumsy command would take the form of:
$ vi `find . -name "*.txt"`


Ugh.

A key contributor to years of misuse is the God-awful syntax for the action commands, a more confusing syntax I've never met.  Albeit, incredibly powerful, but seriously.....WTF?

The first part of the command line is reasonable, straight-forward and typical:
$ find [starting-point] [expression]

$ find . -name "*.txt" will search the current directory and subdirectories for file names that match '*.txt'; straight-forward.

Say you want to display the contents of each of the text files like above, proper form is:
$ find . -name "*.txt" -exec more {} \;

Seriously; '{}' & '\;', what fresh hell is this?

I think a turning point for me was the day that I quit quibbling on how ridiculous the syntax is and simply accepted it; Admission, Surrender & Acceptance.

The '-exec' optional parameter takes the general form of '-exec [command] {} \;'.  Above we want to run more on each of the files, the list of files is represented by the brackets '{}', the delimited ';' implies it's the end of the command parameters.

Conceptually, the find . -name "*.txt" -exec more {} \; equates to a sequence of commands:
$ find . -name "*.txt"
./subdir/helloworld2.txt
./helloworld.txt
./hello.txt


Followed by:
$ more ./subdir/helloworld2.txt ./helloworld.txt ./hello.txt

Similarly, editing each txt file can be done by:
$ find . -name "*.txt" -exec vi {} \;

No puppies cried in the last two commands.

You're also able to chain commands together.  Say for instance you're interested in finding files that contain the word 'hello' in them, the following command will suit the bill:
$ find . -name "*.txt" -exec grep -l 'hello' {} \;

What if however you want to find files that contain 'hello' and 'world' and not necessarily on the same line, you accomplish that by chaining grep commands as follows:
$ find . -name "*.txt" -exec grep -q 'hello' {} \; - exec grep -l 'world' {} \;
./subdir/helloworld2.txt
./helloworld.txt