Programming In C: Literals
This article is part of a series – How to Program Anything: C Programming
I touched on the difference between expressions and statements in my Programming Crash Course article, stating that expressions were “immediately executed” and statements were program control structures. In C this is true, and expressions encompass a large swath of constructs in a program. Expressions in C can be broken down into two or three categories. Some people include variable declarations and workings as expressions, but I’m actually going to cover variable declaration in another article where I can go deeper into their details involving things like scope. This article will focus on literal expressions and the operators of the C language, including assignment, relational, and bit-wise operators. So, let’s get to it shall we?
Literals are when you write a value directly into your code. For example, 10 is a literal, as well as “this is a string.” This comes most apparent in variable assignments:
int a; double b; a = 10; b = 10.54;
In the above code 10 and 10.54 are literals, their values are exactly what they look like. Some people call these kinds of literals constants, but I use the term literal because they are literally what they look like. Now, there are some caveats to literals and I shall cover them here. The first among these caveats is that literals are “translated” into the smallest accepting data type. This means that non fractional numbers are supposed to be ints, single characters become chars, fractional numbers actually buck this trend and become doubles. There are ways to control this, as seen below.
A character is part of a string presumably. That’s what is supposed when you specify a character literal, being of course one ‘letter’. You specify it in between single quotes like so:
char c; c = 'g';
Simple enough, but alas, there are character encodings that require multibyte characters. These are characters that consist of one or more bytes, and usually show up when you’re programming in another language with another character set like Japanese. There are also “wide characters” that are generally 16 bits long. However, it doesn’t complicate things too much, but it does change how the literal is defined. For multibyte characters you simply enclose the characters within single quotes. To specify a wide character literal you have to put an L in front of the literal. This will cause the character literal to be considered “wide” (generally 16 bits). However, with wide characters you have to use a data type that is not built in to C, but instead resides in the standard library, called wchar_t. This requires the inclusion of the <stddef.h> file, a detail outside the scope of this article. Below you can see examples of multibyte and wide characters:
#include <stddef.h> char c; wchar_t w; // single byte character literal c = 'a'; // multibyte character literal c = 'ab'; // wide character literal w = L'q';
You’ll discover in throughout the literals that they are modifiable in various ways by appending letters to them to force the compiler to interpret them a certain way.
NOTE: Not all characters that can be stored in a char literal are easily typed by the programmer. This includes such ASCII characters as the backspace, the alert bell, the return character, and so on. In these cases the programmer has to use what are known as escape sequences. An escape sequence is simply a backslash followed by a qualifier that stands for another character. For example, the escape sequence \n stands for a new line, \t for a tab, and so on. For a full list of escape sequences you can find a companion article on wikipedia.
Integer literals look just like normal numbers and in fact are written as normal numbers without any kind of decimal piece to it. 5 and -34 are both integer literals. As noted before the compiler tries to fit numeric constants into the smallest compatible data type that will hold it, but don’t think that numbers under 255 will go into a char. Once a the compiler decides it’s an int literal it stays an int, however if the literal is large enough to not fit into a standard int it may became a long int. For more information on the difference between a standard int and a long int see the article discussing the basic data types. For example, the literal 73 will fit in an int, and the number 234,123 will fit into a long int.
Now, you can force an integer literal to be interpreted as a long int even if it’s smaller than one by appending the character ‘L’ to the end of it. It can be wither a lowercase or uppercase L, but I prefer to use uppercase as it makes it more apparent. Likewise, negative literals are prepended with a negative sign, causing the standard literal to be assigned to a signed integer. You can also force the compiler to interpret it as an unsigned integer by appending the character ‘U’ to the end of it. Again, uppercase or lowercase works, I just prefer uppercase.
int a; long int b; unsigned int c; // The various modifiers are illustrated: a = -23; b = 76000L; c = 22874U;
NOTE: There are ways to write integer out in a different base than the decimal base 10. You can also write literals out in hexadecimal and octal form. For more information on binary, hexadecimal and octal see my Wonderful World of Binary series elsewhere. To write a hexadecimal value as a literal prepend the value with 0x. So, a byte full of 1’s binary wise would be written as 0xFF. To write an octal simply place a 0 in front of the value, in this sense to write 9 in octal, you’d write 011.
Double literals are numbers that have a decimal component to them, such as 234.567. C also allows you to use scientific notation to detail out a decimal number as well. By default, this literal bucks the trend of smallest container and by default interprets the literal as a double data type. There are ways around this of course. If you want your decimal number to be interpreted as a float rather than the larger double you can append the ‘F’ character to the end of it. This ‘F’ can be upper case or lower case, but I prefer upper case as it stands out more. There is also a way to interpret the literal as a long double and that is to append the ‘L’ character to the end of the literal. How does the compiler know this ‘L’ means long double and not long int? This is because the literal has a decimal component to it, if there were no decimal part it would be an integer instead.
NOTE: In C99 you can also specify a long long modifier by appending ‘LL’ to the end of a literal. This causes the integer to be intepreted as a long long double/int. C99 is the standard that offers the long long modifier, so this only applies to programs compiling against C99.
float f; double d; long double l; // examples of modifiers to literals f = 123.45F; d = 67123.3458; l = 223.999L;
C allows you to specify a string of characters together as a literal, but their use is limited. Because C doesn’t have a string data type, string literals can really only show up in certain places that expect a char array, or a char pointer. Strings are specified with double quotes, and this is important. “a” and ‘a’ are not the same thing to the C compiler, one is a string literal and the other a char literal.
// example of a string literal: char string = "This is a string literal."
The escape sequences apply to strings just as they apply to char literals. For example, if we wanted to include a new line and a tab in a string we might write this:
char string = "\n\tThis is tabbed in.\n\nThis is on another line.";
Literals are very important in programming, as they are one way to get data into a program. Assigning literals to variables allows us to specify a number of things such as the number of times we’re going to perform an operation. Using literals in various parts of the program allow us to specify how large an array is going to be. Using string literals we might hard-code (that’s when you put data that the program uses straight into the program code) an array of error messages that would be output when certain errors happen. Without literals we wouldn’t be able to specify the fine details of a program, or define constants that affect the operation of a program.
This article is part of a series – How to Program Anything: C Programming
If you appreciate this article you might consider supporting my Patreon.
But if a monthly commitment is a bit much, I get it, you might consider buying me a coffee.