31 March, 2008

Off-topic MNDOT Rant

As I found my way to the office this morning while listening to the radio, the radio announcer hinted of a snow forecast for later in the morning. At the time, not a speck of snow, nor rain, was present in brisk morning air.

As I came upon a large vehicle with warning lights....a tow truck? Perhaps an ambulance, or fire engine. What else could it be???

Well, let me tell you. MNDOT in their infinite wisdom decided to salt the road PRIOR to snowfall. What kind of genius salts the road without snow or ice? Surely they are attempting vegetation control of the ditches. That is the only reasonable explanation since applying salt unnecessarily to a road results in cars driving over said salt, crushing said salt, and having the wind blow it off the road into the ditches. Simple as that.

MNDOT isn't underfunded. They have plenty of money to waste, they do it daily. What they don't lack however is incompetence; they surely have a surplus in that area.

24 March, 2008

Same Kid, New Block

Today was the first day at our new office location.

Prior to the move, we found time to scope out our new cube locations.
My immediate neighbor went by the name Andrea. My co-worker taunted
"I'll bet she'll be a smokin' hottie". I laughed, given the hit ratio in
the engineering profession.

Turns out, that he was right. My neighbor is quite fetching. You'd
think that this would be a blessing, given that day-to-day face-to-face
encounters are with people with 5-o'clock shadow....men and women.
Turns out that there is a dark side to having an attractive
neighbor....every man with a pulse finds a reason to visit with her on a daily basis.
This results in an endless stream of distractions so far. While I'm
sure that this is an inconvenience for her, I wouldn't have guessed it
to be such an inconvenience to me (sigh).

15 March, 2008

Burning an Avi/Mpg to Playable Dvd

It took some work, but I finally found out how to burn an Avi or Mpeg file onto a playable dvd.

Step 1: Convert the Avi/Mpeg to proper format
ffmpeg -i InputFile.mpg -aspect 16:9 -target ntsc-dvd foo.mpg

Step 2: Create dvd file structure
dvdauthor -o dvd/ -t foo.mpg
dvdauthor -o dvd/ -T

Step 3: Create ISO Image
mkisofs -dvd-video -v -o DVD.iso dvd/

Step 4: Burn to Disc
growisofs -dvd-compat -Z /dev/scd0=DVD.iso

This will burn an input video file to a playable dvd. This example doesn't include a dvd menu, nor multiple files on one disc. DvdAuthor suffers from the same symptom as many open-source products, little-to-no documentation nor examples. As a result, I wasted about a dozen DVD+R's trying to decrypt it's usage and finally gave up.

Bon Scott Statue Unveiled


I am by all accounts a HUGE AC/DC fan. Have been since the first time my older brother exposed me to "Dirty Deeds Done Dirt Cheap" while racing a Monte Carlo in his 75 Trans Am on the interstate near my home town. Little did I know what an impact that moment would have for the rest of my life.

I became a dedicated fan on that faithful day...and continue to be to-date. That's why it's important to note that 24 February 2008 holds a special day in history. This marks the day that a bronze statue tributing AC/DC first lead man (Dave Evans doesn't count) was unveiled at, his childhood haunt, Fisherman's Warf in Fremantle Australia. It was unveiled as part of the Aussie Rock Concert at Claremont Showgrounds. A proud day for all AC/DC fans.

14 March, 2008

Jeez, We Are Seriously Overpaid

As my current program is coming to a close I've been evaluating alternative programs that my current employer has to offer. In terms of interest, it's pretty slim pickings.

As a result, I've took part in my first phone interview in 3+ years. Things went quite well, the closing question from the HR rep was concerning compensation. Now I'm not currently hitting 6 figures, but I'm charging hard toward the hoop.

Growing up blue collar I know what hard work is; I've shoveled grain, tossed bales, and picked my share of rock for less than $2 / hour. I've spent my share of days working in 90+ degree heat with a gallon of water for the day and little more than a warm bologna and cheese sandwich (oftentimes with mayo.....warmed in the afternoon sun). I've busted hump 'til my back ached, shoulders gave out, and feet grew a crop of blisters from heel to toe. I know what it feels to suffer serious dehydration, and my share of hangovers cured by the recommended dosage of sweating it out with outdoor manual labor. I know what hard work is, and I know what salary you can expect for this type of labor.

I try to keep this in mind time-n-time-again, took keep things in check. I approached an initial salary that competed with my fathers maximum salary he'd been working toward his entire life. Less than 10 years have passed since, and my salary has more than doubled. Rates of change will slow from here on, but still....we are incredibly fortunate in the field that we are in. If you are even moderately competent, you'll demand a salary that will surpass most dual family incomes. Chances are that you'll go home to your well furnished apartment, or quite likely single family home where you'll relax in your easy chair quietly decompressing to the drone of central air. Your reminder of a hard day....a migraine, or perhaps an armful of paperwork/techwork you need to complete before morning. The only joint or muscle issues you'll likely face is a mild case of carpal tunnel.

Just try to remember how easy we have it the next time you find yourself complaining about work. Better yet, keep this in mind on a good day; remembering how well you're paid to do something you truly love.

Cheers.

12 March, 2008

C Storage Classes

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.

11 March, 2008

Global Variables in C

First the disclaimers;
Global variables are bad. Global variables are evil. Global variables are, and will continue to be much like a 6-ft chainsaw, extremely dangerous to use, can regularly be replaced with a safer tool/technique, but are sometimes the proper tool for the job (like cutting down 12-ft diameter trees). None-the-less, on the rare occasion that a global variable is the proper technique, you'll need to know how to define and use them...the subject of the remainder of this post.

The following example will be used to explain techniques for defining and using globals, we will speak to it for the remainder of the post.

package1.h

1 #ifndef PACKAGE1_H
2 #define PACKAGE1_H
3 static const float GlobFloat = 3.14159;
4 static double GlobDouble = 1.23456;
5 extern unsigned GlobUnsigned;
6 //char GlobChar='a';
7
8 void func1(void);
9 #endif

package1.c

1 #include "package1.h"
2 #include
3
4 static int PackageGlobalInt = 1;
5 unsigned GlobUnsigned = 12345;
6
7 void func1() {
8 printf("(%s:%d) PackageGlobalInt(%d)\n",__FILE__,__LINE__,PackageGlobalInt++);
9 printf("(%s:%d) GlobFloat(%f)\n",__FILE__,__LINE__,GlobFloat);
10 printf("(%s:%d) GlobDouble(%lf)\n",__FILE__,__LINE__,GlobDouble++);
11 printf("(%s:%d) GlobUnsigned(%u)\n",__FILE__,__LINE__,GlobUnsigned++);
12 printf("(%s:%d) GlobDouble(%lf)\n",__FILE__,__LINE__,GlobDouble++);
13 printf("(%s:%d) GlobUnsigned(%u)\n",__FILE__,__LINE__,GlobUnsigned++);
14 }
15

package2.h

1 #ifndef PACKAGE2_H
2 #define PACKAGE2_H
3 #include "package1.h"
4
5 extern long GlobLong;
6 void func2(void);
7 #endif

package2.c

1 #include "package2.h"
2 #include
3
4 static int PackageGlobalInt = 2;
5 long GlobLong = 987654321;
6
7 void func2() {
8 printf("(%s:%d) PackageGlobalInt(%d)\n",__FILE__,__LINE__,PackageGlobalInt++);
9 printf("(%s:%d) GlobFloat(%f)\n",__FILE__,__LINE__,GlobFloat);
10 printf("(%s:%d) GlobDouble(%lf)\n",__FILE__,__LINE__,GlobDouble++);
11 printf("(%s:%d) GlobUnsigned(%u)\n",__FILE__,__LINE__,GlobUnsigned++);
12 printf("(%s:%d) GlobLong(%li)\n",__FILE__,__LINE__,GlobLong++);
13 printf("(%s:%d) GlobDouble(%lf)\n",__FILE__,__LINE__,GlobDouble++);
14 printf("(%s:%d) GlobUnsigned(%u)\n",__FILE__,__LINE__,GlobUnsigned++);
15 printf("(%s:%d) GlobLong(%li)\n",__FILE__,__LINE__,GlobLong++);
16 }
17

main.c

1 #include
2 #include "package1.h"
3 #include "package2.h"
4
5 int main() {
6 printf("(%s:%d) main process initializing\n",__FILE__,__LINE__);
7
8 func1();
9 func2();
10
11 printf("(%s:%d) GlobFloat(%f)\n",__FILE__,__LINE__,GlobFloat);
12 printf("(%s:%d) GlobDouble(%lf)\n",__FILE__,__LINE__,GlobDouble);
13 printf("(%s:%d) GlobUnsigned(%u)\n",__FILE__,__LINE__,GlobUnsigned);
14 printf("(%s:%d) GlobLong(%li)\n",__FILE__,__LINE__,GlobLong);
15
16
17 printf("(%s:%d) main process terminating\n",__FILE__,__LINE__);
18 }
19


Globals are a form of interface, so rightly are typically defined in a header file. Package 1 attempts to define 3 global variables. You will soon see that it was only successful in defining one. Before we get into the details, we should review some preliminaries.

#includes
As you should already be aware, header files serve little purpose other than organization of code. When encountering a #include directive, the precompiler does little more than copy-n-pasting the contents into the sourcing file. This is significant in our later discussion.

Static Variables
Static variables cannot be accessed outside a translation unit. For all intents and purposes, a translation unit is a C source file. This, along with what we know about #includes will explain why only one of our intended global variable declarations was successful.

Back To Our Example
The contents of package1.h on lines 3-5 are three attempts to declare a global variable. Note, lines 3-4 define the variables as static, line 5 defining it as external linkage. Why are the first two variables defined as static??? Because if I don't, I get a linker error "multiple definition of . . ." error. Pounding on the keyboard, slowly beating the linker into submission is accomplished by declaring the variable as static. Finally, the linker shuts up; we must have fixed it, right? Wrong!

So, why doesn't lines 3-4 work? More importantly, how do we know it doesn't work? Well, we can confirm that line 4 didn't work by comparing the results of lines package1.c:10, package1.c:12, package2.c:10, package2.c:13, and main.c:12. Note that on package 1 & 2 functions, we are incrementing the contents of GlobDouble. If we were successful in defining a global variable, we should see the variable initially assigned 1.23456, incremented 4 times with a final result of 5.23456.


~/StorageClasses$ ./main | grep GlobDouble
(package1.c:10) GlobDouble(1.234560)
(package1.c:12) GlobDouble(2.234560)
(package2.c:10) GlobDouble(1.234560)
(package2.c:13) GlobDouble(2.234560)
(main.c:12) GlobDouble(1.234560)

Hmmmph, we didn't accomplish what we intended, did we? The static storage class, coupled with the precompiler copy-n-paste behavior resulted in 3 independent variable declarations; one in package1.c, one in package2.c, and one in main.c. Each instance is unique to each translation unit, so incrementing one only affects the declaration in that translation unit.

Line 5 however successfully defined a global variable. How? Well, line 5 simply states that we are declaring a variable, to be defined elsewhere. Declaration simply defines a reference to variable that will be defined elsewhere (in this case, line 5 in package1.c). Translation units: package1.c, package2.c and main.c will each declare a reference to GlobUnsigned, but the single definition of the variable resides in package1.c.

We can confirm that all is well by means of:


~/StorageClasses$ ./main | grep GlobUnsigned
(package1.c:11) GlobUnsigned(12345)
(package1.c:13) GlobUnsigned(12346)
(package2.c:11) GlobUnsigned(12347)
(package2.c:14) GlobUnsigned(12348)
(main.c:13) GlobUnsigned(12349)



It is worth noting that lines 3-4 in package1.h have identical results as line 4 in both package1.c and package2.c. All instances are similar in the matter that their scope is limited to the translation unit in which they are declared.

10 March, 2008

Formal Names For Common C Techniques

If you ever written a C application with custom-defined header files, you've used the pre-processor pattern:


#ifndef FOO_H
#define FOO_H
.
.
.
#endif


Ever wonder what this pattern was called? I never did, until the other day when I searched for it. The pattern is referred to as the 'once-only header' pattern, sometimes called the 'wrapper #ifdef'.

Call it what you want, the intention is to ensure that the header is not copy-n-pasted multiple times in a translation unit, due to multiple direct or indirect includes. The FOO_H is referred to as the 'guard' or 'controlling macro'.

Another common technique that you may have made use of goes something like this:

#ifdef SYS1
#include "sys1.h"
#elif . . .
.
.
.
#endif

This is referred to as a 'computed includes' pattern or technique. Not much else to add, just a name for a common face.