C, Ocean Edition I

Behavioral Model and Language Semantics

Status
Companion Language White Paper
Edition
Ocean Edition I
Compatibility Heritage
ISO C99
Language Name
C

1. Purpose

This document defines the behavioral model of C, Ocean Edition I.

The Ocean Edition I preserves the syntax, computational model, and programming character of C while normalizing historical irregularities into a smaller and more predictable collection of rules.

The guiding principle is:

Where traditional C admits multiple interpretations, historical exceptions, unspecified behavior, or context-dependent transformations, Ocean Edition I chooses the simplest behavior consistent with ordinary programmer intent and applies it uniformly.

This document describes that behavior component by component.

It is intentionally implementation-independent.

The language may be implemented by:

No particular compiler architecture is part of the language.


2. Fundamental Philosophy

Ocean Edition I does not attempt to make C a different kind of language.

It retains:

The language instead pursues:

One predictable rule for each construct.

Where traditional C provides several semantic categories for essentially the same operation, those categories should be collapsed wherever doing so does not destroy useful expressive power.


3. Program Structure

A program consists of one or more translation units.

Each translation unit contains declarations and definitions.

A translation unit may refer to entities defined in other translation units through external declarations.

A complete hosted program contains exactly one externally visible entry function:

int main(void)

or:

int main(int argc, char **argv)

Implementations may support additional environment-specific entry signatures.

Freestanding implementations need not provide main.


4. Source Encoding

Ocean Edition I source text is UTF-8.

Implementations shall accept the ordinary ASCII subset directly.

Ancient source-representation compatibility mechanisms are not part of the language.

In particular:

Line endings are implementation-normalized.


5. Tokens

The language recognizes the familiar C token categories:

Whitespace separates tokens where necessary but otherwise has no semantic meaning.

Comments are treated as whitespace.

Both forms are supported:

/* comment */

and:

// comment

6. Identifiers

Identifiers use the familiar C form.

An identifier names an entity according to its scope and namespace.

Implementations shall support at least:

Implementations may permit additional Unicode identifier characters.

Identifier comparison is case-sensitive.

Thus:

value
Value
VALUE

are three distinct identifiers.


7. Keywords

Ocean Edition I retains the established useful vocabulary of C.

Obsolete storage hints are not part of the language.

In particular:

auto
register

are removed.

The remaining core vocabulary includes familiar C constructs such as:

break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
inline
int
long
restrict
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while

and C99 facilities appropriate to the edition.


8. Preprocessing

Traditional preprocessing remains available where required for C source compatibility.

However, preprocessing is not considered part of the semantic type system.

Its result is source presented to the language proper.

The familiar directive forms may be supported:

#include
#define
#undef
#if
#ifdef
#ifndef
#elif
#else
#endif
#error
#line
#pragma

Ocean Edition I strongly prefers ordinary language facilities over macro abstraction when both can express the same concept.

For example:

static const int max_users = 64;

is preferred to:

#define MAX_USERS 64

and:

static inline int max(int a, int b)
{
	return a > b ? a : b;
}

is preferred to a function-like macro.

This is a programming-model preference rather than a syntactic incompatibility requirement.


9. Includes

The familiar spelling remains:

#include <stddef.h>
#include "local.h"

An implementation may process includes textually, structurally, incrementally, or through another equivalent mechanism.

The observable declarations and definitions are what matter.

Repeated inclusion of the same logical interface should not require implementation-specific behavior beyond normal C compatibility.


10. Declarations

A declaration introduces the existence and type of an entity.

A definition additionally creates the entity or supplies its body.

Ocean Edition I minimizes declaration categories.

For objects there are fundamentally:

definition
external declaration

For functions there are fundamentally:

declaration
definition

Tentative definitions do not exist as a distinct semantic category.


11. Canonical Declaration Order

Declaration specifiers have one canonical conceptual order:

storage
qualifiers
type
declarator

For example:

static const unsigned long flags;
extern volatile unsigned char status;

Redundant permutations need not be accepted.

This reduces syntactic plurality without changing expressive power.


12. Canonical Primitive Type Spellings

The canonical primitive spellings are:

void

char
signed char
unsigned char

short
unsigned short

int
unsigned int

long
unsigned long

long long
unsigned long long

float
double
long double

_Bool

Redundant forms such as:

long int
signed int
unsigned long int

need not be accepted where they convey no additional information.


13. void

void represents the absence of a value.

A function returning no value uses:

void f(void)
{
}

An expression of type void does not produce a usable value.

void * remains the generic object-pointer type.


14. Boolean Values

C99's _Bool type is retained.

Its logical values are false and true.

Conversion from arithmetic or pointer values follows the familiar C truth rule:

zero         false
null pointer false
anything else true

Conditions may directly consume scalar values:

if (count)
{
	...
}

No separate Boolean-only condition syntax is introduced.


15. Character Types

Plain:

char

has one consistent signedness across all Ocean Edition I implementations.

It represents a non-negative byte-sized character unit.

Signed small-integer behavior is requested explicitly with:

signed char

Unsigned small-integer behavior is requested explicitly with:

unsigned char

This removes implementation-dependent behavior from plain char.


16. Integer Representation

Signed integers use two's-complement representation.

There are no:

Every bit pattern of an ordinary integer type represents a value.

Integer widths remain properties of the selected target data model unless exact-width types are used.


17. Exact-Width Integer Types

Where supported by the standard environment, exact-width types include:

int8_t
uint8_t
int16_t
uint16_t
int32_t
uint32_t
int64_t
uint64_t

Address-sized integer types include:

intptr_t
uintptr_t

Code requiring exact layout should use explicit-width types rather than depending upon assumptions about int, long, or related types.


18. Floating-Point Types

The familiar types remain:

float
double
long double

Implementations shall document their representations.

On implementations claiming IEEE floating-point conformance, ordinary IEEE behavior applies consistently.

Floating arithmetic is not silently transformed into integer arithmetic.

NaN and infinity behavior follows the selected floating model.


19. Enumerations

An enumeration defines a meaningful integral type.

enum State
{
	STATE_IDLE,
	STATE_RUNNING,
	STATE_STOPPED
};

The enumerators conceptually have type:

enum State

rather than merely being unrelated integer constants produced as a side effect of the declaration.

Ordinary integral conversions remain permitted where doing so preserves normal C ergonomics.

An enum value is not restricted at runtime to the set of named enumerators.

For example:

enum State state = (enum State)100;

has a valid enum representation if the underlying integer representation can hold that value.

Enumerators are names, not a closed runtime set.


20. Structures

A structure is an aggregate consisting of independently addressable members.

struct Point
{
	int x;
	int y;
};

Members appear in declaration order.

Implementations may insert padding to satisfy alignment requirements.

The layout for a given target is deterministic.

Structure assignment copies the complete value.

a = b;

produces a value-equivalent copy of b in a.


21. Structure Padding

Padding bytes are part of object representation but do not correspond to members.

Whenever an object is zero-initialized, its padding is also zeroed.

Whenever a structure value is copied, its resulting representation is deterministic.

Reading the raw byte representation of a valid initialized structure is defined.

This allows reliable:

Applications should still avoid treating ABI-dependent structure layout as a portable external data format unless that layout is intentional.


22. Unions

A union represents overlapping typed storage.

union Value
{
	float f;
	uint32_t u;
};

All members begin at the same storage location.

Writing one member and then reading another reinterprets the stored object representation through the requested member type.

For example:

union Value value;

value.f = 1.0f;
uint32_t bits = value.u;

is defined.

A union does not maintain an abstract hidden "active member" whose purpose is to prohibit representation inspection.


23. Bitfields

Bitfields retain normal C syntax:

struct Flags
{
	unsigned int ready : 1;
	unsigned int mode : 3;
};

Their physical layout is determined completely by the selected target ABI.

The implementation shall define:

There is no hidden implementation freedom once a target ABI has been selected.


24. Arrays

An array is a first-class fixed-size object consisting of contiguous elements of one type.

int values[16];

has type:

array of 16 int

The array remains an array in all expression contexts unless an explicit operation produces something else.


25. No Implicit Array Decay

Traditional array-to-pointer decay is removed.

Given:

int values[16];

the expression:

values

denotes the array.

If the address of its first element is needed:

&values[0]

is written explicitly.

Thus:

process(&values[0]);

passes an element pointer.

This follows the general rule:

An expression does not silently acquire a different type because of its surrounding context.


26. Array Parameters

Array-looking function parameters that are silently rewritten into pointers are not part of Ocean Edition I.

These forms are rejected:

void process(int values[]);
void process(int values[16]);

