Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> inline 
:(
    Опции темы
bsa
Дата 20.1.2009, 00:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(Lampa24 @ 19.1.2009,  23:46)
А ты бы не мог подробней об этих правилах . 
Просто это вопрос на д\з и мне нужно объяснить почему это так.

Цитата(UnrealMan @ 19.1.2009,  23:41)
Цитата(Lampa24 @  19.1.2009,  21:52 Найти цитируемый пост)
Пасибо огромное!!!!!!

Вкусная лапша, да? smile Приходи ещё, здесь тебя ей накормят по полной smile

????? Это к чему уважаемый???

В двух словах:
Обычная функция записывается в 2 места объектного файла - область кода и "экспортную" таблицу символов. В области кода находится собственно "почти" машинный код (только вместо адресов вызываемых процедур и глобальных переменных, там ссылки на них или просто мусор - реальные значения подставляются на этапе компоновки), а в области таблицы символов находится запись:
<сигнатура функции (считай, ее название и список параметров)>   <смещение отностительно области кода>     <размер кода>

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

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

Если ты помечаешь функцию словом inline, то (в С++) говоришь компилятору, что данная функция является встраиваемой, поэтому не надо помещать ее в экспортную таблицу (т.е. фактически функция статическая). Таким образом, даже если функцию не удалось компилятору встроить, линкер все равно о ней ничего не узнает. В языке си, будет ругаться, поэтому там надо помечать ее еще и static.

P.S.: я попытался использовать простейшую терминологию. Если есть желании знать все в научной, то тебе тут объяснят.
PM   Вверх
UnrealMan
Дата 20.1.2009, 00:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 5
Всего: 32



Цитата(mes @  20.1.2009,  00:01 Найти цитируемый пост)
а из за того что имена функций с inline  для линкера помечены как локальные,
в отличие от имен обычных функций, которые имееют внешнее связывание.


Цитата(bsa @  20.1.2009,  00:16 Найти цитируемый пост)
поэтому не надо помещать ее в экспортную таблицу (т.е. фактически функция статическая). Таким образом, даже если функцию не удалось компилятору встроить, линкер все равно о ней ничего не узнает. 

Lampa24, тебе чья лапша больше нравится: vinter-a или mes-а & bsa? smile
PM MAIL   Вверх
bsa
Дата 20.1.2009, 01:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



Цитата(стандарт 2006 года @  стр. 123)
If a function with external linkage is declared inline in one translation unit, it shall be declared
inline in all translation units in which it appears; no diagnostic is required. An inline function with external linkage
shall have the same address in all translation units.
Если функция с внешним связыванием объявлена как inline в одной единице трансляции, то она должна быть объявлена inline во всех единицах трансляции, в которых используется. Встраиваемая функция с внешним связыванием должна иметь одинаковый адрес во всех единицах трансляции.
Т.е. я был не прав, говоря, что она является фактически static.
PM   Вверх
vinter
Дата 20.1.2009, 06:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(mes @  20.1.2009,  01:01 Найти цитируемый пост)
макрос во первых раскрывается не во время компиляции, а до.

причем тут макрося сказал, что она подобна. И что она встраивается на этапе компиляции, что непонятно?
Цитата(mes @  20.1.2009,  01:01 Найти цитируемый пост)
в третьих  проблема исчезает не из за того, что функция встраивается,

именно из-за этого.
Цитата(mes @  20.1.2009,  01:01 Найти цитируемый пост)
а из за того что имена функций с inline  для линкера помечены как локальные,

линкер к inline функции не имеет никакого отношения, потомучто если inline пожелание было исполнено, то никакой функции нет.
Цитата(bsa @  20.1.2009,  01:16 Найти цитируемый пост)
Таким образом, даже если функцию не удалось компилятору встроить, линкер все равно о ней ничего не узнает

bsa, а ты проверь ;)
UnrealMan, хорошь стебаться, есть, что сказать - говори smile


--------------------
Мой блог
PM MAIL WWW   Вверх
UnrealMan
Дата 20.1.2009, 10:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 5
Всего: 32



