This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

C Constant Expressions

  • 5 contributors

A constant expression gets evaluated at compile time, not run time, and can be used in any place that a constant can be used. The constant expression must evaluate to a constant that is in the range of representable values for that type. The operands of a constant expression can be integer constants, character constants, floating-point constants, enumeration constants, type casts, sizeof expressions, and other constant expressions.

constant-expression :   conditional-expression

conditional-expression :   logical-OR-expression   logical-OR-expression ? expression : conditional-expression

expression :   assignment-expression   expression , assignment-expression

assignment-expression :   conditional-expression   unary-expression assignment-operator assignment-expression

assignment-operator : one of   = *= /= %= += -= <<= >>= &= ^= |=

The nonterminals for struct declarator, enumerator, direct declarator, direct-abstract declarator, and labeled statement contain the constant-expression nonterminal.

An integral constant expression must be used to specify the size of a bit-field member of a structure, the value of an enumeration constant, the size of an array, or the value of a case constant.

Constant expressions used in preprocessor directives are subject to several restrictions. They're known as restricted constant expressions. A restricted constant expression can't contain sizeof expressions, enumeration constants, type casts to any type, or floating-type constants. It can, however, contain the special constant expression defined ( identifier ) .

Operands and Expressions

Was this page helpful?

Additional resources

Constants in C Explained – How to Use #define and the const Qualifier to Define Constants

Bala Priya C

When you're programming, there are times when you'll want the values of certain variables to remain unchanged. In the C language, you'll likely define them as constants.

You can define constants in C in a few different ways. In this tutorial, you'll learn how to use #define and the const qualifier to define them.

Let's get started.

How to Use #define to Define Constants in C

One of the common ways to define constants in C is to use the #define preprocessor directive, as shown below:

In the above syntax:

  • <VAR_NAME> is a placeholder for the name of the constant.
  • It's recommended that you name constants in the uppercase , as it helps differentiate them from other variables defined in the program.
  • <VALUE> is a placeholder for the value that <VAR_NAME> takes.
  • #define is a preprocessor directive.
  • Before the compilation of the program, the preprocessor replaces all occurrences of <VAR_NAME> with <VALUE> .

In C, the preprocessors process the source code ahead of compilation to produce the expanded source code. This is illustrated below.

Image

It's a good practice to include the definition of all constants after the header files in your program, as shown below:

▶ In the next section, you'll see an example using #define to declare C constants.

How to Declare Constants Using #define Example

Consider the following code snippet, where you have two constants STUDENT_ID and COURSE_CODE .

In this example:

  • The preprocessor replaces STUDENT_ID and COURSE_CODE by 27, and 502, respectively. So the body of the main() function will now be:
  • As the printf() function can print out formatted strings, the two occurrences of the format specifiers %d (for decimal integers) are replaced by 27 and 502.
Although #define lets you define constants, you should be careful not to redefine them elsewhere in the program.

For example, the code below, you've redefined STUDENT_ID . And it will compile and execute without errors.

Depending on your compiler, you may get a warning that you're trying to redefine an already-defined constant.

Image

And the value in the most recent definition will be used.

Notice how the redefined value of 207 has been used as the STUDENT_ID , overwriting the previously defined value 27 .

Image

So you now know that the #define constants are in some sense not true constants as you can always redefine them.

Head on to the next section to learn about the const qualifier.

How to Use the const Qualifier to Define Constants in C

In C, <data_type> <var_name> = <value> is the syntax to declare a variable <var_name> of type <data_type> , and to assign it the value <value> .

To make <var_name> a constant, you only need to add the const qualifier to this statement as follows:

Adding the const keyword in the definition of the variable ensures that its value remains unchanged in the program.

The const qualifier makes the variable read-only. And trying to modify it elsewhere in the program will throw errors during compilation.

▶ Head on to the next section to modify the previous example using const .

How to Declare Constants Using const Qualifier Example

From the previous example, you have the constants STUDENT_ID and COURSE_CODE . Now you'll define them as constants using the const qualifier.

  • Since they're both integers, you can define them to be of the int data type, taking the intended values: 27 and 502 .
  • Include the qualifier const in the respective definitions.

This is shown in the code snippet below:

You can see that the code works as expected.

In C, you cannot redefine an existing variable.

For example, if int my_var = 2 is the first definition, your program won't compile successfully if you try redefining my_var as int my_var = 3 .

However, you can always reassign values of a variable.

This means that if int my_var = 2 is the definition, you can assign a different value to my_var using a simple assignment statement like my_var = 3 .

Let's now try modifying the const variable STUDENT_ID .

You'll see that the program doesn't compile successfully.

And the error message reads: error: assignment of read-only variable 'student_id' meaning that you can only read the value of STUDENT_ID and not assign a value to it.

Image

Thus the const qualifier renders a _true constan_t that's immune to changes, and cannot be altered during the execution of the program.

In this tutorial, you've learned how to define constants:

  • using the #define preprocessor directive with the syntax #define <VAR_NAME> <VALUE> , and
  • using the const qualifier to render variables to be read-only .

Hope you found this tutorial helpful. Happy coding!😄

I'm a self-taught programmer and a technical writer from India. I enjoy reading, writing, and coding. I share my learning with the developer community by writing beginner-friendly programming tutorials.

If this article was helpful, share it .

Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started

Next: Execution Control Expressions , Previous: Arithmetic , Up: Top   [ Contents ][ Index ]

7 Assignment Expressions

As a general concept in programming, an assignment is a construct that stores a new value into a place where values can be stored—for instance, in a variable. Such places are called lvalues (see Lvalues ) because they are locations that hold a value.

An assignment in C is an expression because it has a value; we call it an assignment expression . A simple assignment looks like

We say it assigns the value of the expression value-to-store to the location lvalue , or that it stores value-to-store there. You can think of the “l” in “lvalue” as standing for “left,” since that’s what you put on the left side of the assignment operator.

However, that’s not the only way to use an lvalue, and not all lvalues can be assigned to. To use the lvalue in the left side of an assignment, it has to be modifiable . In C, that means it was not declared with the type qualifier const (see const ).

The value of the assignment expression is that of lvalue after the new value is stored in it. This means you can use an assignment inside other expressions. Assignment operators are right-associative so that

is equivalent to

This is the only useful way for them to associate; the other way,

would be invalid since an assignment expression such as x = y is not valid as an lvalue.

Warning: Write parentheses around an assignment if you nest it inside another expression, unless that is a conditional expression, or comma-separated series, or another assignment.

  The basics of storing a value.
  Expressions into which a value can be stored.
  Shorthand for changing an lvalue’s contents.
  Shorthand for incrementing and decrementing an lvalue’s contents.
  Accessing then incrementing or decrementing.
  How to avoid ambiguity.
  Write assignments as separate statements.

Expressions

Learning outcomes ​.

After reading this section, you will be able to:

  • Code various expressions that apply operations on operands of program type

Introduction ​

Programming languages support operators that combine variables and constants into expressions for transforming existing data into new data. These operators take one or more operands. The operands may be variables, constants or other expressions. The C language supports a comprehensive set of these operators for arithmetic, relational and logical expressions.

This chapter describes the supported operators in detail, what happens when the operands are of different types, how to change the type of an operand and the order of evaluation of sub-expressions within expressions. The introduction to this detailed description is a brief overview of the hardware components that evaluate expressions. These are the ALU and FPA inside the CPU.

Evaluating Expressions ​

The ALU evaluates the simplest of instructions on integer values: for instance, additions where the operands are of the same type. The FPA evaluates the simplest of instructions on floating-point values. C compilers simplify C language expressions into sets of hardware instructions that either the ALU or the FPA can process.

The ALU receives the expression's operator from the Control Unit, applies that operator to integer values stored in the CPU's registers and places the result in one of the CPU's registers. The FPA does the same but for floating-point values.