If the parameter is a pointer:

void process(int *values);

If it is a pointer to an array:

void process(int (*values)[16]);

The declaration directly represents the actual type.


27. Variable-Length Arrays

Variable-length arrays are not part of Ocean Edition I.

This is rejected when count is not a compile-time constant:

int values[count];

Fixed arrays remain ordinary C objects:

int values[64];

Runtime-sized storage is represented using explicit dynamic storage or another library mechanism.


28. Flexible Array Members

Flexible array members remain supported:

struct Packet
{
	size_t length;
	unsigned char payload[];
};

The flexible member contributes no fixed element count to the containing structure.

It refers to trailing storage associated with the complete allocated object.


29. Pointers

A pointer represents an address capable of designating an object or function of the appropriate category.

Normal syntax remains:

int *p;
&p;
*p;
p + n;
p - n;
p[i];

No ownership, borrow, fat-pointer, or reference model is introduced.


30. Null Pointers

NULL is the canonical source spelling for a null pointer value.

A null pointer designates no object or function.

Pointers created by default zero initialization begin as null pointers.

On supported Ocean Edition I targets, the null representation is normalized so that zero-initialized pointer storage yields a null pointer.

Code should prefer:

int *p = NULL;

to treating an arbitrary integer literal as pointer notation.


31. Pointer Equality

Two pointers compare equal when they represent the same address and pointer category.

A null pointer compares equal only to another null pointer of a compatible pointer category after ordinary conversions.


32. Pointer Ordering

Relational comparison of valid object pointers produces an address ordering within the implementation's address space.

Thus:

a < b

compares their addresses.

The operation is not limited only to pointers derived from the same array object.

This matches the ordinary systems-programming model of ordered machine addresses.


33. Pointer Arithmetic

Given a pointer to T:

T *p;

then:

p + n

advances by n objects of type T.

Likewise:

p - n

moves backward.

Subtraction of suitably related pointers produces an element distance.

Producing an address that cannot be represented by the target pointer model is invalid and causes defined failure rather than arbitrary undefined behavior.

Dereferencing an address that does not designate a valid object remains an unsafe memory error.


34. Pointer and Integer Conversion

uintptr_t and intptr_t, when provided, are capable of holding ordinary pointer address representations.

A round trip through uintptr_t preserves the address:

uintptr_t raw = (uintptr_t)p;
void *again = (void *)raw;

If the implementation's pointer model contains metadata that cannot survive such conversion, the implementation must expose that limitation rather than silently pretending ordinary integer round-trip semantics exist.


35. Functions

A function has:

Every function declaration is a prototype.

This:

int f();

is not a valid unspecified-parameter declaration.

Zero parameters are written:

int f(void);

36. Function Definitions

Only prototype-style definitions exist.

int add(int a, int b)
{
	return a + b;
}

K&R-style definitions do not exist.


37. Function Designators

A function identifier denotes the function itself.

It does not silently decay into a function pointer.

The address is obtained explicitly:

&compare

Thus:

int (*fn)(int, int) = &compare;

is the canonical pointer construction.

Both functions and function pointers may be called using normal call syntax.


38. Function Calls

Arguments are evaluated strictly from left to right.

Given:

f(a(), b(), c());

the order is:

a()
b()
c()
f(...)

This ordering is guaranteed.

There is no unspecified argument evaluation order.


39. Call Type Safety

A function call must agree with the function's declared type.

Calling a function through an incompatible function-pointer type is invalid.

If incompatibility is statically known, the implementation must diagnose it.

If incompatible invocation is encountered dynamically through unsafe casting, execution shall fail in a defined manner where detection is possible.

The language does not treat calling-convention mismatch as a legitimate optimization opportunity or meaningful program behavior.


40. Return Values

A non-void function returns a value compatible with its declared return type.

A void function returns no value.

Reaching the end of a non-void function other than main without returning a value is invalid.

Reaching the end of:

int main(void)

is equivalent to:

return 0;

41. Objects and Lifetimes

An object has:

An object's lifetime begins when its storage becomes associated with that declared object or allocated object representation.

Every object begins its lifetime with a valid value.


42. Default Initialization

If no initializer is provided, an object is zero-initialized.

Thus:

int count;

begins as zero.

double value;

begins as positive zero.

int *pointer;

begins as a null pointer.

struct Point point;