Цитата(vinter @ 20.1.2009,  06:17)
Цитата(mes @  20.1.2009,  01:01 Найти цитируемый пост)
в третьих  проблема исчезает не из за того, что функция встраивается,

именно из-за этого.

Проблема исчезает из-за того, что исчезает нарушение правила одного определения, а задумано оно так для того, чтобы одни и те же inline-функции сразу в нескольких единицах трансляции могли встраиваться во время компиляции (не дожидаясь компоновки).
PM MAIL   Вверх
vinter
Дата 20.1.2009, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



UnrealMan, так а я что не так сказал?

Цитата(UnrealMan @  20.1.2009,  11:36 Найти цитируемый пост)
Проблема исчезает из-за того, что исчезает нарушение правила одного определения

это же следствие того, что функция ыстроилась


--------------------
Мой блог
PM MAIL WWW   Вверх
UnrealMan
Дата 20.1.2009, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 722
Регистрация: 30.3.2006

Репутация: 5
Всего: 32



Цитата(vinter @  20.1.2009,  10:57 Найти цитируемый пост)
UnrealMan, так а я что не так сказал?

Нет времени объяснять, спроси у экспертов по приготовлению лапши (их надо искать среди тех, у кого на этом форуме под ником написано слово "Эксперт").
PM MAIL   Вверх
baldina
Дата 20.1.2009, 15:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(vinter @ 20.1.2009,  10:57)
UnrealMan, так а я что не так сказал?

Цитата(UnrealMan @  20.1.2009,  11:36 Найти цитируемый пост)
Проблема исчезает из-за того, что исчезает нарушение правила одного определения

это же следствие того, что функция ыстроилась

компилятор ведет себя в соответствии со стандартом: inline функция имеет один адрес во всех единицах трансляции.
технически это означает, что если где-то используется адрес функции, то компилятор генерирует (единственное) определение этой функции. что, заметьте, не мешает ему при вызове этой функции подставлять её встроенное представление вместо вызова, если компилятор считает это нужным. 

вот как, например, может поступить компилятор:

Код

#include <iostream>

inline int f ()
{
  return 1;
}

int main()
{
  using namespace std;

  cout << f() << endl; // встраивание
  cout << f << endl;   // адрес невстроенной функции
  size_t addr = size_t(f);
  typedef int (*fp)();
  cout << fp(addr)() << endl; // вызов невстроенной функции (по адресу f)
}



PM MAIL   Вверх
vinter
Дата 20.1.2009, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(baldina @  20.1.2009,  16:26 Найти цитируемый пост)
inline функция имеет один адрес во всех единицах трансляции.технически это означает, что если где-то используется адрес функции, то компилятор генерирует (единственное) определение этой функции

стандарт другое говорит
Цитата

An inline function shall be defined in
every translation unit in which it is used.

так насколько я понял: при inline будет всегда генерироваться новое определение ф-ии, в каждой еденицы трансляции(типо internal linkage чтоли?). Я правильно это понимаю или нет? Следущий вопрос:  я сталкивался с ситуацией когда была средних размеров inline ф-ия которая находилась в ашнике, все работало замечательно. Но после добавления нескольких строк появилась ошибка линкера, я вв свое время решил, что это из-за того, что ф-ия перестала встраиватся и из-за этого ошибка. Как это объяснить? gcc 4.0.1 кажется..  


--------------------
Мой блог
PM MAIL WWW   Вверх
baldina
Дата 20.1.2009, 21:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



не, vinter, стандарт говорит именно это. и не надо его домысливать, там четко все.

Добавлено через 5 минут и 10 секунд
для начала таки переведи приведенную тобой фразу.

и читай 7.1

Цитата

If a function with external linkage is declared inline in one translation unit, it shall be declared
inline in all translation units in which it appears; no diagnostic is required. An inline function with external linkage
shall have the same address in all translation units.


PM MAIL   Вверх
vinter
Дата 20.1.2009, 23:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