Diagram of relationship between ALU and FPA

The expressions that the ALU can process on integer types are:

The FPA can processes these same kinds of expressions on floating-point types.

Arithmetic Expressions ​

Arithmetic expressions consist of:

  • integral operands - destined for processing by the ALU
  • floating-point operands - destined for processing by the FPA

Integral Operands ​

The C language supports 5 binary and 2 unary arithmetic operations on integral ( int and char ) operands. Here, the term binary refers to two operands; unary refers to one operand.

Binary Operations ​

The binary arithmetic operations on integers are addition, subtraction, multiplication, division and remaindering. Expressions take one of the forms listed below:

operand operandadd the operands
operand operandsubtract the right from the left operand
operand operandmultiply the operands
operand operanddivide the left by the right operand
operand operandremainder of the division of left by right

Division of one integer by another yields a whole number. If the division is not exact, the operation discards the remainder. The expression evaluates to the truncated integer result; that is, the whole number without any remainder. The expression with the modulus operator ( % ) evaluates to the remainder alone.

For example:

Unary Operations ​

The unary arithmetic operations are identity and negation. Expressions take one of the forms listed below:

Arithmetic ExpressionMeaning
operandevaluates to the operand
operandchanges the sign of the operand

The plus operator leaves the value unchanged and is present for language symmetry.

Floating-Point ​

The C language supports 4 binary and 2 unary arithmetic operations on the floating-point ( float and double ) operands.

The binary arithmetic operations on floating-point values are addition, subtraction, multiplication and division. Expressions take one of the forms listed below:

operand operandadd the operands
operand operandsubtract the right from the left operand
operand operandmultiply the operands
operand operanddivide the left by the right operand

The division operator ( / ) evaluates to a floating-point result. There is no remainder operator for floating-point operands.

The unary operations are identity and negation. Expressions take the form listed below:

operandevaluates to the operand
operandchange the sign of the operand

Limits ( Optional ) ​

The result of any operation is an expression of related type. Arithmetic operations can produce values that are outside the range of the expression's type.

Consider the following program, which multiplies two int 's and then two double 's

Compile this program and execute it inputting different values. Try some very small numbers. Try some very large numbers. When does this program give incorrect results? When it does, explain why?

Relational Expressions ​

The C language supports 6 relational operations. A relational expression evaluates a condition. It compares two values and yields 1 if the condition is true and 0 if the condition is false . The value of a relational expression is of type int . Relational expressions take one of the forms listed below:

operand operandoperands are equal
operand operandleft is greater than the right
operand operandleft is greater than or equal to the right
operand operandleft is less than the right
operand operandleft is less than or equal to the right
operand operandleft is not equal to the right

The operands may be integral types or floating-point types.

The following program, accepts two int 's and outputs 1 if they are equal; 0 otherwise:

The first conversion specifier in the format string of the last printf() corresponds to i , the second corresponds to j and the third corresponds to k .

Logical Expressions ​

The C language does not have reserved words for true or false. It interprets the value 0 as false and any other value as true. C supports 3 logical operators. Logical expressions yield 1 if the result is true and 0 if the result is false. The value of a logical expression is of type int. Logical expressions take one of the forms listed below:

operand operandboth operands are true
operand operandone of the operands is true
operandthe operand is not true

The following program, accepts three int 's and outputs 1 if the second is greater than or equal to the first and less than or equal to the third; 0 otherwise:

The conversion specifiers in the last printf() correspond to the arguments in the same order ( first to j , second to i , etc. ) .

deMorgan's Law ​

deMorgan's law is a handy rule for converting conditions in logical expressions. The law states that:

The opposite of a compound condition is the compound condition with all sub-conditions reversed, all &&'s changed to | | 's and all | | 's to &&'s.

Consider the following definition of an adult:

This definition is logically identical to:

The parentheses direct the compiler to evaluate the enclosed expression first.

By applying deMorgan's law , we can often re-write a compound condition in a more readable form.

Shorthand Assignments ​

The C language also supports shorthand operators that combine an arithmetic expression with an assignment expression. These operators store the result of the arithmetic expression in the left operand.

C has 5 binary and 2 unary shorthand assignment operators for integral ( int and char ) operands.

Binary Operands ​

The binary operators yield the same result as shown in the longhand expressions listed alongside:

ExpressionShorthandLonghandMeaning
operand operand add 4 to i and assign to i
operand operand subtract 4 from i and assign to i
operand operand multiply i by 4 and assign to i
operand operand divide i by 4 and assign to i
operand operand remainder after i / 4 and assign to i

Unary Operands ​

The unary operators yield the same result as shown in the longhand expressions listed alongside:

ExpressionShorthandLonghandMeaning
++operand increment i by 1
operand++ increment i by 1
--operand decrement i by 1
operand-- decrement i by 1

We call the unary operator that precedes its operand a prefix operator and the unary operator that succeeds its operand a postfix operator.

The difference between the prefix and postfix expressions is in the value of the expression itself. The prefix operator changes the value of its operand and sets the expression's value to be the changed value. The postfix operator sets the expression's value to the operand's original value and then changes the operand's value. In other words, the prefix operator changes the value before using it, while the postfix operator changes the value after using it.

Floating-Point Operands ​

C has 4 binary and 2 unary shorthand assignment operators for floating-point ( float and double ) operands.

The binary operators yield the same result as in the longhand expressions listed alongside:

ExpressionShorthandLonghandMeaning
operand operand add 4.1 to x and assign to x
operand operand subtract 4.1 from x and assign to x
operand operand multiply x by 4.1 and assign to x
operand operand divide x by 4.1 and assign to x
ExpressionShorthandLonghandMeaning
++operand increment i by 1.0
operand++ increment i by 1.0
--operand decrement i by 1.0
operand-- decrement i by 1.0

The prefix and postfix operators operate on floating-point operands in the same way as on integral operands.

Ambiguities ​

Compact use of shorthand operators can yield ambiguous results across different platforms. Consider the following longhand statements:

One compiler may increment the first i before the addition, while another compiler may increment i after the addition. The C language does not address this ambiguity and only stipulates that the value must be incremented before the semi-colon. To avoid ambiguity, we re-write this code to make our intent explicit:

The C language supports conversions from one type to another. To convert the type of an operand, we precede the operand with the target type enclosed within parentheses. We call such an expression a cast. Casting expressions take one of the forms listed below:

( ) version of operand
( ) version of operand
( ) version of operand
( ) version of operand
( ) version of operand
( ) version of operand
( ) version of operand
( ) version of operand

Consider the example below. To obtain the number of hours in fractional form, we cast minutes to a float type and then divide it by 60. The input and output are listed on the right:

Without the type cast, the output for the same input would have been 0.00 hours.

Mixed-Type Expressions ​

Since CPUs process integral expressions and floating-point expressions differently ( using the ALU and the FPA respectively ) , they only handle expressions with operands of the same type. For expressions with operands of different types, we need rules for converting operands of one type to another type.

The C language using the following ranking:

higher
...
...
...
...
...
...
lower

There are two distinct kinds of expressions to consider with respect to type coercion:

  • assignment expressions
  • arithmetic and relational expressions

Assignment Expressions ​

Promotion ​.

If the left operand in an assignment expression is of a higher type than the right operand, the compiler promotes the right operand to the type of the left operand. For the example below, the compiler promotes the right operand ( loonies ) to a double before completing the assignment:

Narrowing ​

If the left operand in an assignment expression is of a lower type than the right operand, the compiler truncates the right operand to the type of the left operand. For the example below, the compiler truncates the type of the right operand ( cash ) to an int :

Arithmetic and Relational Expressions ​

C compilers promote the operand of lower type in an arithmetic or relational expression to an operand of the higher type before evaluating the expression. The table below lists the type of the promoted operand.

Table of type promotion from left operand to right operand

Compound Expressions ​