begins with all members recursively zero-initialized.

Arrays are recursively zero-initialized.

Union default initialization initializes its first declared member to its zero value and normalizes the complete storage representation.


43. Explicit Initialization

An explicit initializer supplies the initial value.

int count = 10;

Aggregate initialization follows C99 rules.

Unspecified aggregate elements or members are zero-initialized.

Example:

int values[8] = {
	[3] = 7,
};

produces:

0 0 0 7 0 0 0 0

44. Storage Duration

Ocean Edition I recognizes the familiar storage-duration categories:

Block-scope objects normally have automatic duration.

File-scope objects have static duration.

A block-scope static object has static duration.


45. static

static has two accepted contextual meanings derived from the same concept of locally owned persistent identity.

At file scope:

static int counter;

the entity has translation-unit-local linkage.

At block scope:

void f(void)
{
	static int counter;
}

the object persists across function invocations.

Other historical uses are not retained.

In particular, array-parameter forms involving static are rejected.


46. extern

extern means:

This is a declaration of an entity defined elsewhere.

Thus:

extern int counter;

declares an object.

An extern declaration does not define or initialize storage.

Therefore:

extern int counter = 1;

is invalid.


47. File-Scope Definitions

At file scope:

int counter;

is a definition.

It defines one zero-initialized object.

There are no tentative definitions.

A second definition of the same externally linked entity is invalid unless a separate platform linkage mechanism explicitly provides otherwise.


48. Linkage

Entities may have:

Ordinary file-scope definitions have external linkage unless declared static.

static file-scope entities have translation-unit-local linkage.

Block-local ordinary objects have no linkage.

extern declarations refer to externally linked entities.


48.1 Namespaces and Linkage

An entity with external linkage has a linkage name, which is the name the linker sees.

For an entity declared outside any namespace, the linkage name is the identifier itself. This is ordinary C, and it is unchanged.

For an entity declared inside a namespace, the linkage name is formed by joining the enclosing namespace names and the identifier with a double underscore.

Thus:

namespace net
{
	int open(const char *host);
}

declares an entity whose qualified name is:

net::open

and whose linkage name is:

net__open

The mapping is fixed by the language rather than chosen by the implementation. A C translation unit therefore reaches the entity by declaring the linkage name:

int net__open(const char *host);

No shim is required in either direction, and the object file is an ordinary object file.

An entity with translation-unit-local linkage has no linkage name, because it has no external name. static inside a namespace means what static means everywhere else:

namespace net
{
	static int retry_count;
}

retry_count is not exported. Its qualified name still exists for lookup within the translation unit, and no symbol appears in the object file.

Namespace membership is a property of the name, not of the entity's storage, lifetime, type, or representation. Two entities in different namespaces are as unrelated as two entities with different names, which is exactly what the prefix convention already achieved by hand.


49. const

const means that modification is not permitted through the qualified object or access path.

For an object declared directly const:

const int limit = 10;

the object may not be modified after initialization.

Removing the qualifier through a cast does not make mutation legal.

For:

int value = 10;
const int *p = &value;

the object itself remains mutable through other valid non-const access paths.

p simply cannot be used to modify it.


50. volatile

volatile means:

Every source-level access is externally observable and must occur.

Reads must actually read.

Writes must actually write.

The implementation may not remove, combine, invent, or reorder volatile accesses in a manner that changes their prescribed ordering relative to other volatile accesses.

volatile does not imply:


51. restrict

restrict expresses an explicit non-aliasing promise.

During the relevant execution scope, the restricted pointer and its derived access paths are the designated means by which the relevant storage is accessed according to the restriction contract.

Ordinary pointers do not imply non-aliasing.

Thus:

void copy(
	float *restrict dst,
	const float *restrict src,
	size_t count
);

provides stronger alias information than:

void copy(
	float *dst,
	const float *src,
	size_t count
);

52. inline

inline is an optimization intent, not a linkage subsystem.

The useful conventional form is:

static inline int min(int a, int b)
{
	return a < b ? a : b;
}

Whether a call is physically inlined is always an implementation decision.

Bare inline and extern inline forms with historical C99 linkage semantics are not part of Ocean Edition I.


53. Arithmetic Expressions

Arithmetic operators retain their familiar syntax:

+
-
*
/
%

Arithmetic uses the language's usual integer and floating conversion rules, except where Ocean Edition I explicitly normalizes historically dangerous behavior.


