int x; // x is an int int* x; // x is a pointer to int int** x; // x is a pointer to a pointer to int int[] x; // x is an array of ints int*[] x; // x is an array of pointers to ints int[]* x; // x is a pointer to an array of intsArrays, when lexically next to each other, read right to left:
int[3] x; // x is an array of 3 ints int[3][5] x; // x is an array of 3 arrays of 5 ints int[3]*[5] x; // x is an array of 5 pointers to arrays of 3 intsPointers to functions are declared as subdeclarations:
int (*x)(char); // x is a pointer to a function taking a char argument // and returning an int int (*[] x)(char); // x is an array of pointers to functions // taking a char argument and returning an intC-style array declarations, where the [] appear to the right of the identifier, may be used as an alternative:
int x[3]; // x is an array of 3 ints int x[3][5]; // x is an array of 3 arrays of 5 ints int (*x[5])[3]; // x is an array of 5 pointers to arrays of 3 intsIn a declaration declaring multiple declarations, all the declarations must be of the same type:
int x,y; // x and y are ints int* x,y; // x and y are pointers to ints int x,*y; // error, multiple types int[] x,y; // x and y are arrays of ints int x[],y; // error, multiple types
alias abc.Foo.bar myint;Aliased types are semantically identical to the types they are aliased to. The debugger cannot distinguish between them, and there is no difference as far as function overloading is concerned. For example:
alias int myint; void foo(int x) { . } void foo(myint m) { . } error, multiply defined function fooType aliases are equivalent to the C typedef.
typedef int myint; void foo(int x) { . } void foo(myint m) { . } . myint b; foo(b); // calls foo(myint)
struct ABC x;are not allowed, replace with:
ABC x;
[Note: perhaps we should do away with unions entirely, or at least unions that contain pointers.]
struct X { int a; int b; int c; int d = 7;} static X x = { a:1, b:2}; // c is set to 0, d to 7 static X z = { c:4, b:5, a:2 , d:5}; // z.a = 2, z.b = 5, z.c = 4, d = 5
union U { int a; double b; } static U u = { b : 5.0 }; // u.b = 5.0Other members of the union that overlay the initializer, but occupy more storage, have the extra storage initialized to zero.
enum identifier { EnumMembers }Enums, of course, replace the usual use of #define macros to define constants. Enums can be either anonymous, in which case they simply define integral constants, or they can be named, in which case they introduce a new type.
enum { A, B, C };Defines the constants A=0, B=1, C=2 in a manner equivalent to:
const int A = 0; const int B = 1; const int C = 2;Whereas:
enum X { A, B, C };Define a new type X which has values X.A=0, X.B=1, X.C=2
Named enum members can be implicitly cast to integral types, but integral types cannot be implicitly cast to an enum type.
Enums must have at least one member.
.min Smallest value of enum .max Largest value of enum .size Size of storage for an enumerated value For example: X.min is X.A X.max is X.C X.size is same as int.size
VersionSpecification version = Identifier ; version = Integer ;Version specifications do not declare any symbols, but instead set a version in the same manner that the -version does on the command line. The version specification is used for conditional compilation with version attributes and version statements.
The version specification makes it straightforward to group a set of features under one major version, for example:
version (ProfessionalEdition) { version = FeatureA; version = FeatureB; version = FeatureC; } version (HomeEdition) { version = FeatureA; } ... version (FeatureB) { ... implement Feature B ... }