Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Conversion operations

David Tarditi edited this page May 10, 2018 · 8 revisions

Implicit type conversions

C allow implicit conversion operations at assignments, function call arguments, and function returns. For pointer types, conversions between void * pointers and other pointer types are allowed. When an expected type differs from the actual type, and one type is void * and other type is a pointer type, an impicit conversion is done.

The Checked C extension allows implicit conversions between different kinds of pointer types too. These must meet target bounds requirements at compile time. They cannot be points of runtime failure.

Conversion from unchecked pointer types

A T * can be converted to a _Ptr<T> or _Array_ptr<T>. There are only a few kinds of T * expressions that have known bounds, though:

int x;
_Ptr<int> p = &x;       // OK, &x meets bounds requirements.
_Array_ptr<int> p = &x; // OK, no bounds required.
_Array_ptr<int> p : count(1) = &x; // OK, &x meets bounds requirements.
_Array_ptr<int> p : count(2) = &x; // Error, &x does not meet bounds requirements.

int arr[10];
_Ptr<int> r = arr;       // OK, arr meets bounds requirements.
_Array_ptr<int> r = arr; // OK, no bounds required.
_Array_ptr<int> r : count(10) = r;  // OK, arr meets bounds requirements.
_Array_ptr<int> r : count(11) = r;  // Error, x does not meet bounds requirements.

f(int *x) {
   _Ptr<int> p = x;       // Error, x does not bounds requirements for Ptr.
   _Array_ptr<int> r : count(1) = x; // Error, x does not bounds requirement.
}

## Conversions between checked pointer types

Some conversions between checked pointers to the same type are allowed:
- \_Ptr<T> can be converted to a \_Array_ptr<T>
- \_Array_ptr<T> can be converted to a _Ptr<T>
- \_Nt_array_ptr<T> can be converted to a _Ptr<T> or _Array_ptr<T>.

// Implicit conversion from _Ptr to _Array_ptr void f(_Array_ptr a count(len), int len); void g(_Ptr b) { f(b, 1); }

_Array_ptr c : count(5); _Ptr d = c + 2;


## Conversions to unchecked pointer types

Implicit conversions from checked pointer types to unchecked pointer types are
allowed only at
[bounds-safe interfaces](https://github.com/Microsoft/checkedc/wiki/Bounds-safe-interfaces),
where the expected checked bounds or types have been declared.
Otherwise they are not allowed.

# Explicit type conversions

There are 3 conversion operators between pointer types.  In the follwoing descriptions,
the type `D` is the result type. It must be a pointer type.  The expression _e_
must have a pointer or integer type.  The value of each conversion operation
is the value of _e_ reinterpreted bitwise as a value of type `D`.
- C-style casts, given by `(D)` _e_.  If `D` is `_Ptr<T>` or `T *`, _e_ must have space for
a value of type `T`.   This must be provable at compile-time.  Runtime failures
cannot occur at these casts.
- Dynamically-checked bounds casts, given by `_Dynamic_bounds_cast<T>(`_e_`,`,_bounds-expr_`)`.
The bounds of _e_ are checked at runtime against _bounds-expr_.
If the bounds are not satisfied, a runtime fault is signalled.
If `D` is a `_Ptr<T>` or `T *` type, _bounds-expr_ is omitted and
the bounds are for a single element of type `T`.   Note that for count
bounds expressions, _bounds_expr_ are the bounds for the value at the new type `T`, not the original type of _e_.
- Trusted bounds cast, given by `_Assume_bounds_cast(`_e_`,`_bounds-expr_`)`.
The bounds of the resulting expression are assumed be `_bounds_expr`.  If T is
a `_Ptr<S>` or `S *` type, _bounds-expr_ is omitted.

Here are examples:

// Reinterpret a pointer to an array of characters as a pointer // to an integer. _Array_ptr a : count(12) = ... _Ptr b = (_Ptr) a;

// Reinterpret pointers to characters as pointers ot integers. // lb and ub have bound(unknown), so they cannot be used // to access memory. _Array_ptr lb = (_Array_ptr) a; _Array_ptr ub = (_Array_ptr) (b + 12);

// Reinterpret a pointer to an array of characters to a pointer // to an array of integers. This will fail at runtime if // sizeof(int) > 3. _Array_ptr c : count(3) = _Dynamic_bounds_cast<_Array_ptr>(a, count(3));

// Create a checked_pointer to a hardware buffer. unsigned int hardware_buf = 0xf0000; _Array_ptr d : count(4096) = _Assume_bounds_cast<_Array_ptr>(hardware_buf, 4096);

Clone this wiki locally