Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
693 views
in Technique[技术] by (71.8m points)

c - Can you use restrict-ed pointers to access the same object in some cases?

Most definitions of restrict say that it's a promise from the programmer to the compiler that for the lifetime of the pointer, the pointer is the only way that object is accessed. This allows the compiler to optimize the output, because it knows that it will be accessed only by one pointer and thus can be changed only by it. Which if I understand correctly usually means that the program doesn't have to reload the value the pointer points to.

If this is correct then there should be some exceptions when the restrict keyword should be usable even if it goes against the intent of how it should be used.

One thing that comes to mind would be when the data the pointer points to never actually changes during the lifetime of the pointer. In such case there is no need to reload the data even if the pointers point to the same location, because they don't change in the lifetime of the pointers. E.g.:

int max(int *restrict a, int *restrict b) {
  return((*a > *b) ? *a : *b);
}

int main(void) {
  int num = 3;
  int max = max(&num, &num);
}

Is this a valid use of restrict even though it goes against how it was supposed to be used? Will using the restrict keyword like this result in undefined behaviour?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You may sometimes use restrict-qualified pointers to access the same objects as other pointers, but only if the pointed-to objects are not modified. Here are C 2011 (N1570) 6.7.3.1 paragraphs 1-3 and the first part of paragraph 4 interspersed with how they apply to the code in the question.

6.7.3.1 Formal definition of restrict

1 Let D be a declaration of an ordinary identifier that provides a means of designating an object P as a restrict-qualified pointer to type T.

So int * restrict a is such a declaration D. When max is called with max(&num, &num);, the object P is num (or, more formally, the object named by num), and T is int. Similarly, int * restrict b is another such declaration.

2 If D appears inside a block and does not have storage class extern, let B denote the block. If D appears in the list of parameter declarations of a function definition, let B denote the associated block. Otherwise, let B denote the block of main (or the block of whatever function is called at program startup in a freestanding environment).

These declarations appear in the parameter declarations of a function definition, so B is the block of the function definition, that is, the body of max.

3 In what follows, a pointer expression E is said to be based on object P if (at some sequence point in the execution of B prior to the evaluation of E) modifying P to point to a copy of the array object into which it formerly pointed would change the value of E.137) Note that ‘‘based’’ is defined only for expressions with pointer types.

The function max contains pointer expressions a and b, twice each, so these are each an instance of a pointer expression E. These expressions depend on the parameters a and b, respectively, because if we changed a to point to a copy of num instead of pointing to num, then a would have a different value (obviously), and similarly for b. (Although num is a scalar object, it acts like an array containing a single element for purposes of pointer arithmetic.)

4 During each execution of B, let L be any lvalue that has &L based on P. If L is used to access the value of the object X that it designates, and X is also modified (by any means), then the following requirements apply:…

During the execution of max, the lvalue *a has its address (&*a, which is a) based on P (a), so the lvalue *a is an instance of L. This lvalue is used to access num, so num is an instance of an object X. However num is never modified during the execution of max. Therefore, the requirements that follow do not apply. Similarly the lvalue *b refers to an object (num) that is never modified during the execution of max.

Therefore, the code in max does not violate the requirements for restrict, and its behavior is defined by the C standard.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...