Learning the C Programming Language as a Classical Musician

Episode 8

Welcome back and thank you for joining me on this new episode on learning how to code with the C programming language. In the last episode, we focused our attention on the lifetime of objects in a C program. Today we will start up with looking at name spaces, C’s fancy word for categories.

Let’s get started.

Lookup and namespaces

What we are covering today happens during the code compiling process and will help us understand how some things in C are allowed to us, while some others are not. Imagine an inspector who is going to check that everything is in order: it is going to analyse line by line and only when one is given as correct it can pass to the next one.

When this inspector encounters an identifier, such as the word notes in the object int notes = 12;, it performs a research—called lookup in technical terms—to locate its declarator. In this case they coincide, but image that, later in the program, I want to deny the existence of any note which is on the white keys (!): I will then write notes = 5; as the black keys on the piano are five. When the program encounters notes it goes back to its declaration (int notes = 12;) and checks that it is currently in scope. We spent a good amount of time on the concept of scope but, to be sure nothing escaped us, the program makes sure that we can access that object, that it is available to us.

One of the greatest flexibilities allowed by the C programming language is that it allows for independent identifiers to bear the same name, i.e., to be equal, and in the same scope, as long as they belong to different categories, called name spaces. There are a total of six name spaces and, practically, we could have the same identifier reported into those six categories without incurring in an error but let’s get a more in-depth look at these.

Label namespace

What is a label? Let’s start simple: it is a sticker we attach to an object to categorise it and to access it with ease in the future. Plenty of software programs have labels built into them, included in macOS (they are called tags). In programming, they are used to make the code more approachable to the reader. An example of this is the switch statement, where code gets executed according to its conformity to a given value.

int noteC = 1;
    
switch (noteC) {
	case 1:
        printf("C is the first note of the scale\n"); 
        break;
    case 2:
        printf("This may be the B-flat major scale\n");
        break;
            
    default:
        printf("Think again!\n");
        break;
}

In this code, we create an integer variable object called noteC, representing the place of the note C in a scale. The switch statement allows us to verify that the value of noteC is equal to a certain value, and, in that case, execute the appropriate code. In this case, we check whether noteC is equal to 1, in which case we print to the console that “C is the first note of the scale”. Should the value of noteC be 2 we would print a different statement, while if it had any other value, we would ask the user to think again. This is the briefest introduction to the switch statement I could possibly think of, and we will come back to it in a future episode.

In this example, the words case and default, followed by a column :, are both labels. In C, any statement can be preceded by a label, as long as you write its name followed by a column, but there is an important limitation: it must be within a function. It is clear, then, that we cannot use the same name for something else in the label name space. For a quick example, look at what happens here:

We cannot use firstStatement for a label again, as it would break the rule of the label namespace.

Another kind of label is the goto label, which simply moves the line of code execution to another place, indicated by the statement which follows the label. It’s not indispensable now, so I will leave it for later.

Tag namespace

Wait! I’ve just said before that tags and labels are the same, but are they? In Italian, the words “tag” and “label” have very similar translations, and many examples given in the Oxford Dictionary even overlap. In programming, a tag is a specific label given to structures, unions, and enumerated types. Very briefly:

  • Structures, identified with te struct tag, is a type consisting of a sequence of members whose storage is allocated in an ordered sequence. Think of it as a section of contiguous storage with other sections interconnected to it.
  • Unions, identified with the union tag, is a type consisting of a sequence of members whose storage overlaps. The value of at most one of the members can be stored in a union at any one time. This will all become clearer in the future, do not worry.
  • Enumerated types, or enumerations—tag enum—, are mainly used to assign names to integral constants, the names make a program easy to read and maintain. For example, if I wanted to create a D-major scale, giving the reader note names, but letting the program store them as integers, I would use an enum.

Whatever we call them during declaration, we cannot assign the same name to another object in the same namespace, regardless of what type it is. That means: we cannot have an enum DmajorScale and a struct or a union with the same identifier. The error Xcode would throw is not excessively clear, but I hope this helps:

Member namespace

All identifiers declared as members of any one struct or union are part of the name space introduced with the struct or union. After the complexity that the first two namespaces had, this is a piece of cake, and it goes once more back to what we looked at when studying scope: if we create an object inside a structure, we cannot create another object with the same name. Here is what happens in Xcode:

Attributes namespace

The upcoming standard of the C language (C23) is going to introduce the concept of attributes, which are a kind of descriptors that precede appropriate parts of code. Their syntax is enclosed by double square brackets, such as [[myAttribute]]. Since this is not yet standard, I will not risk talking about it, just know that you will not be allowed to give the same name to two different attributes (by the way, why would you?).

Everybody free!

Any object that doesn’t belong to one of the previous categories, and therefore defined with an ordinary identifier, shares a namespace.

In this namespace, you cannot use the same name for two different objects, may they be variables, constants, pointers, functions, whatever.

How does it work?

At the moment of lookup, the name space of an identifier is determined by how it will be used:

  1. If it is appearing as the operand of a goto statement, it is looked up in the label name space.
  2. If it follows the keyword struct, union, or enum, it is looked up in the tag name space.
  3. If it follows the member access or member access through pointer operator (for example a[b] to access the b-th element of the a array), it is looked up in the name space of members of the type determined by the left-hand operand of the member access operator (the one to the left of the = sign).
  4. If it directly appears in an attribute specifier ([[...]]) is looked up in the global attribute name space (coming in C23).
  5. If it follows the :: token following an attribute prefix, it is looked in the name space introduced by the attribute prefix (coming in C23).
  6. All other identifiers are looked up in the name space of ordinary identifiers.

What’s next?

And that’s it for today! I hope you did not find this too hard to follow and that the examples I provided were clear enough.

In the next episode we will start the approach to more practical examples, as we will be looking at types in C. We have already touched the concept of type many times, but we have never delved deep into it. Now the time has come!

Bottom Line

Thank you for reading today’s article.

If you have any question or suggestion, please leave a comment below or contact me using the dedicated contact form. Assuming you do not already do so, please subscribe to my newsletter on Gumroad, to receive exclusive discounts and free products.

I hope you found this article helpful, if you did, please like it and share it with your friends and peers. Don’t forget to follow me on this blog and to let me know what you think.

If you are interested in my music engraving services and publications don’t forget to visit my Facebook page and the pages where I publish my scores (Gumroad, SheetMusicPlus, ScoreExchange and on Apple Books).

You can also support me by buying Paul Hudson’s Swift programming books from this Affiliate Link or BigMountainStudio’s books from this Affiliate Link.

Thank you so much for reading!

Until the next one, this is Michele, the Music Designer.

Published by Michele Galvagno

Professional Musical Scores Designer and Engraver Graduated Classical Musician (cello) and Teacher Tech Enthusiast and Apprentice iOS / macOS Developer Grafico di Partiture Musicali Professionista Musicista classico diplomato (violoncello) ed insegnante Appassionato di tecnologia ed apprendista Sviluppatore iOS / macOS

2 thoughts on “Learning the C Programming Language as a Classical Musician

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create your website with WordPress.com
Get started
%d bloggers like this: