2012-04-27 2 views
0

Мой вопрос о statement expressions, которые добавлены в качестве расширения в GNU C. Рассмотрим следующий код:Является ли переопределение переменных в выражениях выражений безопасными?

#include <stdlib.h> 
#include <stdio.h> 

int main(void) 
{ 
    int i = 0; 
    printf("%d\n", i); 

    {int i = 1;printf("%d\n", i);} 

    printf("%d\n", i); 
    return EXIT_SUCCESS; 
} 

Компиляция (gcc -Wall -std=gnu99 lala.c -o lala) и запуск даст:

0 
1 
0 

Эта практика (использование расширения) является довольно обычным явлением, особенно в container_of в ядре Linux:

#define container_of(ptr, type, member) ({ \ 
       const typeof(((type *)0)->member) *__mptr = (ptr); 
       (type *)((char *)__mptr - offsetof(type,member));}) 

Как и в этом случае, я хочу определить макрос, который объявляет локальную переменную и что-то делает с ней. Однако я хочу сделать это, не загрязняя имена переменных, доступные в текущей области действия, и избегать возможных переопределений. Я не смог найти в документации информацию о том, как точно определяется область видимости в случаях переопределений.

В приведенном выше случае от компилятора не выдается предупреждение о переопределении. Мой вопрос заключается в том, могу ли я полагаться на то, что переменная, ограниченная внутри выражения оператора, не будет влиять на переменную с тем же именем во внешней области?

+0

Что не допускается в объявлении переменных, имена которых начинаются с двух подчеркивания. – dreamlax

+2

Разве ваше использование не просто составное заявление? для того, чтобы оно было выражением оператора, оно должно быть заключено в скобки в соответствии с связанной документацией – msam

+0

@msam: yes, но я хочу определить макрос, используя скобки –

ответ

2

Уверенный, что это безопасно, это то, для чего предназначены области.

(И как dreamlax указывает в своем комментарии, идентификаторы с двумя символами подчеркивания зарезервированы для реализации (компилятор, библиотеки, хостинг environement ...), так что вы не должны использовать их.)

+0

Правильный, глупый вопрос: P Ключевое слово, которое я должен был бы известная была «теневая переменная», что-то, что я неожиданно не встречал раньше (вероятно, потому, что в целом люди избегают их). –

0

Что касается сфера

от 3.1.2.1 ANSI C (аналогично 6.2.1 в C99):

Если описатель или спецификатор типа, который объявляет идентификатор появляется внутри блока или в списке деклараций параметров в функции Defi Определение, идентификатор имеет блок объем, который заканчивается в}, который закрывает связанный блок

...

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

Так предполагая, что компилятор соответствует вы должны быть в состоянии сделать ваше предположение, что переменная область видимости внутри выражения не будет влиять на переменную во внешнем объеме

+0

только выложил это как ответ, потому что слишком долго быть комментарием – msam

Смежные вопросы