A compound expression is an expression that contains an expression as one of its operands. C compilers evaluate compound expressions according to specific rules called rules of precedence. These rules define the order of evaluation of expressions based on the operators involved. C compilers evaluate the expression with the operator that has the highest precedence first.

The order of precedence, from highest to lowest, and the direction of evaluation are listed in the table below:

left to right
right to left
right to left
left to right
left to right
left to right
left to right
left to right
left to right
right to left

To change the order of evaluation, we introduce parentheses. C compilers evaluate the expressions within parentheses ( ( ) ) before applying the rules of precedence. For example:

  • Learning Outcomes
  • Introduction
  • Evaluating Expressions
  • Integral Operands
  • Binary Operations
  • Unary Operations
  • Limits (Optional)
  • deMorgan's Law
  • Binary Operands
  • Unary Operands
  • Ambiguities
  • Arithmetic and Relational Expressions
  • Compound Expressions

C Programming Tutorial

  • Assignment Operator in C

Last updated on July 27, 2020

We have already used the assignment operator ( = ) several times before. Let's discuss it here in detail. The assignment operator ( = ) is used to assign a value to the variable. Its general format is as follows:

The operand on the left side of the assignment operator must be a variable and operand on the right-hand side must be a constant, variable or expression. Here are some examples:

x = 18 // right operand is a constant y = x // right operand is a variable z = 1 * 12 + x // right operand is an expression

The precedence of the assignment operator is lower than all the operators we have discussed so far and it associates from right to left.

We can also assign the same value to multiple variables at once.

here x , y and z are initialized to 100 .

Since the associativity of the assignment operator ( = ) is from right to left. The above expression is equivalent to the following:

Note that expressions like:

x = 18 y = x z = 1 * 12 + x

are called assignment expression. If we put a semicolon( ; ) at the end of the expression like this:

x = 18; y = x; z = 1 * 12 + x;

then the assignment expression becomes assignment statement.

Compound Assignment Operator #

Assignment operations that use the old value of a variable to compute its new value are called Compound Assignment.

Consider the following two statements:

x = 100; x = x + 5;

Here the second statement adds 5 to the existing value of x . This value is then assigned back to x . Now, the new value of x is 105 .

To handle such operations more succinctly, C provides a special operator called Compound Assignment operator.

The general format of compound assignment operator is as follows:

where op can be any of the arithmetic operators ( + , - , * , / , % ). The above statement is functionally equivalent to the following:

Note : In addition to arithmetic operators, op can also be >> (right shift), << (left shift), | (Bitwise OR), & (Bitwise AND), ^ (Bitwise XOR). We haven't discussed these operators yet.

After evaluating the expression, the op operator is then applied to the result of the expression and the current value of the variable (on the RHS). The result of this operation is then assigned back to the variable (on the LHS). Let's take some examples: The statement:

is equivalent to x = x + 5; or x = x + (5); .

Similarly, the statement:

is equivalent to x = x * 2; or x = x * (2); .

Since, expression on the right side of op operator is evaluated first, the statement:

is equivalent to x = x * (y + 1) .

The precedence of compound assignment operators are same and they associate from right to left (see the precedence table ).

The following table lists some Compound assignment operators:

Operator Description
equivalent to
equivalent to
equivalent to
equivalent to

The following program demonstrates Compound assignment operators in action:

#include<stdio.h> int main(void) { int i = 10; char a = 'd'; printf("ASCII value of %c is %d\n", a, a); // print ASCII value of d a += 10; // increment a by 10; printf("ASCII value of %c is %d\n", a, a); // print ASCII value of n a *= 5; // multiple a by 5; printf("a = %d\n", a); a /= 4; // divide a by 4; printf("a = %d\n", a); a %= 2; // remainder of a % 2; printf("a = %d\n", a); a *= a + i; // is equivalent to a = a * (a + i) printf("a = %d\n", a); return 0; // return 0 to operating system }

Expected Output:

ASCII value of d is 100 ASCII value of n is 110 a = 38 a = 9 a = 1 a = 11

Load Comments

  • Intro to C Programming
  • Installing Code Blocks
  • Creating and Running The First C Program
  • Basic Elements of a C Program
  • Keywords and Identifiers
  • Data Types in C
  • Constants in C
  • Variables in C
  • Input and Output in C
  • Formatted Input and Output in C
  • Arithmetic Operators in C
  • Operator Precedence and Associativity in C
  • Increment and Decrement Operators in C
  • Relational Operators in C
  • Logical Operators in C
  • Conditional Operator, Comma operator and sizeof() operator in C
  • Implicit Type Conversion in C
  • Explicit Type Conversion in C
  • if-else statements in C
  • The while loop in C
  • The do while loop in C
  • The for loop in C
  • The Infinite Loop in C
  • The break and continue statement in C
  • The Switch statement in C
  • Function basics in C
  • The return statement in C
  • Actual and Formal arguments in C
  • Local, Global and Static variables in C
  • Recursive Function in C
  • One dimensional Array in C
  • One Dimensional Array and Function in C
  • Two Dimensional Array in C
  • Pointer Basics in C
  • Pointer Arithmetic in C
  • Pointers and 1-D arrays
  • Pointers and 2-D arrays
  • Call by Value and Call by Reference in C
  • Returning more than one value from function in C
  • Returning a Pointer from a Function in C
  • Passing 1-D Array to a Function in C
  • Passing 2-D Array to a Function in C
  • Array of Pointers in C
  • Void Pointers in C
  • The malloc() Function in C
  • The calloc() Function in C
  • The realloc() Function in C
  • String Basics in C
  • The strlen() Function in C
  • The strcmp() Function in C
  • The strcpy() Function in C
  • The strcat() Function in C
  • Character Array and Character Pointer in C
  • Array of Strings in C
  • Array of Pointers to Strings in C
  • The sprintf() Function in C
  • The sscanf() Function in C
  • Structure Basics in C
  • Array of Structures in C
  • Array as Member of Structure in C
  • Nested Structures in C
  • Pointer to a Structure in C
  • Pointers as Structure Member in C
  • Structures and Functions in C
  • Union Basics in C
  • typedef statement in C
  • Basics of File Handling in C
  • fputc() Function in C
  • fgetc() Function in C
  • fputs() Function in C
  • fgets() Function in C
  • fprintf() Function in C
  • fscanf() Function in C
  • fwrite() Function in C
  • fread() Function in C

Recent Posts

  • Machine Learning Experts You Should Be Following Online
  • 4 Ways to Prepare for the AP Computer Science A Exam
  • Finance Assignment Online Help for the Busy and Tired Students: Get Help from Experts
  • Top 9 Machine Learning Algorithms for Data Scientists
  • Data Science Learning Path or Steps to become a data scientist Final
  • Enable Edit Button in Shutter In Linux Mint 19 and Ubuntu 18.04
  • Python 3 time module
  • Pygments Tutorial
  • How to use Virtualenv?
  • Installing MySQL (Windows, Linux and Mac)
  • What is if __name__ == '__main__' in Python ?
  • Installing GoAccess (A Real-time web log analyzer)
  • Installing Isso

Codeforwin

Constant pointer and pointer to constant in C

Quick links.

  • Constant pointer
  • Pointer to constant
  • Constant pointer to constant

Pointers are the most powerful as well as complex component of C programming. For newbies, it’s like learning rocket science in C. However, I have tried my best to simplify things.

In this ongoing series of C programming tutorial, I have explained many concepts related to pointers. Here in this section we will focus on some confusing pointer terminologies. We will learn and compare constant pointer with pointer to constant and constant pointer to constant .

What is constant pointer?

To understand a constant pointer, let us recall definition of a constant variable . Constant variable is a variable whose value cannot be altered throughout the program.

Similarly, constant pointer is a pointer variable whose value cannot be altered throughout the program. It does not allows modification of its value, however you can modify the value pointed by a pointer.

