2016-11-12 5 views
1

Вот пример того, что у меня происходит. Этот первый фрагмент кода не будет работать.Почему это задание не работает вне функции?

typedef struct { 
    char *desc; 
    unsigned quantity; 
} item; 

item *inventory[INVENTORY_SIZE]; 

item thing = { "This is a thing.", 2 }; 
inventory[0] = &thing; // Fail. 

int main(void){ 
    // Code goes here. 
} 

Следующий код будет работать, однако.

typedef struct { 
    char *desc; 
    unsigned quantity; 
} item; 

item *inventory[INVENTORY_SIZE]; 

item thing = { "This is a thing.", 2 }; 

int main(void){ 
    inventory[0] = &thing; // Works. 
} 

Я знаю, что не могу вызывать функции вне функции, но я могу назначить глобальные функции вне функции. Это похоже на задание. Итак, почему это не работает?

EDIT: Как только я нажал «сообщение», я думаю, что понял ответ. Вы можете назначать значения в объявлении вне функции, но только если это объявление. Это ответ, не так ли?

+0

Я думаю, вы неправильно поняли разницу между * присваиванием * и * инициализацией *. Ваш первый. Это может быть только последний, если он должен быть там, где вы делаете то, что делаете. Вы можете делать то, что хотите, но только как инициализацию, которая потребует переупорядочения некоторого кода и предоставления вашему указателю массива инициализации. – WhozCraig

+0

Повторите свое редактирование (и прочитайте вместе с моим ответом), вы не «присваиваете значения в объявлении вне функции», вы инициализируете объект как часть его объявления. Вы правы, что он * выглядит * как задание, за исключением довольно вопиющего факта, что он * не * :-) – paxdiablo

ответ

1
item thing = { "This is a thing.", 2 }; 

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

С другой стороны,

inventory[0] = &thing; 

является задание, которое должно быть в зависимости от некоторого описания.

В нижней строке вы не должны применять правила инициализации к назначениям.

0

Прежде всего,

item thing = { "This is a thing.", 2 } 

является initialization, который является частным случаем, а не присваивание. Это устанавливает начальное значение переменной. Инициализация связана с объявлением, поэтому она может находиться в области файлов.

assignment expression может находиться только внутри функции. Чтобы выразить это простыми словами, назначение должно выполняться во время выполнения, поэтому, если оно не находится внутри области видимости функции, нет способа узнать , когда выполнить его.

0

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

1

Это должно работать, если это то, что вы пытаетесь достичь:

item thing = { "This is a thing.", 2 }; 
item *inventory[INVENTORY_SIZE] = {&thing}; 

Это definitions (так как они находятся в области видимости верхнего уровня), так что компилятор будет идти вперед и выделить память для них это единица перевода.

5

Когда мы пишем:

data_type variableName = someValue; 

Это означает, что мы первые объявляя VARIABLENAME быть переменной и типа DATA_TYPE. Впоследствии присваивание значения выполняется сразу после этого, и поскольку это первое значение, присвоенное variableName, оно также инициализирует его someValue.

Это разрешено. Это особый тип функции, системная функция, известная как инициализация.

Но написание

variableName = someValue; 

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

Это не возможно вне функции.

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