3.2.2. C and C++ language extensions

This section describes the extensions to both the ANSI C language, and the ISO/IEC C++ language that are accepted by the compilers. See C language extensions for those extensions that apply only to C. None of these extensions are available if the compiler is restricted to compiling strict ANSI C or strict ISO/IEC C++. This is the case, for example, when the -strict compiler option is specified.

Identifiers

The $ character is a legal character in identifiers.

Void returns and arguments

Any void type, including a typedef to void, is permitted as the return type in a function declaration, or the indicator that a function takes no argument. For example, the following is permitted:

typedef void VOID;
int fn(VOID);       // Error in -strict C and C++
VOID fn(int x);     // Error in -strict C

long long

ARM C and C++ compilers support 64-bit integer types through the type specifier long long and unsigned long long. They behave analogously to long and unsigned long with respect to the usual arithmetic conversions. long long is a synonym for __int64.

Integer constants can have:

  • an ll suffix to force the type of the constant to long long, if it fits, or to unsigned long long if it does not fit

  • an llu (or ull) suffix to force the type of the constant to unsigned long long.

Format specifiers for printf() and scanf() can include ll to specify that the following conversion applies to a long long argument, as in %lld or %llu.

Also, a plain integer constant is of type long long or unsigned long long if its value is large enough. There is a warning message from the compiler indicating the change. For example, in strict ANSI C 2147483648 has type unsigned long. In ARM C and C++ it has the type long long. One consequence of this is the value of an expression such as:


2147483648 > –1 

is 0 in strict C and C++, and 1 in ARM C and C++.

The following restrictions apply to long long:

  • long long enumerators are not available.

  • The controlling expression of a switch statement cannot have (unsigned) long long type. Consequently case labels must also have values that can be contained in a variable of type unsigned long.

Inline assembler

The ARM C++ compilers support the syntax in the ISO/IEC C++ standard, with the restriction that the string-literal must be a single string, for example:

asm("instruction[;instruction]");

The asm declaration must be inside a C++ function. You cannot include comments in the string literal.

The ARM C and C++ compilers also support an extended inline assembler syntax, introduced by the asm keyword (C++), or the __asm keyword (C and C++).

The inline assembler is invoked with the assembler specifier, and is followed by a list of assembler instructions inside braces, for example:

__asm
{
    instruction [; instruction]
    ...
    [instruction]
}

If two instructions are on the same line, you must separate them with a semicolon. If an instruction requires more than one line, line continuation must be specified with the backslash character \. You can use C or C++ comments anywhere within an inline assembly language block.

You can use an asm or __asm statement anywhere a statement is expected.

The ARM compilers support the full ARM instruction set, including generic coprocessor instructions, but not BX and BLX.

The Thumb compilers support the full Thumb instruction set except for BX and BLX. Using inline Thumb assembly routines, however, is deprecated and generates a warning message.

See the chapter on Mixing C, C++, and assembly language in the ADS Developer Guide for more information on inline C and C++ assemblers.

Keywords

ARM implements some keyword extensions for functions and variables. See:

Hexadecimal floating-point constants

ARM implements an extension to the syntax of numeric constants in C to enable explicit specification of floating-point constants as IEEE bit patterns. The syntax is:

0f_n

Interpret an 8-digit hex number n as a float.

0d_nn

Interpret a 16-digit hex number nn as a double.

There must be exactly eight digits for float constants. There must be exactly 16 digits for double constants.

Read/write constants

For C++ only, a linkage specification for external constants indicates that a constant can be dynamically initialized or have mutable members.

Note

The use of "C++:read/write" linkage is only necessary for code compiled /ropi or /rwpi. If you recompile existing code with either of these options, you must change the linkage specification for external constants that are dynamically initialized or have mutable members.

Compiling C++ with either the /ropi or /rwpi options deviates from the C++ standard. The declarations in Example 3.5 assume that x is in a read-only segment.

Example 3.5. External access

extern const T x;
extern "C++" const T x;
extern "C" const T x;

Dynamic initialization of x (including user-defined constructors) is not possible for the constants and T cannot contain mutable members. The new linkage specification in Example 3.6 declares that x is in a read/write segment (even if it was initialized with a constant). Dynamic initialization of x is allowed and T can contain mutable members. The definitions of x, y, and z in another file must have the same linkage specifications.

Example 3.6. Linkage specification

extern const int z;      /* in read-only segment, cannot  */	
                         /* be dynamically initialized    */	
extern "C++:read/write" const int y; /* in read/write segment */	
                         /* can be dynamically initialized */	
extern "C++:read/write" {	
  const int i=5;         /* placed in read-only segment, */	
                         /* not extern because implicitly static */	
  extern const T x=6;    /* placed in read/write segment */	
  struct S {	
     static const T T x; /* placed in read/write segment */	
  };	
}

Constant objects must not be redeclared with another linkage. The code in Example 3.7 produces a compile error.

Example 3.7. Compiler error

extern "C++"  const T x;
extern "C++:read/write"  const T x; /* error */

Note

Because C does not have the linkage specifications, you cannot use a const object declared in C++ as extern "C++:read/write" from C.

Copyright © 1999-2001 ARM Limited. All rights reserved.ARM DUI 0067D
Non-Confidential