baldina, ну и что? покад\жи мне в каком месте изначальнеого кода есть 
Цитата(baldina @  20.1.2009,  22:57 Найти цитируемый пост)
it shall be declaredinline in all translation units in which it appears; no diagnostic is required

и это не отменяет вопросов заданнных ранее, я ничего не домысливаю, я всего лишь пытаюсь понять. Анрыл вон знает и молчит как партизан, обиделся наверно  smile 


--------------------
Мой блог
PM MAIL WWW   Вверх
baldina
Дата 21.1.2009, 00:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



в изначальном коде функция определена в ашнике, включаемом в двух файлах. т.е. имеем определение ее в нескольких единицах трансляции. 
покуда она не inline это нарушает правило одного определения. 
как только она становится inline ничего не нарушается. и ошибок компиляции нет. 
встраивается она или нет совершенно неважно, это деталь реализации. вариант реализации (MSVC так делает) я показал - может иметь место встраивание и не-встраивание одновременно. но это уже не относится к вопросу smile

Добавлено через 1 минуту и 20 секунд
Цитата

Анрыл вон знает


читай стандарт, тоже знать будешь. думаешь он молчит - время экономит? хочет что бы ты сам прочел. так полезнее.
PM MAIL   Вверх
vinter
Дата 21.1.2009, 00:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



baldina,  остается неотвеченный вопрос
Цитата(vinter @  20.1.2009,  20:50 Найти цитируемый пост)
Следущий вопрос:  я сталкивался с ситуацией когда была средних размеров inline ф-ия которая находилась в ашнике, все работало замечательно. Но после добавления нескольких строк появилась ошибка линкера, я вв свое время решил, что это из-за того, что ф-ия перестала встраиватся и из-за этого ошибка. Как это объяснить? gcc 4.0.1 кажется..  

остальное я понял, но не совсем понял смысл этого и еще, встроить функцию это не просто впихнуть ее код где надо, это определенный гемморой. Как тогда быть с единственнно определенной функцией, и как быть с цитаатой из стандарта приведенной мной выше.
Цитата(baldina @  21.1.2009,  01:04 Найти цитируемый пост)
хочет что бы ты сам прочел. так полезнее.

я прочел, вопросы остались. То, что полезнее не спорю, если бы не Анрыл, я бы стандарт наверно не скоро открыл smile


--------------------
Мой блог
PM MAIL WWW   Вверх
baldina
Дата 21.1.2009, 00:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата

я сталкивался с ситуацией когда была средних размеров inline ф-ия которая находилась в ашнике, все работало замечательно

какая ошибка линкера? в скольких единицах трансляции была эта функция? в скольких разных местах на диске был одноименный ашник с одноименной функцией? хорошо бы код глянуть

Цитата

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


Скомпилить код таким образом, что бы функция была определена один раз (по единственному адресу) - это задача компилятора.
Определить inline функцию в каждой единице трансляции, где она используется - обязанность программиста.
Здесь нет противоречий. Это буквально то, что в стандарте. В чем вопрос?

Добавлено через 4 минуты и 19 секунд
vinter, стандарт содержит как требования к коду, так и гарантии программисту (требования к компилятору).

Цитата

If a function with external linkage is declared inline in one translation unit, it shall be declared
inline in all translation units in which it appears

Это обязан обеспечить программист

Цитата

An inline function with external linkage
shall have the same address in all translation units.

Это обязан обеспечить компилятор


PM MAIL   Вверх
vinter
Дата 21.1.2009, 08:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(baldina @  21.1.2009,  01:49 Найти цитируемый пост)
какая ошибка линкера?

повторное определение

Цитата(baldina @  21.1.2009,  01:49 Найти цитируемый пост)
 в скольких разных местах на диске был одноименный ашник с одноименной функцией?

один ашник, в одном месте smile

Цитата(baldina @  21.1.2009,  01:49 Найти цитируемый пост)
в скольких единицах трансляции была эта функция?

включался ашник в несколько юнитов.


--------------------
Мой блог
PM MAIL WWW   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0942 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.