54. Signed Integer Overflow

Signed integer overflow is defined.

Arithmetic uses finite-width two's-complement behavior.

For example, if int is 32 bits:

INT_MAX + 1

produces:

INT_MIN

The operation is not undefined.

Unsigned arithmetic retains modular behavior.


55. Integer Narrowing

Conversion from a wider integer type to a narrower integer type is deterministic.

The low-order destination-width bits are retained.

The resulting bit pattern is interpreted according to the destination type.

There is no implementation-defined signed narrowing behavior.


56. Integer Widening

Widening preserves the mathematical value where representable.

Signed values are sign-extended.

Unsigned values are zero-extended.


57. Signed and Unsigned Comparisons

Mixed signed and unsigned comparisons follow value-preserving semantics rather than blindly converting a negative signed operand into a large unsigned value.

For example:

-1 < 1u

is true.

The comparison is conceptually performed using the mathematical values of both operands where both can be represented in a suitable comparison domain.

Only when one side cannot be represented in such a common domain does the language fall back to width-aware magnitude rules.

This avoids one of C's most common silent arithmetic surprises.


58. Division

Integer division truncates toward zero.

For example:

7 / 3

produces:

2

and:

-7 / 3

produces:

-2

Division by zero causes a defined runtime trap.

The signed overflow case:

INT_MIN / -1

also traps because no representable signed result exists.


59. Remainder

Remainder follows division.

For valid operands:

a == (a / b) * b + (a % b)

Division by zero or remainder by zero traps.


60. Shifts

Shift operators retain:

<<
>>

The shift count must satisfy:

0 <= count < width of promoted left operand

An invalid count traps.

There is no undefined shift count behavior.


61. Left Shift

Left shift operates on the finite-width bit representation.

Bits shifted beyond the width are discarded.

Signed left shift does not become undefined merely because the mathematical result exceeds the positive signed range.

The resulting bit pattern is interpreted according to the left operand's resulting integer type.


62. Right Shift

Unsigned right shift inserts zero bits.

Signed right shift is arithmetic.

The sign bit is replicated.

Therefore behavior is consistent across implementations.


63. Unary Negation

Unary:

-x

uses the same finite-width arithmetic rules as subtraction from zero.

Negating the minimum representable signed value therefore wraps according to two's-complement representation rather than invoking undefined behavior.


64. Increment and Decrement

The familiar operators remain:

++x
x++
--x
x--

Their value semantics remain those of C.

Evaluation order is governed by the universal left-to-right sequencing rules.

Overflow follows the same deterministic integer rules as ordinary addition and subtraction.


65. Evaluation Order

Unless syntax explicitly requires otherwise, subexpressions evaluate left-to-right.

This applies to:

Operator precedence determines grouping.

Evaluation order determines execution.

They are separate rules.


66. Short-Circuit Operators

Logical AND:

a && b

evaluates a first.

b is evaluated only if a is true.

Logical OR:

a || b

evaluates a first.

b is evaluated only if a is false.

The result is logically false or true.


67. Conditional Operator

The conditional operator:

condition ? a : b

evaluates condition first.

Exactly one of a or b is evaluated.


68. Assignment

Assignment retains:

lhs = rhs

The right-hand expression is evaluated and converted to the destination type.

The resulting value is stored in the destination object.

Assignment itself produces the stored value as an expression result, preserving traditional C behavior.


69. Compound Assignment

Operators such as:

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

perform the corresponding operation and assignment.

The left operand is evaluated once.

Overflow and invalid arithmetic follow the same rules as the corresponding ordinary operator.


70. Comparison

The familiar comparison operators remain:

==
!=
<
<=
>
>=

Arithmetic values compare according to their normalized conversion rules.

Pointers compare according to pointer equality and ordering semantics.

The result is logically false or true.


71. Bitwise Operators

Bitwise operators remain:

&
|
^
~

They operate directly on integer bit representations.

Signed integer representation is two's-complement, so bitwise behavior is deterministic.


72. Logical Truth

Scalar values have truth according to:

integer zero       false
floating zero      false
null pointer       false
all other scalar values true

NaN is true because it is not numerical zero.


73. sizeof

sizeof returns the storage size of a type or object in units of char.

It does not evaluate an ordinary value operand.

Because variable-length arrays are absent, sizeof is not made dynamically evaluative by array extents.