In other words, constant pointer is a pointer that can only point to single object throughout the program.

Syntax to declare constant pointer

Note: You must initialize a constant pointer at the time of its declaration.

Example to declare constant pointer

Note: We use const keyword to declare a constant pointer.

The compiler will generate compilation error on failure of any of the two conditions.

  • You must initialize a constant pointer during its declaration.
  • A constant pointer must not be re-assigned.

Example program to use constant pointer

Let us write an example program to demonstrate constant pointer in C.

Let us dry run the above program.

  • First, we declared two integer variable num1 , num2 and an integer constant pointer const_ptr that points to num1 .
  • The statement *const_ptr = 10; assigns 10 to num1 .
  • Next we tried re-assignment of constant pointer i.e. const_ptr = &num2; . The statement will generate compilation error, since a constant pointer can only point to single object throughout the program.
  • The last two printf() statements are used to test value of num1 .

On compilation it generates following error message.

What is pointer to constant?

Pointer to constant is a pointer that restricts modification of value pointed by the pointer. You can modify pointer value, but you cannot modify the value pointed by pointer.

Note: There is a minor difference between constant pointer and pointer to constant. A constant pointer can only point to single object throughout the program. You can, alter the value pointed by pointer, but cannot alter pointer value. Whereas pointer to a constant cannot modify the value pointed by pointer, but can alter its value.

Syntax to declare pointer to constant

Example to declare pointer to constant, example program to use pointer to constant.

Let us demonstrate pointer to a constant using an example.

The above program generates compilation error, since we tried to assign value to read only memory location (i.e. the value pointed by the pointer). Below is the compilation error generated by *ptr_const = 100;

Note: Pointer to constant restricts modification of value pointed by the pointer. However, do not think that C compiler converts variable pointed by pointer as constant variable.

Pointer to constant does not allows you to modify the pointed value, using pointer. However, you can directly perform modification on variable (without using pointer). For example,

What is constant pointer to constant?

A constant pointer to constant is a combination of constant pointer and pointer to constant . It is a pointer that does not allow modification of pointer value as well as value pointed by the pointer.

Syntax to declare constant pointer to constant

Example to declare constant pointer to constant, example program to use constant pointer to constant.

Let us demonstrate the concept of constant pointer to constant in C program.

The above program generates two compilation error. First in the statement ptr = &num2; since we tried to assign value to a constant pointer. Second in the statement *ptr = 100; since we tried to assign value pointed by a pointer to constant.

Difference between constant pointer, pointer to constant and constant pointer to constant

Okay so got basic picture of a constant pointer, pointer to constant and constant pointer to constant. Let us summarize the things for quick recap.

Constant pointerPointer to constantConstant pointer to constant
Pointer value cannot be modifiedPointer value can be modifiedPointer value cannot be modified
Value pointed by the pointer can be modifiedValue pointed by the pointer cannot be modifiedValue pointed by the pointer cannot be modified

Constant expressions

(C++11)
(C++11)
(C++11)
General
(lvalue, rvalue, xvalue)
(sequence points)
(C++11)
Literals
including
(C++11)
(C++11)
Operators
: , , , , , , , , , ,
: , , ,
: , , , , , , , , , , , ,
: , ,
: , , , , ,
: , , , , , ,
: , , ,
(C++17)
(C++11)
(C++11)
Conversions
,

Defines an expression that can be evaluated at compile time.

Such expressions can be used as non-type template arguments, array sizes, and in other contexts that require constant expressions, e.g.

Core constant expressions Constant expression Notes See also

[ edit ] Core constant expressions

A core constant expression is any expression that does not have any one of the following in any subexpression (ignoring the unevaluated arguments of && , || , and ?: )

An expression whose result is not mathematically defined or is out of range for its type. double d1 = 2.0/1.0; // OK constexpr double d2 = 2.0/0.0; // Error: not defined constexpr int n = <int>::max() + 1; // Error: overflow (until C++14)
An expression whose evaluation leads to any form of core language (since C++17) undefined behavior (including signed integer overflow, division by zero, pointer arithmetic outside array bounds, etc). Whether standard library undefined behavior is detected is unspecified. (since C++17) (since C++14)
conversion from void* to any pointer-to-object type (since C++14)
This section is incomplete
Reason: needs more mini-examples and less standardese

[ edit ] Constant expression

  • Integral constant expression is an expression of integral or unscoped enumeration type implicitly converted to a prvalue, where the converted expression is a core constant expression. If an expression of class type is used where an integral constant expression is expected, the expression is contextually implicitly converted to an integral or unscoped enumeration type.
  • Converted constant expression is an expression implicitly converted to prvalue of type T, where the converted expression is a core constant expression, and the implicit conversion sequence contains only:
  • constexpr user-defined conversions (so a class can be used where integral type is expected)
  • lvalue-to-rvalue conversions
  • integral promotions
  • non-narrowing integral conversions
(since C++17)
  • And if any reference binding takes place, it is direct binding (not one that constructs a temporary object)
  • Literal constant expression is a prvalue core constant expression of non-pointer literal type (after conversions as required by context). A literal constant expression of array or class type requires that each subobject is initialized with a constant expression.
  • Reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function.
  • Address constant expression is a prvalue core constant expression (after conversions required by context) of type std:: nullptr_t or of a pointer type, which points to an object with static storage duration, one past the end of an array with static storage duration, to a function, or is a null pointer.

[ edit ] Notes

Implementations are not permitted to declare library functions as unless the standard says the function is (since C++14)
This section is incomplete
Reason: examples

[ edit ] See also

  • constexpr specifier
  • std:: is_literal_type
  • Todo with reason
  • C Data Types
  • C Operators
  • C Input and Output
  • C Control Flow
  • C Functions
  • C Preprocessors
  • C File Handling
  • C Cheatsheet
  • C Interview Questions

Different ways to declare variable as constant in C

There are many different ways to make the variable as constant in C. Some of the popular ones are:

  • Using const Keyword
  • Using Macros
  • Using enum Keyword

1. Using const Keyword

The const keyword specifies that a variable or object value is constant and can’t be modified at the compilation time.

The below example demonstrates use of the const keyword.

2. Using Macros

We can also use Macros to define constant, but there is a catch. Since Macros are handled by the pre-processor(the pre-processor does text replacement in our source file, replacing all occurrences of ‘var’ with the literal 5) not by the compiler. Hence it wouldn’t be recommended because Macros doesn’t carry type checking information and also prone to error. In fact not quite constant as ‘var’ can be redefined like this.

