Studio:Scl union
The scl_union pragma
Unions are C language constructs that have a set of members, of which at most one can be stored in the union object at any time. The stored member is called the "active" member. The scl_union pragma identifies which union member is the active member when a union is part of a payload.
Syntax
#pragma scl_union(union-name, active-index) #pragma scl_union(union-name, discriminant-specification) #pragma scl_union(parent-name, union-name, active-index) #pragma scl_union(parent-name, union-name, discriminant-specification)
Parameters | Type | Description |
parent-name | String | Name of structure encapsulating the union |
union-name | String | Name of the union |
active-index | Integer | Zero-based index for the active overlay |
discriminant-name | String | Field name indicating the active overlay |
Notes
For each union that is part of a message or function, there must be a means to determine which member is active. There are two basic methods for identification of the active member:
- One union member is designated as always active. The union will be treated as if this member is permanently active, there is no discriminant, nor any way to change the active member.
- A secondary field is designated as the discriminant and its value determines which (if any) of the union members are active.
Discriminants
Unions within the source code are easily identified by the "union" keyword. As discriminants are not easy to identify, the scl_union() pragma is necessary to identify them. The scl_union_activate() pragma is optionally used to define a mapping between discriminant values and union members.
Within a discriminated union, the discriminant value determines the active member of the union, resulting in a mapping between discriminant values and union members. A number of mapping choices are supported:
- In the simplest mapping, a discriminant value of n directly identifies the nth union member as active. In other words, a value of 0 would indicate the first union member, a value of 1 would indicate the second, etc.
- If the discriminant is an enumerated type, it is possible to set up an association between enumeration constants and active members such that the nth enumeration constant (in declared order, not value order) maps to the nth union member.
- It is also possible to create an explicit map between discriminant value sets and active members by specifying that a particular value or set of values maps to a specific member.
The following constraints are enforced for the mapping between discriminant values and union members:
- A particular discriminant value may map only to a single union member.
- A particular field may act as a discriminant for more than one union
- A single union may only have a single discriminant field.
- The type of the discriminant field must be an integer or enumerated type or must have been cast (using scl_cast()) to an integer or enumerated type.
- Any scl_values() pragma applied to the discriminant field affects the default mapping between discriminant values and union members.
Default Mapping
As mentioned previously, the scl_union() pragma is used to identify the discriminant for a union and scl_union_activate() is used to map discriminant values to union members. If there are no scl_union_activate() pragmas for a particular discriminated union, then the mapping between the discriminant and members is said to be default. The default mapping depends on the type of the discriminant:
- If the discriminant is one of the standard integer types, or has been cast to one of the standard integer types using scl_cast(), then the value of the discriminant identifies the position of the active member; i.e., a value of 0 indicates the first union member, a value of 1 the second, etc.
- If the discriminant is an enumerated type or has been cast to an enumerated type, or has had a set of constant values prescribed using scl_values(), then each constant has both a value and a position within the list. It is the position, rather than the value, that identifies the active member. When the discriminant takes on the value of the constant from position n, the nth union member is active. In the case of two constants from the same list have the same value, but different positions, an error is recognized.
Explicit Mappings
A union that has at least one scl_union_activate() pragma applied to it is said to have an explicit mapping. When a union has an explicit mapping, there is no default mapping; rather all mapping between discriminant values and union members is prescribed by the set of scl_union_activate() pragmas for the unions. For more details on using scl_union_activate(), click here.
Internal and External Discriminants
A union’s discriminant is either internal or external. A union has an external discriminant if the discriminant field is not contained within the union.
An internal discriminant is one that is located inside the union. If a union has an internal discriminant the following must be true:
- Every member of the union must have a field that corresponds to the internal discriminant. All such fields must be of exactly the same type, or they must have had exactly the same scl_cast() or scl_values() specifications applied. Furthermore, all such fields must be positioned in exactly the same memory location within the union. If they are located in a payload block other than the one containing the union, then the expression "path" leading to each must be the same in the sense that all corresponding pointers across all the members have exactly the same offsets.
For additional information on scl_union, including constraints, refer to the section on scl_union in the [SCL Reference Guide].