Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are the literal and constant the same concept in C?

Tags:

c

Are the literal and constant the same concept in C? Is there any difference between them in usage?

like image 966
Victor S Avatar asked Jul 31 '12 03:07

Victor S


3 Answers

Literals and constants are significantly different things in C. It can be said that the term literal in C stands for unnamed object that occupies memory (literals are typically lvalues), while the term constant stands for (possibly named) value that does not necessarily occupy memory (constants are rvalues).

"Classic" C (C89/90) had only one kind of literal: string literal. There were no other kinds of literals in that C. C99 additionally introduced so called compound literals.

Meanwhile, the term constant refers to explicit values, like 1, 2.5f, 0xA and 's'. Additionally, enum members are also recognized as constants in C.

Again, since literals in C are lvalues, you can take and use their addresses

const char *s = "Hello";
char (*p)[6] = &"World";
int (*a)[4] = &(int []) { 1, 2, 3, 4 };

Since constants are rvalues, you can't take their addresses.

Objects declared with const keyword are not considered constants in C terminology. They cannot be used where constant values are required (like case labels, bit-field widths or global,static variable initialization).

P.S. Note that the relevant terminology in C is quite different from that of C++. In C++ the term literal actually covers most of what is known in C as constants. And in C++ const objects can form constant expressions. People are sometimes trying to impose C++ terminology onto C, which often leads to confusion.

(See also Shall I prefer constants over defines?)

like image 143
AnT Avatar answered Oct 29 '22 15:10

AnT


The C standard (specifically ISO/IEC 9899, Second edition, 1999-12-01) does not define “literal” by itself, so this is not a specific concept for C. I find three uses of “literal”, described below.

First, a string literal (or “string-literal” in the formal grammar) is a sequence of characters inside quotation marks, optionally prefixed with an “L” (which makes it a wide string literal). This is undoubtedly called a literal because each character in the string stands for itself: A ”b” in the source text results in a “b” in the string. (In contrast the characters “34” in the source text as a number, not a string, result in the value 34 in the program, not in the characters “3” and “4”.) The semantics of these literals are defined in paragraphs 4 and 5 of 6.4.5. Essentially, adjacent literals are concatened ("abc" "def" is made into "abcdef"), a zero byte is appended, and the result is used to initialize an array of static storage duration. So a string literal results in an object.

Second, a compound literal is a more complicated construct used to create values for structures. “Compound literal” is an unfortunate name, because it is not a literal at all. That is, the characters in the source text of the literal do not necessarily stand for exactly themselves. In fact, a compound literal is not even a constant. A compound literal can contain expressions that are evaluated at run-time, including function calls!

Third, in 6.1 paragraph 1, the standard indicates that “literal words and character set members” are indicated by bold type. This use of “literal” is describing the standard itself rather than describing things within the C language; it means that “goto” in the standard means the string “goto” in the C language.

Aside from string literals, I do not think “literal” is a particular concept in C.

”Constant”, however, is a significant concept.

First, there are simple constants, such as “34”, “4.5f”, and “'b'”. The latter is a character constant; although written with a character, it has an integer value. Constants include integer constants (in decimal, octal, and hexadecimal), floating constants (in decimal and hexadecimal), character constants, and enumeration constants. Enumeration constants are names specified in “enum” constructs.

Second, there are constant expressions, defined in 6.6. A constant expression can be evaluated during translation (compile time) rather than run time and may be used any place that a constant may be. 6.6 sets certain rules for constant expressions. As an example, if x is a static array, as declared by static int x[8];, then &x[(int) (6.8 * .5)] is a constant expression: It is the address of element 3 of x. (You would rarely using floating-point to index arrays, but I include it in the example to show it is allowed as part of a constant expression.)

Regarding “const”: The standard does not appear to specifically define a const-qualified object as constant. Rather, it says that attempting to modify an object defined with a const-qualified type through an lvalue (such as a dereferenced pointer) with non-const-qualified type, the behavior is undefined. This implies a C implementation is not required to enforce the constantness of const objects. (Also, note that having a pointer-to-const does not imply the pointed-to object is const, just that the dereferenced pointer is not a modifiable lvalue. There could be a separate pointer to the same object that is not const-qualified. For example, in int i; int *p = &i; const int *q = p;, q is a pointer-to-const-int, but i is not a const object, and p is a pointer to the same int although it is pointer-to-int, without const.)

like image 21
Eric Postpischil Avatar answered Oct 29 '22 17:10

Eric Postpischil


Not quite. Constant variables (as opposed to constants defined in macros) are actual variables with dedicated storage space, so you can take the address of them. You can't take the address of a literal.

Edit: Sorry everyone, it appears that I was mistaken.

like image 33
Antimony Avatar answered Oct 29 '22 16:10

Antimony