For:

int values[16];
sizeof(values)

is the size of the entire array.

Arrays do not decay.


74. Alignment

Objects have alignment requirements defined by their types and target ABI.

An implementation shall provide the alignment facilities required by its supported C environment.

Misaligned accesses may either be supported according to the target or cause defined failure.

They are not treated as a license for unrelated program transformations.


75. Casts

C-style casts remain:

(type)value

Casts may explicitly request conversions between compatible categories.

Unsafe casts remain possible.

For example:

void *p;
int *q = (int *)p;

The programmer remains responsible for ensuring that dereferencing the resulting pointer is valid.

Casts do not suppress the fundamental semantics of object mutability, valid storage, or call compatibility.


76. Object Representation

Every object has a byte representation.

Its representation may be inspected through character-type access.

For example:

unsigned char *bytes = (unsigned char *)&object;

is valid.

Primitive integer bit patterns are fully defined according to the target representation rules.

Structures may contain deterministic padding.

Unions intentionally expose overlapping representations.


77. Aliasing

Ordinary object pointers may alias.

Type difference alone does not allow an implementation to assume that two addresses refer to distinct storage.

Explicit restrict contracts or provable program facts may establish stronger non-aliasing guarantees.

Character pointers may inspect the representation of any object.


78. Allocated Storage

Dynamically allocated storage begins as raw storage with suitable alignment according to the allocator's contract.

The storage becomes associated with an object representation when a value of that type is stored into it or copied into it.

The rule is intentionally direct:

Storing a valid T representation into suitably aligned storage establishes a valid T object there.

No additional hidden effective-type state machine is required.


79. Byte Copying

Byte copying preserves object representation.

Copying the complete representation of a valid object of type T into suitably aligned destination storage establishes an equivalent T representation there.

This makes ordinary low-level copying behavior explicit.


80. memcpy and Overlap

Ocean Edition I standard-library behavior should prefer overlap-safe copying.

A conforming memcpy may provide the same overlap-safe semantics traditionally associated with memmove.

Thus copying bytes between overlapping regions produces the result obtained as though the source bytes were first preserved and then written to the destination.

This removes an unnecessary distinction where implementations can provide the intuitive behavior efficiently.

memmove may remain for source compatibility.


81. String Literals

A string literal is an immutable character array.

For:

"hello"

the conceptual type is:

array of 6 const char

including the terminating zero byte.

Writing to string literal storage is invalid.

The type system reflects the actual mutability.


82. Adjacent String Literals

Adjacent string literals concatenate at translation time:

const char *message =
	"hello "
	"world";

This remains supported.


83. Character Literals

A character literal contains one character value:

'a'

Multi-character character constants such as:

'abcd'

are not part of Ocean Edition I.

They are too implementation-dependent to justify preserving.


84. String and Memory Library Behavior

Standard string and memory functions should have deterministic preconditions and failure behavior.

Operations which can naturally support overlap safely should do so.

Operations requiring valid null-terminated strings still require them.

Passing an invalid pointer remains an unsafe memory error.

Library semantics should avoid introducing arbitrary undefined behavior where a deterministic result or trap can reasonably be specified.


85. Blocks

A block:

{
	...
}

introduces a nested scope.

Automatic objects declared within the block normally live until the block exits.

static block objects persist beyond individual executions.


86. if

Conditional execution remains:

if (condition)
{
	...
}
else
{
	...
}

The condition is evaluated once.

Nonzero scalar values are true.

Zero scalar values are false.


87. while

A while loop:

while (condition)
{
	body();
}

evaluates the condition before each iteration.


88. do while

A do loop:

do
{
	body();
}
while (condition);

executes the body once before testing the condition.


89. for

A for loop retains normal C form:

for (init; condition; step)
{
	body();
}

Its conceptual execution is:

init

while (condition)
{
	body
	step
}

with ordinary lexical scoping.


90. break

break exits the innermost enclosing loop or switch.


91. continue

continue advances to the next iteration of the innermost enclosing loop according to that loop's defined control path.


92. switch

switch retains standard C behavior.

switch (value)
{
	case 1:
		...
		break;

	default:
		...
		break;
}

The controlling expression is evaluated once.

Case labels are compile-time integral constants compatible with the controlling type.


93. Fallthrough

Case fallthrough remains legal.

case 1:
	prepare();

