Skip to main content

A 7 17 Assignment Expressions

This page is a generated reference surface for selective reading. It exists to keep the learner apps guide-first while still preserving source access.

Learning objectives

  • Explain the main ideas and vocabulary in A 7 17 Assignment Expressions.
  • Work through the source examples for A 7 17 Assignment Expressions without depending on raw chunk order.
  • Use A 7 17 Assignment Expressions as selective reference when learner modules point back to The C Programming Language.

Prerequisites

  • None curated yet.

Module targets

  • module-01-c-programming-fundamentals

AI companion modes

  • Explain simply
  • Socratic tutor
  • Quiz me
  • Challenge my understanding
  • Diagnose my confusion
  • Generate extra practice
  • Revision mode
  • Connect forward / backward

Source-of-truth note

This unit is anchored to The C Programming Language and the source chapter "A 7 17 Assignment Expressions". Use external resources only to clarify, extend, or modernize details without replacing the chapter's conceptual spine.

External enrichment

No chapter-specific enrichment resources are curated yet. Add them in the unit manifest when a source clearly improves learning.

Source provenance

  • Primary source: The C Programming Language
  • Source chapter: A 7 17 Assignment Expressions
  • Raw source file: 068-a-7-17-assignment-expressions.md

Merged source

A 7 17 Assignment Expressions

A.7.17 Assignment Expressions

There are several assignment operators; all group right-to-left.

assignment-expression:

conditional-expression unary-expression assignment-operator assignment-expression assignment-operator: one of

= *= /= %= += -= <<= >>= &= ^= |=

All require an lvalue as left operand, and the lvalue must be modifiable: it must not be an array, and must not have an incomplete type, or be a function. Also, its type must not be qualified with const; if it is a structure or union, it must not have any member or, recursively, submember qualified with const. The type of an assignment expression is that of its left operand, and the value is the value stored in the left operand after the assignment has taken place.

In the simple assignment with=, the value of the expression replaces that of the object referred

to by the lvalue. One of the following must be true: both operands have arithmetic type, in which case the right operand is converted to the type of the left by the assignment; or both operands are structures or unions of the same type; or one operand is a pointer and the other is a pointer to void, or the left operand is a pointer and the right operand is a constant expression with value 0; or both operands are pointers to functions or objects whose types are the same except for the possible absence ofconstorvolatilein the right operand.

An expression of the formE1 op= E2is equivalent to E1 = E1 op (E2)except that E1is

evaluated only once.

A.7.18 Comma Operator expression:

assignment-expression expression,assignment-expression

A pair of expressions separated by a comma is evaluated left-to-right, and the value of the left expression is discarded. The type and value of the result are the type and value of the right operand. All side effects from the evaluation of the left-operand are completed before beginning the evaluation of the right operand. In contexts where comma is given a special meaning, for example in lists of function arguments (Par.A.7.3.2) and lists of initializers (Par.A.8.7), the required syntactic unit is an assignment expression, so the comma operator appears only in a parenthetical grouping, for example,

f(a, (t=3, t+2), c)

has three arguments, the second of which has the value 5.

A.7.19 Constant Expressions

Syntactically, a constant expression is an expression restricted to a subset of operators:

constant-expression:

conditional-expression

Expressions that evaluate to a constant are required in several contexts: after case, as array bounds and bit-field lengths, as the value of an enumeration constant, in initializers, and in certain preprocessor expressions.

Constant expressions may not contain assignments, increment or decrement operators, function calls, or comma operators; except in an operand of sizeof. If the constant expression is required to be integral, its operands must consist of integer, enumeration, character, and floating constants; casts must specify an integral type, and any floating constants must be cast to integer. This necessarily rules out arrays, indirection, address-of, and structure member operations. (However, any operand is permitted forsizeof.)

More latitude is permitted for the constant expressions of initializers; the operands may be any type of constant, and the unary&operator may be applied to external or static objects, and to external and static arrays subscripted with a constant expression. The unary &operator can also be applied implicitly by appearance of unsubscripted arrays and functions. Initializers must evaluate either to a constant or to the address of a previously declared external or static object plus or minus a constant.

Less latitude is allowed for the integral constant expressions after #if; sizeofexpressions, enumeration constants, and casts are not permitted. See Par.A.12.5.

A.8 Declarations

Declarations specify the interpretation given to each identifier; they do not necessarily reserve storage associated with the identifier. Declarations that reserve storage are called definitions.

Declarations have the form declaration:

