2016-09-07 36 views
6

Поскольку строгое наложение псевдонимов может помочь лучше оптимизировать компилятор, C99 представила ключевое слово restrict, которое может использоваться в качестве квалификатора переменной, если программисты гарантируют, что к нему не будет доступен указатель на другой тип. Тем не менее, приведение типов между разными типами неизбежно по нескольким причинам, и это заставит компилятор предположить, что один указатель не является псевдонимом другого. Поэтому метод обходного пути состоит в том, чтобы отключить глобальную оптимизацию строгих псевдонимов, передав -fno-strict-aliasing (флаг GCC). Это совершенно не имеет смысла, потому что может быть только два указателя, которые не должны быть полностью оптимизированы. Следовательно, почему бы не ввести противоположное ключевое слово restrict, которое сообщает компилятору, что не предполагают, что эти два указателя указывают на разные адреса. Это несколько похоже на то, что делает volatile, и что говорит компилятору, что эта переменная сильно изменена, поэтому относитесь к ним особым образом. Возможно ли создать такое ключевое слово?Противоположное ключевое слово "ограничить" в C?

EDIT: Существует способ решить эту проблему. См. Комментарий yano's.

+3

Строгое сглаживание не является гарантией того, что к чему-то не будет доступен более чем один указатель - просто он не будет доступен (обычно) с помощью указателя на другой тип. 'ограничение' отличается. – Dmitri

+1

У вас есть конкретный MVCE? –

+0

Я реализую связанный список XOR, который будет приписывать два разных типа указателей. Это заставляет GCC запутаться и произвести excgables segfault без установки флага '-fno-strict-aliasing'. Я считаю, что отвращение к глобальной оптимизации очень жаль. –

ответ

0

Учитывая код:

int foo(int * restrict p) 
{ 
    *p = 3; 
    someOutsideFunction(); 
    return *p; 
} 

компилятор имеет право предположить, что до тех пор, как p находится в области видимости, ни один объект , который написан с использованием *p будет доступен через любые другие, чем с помощью указателя средств, копируется или иным образом «выведено» отp. Другие указатели на объект могут существовать в другом месте юниверса, но до тех пор, пока foo не вернется, ни один из них не будет доступен для доступа к *p. Следовательно, компилятор может заменить выше

int foo(int * restrict p) 
{ 
    someOutsideFunction(); 
    *p = 3; 
    return 3; 
} 

, так как он может видеть, что ни один указатель скопировано или полученный из p не всегда подвергается таким образом, чтобы someOutsideFunction не мог видеть его, и, таким образом, не законным способом для someOutsideFunction, чтобы получить доступ к объект *p.

someOutsideFunction Если может - без ведома обработки компилятора foo --include ключевого слова, которое вело себя как противоположность restrict, и может позволить ему получить доступ к объекту, идентифицированный p [получающему указатель на этот объект из глобальных переменных или другие такие средства], что сделало бы невозможным для обработки компилятором foo знать, может ли someOutsideFunction получить доступ к *p, и, таким образом, ему не удастся узнать, может ли он безопасно применять указанную оптимизацию.