The below example demonstrates use of macros (#define).

Note: preprocessor and enum only works as a literal constant and integers constant respectively. Hence they only define the symbolic name of constant. Therefore if you need a constant variable with a specific memory address use either ‘const’ or ‘constexpr’ according to the requirement.

3. Using enum Keyword

Enumeration (or enum ) is a user defined data type in C. It is mainly used to assign names to integral constants, that make a program easy to read and maintain.

The below example demonstrates use of the enum keyword.

Note: The data types of enum are of course limited as we can see in above example.

Please Login to comment...

Similar reads.

  • C-Data Types
  • How to Get a Free SSL Certificate
  • Best SSL Certificates Provider in India
  • Elon Musk's xAI releases Grok-2 AI assistant
  • What is OpenAI SearchGPT? How it works and How to Get it?
  • Content Improvement League 2024: From Good To A Great Article

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

  • Skip to main content
  • Skip to search
  • Skip to select language
  • Sign up for free
  • Português (do Brasil)

TypeError: invalid assignment to const "x"

The JavaScript exception "invalid assignment to const" occurs when it was attempted to alter a constant value. JavaScript const declarations can't be re-assigned or redeclared.

What went wrong?

A constant is a value that cannot be altered by the program during normal execution. It cannot change through re-assignment, and it can't be redeclared. In JavaScript, constants are declared using the const keyword.

Invalid redeclaration

Assigning a value to the same constant name in the same block-scope will throw.

Fixing the error

There are multiple options to fix this error. Check what was intended to be achieved with the constant in question.

If you meant to declare another constant, pick another name and re-name. This constant name is already taken in this scope.

const, let or var?

Do not use const if you weren't meaning to declare a constant. Maybe you meant to declare a block-scoped variable with let or global variable with var .

Check if you are in the correct scope. Should this constant appear in this scope or was it meant to appear in a function, for example?

const and immutability

The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in case the content is an object, this means the object itself can still be altered. This means that you can't mutate the value stored in a variable:

But you can mutate the properties in a variable:

cppreference.com

Implicit conversions.

(C11)
Miscellaneous
General
(C11)
(C99)

When an expression is used in the context where a value of a different type is expected, conversion may occur:

Conversions take place in the following situations:

Conversion as if by assignment Default argument promotions Usual arithmetic conversions Value transformations Lvalue conversion Array to pointer conversion Function to pointer conversion Implicit conversion semantics Compatible types Integer promotions Boolean conversion Integer conversions Real floating-integer conversions Real floating-point conversions Complex type conversions Imaginary type conversions Real-complex conversions Real-imaginary conversions Complex-imaginary conversions Pointer conversions Notes References See also

[ edit ] Conversion as if by assignment

  • In the assignment operator, the value of the right-hand operand is converted to the unqualified type of the left-hand operand.
  • In scalar initialization , the value of the initializer expression is converted to the unqualified type of the object being initialized
  • In a function-call expression , to a function that has a prototype, the value of each argument expression is converted to the type of the unqualified declared types of the corresponding parameter
  • In a return statement , the value of the operand of return is converted to an object having the return type of the function

Note that actual assignment, in addition to the conversion, also removes extra range and precision from floating-point types and prohibits overlaps; those characteristics do not apply to conversion as if by assignment.

[ edit ] Default argument promotions

In a function call expression when the call is made to

Each argument of integer type undergoes integer promotion (see below), and each argument of type float is implicitly converted to the type double

Note that float and float are not promoted to double and double in this context.

(since C99)

[ edit ] Usual arithmetic conversions

The arguments of the following arithmetic operators undergo implicit conversions for the purpose of obtaining the common real type , which is the type in which the calculation is performed:

  • binary arithmetic * , / , % , + , -
  • relational operators < , > , <= , >= , == , ! =
  • binary bitwise arithmetic & , ^ , | ,
  • the conditional operator ?:
If one operand has decimal floating type, the other operand shall not have standard floating,

complex, or imaginary type.

(since C23)
  • integer or real floating type to long double
double double (since C99)
  • integer or real floating type to double
(since C99)
  • integer type to float (the only real type possible is float, which remains as-is)
  • If the types are the same, that type is the common type.
  • If the types have the same signedness (both signed or both unsigned), the operand whose type has the lesser conversion rank 1 is implicitly converted 2 to the other type.
  • If the unsigned type has conversion rank greater than or equal to the rank of the signed type, then the operand with the signed type is implicitly converted to the unsigned type.
  • If the signed type can represent all values of the unsigned type, then the operand with the unsigned type is implicitly converted to the signed type.
  • Else, both operands undergo implicit conversion to the unsigned type counterpart of the signed operand's type.

The result type is determined as follows:

z = 1 + 2*I; double f = 3.0; z + f; // z remains as-is, f is converted to double, the result is double complex
(since C99)

As always, the result of a floating-point operator may have greater range and precision than is indicated by its type (see FLT_EVAL_METHOD ).

Note: real and imaginary operands are not implicitly converted to complex because doing so would require extra computation, while producing undesirable results in certain cases involving infinities, NaNs and signed zeros. For example, if reals were converted to complex, 2.0×(3.0+i∞) would evaluate as (2.0+i0.0)×(3.0+i∞) ⇒ (2.0×3.0–0.0×∞) + i(2.0×∞+0.0×3.0) ⇒ NaN+i∞ rather than the correct 6.0+i∞. If imaginaries were converted to complex, i2.0×(∞+i3.0) would evaluate as (0.0+i2.0) × (∞+i3.0) ⇒ (0.0×∞ – 2.0×3.0) + i(0.0×3.0 + 2.0×∞) ⇒ NaN + i∞ instead of –6.0 + i∞.

(since C99)

Note: regardless of usual arithmetic conversions, the calculation may always be performed in a narrower type than specified by these rules under the as-if rule

[ edit ] Value transformations

[ edit ] lvalue conversion.

Any lvalue expression of any non-array type, when used in any context other than

  • as the operand of the address-of operator (if allowed)
  • as the operand of the pre/post increment and decrement operators .
  • as the left-hand operand of the member access (dot) operator.
  • as the left-hand operand of the assignment and compound assignment operators.
  • as the operand of sizeof

undergoes lvalue conversion : the type remains the same, but loses const / volatile / restrict -qualifiers and atomic properties, if any. The value remains the same, but loses its lvalue properties (the address may no longer be taken).

If the lvalue has incomplete type, the behavior is undefined.

If the lvalue designates an object of automatic storage duration whose address was never taken and if that object was uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

This conversion models the memory load of the value of the object from its location.

[ edit ] Array to pointer conversion

Any lvalue expression of array type , when used in any context other than

  • as the operand of the address-of operator
  • as the operand of typeof and typeof_unqual (since C23)
  • as the string literal used for array initialization

undergoes a conversion to the non-lvalue pointer to its first element.

If the array was declared register , the behavior is undefined.

[ edit ] Function to pointer conversion

Any function designator expression, when used in any context other than

undergoes a conversion to the non-lvalue pointer to the function designated by the expression.

[ edit ] Implicit conversion semantics

Implicit conversion, whether as if by assignment or a usual arithmetic conversion , consists of two stages:

[ edit ] Compatible types

Conversion of a value of any type to any compatible type is always a no-op and does not change the representation.

[ edit ] Integer promotions

Integer promotion is the implicit conversion of a value of any integer type with rank less or equal to rank of int or of a bit-field of type _Bool (until C23) bool (since C23) , int , signed int , unsigned int , to the value of type int or unsigned int .

If int can represent the entire range of values of the original type (or the range of values of the original bit-field), the value is converted to type int . Otherwise the value is converted to unsigned int .

The value from a bit-field of a bit-precise integer type is converted to the corresponding bit-precise integer type. Otherwise, bit-precise integer types are exempt from the integer promotion rules.

(since C23)

Integer promotions preserve the value, including the sign:

rank above is a property of every integer type and is defined as follows:

the rank of a bit-precise signed integer type shall be greater than the rank of any standard integer type with less width or any bit-precise integer type with less width. the rank of any bit-precise integer type relative to an extended integer type of the same width is implementation-defined. (since C23)

Note: integer promotions are applied only

  • as part of usual arithmetic conversions (see above)
  • as part of default argument promotions (see above)
  • to the operand of the unary arithmetic operators + and -
  • to the operand of the unary bitwise operator ~
  • to both operands of the shift operators << and >>

A value of any scalar type can be implicitly converted to _Bool(until C23)bool(since C23). The values that compare equal to an integer constant expression of value zero(until C23)are a zero (for arithmetic types), null (for pointer types) or have a type of (since C23) are converted to 0(until C23)false(since C23), all other values are converted to 1(until C23)true(since C23).

0.5; // b1 == 1 (0.5 converted to int would be zero) bool b2 = 2.0* ; // b2 == 1 (but converted to int would be zero) bool b3 = 0.0 + 3.0*I; // b3 == 1 (but converted to int would be zero) bool b4 = 0.0/0.0; // b4 == 1 (NaN does not compare equal to zero) bool b5 = nullptr; // b5 == 0 (since C23: nullptr is converted to false)
(since C99)

[ edit ] Integer conversions

A value of any integer type can be implicitly converted to any other integer type. Except where covered by promotions and boolean conversions above, the rules are:

  • if the target type can represent the value, the value is unchanged
  • otherwise, if the target type is unsigned, the value 2 b , where b is the number of value bits in the target type, is repeatedly subtracted or added to the source value until the result fits in the target type. In other words, unsigned integers implement modulo arithmetic.
  • otherwise, if the target type is signed, the behavior is implementation-defined (which may include raising a signal)

[ edit ] Real floating-integer conversions

A finite value of any real floating type can be implicitly converted to any integer type. Except where covered by boolean conversion above, the rules are:

  • The fractional part is discarded (truncated towards zero).
  • If the resulting value can be represented by the target type, that value is used
  • otherwise, the behavior is undefined

A value of any integer type can be implicitly converted to any real floating type.

  • if the value can be represented exactly by the target type, it is unchanged
  • if the value can be represented, but cannot be represented exactly, the result is an implementation-defined choice of either the nearest higher or nearest lower value, although if IEEE arithmetic is supported, rounding is to nearest. It is unspecified whether FE_INEXACT is raised in this case.
  • if the value cannot be represented, the behavior is undefined, although if IEEE arithmetic is supported, FE_INVALID is raised and the result value is unspecified.

The result of this conversion may have greater range and precision than its target type indicates (see FLT_EVAL_METHOD ).

If control over FE_INEXACT is needed in floating-to-integer conversions, rint and nearbyint may be used.

[ edit ] Real floating-point conversions

A value of any real floating type can be implicitly converted to any other real floating type.

  • If the value can be represented by the target type exactly, it is unchanged
  • if the value can be represented, but cannot be represented exactly, the result is the nearest higher or the nearest lower value (in other words, rounding direction is implementation-defined), although if IEEE arithmetic is supported, rounding is to nearest
This section is incomplete
Reason: check IEEE if appropriately-signed infinity is required

A value of any complex type can be implicitly converted to any other complex type. The real part and the imaginary part individually follow the conversion rules for the real floating types.

d = 0.1 + 0.1*I; float f = d; // f is (0.100000001490116119384765625, 0.100000001490116119384765625)

A value of any imaginary type can be implicitly converted to any other imaginary type. The imaginary part follows the conversion rules for the real floating types.

d = 0.1* ; float f = d; // f is 0.100000001490116119384765625*I

A value of any real floating type can be implicitly converted to any complex type.

A value of any complex type can be implicitly converted to any real floating type

Note: in complex-to-real conversion, a NaN in the imaginary part will not propagate to the real result.

z = 0.5 + 3*I; float f = z; // the imaginary part is discarded, f is set to 0.5 z = f; // sets z to 0.5 + 0*I

A value of any imaginary type can be implicitly converted to any real type (integer or floating-point). The result is always a positive (or unsigned) zero, except when the target type is _Bool(until C23)bool(since C23), in which case boolean conversion rules apply.

A value of any real type can be implicitly converted to any imaginary type. The result is always a positive imaginary zero.

z = 3*I; bool b = z; // Boolean conversion: sets b to true float f = z; // Real-imaginary conversion: sets f to 0.0 z = 3.14; // Imaginary-real conversion: sets z to 0*_Imaginary_I

A value of any imaginary type can be implicitly converted to any complex type.

A value of any complex type can be implicitly converted to any imaginary type

z = I * (3*I); // the complex result -3.0+0i loses real part // sets z to 0*_Imaginary_I
(since C99)

[ edit ] Pointer conversions

A pointer to void can be implicitly converted to and from any pointer to object type with the following semantics:

  • If a pointer to object is converted to a pointer to void and back, its value compares equal to the original pointer.
  • No other guarantees are offered

A pointer to an unqualified type may be implicitly converted to the pointer to qualified version of that type (in other words, const , volatile , and restrict qualifiers can be added). The original pointer and the result compare equal.

Any integer constant expression with value ​ 0 ​ as well as integer pointer expression with value zero cast to the type void * can be implicitly converted to any pointer type (both pointer to object and pointer to function). The result is the null pointer value of its type, guaranteed to compare unequal to any non-null pointer value of that type. This integer or void* expression is known as null pointer constant and the standard library provides one definition of this constant as the macro NULL .

[ edit ] Notes

Although signed integer overflow in any arithmetic operator is undefined behavior, overflowing a signed integer type in an integer conversion is merely unspecified behavior.

On the other hand, although unsigned integer overflow in any arithmetic operator (and in integer conversion) is a well-defined operation and follows the rules of modulo arithmetic, overflowing an unsigned integer in a floating-to-integer conversion is undefined behavior: the values of real floating type that can be converted to unsigned integer are the values from the open interval (-1; Unnn_MAX+1) .

Conversions between pointers and integers (except from pointer to _Bool (until C23) bool (since C23) and (since C99) from integer constant expression with the value zero to pointer), between pointers to objects (except where either to or from is a pointer to void) and conversions between pointers to functions (except when the functions have compatible types) are never implicit and require a cast operator .

There are no conversions (implicit or explicit) between pointers to functions and pointers to objects (including void*) or integers.

[ edit ] References

  • C23 standard (ISO/IEC 9899:2024):
  • 6.3 Conversions (p: TBD)
  • C17 standard (ISO/IEC 9899:2018):
  • 6.3 Conversions (p: 37-41)
  • C11 standard (ISO/IEC 9899:2011):
  • 6.3 Conversions (p: 50-56)
  • C99 standard (ISO/IEC 9899:1999):
  • 6.3 Conversions (p: 42-48)
  • C89/C90 standard (ISO/IEC 9899:1990):
  • 3.2 Conversions

[ edit ] See also

for Implicit conversions
  • Todo with reason
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 23 May 2024, at 04:31.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

Learn C practically and Get Certified .

Popular Tutorials

Popular examples, reference materials, learn c interactively, c introduction.

  • Getting Started with C
  • Your First C Program

C Fundamentals

C variables, constants and literals.

C Data Types

  • C Input Output (I/O)
  • C Programming Operators

C Flow Control

  • C if...else Statement
  • C while and do...while Loop
  • C break and continue
  • C switch Statement
  • C goto Statement
  • C Functions
  • C User-defined functions
  • Types of User-defined Functions in C Programming
  • C Recursion
  • C Storage Class

C Programming Arrays

  • C Multidimensional Arrays
  • Pass arrays to a function in C

C Programming Pointers

  • Relationship Between Arrays and Pointers
  • C Pass Addresses and Pointers
  • C Dynamic Memory Allocation
  • C Array and Pointer Examples
  • C Programming Strings
  • String Manipulations In C Programming Using Library Functions
  • String Examples in C Programming

C Structure and Union

  • C structs and Pointers
  • C Structure and Function

C Programming Files

  • C File Handling
  • C Files Examples

C Additional Topics

C Keywords and Identifiers

  • C Precedence And Associativity Of Operators
  • C Bitwise Operators
  • C Preprocessor and Macros
  • C Standard Library Functions

C Tutorials

C Type Conversion

List of all Keywords in C Language

In the previous tutorial you learnt about C comments . Now, let's learn about variables, constants and literals in C.

In programming, a variable is a container (storage area) to hold data.

To indicate the storage area, each variable should be given a unique name ( identifier ). Variable names are just the symbolic representation of a memory location. For example:

Here, age is a variable of int type and we have assigned an integer value 25 to it.

The value of a variable can be changed, hence the name variable.

Visit this page to learn more about different types of data a variable can store .

1. A variable name can only have letters (both uppercase and lowercase letters), digits and underscore.

2. The first letter of a variable should be either a letter or an underscore.

3. There is no rule on how long a variable name (identifier) can be. However, you may run into problems in some compilers if the variable name is longer than 31 characters.

Note: You should always try to give meaningful names to variables. For example: firstName is a better variable name than fn .

C is a strongly typed language. This means that the variable type cannot be changed once it is declared. For example:

Here, the type of number variable is int . You cannot assign a floating-point (decimal) value 5.5 to this variable. Also, you cannot redefine the data type of the variable to double . By the way, to store the decimal values in C, you need to declare its type to either double or float .

If you want to define a variable whose value cannot be changed, you can use the const keyword. This will create a constant. For example,

Notice, we have added keyword const .

Here, PI is a symbolic constant; its value cannot be changed.

You can also define a constant using the #define preprocessor directive. We will learn about it in C Macros tutorial.

Literals are data used for representing fixed values. They can be used directly in the code. For example: 1 , 2.5 , 'c' etc.

Here, 1 , 2.5 and 'c' are literals. Why? You cannot assign different values to these terms.

1. Integers

An integer is a numeric literal(associated with numbers) without any fractional or exponential part. There are three types of integer literals in C programming:

  • decimal (base 10)
  • octal (base 8)
  • hexadecimal (base 16)

For example:

In C programming, octal starts with a 0 , and hexadecimal starts with a 0x .

2. Floating-point Literals

A floating-point literal is a numeric literal that has either a fractional form or an exponent form. For example:

Note: E-5 = 10 -5

3. Characters

A character literal is created by enclosing a single character inside single quotation marks. For example: 'a' , 'm' , 'F' , '2' , '}' etc.

4. String Literals

A string literal is a sequence of characters enclosed in double-quote marks. For example:

5. Escape Sequences

Sometimes, it is necessary to use characters that cannot be typed or has special meaning in C programming. For example: newline(enter), tab, question mark etc.

In order to use these characters, escape sequences are used.

Escape Sequences Character
Backspace
Form feed
Newline
Return
Horizontal tab
Vertical tab
Backslash
Single quotation mark
Double quotation mark
Question mark
Null character

For example: \n is used for a newline. The backslash \ causes escape from the normal way the characters are handled by the compiler.

Table of Contents

  • Floating-point Literals
  • String Literals
  • Escape Sequences

Video: Variables in C Programming

Sorry about that.

Our premium learning platform, created with over a decade of experience and thousands of feedbacks .

Learn and improve your coding skills like never before.

  • Interactive Courses
  • Certificates
  • 2000+ Challenges

Related Tutorials

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Expression assigned to a wider essential type

I get the following warning from our analysis tool Composite expression assigned to a wider essential type This is the code:

I tried the following:

but that then throws this warning Shift left of signed quantity (int) so I guess I am not understanding the issue correctly. How do I fix this error?

Lundin's user avatar

  • have you tried result = (uint32_t)(1U << resolution); –  Jean-François Fabre ♦ Commented Oct 24, 2017 at 11:04
  • @Jean-FrançoisFabre Yes and that resulted in an different issue Impermissible cast of composite expression (wider essential type for the destination) –  homeGrown Commented Oct 24, 2017 at 11:05
  • what about result = 1UL << resolution; ? what is your platform? have you printed sizeof(1U) ? –  Jean-François Fabre ♦ Commented Oct 24, 2017 at 11:06
  • 1 Since 1U is unsigned int , which may not be the same as uint32_t on some platforms, try result = ((uint32_t)1) << resolution; –  Sergey Kalinichenko Commented Oct 24, 2017 at 11:07
  • @Jean-FrançoisFabre Yes that's the one that worked great thanks –  homeGrown Commented Oct 24, 2017 at 11:08

4 Answers 4

This sounds as if you are running a MISRA-C:2012 checker. Essential type and composite expression are terms from MISRA-C, not from the C standard.

In order to understand anything at all from this warning, you have to study the meaning of essential type (MISRA-C:2012 8.10) and composite expression (MISRA-C:2012 8.10.3).

As for the reason for the warning, it is rule 10.6:

The value of a composite expression shall not be assigned to an object with wider essential type.

If we ignore the meaning of all these terms, what the rule boils down to is that if you have an operation with 2 operands of a smaller type, the result should not get assigned to a variable of larger type than those operands.

This is to prevent code like this:

On a 16 bit system, the operands a and b will not get promoted, so the actual operation will get carried out on 16 bit type - and there will be an unsigned wrap-around (or overflow in case of signed variables).

Confused programmers that don't understand how implicit type promotions work in C might think that the above operation gets carried out on uint32_t just because the result is stored in such a type. But this is not correct, the left-hand side of the assignment operator has nothing to do with the sub-expression a + b what-so-ever. Which type that gets used in sub-expressions is entirely determined by operator precedence, and = has lower precedence than + .

Apparently MISRA-C believes that such misunderstandings are common, which is the rationale for this rule.

As for how to fix it, it is easy:

  • Thanks very much for the detailed response and explaining the rational behind the rule. –  homeGrown Commented Oct 24, 2017 at 16:15

This happens because 1U does not match uint32_t type. Use UINT32_C(...) macro to ensure type compatibility:

Sergey Kalinichenko's user avatar

  • The UINT32_C macro is actually problematic to use with MISRA-C - which this is. Because MISRA-C does not regard UINT32_C(1) as an integer constant, it only regards 1 as one and it demands that all integer constants must have a 1U suffix. But if you would write UINT32_C(1U) , the compiler will go bananas. And to be picky UINT32_C actually gives a type of uint_least32_t and not uint32_t . A better solution would be to use (uint32_t)1U . –  Lundin Commented Oct 24, 2017 at 15:25

On your system 1U is probably 16-bit unsigned (which explains the "wider type" when trying to assign to 32-bit unsigned).

In that case, I would use the long suffix for the literal:

(some comments suggest ((uint32_t)1U) << resolution which would be the most portable way after all)

Jean-François Fabre's user avatar

  • ((uint32_t)1) << resolution indeed is better. [unsigned] long is 64 bits in the LP64 data model used on most Unix/Linux systems. –  Andrew Henle Commented Oct 24, 2017 at 15:26
  • To be MISRA compliant (the question is about MISRA-C), use (uint32_t)1U . –  Lundin Commented Oct 24, 2017 at 15:26

1U may be narrower (16-bit) than uint32_t and therefore "Composite expression assigned to a wider essential type". A shift of a 16-bit unsigned by 20 does not make 0x100000,

The narrow-ness of resolution is not an issue here.

How do I fix this error?

I prefer to avoid casting when able and offer 2 alternatives. Both effectively first make a 1 of the destination type without casting. The compiler will certainly emit optimized code.

chux - Reinstate Monica's user avatar

  • The error is a MISRA error though, so non-compliant code won't solve anything. The compound assignment is ok for MISRA but not the second alternative. Plus, you need to use U suffix on all integer constants, regardless of how wide int happens to be. –  Lundin Commented Oct 25, 2017 at 8:36
  • @Lundin Concerning appending U , would uint16_t a = 40000; and/or result = 1; generate a MISRA warning/error? –  chux - Reinstate Monica Commented Oct 25, 2017 at 14:43
  • Yes it would, MISRA is rather rigid when it comes to integer constants. –  Lundin Commented Oct 26, 2017 at 6:36

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c lint misra or ask your own question .

  • The Overflow Blog
  • Where does Postgres fit in a world of GenAI and vector databases?
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites
  • What does a new user need in a homepage experience on Stack Overflow?
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • Staging Ground Reviewer Motivation

Hot Network Questions

  • Is there a phrase for someone who's really bad at cooking?
  • Why there is no article after 'by'?
  • Are carbon fiber parts riveted, screwed or bolted?
  • Do metal objects attract lightning?
  • Dress code for examiner in UK PhD viva
  • Completely introduce your friends
  • Does the Greek used in 1 Peter 3:7 properly translate as “weaker” and in what way might that be applied?
  • Why was this lighting fixture smoking? What do I do about it?
  • How much payload could the Falcon 9 send to geostationary orbit?
  • If inflation/cost of living is such a complex difficult problem, then why has the price of drugs been absoultly perfectly stable my whole life?
  • Stuck on Sokoban
  • Manifest Mind vs Shatter
  • How do we reconcile the story of the woman caught in adultery in John 8 and the man stoned for picking up sticks on Sabbath in Numbers 15?
  • Correct Expression for Centripetal Force
  • Why is PUT Request not allowed by default in OWASP CoreRuleSet
  • My visit is for two weeks but my host bought insurance for two months is it okay
  • Purpose of burn permit?
  • Are quantum states like the W, Bell, GHZ, and Dicke state actually used in quantum computing research?
  • How can judicial independence be jeopardised by politicians' criticism?
  • How does the summoned monster know who is my enemy?
  • Integral concerning the floor function
  • `Drop` for list of elements of different dimensions
  • How would you say a couple of letters (as in mail) if they're not necessarily letters?
  • DATEDIFF Rounding

assignment to constant expression c

IMAGES

  1. What is constant expression in C?

    assignment to constant expression c

  2. Constant Expressions in C++

    assignment to constant expression c

  3. [Solved] C++ expected constant expression

    assignment to constant expression c

  4. Programming Univbasics Expression And...

    assignment to constant expression c

  5. Mastering C++ Standard Library Features : Constant Expressions

    assignment to constant expression c

  6. Solved c. Identify the equilibrium constant expression in

    assignment to constant expression c

VIDEO

  1. Lec

  2. Complete the following solubility constant expression for PbCrO4

  3. Writing Equilibrium Constant Expression of a Weak Acid

  4. Assignment Operator in C Programming

  5. Augmented assignment operators in C

  6. Non-Constant Growth Stock Valuation

COMMENTS

  1. Details of what constitutes a constant expression in C?

    9. C defines at least 3 levels of "constant expression": constant expression (unqualified) arithmetic constant expression. integer constant expression. 6.6 paragraph 3 reads: Constant expressions shall not contain assignment, increment, decrement, function-call, or comma operators, except when they are contained within a subexpression that is ...

  2. Constant expressions

    Integer constant expression. An integer constant expression is an expression that consists only of operators other than assignment, increment, decrement, function-call, or comma, except that cast operators can only cast arithmetic types to integer types unless they are part of an operand to a sizeof, _Alignof (since C11) or typeof/typeof_unqual (since C23) operator.

  3. C Constant Expressions

    An integral constant expression must be used to specify the size of a bit-field member of a structure, the value of an enumeration constant, the size of an array, or the value of a case constant. Constant expressions used in preprocessor directives are subject to several restrictions. They're known as restricted constant expressions.

  4. What is the result of an assignment expression in C?

    1. This is an infinite loop. It first assign 10 to c, then compare it with c > 0, then again loop starts, assign 10 to c, compare it with c>0 and so on. Loop never ends. This is equivalent to the following: while(c=10); /* Because c assign a garbage value, but not true for all cases maybe it assign 0 */. while(c);

  5. Constants in C Explained

    How to Use #define to Define Constants in C. One of the common ways to define constants in C is to use the #define preprocessor directive, as shown below: #define <VAR_NAME> <VALUE>. In the above syntax: <VAR_NAME> is a placeholder for the name of the constant. It's recommended that you name constants in the uppercase, as it helps differentiate ...

  6. Constant expressions

    An address constant expression is a prvalue core constant expression (after conversions required by context) of type std::nullptr_t or of a pointer type, which points to an object with static storage duration, one past the end of an array with static storage duration, to a function, or is a null pointer.

  7. Assignment Expressions (GNU C Language Manual)

    7 Assignment Expressions. As a general concept in programming, an assignment is a construct that stores a new value into a place where values can be stored—for instance, in a variable. Such places are called lvalues (see Lvalues) because they are locations that hold a value. An assignment in C is an expression because it has a value; we call it an assignment expression.

  8. Expressions

    Introduction. Programming languages support operators that combine variables and constants into expressions for transforming existing data into new data. These operators take one or more operands. The operands may be variables, constants or other expressions. The C language supports a comprehensive set of these operators for arithmetic ...

  9. Assignment Operator in C

    The assignment operator ( = ) is used to assign a value to the variable. Its general format is as follows: variable = right_side. The operand on the left side of the assignment operator must be a variable and operand on the right-hand side must be a constant, variable or expression. Here are some examples:

  10. Assignment operators

    Assignment performs implicit conversion from the value of rhs to the type of lhs and then replaces the value in the object designated by lhs with the converted value of rhs . Assignment also returns the same value as what was stored in lhs (so that expressions such as a = b = c are possible). The value category of the assignment operator is non ...

  11. Assignment and shorthand assignment operator in C

    Shorthand assignment operator combines one of the arithmetic or bitwise operators with assignment operator. For example, consider following C statements. int a = 5; a = a + 2; The above expression a = a + 2 is equivalent to a += 2. Similarly, there are many shorthand assignment operators. Below is a list of shorthand assignment operators in C.

  12. Constant pointer and pointer to constant in C

    First in the statement ptr = &num2; since we tried to assign value to a constant pointer. Second in the statement *ptr = 100; since we tried to assign value pointed by a pointer to constant. constantpointerconstant.c: In function 'main': constantpointerconstant.c:14:9: error: assignment of read-only variable 'ptr'.

  13. Constants in C

    Constants in C. The constants in C are the read-only variables whose values cannot be modified once they are declared in the C program. The type of constant can be an integer constant, a floating pointer constant, a string constant, or a character constant. In C language, the const keyword is used to define the constants.

  14. Constant expressions

    16) an increment or a decrement operator. 17) a typeid expression applied to a glvalue of polymorphic type. 18) a new-expression or a delete-expression. 19) a subtraction operator between two pointers. 20) an equality or relational operator when the result is unspecified. 21) an assignment or a compount assignment operator.

  15. Different ways to declare variable as constant in C

    There are many different ways to make the variable as constant in C. Some of the popular ones are: Using const Keyword. Using Macros. Using enum Keyword. 1. Using const Keyword. The const keyword specifies that a variable or object value is constant and can't be modified at the compilation time. Syntax.

  16. TypeError: invalid assignment to const "x"

    The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in case the content is an object, this means the object itself can still be altered. This means that you can't mutate the value stored in a variable: js.

  17. Implicit conversions

    Conversion as if by assignment. In the assignment operator, the value of the right-hand operand is converted to the unqualified type of the left-hand operand.; In scalar initialization, the value of the initializer expression is converted to the unqualified type of the object being initialized ; In a function-call expression, to a function that has a prototype, the value of each argument ...

  18. C Variables, Constants and Literals

    For example: Decimal: 0, -9, 22 etc. Octal: 021, 077, 033 etc. Hexadecimal: 0x7f, 0x2a, 0x521 etc. In C programming, octal starts with a 0, and hexadecimal starts with a 0x. 2. Floating-point Literals. A floating-point literal is a numeric literal that has either a fractional form or an exponent form. For example:

  19. Receiving 'Expression being assigned must be constant' when it is

    17. Unfortunately, if you are using the const keyword the value on the right side of the '=' must be a compile-time constant. Using a "string".length requires .NET code to execute which can only occur when the application is running, not during compile time. You can consider making the field readonly rather than a const.

  20. c

    Then, correcting the data type, considering the char array is used, In the first case, arr = "Hello"; is an assignment, which is not allowed with an array type as LHS of assignment. OTOH, char arr[10] = "Hello"; is an initialization statement, which is perfectly valid statement. edited Oct 28, 2022 at 14:48. knittl.

  21. c

    1U may be narrower (16-bit) than uint32_t and therefore "Composite expression assigned to a wider essential type". A shift of a 16-bit unsigned by 20 does not make 0x100000, uint32_t result; uint8_t resolution; result = 1U << resolution; // Potential 16-bit assignment to a 32-bit type. The narrow-ness of resolution is not an issue here.