case 2:
	execute();
	break;

The implementation should diagnose suspicious accidental fallthrough by default.

The language does not introduce mandatory new syntax merely to preserve an existing useful behavior.


94. goto

goto remains a primitive control-flow operation.

goto cleanup;

jumps to the matching label within the function, subject to object-lifetime restrictions.

It remains useful for low-level cleanup and state-machine code.


95. Labels

Labels have function scope.

They identify valid jump destinations.

Jumping into a region in a manner that would violate the initialization or lifetime requirements of objects declared there is invalid.


96. Scope

The familiar scope categories remain:

Names resolve according to the nearest applicable declaration in the appropriate namespace.


97. Namespaces

C's separate identifier namespaces are retained where they provide useful compatibility:

Thus:

struct Node
{
	int Node;
};

may remain legal because the names occupy distinct namespaces.

This is unusual but coherent and deeply embedded in C syntax.


98. typedef

A typedef introduces an alias.

typedef unsigned long index_t;

It does not create a new nominal type.

Aliases are interchangeable with their underlying type.


99. Initializer Lists

Aggregate initializer lists retain C99 syntax.

struct Point point = {
	10,
	20,
};

Designated initializers remain available:

struct Point point = {
	.y = 20,
	.x = 10,
};

Missing members are zero-initialized.


100. Compound Literals

Compound literals remain:

(struct Point){
	.x = 10,
	.y = 20,
}

They create an object value of the indicated type with the appropriate storage duration for their context.


101. Designated Initializers

Both member and array designators remain:

struct Point point = {
	.x = 10,
};

and:

int values[8] = {
	[4] = 20,
};

Unspecified portions are zero-initialized.


102. Variadic Functions

Variadic functions remain:

int printf(const char *format, ...);

Named arguments are evaluated left-to-right before variadic arguments continue in the same order.

Variadic arguments undergo the edition's defined default argument conversions.

The language should specify these conversions explicitly and consistently.


103. Default Argument Promotions

Where compatibility with C variadic conventions requires promotion, the rule remains explicit.

For variadic arguments:

These promotions are part of the variadic calling contract rather than a general excuse for hidden type changes elsewhere.


104. Sequence and Side Effects

The traditional concept of sequence points is replaced by direct evaluation-order semantics.

Each expression has a deterministically ordered sequence of evaluations.

A modification becomes visible to evaluations sequenced after it.

Programs need not reason about "unsequenced modifications" as a special semantic category.


105. Undefined Behavior

Ocean Edition I intentionally minimizes undefined behavior.

The language distinguishes:

Defined behavior

The operation has a specified result.

Defined trap

The operation is invalid and execution terminates through the implementation's defined trap mechanism.

Unsafe memory behavior

The program accesses storage that does not designate a valid object in the required manner.

Unsafe memory behavior remains possible because Ocean Edition I remains a manually managed systems language.

Undefined behavior is not used merely to simplify optimizer reasoning where a deterministic machine-oriented behavior is available.


106. Typical Defined Traps

Examples include:

integer division by zero
integer remainder by zero
invalid shift count
unrepresentable signed division result
detected incompatible function invocation
certain impossible pointer-address operations

The implementation may diagnose these statically when provable.


107. Unsafe Memory Errors

Examples include:

dereferencing an invalid pointer
use-after-free
writing outside an allocated object
reading outside an allocated object
double free
invalid allocator ownership
accessing storage after lifetime end

Ocean Edition I does not impose mandatory runtime memory safety.

Implementations may provide diagnostic, sanitizer, or checked modes.


108. Compile-Time Diagnostics

A conforming implementation should reject or diagnose errors knowable at translation time.

Examples include:

int a[4];
a[7] = 1;

when the out-of-bounds access is statically evident.

Likewise:

A deterministic language should use knowledge it already possesses.


109. Warnings

Non-invalid but suspicious constructs should be diagnosed where practical.

Examples include:

Warnings do not redefine valid program behavior unless a strict conformance profile explicitly promotes them to errors.


110. Hosted and Freestanding Environments

Ocean Edition I supports both traditional C execution models.

A hosted implementation provides the expected language environment and standard library profile.

A freestanding implementation may omit facilities requiring an operating system or hosted runtime.

The core language semantics remain the same.

Pointers, arithmetic, objects, arrays, structs, unions, control flow, and initialization do not change merely because the program is freestanding.


