2010-01-02 2 views
2

я родом из PHP фона и изучает эту страницу http://cocoadevcentral.com/articles/000081.php, прежде чем я ступить в некоторые из более твердого материала в отношении Objective-Cпомощи понимания ЬурейеЙ структура

если я типа что-то вроде этого

typedef struct { 
int lengthInSeconds; 
int yearRecorded; 
} Song; 

и при настройке функции или переменной типа Song, что это значит? Я понимаю, что, устанавливая функцию как int или, возможно, float, выход будет связан с его набором типов. но когда я делаю что-то вроде этого

Song myvariable; 
or 
Song myfunction(int params) { } 

what type is Song setting? 

благодаря

ответ

1

Вот википедии статья о структурах языка C.

http://en.wikipedia.org/wiki/Struct_%28C_programming_language%29

+0

я прочитал статью на википедии. но не понимаю его цели, будет ли он похож на написание классов в php? – SarmenHB

+0

Структуры аналогичны классам, в которых они группируют несколько других переменных (в данном случае два ints) в автономный пакет данных (см. Другие ответы NSResponder и lpthnc). Однако идеологии C-структуры и PHP-класса довольно разные. –

2

Предполагая, что Objective C очень близка к C, вы делаете это:

Song myvariable; // creates the truct in memory 
myvariable.lengthInSeconds = 10; 
myvariable.yearRecorded = 2010; 

Я не могу сказать, что функция делает, потому что вы не дали его осущ.

Вот как исправить функцию, чтобы сделать что-то «полезное»:

Song myfunction(int params) { 
    Song ret; 
    ret.lengthInseconds = params * 69; 
    ret.yearRecorded = 3*5*7*9*11; 
    return ret; 
} 

(Jut, чтобы показать, что эта функция может сделать что угодно ...

2

В первом случае:

Song myvariable; 

вы объявляя MyVariable быть экземпляром структуры вы объявлены в вашем ЬурейеЕ.

Во втором случае:

Song myfunction(int params) { } 

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

+0

Я бы просто добавил, что первое означает «зарезервировать достаточное пространство памяти для хранения структуры типа Song и называть ее myvariable», а второе: «Я обещаю, что эта функция вернет структуру типа Song». –

15

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

typedef struct { 
int lengthInSeconds; 
int yearRecorded; 
} Song; 

Здесь на самом деле происходят две вещи. Во-первых, вы определяете анонимный struct:

struct { 
int lengthInSeconds; 
int yearRecorded; 
} 

Этот анонимный struct может быть использован в любом месте типа (например, int или const char*) могут быть использованы. Следующий пример на самом деле действует, хотя никто и никогда не должен писать код, как это, потому что это обслуживание кошмар:

struct { 
int lengthInSeconds; 
int yearRecorded; 
}* GetSongInfo(const char* songName); 

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

я говорил, что в качестве «анонимного struct», потому что с именем форма структуры выглядит следующим образом:

struct Song { 
int lengthInSeconds; 
int yearRecorded; 
} 

Теперь вы можете обратиться к этой структуре по имени, но не в моде вы думаете ближайшее от языков, отличных от C! В частности, функция выше теперь будет объявлена ​​как:

struct Song* GetSongInfo(const char* songName); 

Обратите внимание, что имя типа является struct Song и не только Song! По сути, у struct s есть собственное собственное пространство имен ... так что ничего не существует, чтобы гарантировать, что struct Song и Song - это то же самое! Я понятия не имею, поддерживает ли Objective C это безумие, но я бы сказал, что он находится в безопасности.

Во-вторых, вы подаете эту анонимную структуру до typedef. typedef просто берет один тип и определяет имя для него, которое вы можете использовать позже. Итак, вы действительно говорите: «Song является псевдонимом для этого struct {...} Я только что объявил».

По typedef ING Song, вы можете вместо этого написать:

Song* GetSongInfo(const char* songName); 

(Да, я знаю, что это было бы лучше вернуться const Song*, но это не относится к делу.)

Это может заинтересовать вас обратите внимание, что C имеет множество typedefs в своих стандартных библиотеках, предназначенных для отделения данных платформы от деталей стандарта C. Например, <unistd.h> определяет size_t, целочисленный тип, который представляет собой размер (и является типом возврата встроенной функции sizeof()), и по расширению тип, который вы должны передать таким функциям, как malloc(). Существует также недавний заголовок <stdint.h>, который определяет целочисленные типы по их размеру в битах, например. uint8_t для 8-разрядного целого числа без знака. Линия в <stdint.h> вероятно выглядит примерно так:

typedef unsigned char uint8_t; 

Поскольку большинство платформ имеют 8-битные символы. (Я запрограммировал для некоторых платформ, таких как TI DSP, где char не был 8 бит, обычно это было 16, поскольку процессор не мог получить доступ к частям слов. Пока не будем игнорировать вырожденные платформы.)

Наконец, чтобы объяснить свои примеры:

Song myvariable; 

объявляет память для Song структуры. Если это определение функции, это хранилище будет выделено в стеке и выпущено, когда функция завершится. Если он находится вне определения функции, он будет выделен как глобальный. В любом случае он будет неинициализирован, что в C означает, что он может содержать любые случайные значения. C не отслеживает неинициализированные переменные или задает их как «неинициализированные» или что-то вроде PHP и Python. C не генерирует исключений.

Song myfunction(int params) { } 

Это определяет функцию, которая принимает целое число и возвращает Song структуру.Оператор return для функции должен иметь значение Song. Например:

Song myfunction(int params) 
{ 
    Song result; 
    result.lengthInSeconds = GetSongLength(params); 
    result.yearRecorded = GetSongYear(params); 
    return result; 
} 

Эта функция выделяет пространство в стеке для Song, заполняет его поля с помощью вызова функций, которые возвращают int с, затем return копирует структуру result в пространство, отведенное для возвращаемого значения, и, наконец, при завершении функции освобождается память для result. Обычно компилятор может оптимизировать копию, неявную в инструкции return. Кроме того, там может быть другой (возможно, оптимизировано) скопировать из хранилища возвращаемого значения до конечного пункта назначения, например, когда вы говорите:

Song foundSongInfo = myfunction(params); 

Кстати, возвращаясь struct с на стек неодобрением, так как компиляторы обычно лучше оптимизировать, если возвращаемое значение вписывается в регистр (т. е. является простым типом). (Есть исключения в C++ с перегрузкой операторов, но это не по теме.) Лучшее определение было бы:

void myfunction(int params, Song* found) 
{ 
    found->lengthInSeconds = GetSongLength(params); 
    found->yearRecorded = GetSongYear(params); 
} 

Это позволяет избежать всех дополнительных копий. Вы называете это так:

Song foundSongInfo; 
myfunction(params, &foundSongInfo); 

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

я, возможно, пропустили некоторые вещи, дайте мне знать, если это имеет смысл ...

+0

Один из лучших ответов, которые я когда-либо видел в StackOverflow. Благодаря! –

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