2016-02-10 3 views
1

Это a follow up questionимя переменной старшинство в с

Рассмотрим следующий пример кода:

#include <stdio.h> 
int asdf = 5; 
int main(void) { 
    sub(10); 
    return 0; 
} 
int sub (int asdf) 
{ 
    printf("%d\n",asdf); 
} 

В этом случае, как глобальная переменная, и местный аргумент использовать то же имя, asdf. Код выводит 10, поэтому используется локальная переменная. Ошибка компиляции или предупреждение не выбрасывается.

глобальная переменная по-прежнему доступны из sub(), о чем свидетельствует, когда я изменить sub «ы декларации в

int sub (int asd) 

кода выводит 5. Таким образом, я знаю sub() может получить доступ к глобальной переменной, но она делает не.

Я не смог найти четкого определения о размахе старшинства в стандарте с, поэтому мой вопрос:

Учитывая сценарий выше, называя локальные и глобальные переменные такой же просто плохая практика, или это вызвать ошибки/UB?

+0

Использование глобальных переменных - это плохая практика, если только они не являются константами. – hgiesel

+1

http://www.tutorialspoint.com/cprogramming/c_scope_rules.htm – user3159253

+0

Это не UB, но наверняка, как может быть, вы получите сообщение об ошибке в своем коде раньше или позже. –

ответ

6

Из проекта спецификации C11

6.2.1 Областей идентификаторов

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

[...] Если идентификатор обозначает два разных объекта в одном и том же пространстве имен , области могут перекрываться. Если это так, область действия одного объекта (внутренняя область) будет полностью закрыта перед областью другого объекта (внешний объем). Внутри внутренней области идентификатор обозначает объект, объявленный во внутренней области; объект, объявленный во внешнем пространстве, скрыт (и не отображается) во внутренней области.

Таким образом, функция функции, называемая asdf, скрывает глобальную переменную asdf внутри функции. Предоставление локальных и глобальных переменных одним и тем же идентификатором является плохой практикой, но допускается спецификацией.

1

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

+0

@undur_gongor Скрытие. – user1803551

0

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

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

2

Принимая во внимание описанный выше сценарий, называет локальные и глобальные переменные одной и той же просто плохой практикой или вызывает ошибки/UB?

Это плохая практика и не является неопределенным поведением.

Рассмотрите большую программу со многими авторами. В этом случае становится трудно определить, используется ли используемая переменная в функции или глобальной переменной. Рассмотрите, что произойдет, если произойдут какие-либо изменения, если исходный автор оставил работу, а новый человек пытается понять код. Программа становится сложнее поддерживать.

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

1

Formal parameters, рассматриваются как локальные переменные с-в функции, и они имеют приоритет над глобальными переменными.

При использовании метода следующим образом, вы используете значение переменной передается в метод в качестве параметра, и это определяется на вызов метода:

int sub (int asdf) 
{ 
    printf("%d\n",asdf); 
} 

например:

sub(10); // asdf is being assigned the value of 10 and asdf is a different variable. 

И действует так же, как:

int sub (int adf) 
{ 
    printf("%d\n",adf); 
} 

Это не позволяет использовать параметр int, передаваемый в метод, поэтому используется значение глобальной переменной.

int sub (int adf) 
{ 
    printf("%d\n",asdf); 
} 

Или вы могли бы назвать оригинальный метод, как:

sub(asdf); 

В любом случае, это не имеет никакого реального значения имен она будет глобальной переменной. Поскольку это может быть достигнуто с использованием int anything, и тогда глобальную переменную можно получить независимо. Это действительно путано.

Любая двусмысленность наименования считается плохой практикой.

Тогда есть проблемы с использованием глобальных переменных, тривиально, и это проблемы, которые могут возникнуть с программой по треку, о чем упоминалось в других ответах здесь.

1

Да, очевидно, что это плохая практика обозначения двух переменных с одинаковым именем.

В этих сценариях можно различать с помощью ключевого слова extern. Рассмотрим приведенный ниже пример.

#include <stdio.h>  

int a = 12;    

int main(void)   
{   
    int a = 15;    
    printf("Inside a's main local a = : %d\n", a); 

    { 
     extern int a; 
     printf("In a global a = %d\n", a); 
    } 

    return 0; 
} 

Это даст Op

Inside a's main local a = : 15 
In a global a = 12 

компилятор не будет бросать какие-либо ошибки.

0

Глобальная переменная, конечно, плохая практика. Кроме того, я не вижу здесь ничего неожиданного в отношении приоритета имени переменной.

Понятно, что компилятор всегда ищет имя переменной, скажем x, в самом узком диапазоне сначала.

  • Если он найдет x в локальном масштабе, он остановится там и никогда не проверяет наличие каких-либо других областей. Это ваш случай, когда у вас есть две переменные asdf, одна локальная и одна глобальная. Поскольку компилятор нашел asdf в sub(), он никогда не будет искать глобальный. Это поведение также называется имя скрывается.
  • Только в том случае, если он не найден x в локальной области, он расширит поиск до более широкой области действия, до глобальной области.

Это имя скрывается самое относится и к различным областях, а также, например:

int i = 10; 
for(int i = 5; i < 9; i++) 
{ 
    printf("i = %d (inside for loop)\n", i); // <-- i = 10 is hidden in this loop 
} 
printf("i = %d (outside for loop)\n", i); 

Btw, ваш прототип неверен, возвращаемый тип должен быть void, а не int.

void sub (int asdf); 
Смежные вопросы