-
Notifications
You must be signed in to change notification settings - Fork 15
using random pointers, but only guarded by an if
comparison
#27
Comments
Your specific example code is unlikely to be optimized because
That's more about whether |
C's Note the counterfactual:
6.7.3.1 Formal definition of restrict1Let 2If 3In what follows, a pointer expression Note 119 - In other words, 4During each execution of
5Here an execution of 6A translator is free to ignore any or all aliasing implications of uses of restrict. 7 EXAMPLE 1The file scope declarations int * restrict a;
int * restrict b;
extern int c[]; assert that if an object is accessed using one of a, b, or c, and that object is 8 EXAMPLE 2The function parameter declarations in the following example void f(int n, int * restrict p, int * restrict q)
{
while (n-- > 0)
*p++ = *q++;
} assert that, during each execution of the function, if an object is accessed through 9The benefit of the restrict qualifiers is that they enable a translator to make an void g(void)
{
extern int d[100];
f(50, d + 50, d); // valid
f(50, d + 1, d); // undefined behavior
} 10 EXAMPLE 3The function parameter declarations void h(int n, int * restrict p, int * restrict q, int * restrict r)
{
int i;
for (i = 0; i < n; i++)
p[i] = q[i] + r[i];
} illustrate how an unmodified object can be aliased through two restricted pointers. In particular, if 11 EXAMPLE 4The rule limiting assignments between restricted pointers does not distinguish between a {
int * restrict p1;
int * restrict q1;
p1 = q1; // undefined behavior
{
int * restrict p2 = p1; // valid
int * restrict q2 = q1; // valid
p1 = q2; // undefined behavior
p2 = q2; // undefined behavior
}
} 12The one exception allows the value of a restricted pointer to be carried out of the typedef struct { int n; float * restrict v; } vector;
vector new_vector(int n)
{
vector t;
t.n = n;
t.v = malloc(n * sizeof (float));
return t;
} |
In #26, @arielb1 gave this example code. It takes a random
*mut
and dereferences it -- but only after double checking that it is a valid value:The challenge here is that we are using a
*mut
-- but only after (dynamically) comparing it for correctness. This seems to get at a key question: the extent to which users are permitted to think of the actions of the code as a kind of "turing machine".Many legit (or potentially legit) uses of uninitialized memory have this general feeling.
Random but maybe unrelated example: I have at times used sets that require only O(1) initialization. For example, a set consisting of the integers 0..N might work like:
index: [usize; N] // uninitialized
members: [usize; N] // uninitialized
count: usize
To add a new item
i
, you do:self.index[i] = self.count; self.members[self.count] = i; self.count += 1
To check if item
i
is present you do:let m = self.index[i]; m < self.count && self.members[m] == i
The text was updated successfully, but these errors were encountered: