Clang++ компилируется, но не запускается

  • В языке программирования со статической областью видимости , например, в большинстве других языков программирования (, таких как C ),

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

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

  • В языке программирования с динамической областью видимости ,

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

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


  • Здесь полезно знать историю.

    1. кш93

    1. В ksh93, функция, по крайней мере одна объявленная с синтаксисом ksh (function f {...}), следует за статической областью видимости .

      Переменные, объявленные с помощью typesetв функции, являются локальными переменными функции.

      a=global_a
      function f {
        typeset a=f_a
        g
      }
      
      function g {
        echo "$a"
      }
      
      f
      

      выведет global_a.

      typeset -i varв функции изменяет тип локального varпеременная с созданием ее экземпляра в области видимости функции, если она не было уже.

    2. В ksh93, функция, объявленная с синтаксисом Борна (f() {...}), вообще не выполняет область видимости. В связи с этим код функции выглядит так, как будто встроен в вызывающую функцию,поэтому любая переменная, появляющаяся в нем, будет иметь ту же область действия, что и в вызывающем объекте, поэтому либо глобальная, либо локальная для верхней -большей части функции, объявленной с синтаксисом ksh в ее дереве вызовов. typesetобъявил бы переменную в самой верхней -самой функции (или в глобальной области видимости, если в дереве вызовов )не было синтаксической функции ksh -.

      Например, поскольку в синтаксических функциях ksh -все переменные являются либо частными, либо глобальными, чтобы реализовать наш integerкак в bash, нам нужно будет сделать это как:

      integer() { typeset -i "$1"; }
      

      То есть используется синтаксис функции Борна , который не выполняет область видимости в все.

      Или с использованием синтаксиса ksh:

      function integer { typeset -i "$1"; }
      

      , но вызывается как:

      . integer var
      

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

      Или используя синтаксис ksh:

      function integer { typeset -ni "$1"; }
      

      Где переменная передается как ссылка с -n, как в C или большинство других языков программирования.

    2. Все остальные борны -похожи на снаряды

    Все другие Bourne -подобные оболочки (, включая ksh88, ksh93, были полностью переписаны, и изменение статической области видимости было (воспринято как минимум )предварительным -необходимым условием для функциональные возможности, которые когда-либо будут включены в стандарт POSIX)реализуют динамическую область видимости .

    1. Переменная, объявленная с typesetбез -gв функции, имеет локальную область видимости функции.

      Например, typeset -i varобъявит локальную переменную (в текущей области действия функции )и установит целочисленный атрибут .

      Например, в коде вверху все они будут выводить f_a. То есть gвидит локальную переменную f.

      Другой пример:если fвызывает g, который вызывает h. Если hделает не объявлять varпеременную локальную в своей области видимости, она увидит gпеременная или, возможно, f, если gне объявил varлокальным, или, возможно, переменная из нижней -самой области видимости.

    2. Во всех bash, zsh, yash, mksh, можно изменить тип или значение переменной в функции, не делая ее локальной для этой функции, используяtypeset -g. Как с этим integerв приведенном вами примере. Но это делается по-разному в зависимости от оболочки.

      • В mksh, yash, zsh, typeset -gне влияет на переменную в нижней -самой(глобальной)области видимости, но в том объеме, в котором он определен в настоящее время .

        Например, в то время как typeset -i varобъявляет локальную переменную (в текущей области действия функции )и устанавливает целочисленный атрибут , typeset -gi varпросто делает последнюю часть (без влияющие на сферу примененияvar).

        Например, когда функция вызывает мою функцию integerвыше, чтобы добавить целочисленный атрибут к переменной, как в:

        f() {
         local myvar
         integer myvar
        ...
        }
        

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

      • Вbashtypeset -gвлияет на экземпляр переменной в глобальной (нижней -самой )области . Хотя это то, что означает g, это бесполезно в оболочках с динамическим область видимости, например bash.

        Например, в первом примере в вашем вопрос, вывод 1+1показывает, что целочисленный атрибут имеет не добавлено в переменную. В добавлена ​​переменная aв глобальной области видимости, но не той, что функция fимеет доступ к.

0
22.10.2019, 18:17
1 ответ

Такой компилятор, как clang++, компилирует только исходный код. В вашем случае он создает исполняемый файл a.out(, поскольку вы явно не указали ему использовать другое имя выходного файла, используя параметр -o). Компилятор не будет автоматически запускать полученный исполняемый файл.Эти вещи также справедливы дляg++(компилятора GNU C++ ), а также для clangи gccкомпиляторов C (и большинства других компиляторов языков, требующих компиляции ).

Чтобы запустить исполняемый файл, введите команду

./a.out

в командной строке оболочки.

Чтобы дать исполняемому файлу имя, отличное от традиционного по умолчанию a.out, используйте что-то вроде

clang++ -o myprog file_name.cpp

для создания myprogиз исходников в file_name.cpp.


Учитывая исходники в одном файле file_name.cpp, makeтакже можно использовать для компиляции исходников в исполняемый файл file_nameс помощью команды

make file_name

находясь в том же каталоге, что и файл исходного кода (, но только если исходный код был обновлен с момента последней компиляции file_name). Для этого не требуется присутствия Makefile, вместо этого будут использоваться неявные правила, встроенные в makeдля компиляции исходных кодов C++.

Используйте

CXX=clang++ make file_name

для явного использования компилятора clang++.

Для получения дополнительной информации см. документацию GNU makeо неявных правилах(других реализациях make, например. в системах BSD используйте аналогичные неявные правила ).

3
28.01.2020, 02:22

Теги

Похожие вопросы