В ядре Linux 2.6.26 я нашел «#define atomic_read (v) ((v) -> counter + 0)», почему «+0»? - PullRequest
9 голосов
/ 24 апреля 2019

Я нашел это в linux-2.6.26 (linux-2.6.26 / include / asm-alpha / atomic.h), и не знаю, почему здесь +0.

#define atomic_read(v)      ((v)->counter + 0)
#define atomic64_read(v)    ((v)->counter + 0)

Ответы [ 3 ]

10 голосов
/ 24 апреля 2019

Если + 0 не используется, это будет lvalue, который вы можете назначить случайно, то есть

if (atomic_read(v) = 42) {
    ...
}

будет "работать" ... Вместо + 0 вы можете просто использоватьунарный +, то есть

(+(v)->counter)

Однако + 0 имеет один хорошее преимущество перед + в общем случае: + требует, чтобы аргумент был арифметикой тип - но указатели не арифметического типа.Тем не менее, + 0 будет работать как для указателей (и только для указателей, вы можете использовать &* для преобразования lvalue в значение выражения; это гарантированно будет работать даже для нулевых указателей)

7 голосов
/ 24 апреля 2019

Возможно, что + 0 было добавлено для компилятора для выдачи диагностики в случае переопределения функционально-подобных макросов atomic_read и atomic64_read.

Согласно CСтандартно можно переопределить идентификатор, который является функционально-подобным макросом, если второе определение также является функционально-подобным макросом, имеющим одинаковое число и написание параметров, и два списка замены идентичны.

Из стандарта C11 (n1570) раздел 6.10.3 / 2 :

... Аналогично, идентификатор, в настоящее время определяемый как функциональный макрос, не должен быть переопределен другим#define директива предварительной обработки, если только второе определение не является функционально-подобным макроопределением, имеющим одинаковое число и написание параметров, и два списка замены идентичны.

Версия ядра (2.6.26) довольно старый, но аналогичный запрет на такое переопределение можно найти в более старых стандартах до стандарта C89.

В настоящее время макрест atomic_read и atomic64_read определены в файле atomic.h.

Если пользователь переопределит их в некотором исходном файле, как показано ниже:

#define atomic_read(v)      (v)->counter 

Компилятор выдастдиагностика о переопределении.Это предупреждение выдается, потому что в определении atomic_read из файла atomic.h присутствует + 0.

Если бы не + 0, компилятор не выдал бы диагностику.

Минимальный пример, демонстрирующий эту проблему:

//atomic.h
#define atomic_read(v)      ((v)->counter + 0)
#define atomic64_read(v)    ((v)->counter)

//some source file that includes atomic.h
#define atomic_read(v)      ((v)->counter) //redefinition error 
#define atomic64_read(v)    ((v)->counter) //no redefinition error 

См. Демо

5 голосов
/ 24 апреля 2019

Он не дает результату быть lvalue, поэтому вы не можете ошибочно присвоить ему или получить его адрес.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...