(That's C divided-by divided-by. C-- was already taken.)
C// is a simple language based on C (though valid C// programs aren't necessarily valid C programs). Due to it being based on C and compiling to C, many behaviors that are undefined or unspecified in C are also undefined or unspecified in C//.
C// accepts both types of C++ comments (//
and /* */
). Identifiers are sequences of characters that can contain letters, underscores, and digits, and cannot start with a digit. The following words are reserved and cannot be used as identifiers: struct
, int
, void
, if
, else
, while
, return
C// has two built-in types: void
and int
. void
can only be used as a return type of a function, and indicates that the function doesn't return anything. int
is a signed machine integer; if this overflows, behavior is undefined.
Structures can be defined the same way as in C:
struct name_of_struct { // variable declarations go here int x; int y; };
Variable declarations cannot be combined (like int x, y;
). The semicolon at the end of the struct definition is optional. Once a struct is defined, it can be used as a type, but it must always be preceded by the keyword struct
(so, struct MyStruct var;
, not MyStruct var;
). There are no typedefs in C//.
Variables of structure types are always passed by value. If a struct
-typed variable is passed to a function or copied to another variable, no changes made to either structure will be visible in the other structure. Implementations may decide, as an optimization, to pass structure values by reference instead of by value, as long as this does not change the behavior of the program (aside from memory usage and speed). For instance, the following code will print 1:
struct s {int x;}; void do_something(struct s var) { var.x = 2; // does not modify var1 } int main() { struct s var1; struct s var2; var1.x = 1; do_something(var1); var2 = var1; var2.x = 3; // does not modify var1 print(var1.x); return 0; }
Structures must be defined before they're used in other structures or in function arguments and return values.
Functions are defined like they are in C:
type funciton_name(type1 arg1, type2 arg2) { statements }
Functions may have any number of parameters. Functions cannot and do not need to have prototypes; functions defined anywhere in the file can call functions defined anywhere else in the file. If the return type is not void
, the function must execute a 'return' statement before leaving the body; if it does not, the result is undefined.
The following statements exist, with the same semantics as C unless otherwise specified:
{ statements }
type name;
type name = expression;
lvalue = expression;
foo().x
is not a valid lvalue). Compound assignment operators are not supported.if(condition) statement
if(condition) statement else statement
while(condition) statement
return expression;
void
return;
void
expression;
The following types of expression exist:
functionname(arg1, arg2)
+
, -
, *
, /
, %
, ==
, !=
, <
, <=
, &&
, and ||
, which all take integer arguments, return an integer, and have the same semantics as in C.Precedence is the same as in C. Precedence can be overridden with parentheses.
Evaluation order for arguments to a function or operands to an operator (except &&
and ||
) is unspecified.
Each C// program must define a function with the signature int main()
which will be called when the program executes. The return value of this function is passed to the system as the exit code of the program.
Each C// program has access to a function with the signature void print(int n)
which displays a single integer followed by a newline. This function does not need to (and cannot) be declared.
expr | → | integer |
| | id | |
| | expr . id |
|
| | expr ( (expr (, expr)*)? ) |
|
| | ( expr ) |
|
| | expr (+ | - | * | / | % | == | != | < | <= | && | || ) expr |
|
stmt | → | { stmt* } |
| | expr = expr ; |
|
| | if ( expr ) stmt (else stmt)? |
|
| | while ( expr ) stmt |
|
| | return expr? ; |
|
| | expr ; |
|
| | type id (= expr) ; |
|
top-decl | → | type id ( (type id (, type id)*)? ) { stmt* } |
| | struct id { (type id ; )* } ; ? |
|
program | → | top-decl* |
Precedence:
.
, ()
(postfix)*
, /
, %
(ltr)+
, -
(ltr)==
, !=
, <
, <=
(nonassoc)&&
(ltr)||
(ltr)if
/else
(ltr)