111. Standard Library Philosophy

The standard library should follow the same principles as the language.

Where traditional behavior is already sensible, preserve it.

Where several APIs differ only because of historical constraints, normalize behavior where compatibility permits.

Where an operation can fail, define the failure contract.

Where overlap can be handled safely without changing the programmer's conceptual operation, prefer safe overlap semantics.

Where object sizes are available, implementations should expose diagnostics and checked variants without changing ordinary C syntax.


112. Implementation-Defined Behavior

Some implementation-defined behavior remains unavoidable.

Examples may include:

However:

Implementation-defined behavior must correspond to a genuine target property, not merely to historical specification indecision.

If every supported modern target can share one reasonable rule, the language should prefer defining it universally.


113. Unspecified Behavior

Ocean Edition I should contain very little unspecified behavior.

Where multiple execution orders are observable, an order should ordinarily be chosen.

Where multiple representations are possible only because targets genuinely differ, the property should be implementation-defined.

"One of several things happens and the implementation need not say which" should be treated as a last resort.


114. Compatibility Principle

Ocean Edition I favors source that is already valid, ordinary-looking C.

When behavior differs from traditional C, conversion should usually be mechanical.

Examples include:

implicit array decay
→ write &array[0]

function address decay
→ write &function

old f()
→ write f(void)

extern definition
→ remove extern

register object
→ remove register

VLA
→ use explicit dynamic storage

multi-character literal
→ construct the intended value explicitly

The language should remain close enough to traditional C that moving code between them is an engineering task rather than a port to a different programming model.


115. Behavioral Summary

The Ocean Edition I can be summarized through a small number of universal laws.

Law 1 — Syntax means what it says

An array declaration creates an array.

A pointer declaration creates a pointer.

An external declaration declares something external.

A definition defines something.

Law 2 — Expressions keep their types

Arrays do not become pointers merely because context wants one.

Functions do not become function pointers merely because context wants one.

Explicit syntax performs explicit transformations.

Law 3 — Evaluation has an order

Ordinary subexpressions evaluate left-to-right.

Programs do not depend upon compiler-chosen argument order.

Law 4 — Objects begin valid

Every object begins its lifetime with a defined value.

No ordinary object begins as semantic poison.

Law 5 — Arithmetic describes finite machines

Signed integers use two's-complement behavior.

Overflow is defined.

Shifts are defined.

Invalid arithmetic traps.

Law 6 — Target differences must be real

ABI, alignment, widths, and endianness may differ.

Arbitrary historical ambiguity should not.

Law 7 — Optimization does not define semantics

A program's meaning is determined by the language.

Implementations optimize that meaning.

The language does not declare inconvenient executions nonexistent merely to aid optimization.

Law 8 — Dangerous is allowed

Pointers remain unsafe.

Manual storage remains unsafe.

Casts remain powerful.

Direct hardware interaction remains possible.

Ocean Edition I does not confuse danger with ambiguity.

Law 9 — Existing C syntax is preferred

New syntax is not introduced merely to repair a rule that existing C syntax can already express clearly.

Law 10 — Fewer categories are better

Where two language concepts exist only because history accumulated them separately, Ocean Edition I seeks one general rule.


116. Final Behavioral Thesis

The behavioral contract of C, Ocean Edition I is intentionally simple:

Programs should behave the way an experienced systems programmer expects the machine-oriented C source to behave, unless there is a compelling technical reason otherwise.

When the programmer writes:

int x;

x has a value.

When the programmer writes:

a() + b()

a() happens before b().

When the programmer writes:

int values[16];

values remains an array.

When the programmer writes:

&values[0]

they have explicitly requested an address.

When signed arithmetic exceeds its range, finite-width arithmetic still occurred.

When bits are shifted right through a signed value, the operation has one meaning.

When a union member is inspected through another member, the programmer is intentionally examining overlapping representation.

When const is written, mutation is forbidden.

When extern is written, the declaration does not secretly become a definition.

When restrict is written, it communicates an actual aliasing guarantee.

When volatile is written, accesses actually happen.

When the target genuinely differs, the implementation documents the difference.

And when the language can reasonably provide one answer, it does.

Ocean Edition I therefore does not attempt to protect the programmer from the machine.

It attempts to protect the programmer from C's historical uncertainty about the machine.

That is the behavioral foundation of C, Ocean Edition I.