declaration-specifiers init-declarator-listopt;

The declarators in the init-declarator list contain the identifiers being declared; the declarationspecifiers consist of a sequence of type and storage class specifiers.

declaration-specifiers:

storage-class-specifier declaration-specifiersopt type-specifier declaration-specifiersopt type-qualifier declaration-specifiersopt init-declarator-list:

init-declarator init-declarator-list,init-declarator init-declarator:

declarator

declarator=initializer

Declarators will be discussed later (Par.A.8.5); they contain the names being declared. A declaration must have at least one declarator, or its type specifier must declare a structure tag, a union tag, or the members of an enumeration; empty declarations are not permitted.

A.8.1 Storage Class Specifiers

The storage class specifiers are:

storage-class specifier:

auto register static extern typedef

The meaning of the storage classes were discussed in Par.A.4.4.

Theautoandregisterspecifiers give the declared objects automatic storage class, and may be used only within functions. Such declarations also serve as definitions and cause storage to be reserved. A registerdeclaration is equivalent to an autodeclaration, but hints that the declared objects will be accessed frequently. Only a few objects are actually placed into registers, and only certain types are eligible; the restrictions are implementation-dependent.

However, if an object is declared register, the unary &operator may not be applied to it, explicitly or implicitly.

The rule that it is illegal to calculate the address of an object declared register, but actually taken to beauto, is new.

Thestaticspecifier gives the declared objects static storage class, and may be used either inside or outside functions. Inside a function, this specifier causes storage to be allocated, and serves as a definition; for its effect outside a function, see Par.A.11.2.

A declaration with extern, used inside a function, specifies that the storage for the declared objects is defined elsewhere; for its effects outside a function, see Par.A.11.2.

Thetypedefspecifier does not reserve storage and is called a storage class specifier only for syntactic convenience; it is discussed in Par.A.8.9.

At most one storage class specifier may be given in a declaration. If none is given, these rules are used: objects declared inside a function are taken to be auto; functions declared within a function are taken to beextern; objects and functions declared outside a function are taken to bestatic, with external linkage. See Pars. A.10-A.11.

A.8.2 Type Specifiers

The type-specifiers are type specifier:

void char short int long float double signed unsigned struct-or-union-specifier enum-specifier typedef-name

At most one of the wordslongorshortmay be specified together withint; the meaning is the same ifintis not mentioned. The wordlongmay be specified together withdouble. At most one ofsignedor unsignedmay be specified together withintor any of its shortor longvarieties, or with char. Either may appear alone in which case intis understood. The signed specifier is useful for forcing char objects to carry a sign; it is permissible but redundant with other integral types.

Otherwise, at most one type-specifier may be given in a declaration. If the type-specifier is missing from a declaration, it is taken to beint.

Types may also be qualified, to indicate special properties of the objects being declared.

type-qualifier:

const volatile

Type qualifiers may appear with any type specifier. Aconstobject may be initialized, but not thereafter assigned to. There are no implementation-dependent semantics for volatile objects.

Theconstandvolatileproperties are new with the ANSI standard. The purpose ofconstis to announce objects that may be placed in read-only memory, and perhaps to increase opportunities for optimization. The purpose ofvolatileis to force an implementation to suppress optimization that could otherwise occur. For example, for a machine with memory-mapped input/output, a pointer to a device register might be declared as a pointer to volatile, in order to prevent the compiler from removing apparently redundant references through the pointer. Except that it should diagnose explicit attempts to changeconstobjects, a compiler may ignore these qualifiers.

A.8.3 Structure and Union Declarations

A structure is an object consisting of a sequence of named members of various types. A union is an object that contains, at different times, any of several members of various types. Structure and union specifiers have the same form.

struct-or-union-specifier:

struct-or-union identifieropt{struct-declaration-list}

struct-or-union identifier struct-or-union:

struct union

A struct-declaration-list is a sequence of declarations for the members of the structure or union:

struct-declaration-list:

struct declaration struct-declaration-list struct declaration

struct-declaration: specifier-qualifier-list struct-declarator-list;

specifier-qualifier-list:

type-specifier specifier-qualifier-listopt type-qualifier specifier-qualifier-listopt struct-declarator-list:

struct-declarator struct-declarator-list,struct-declarator

Usually, a struct-declarator is just a declarator for a member of a structure or union. A structure member may also consist of a specified number of bits. Such a member is also called abit-field; its length is set off from the declarator for the field name by a colon.

struct-declarator:

declarator declaratoropt :constant-expression