Страница 204 из 386

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 14:57:17
Аlex
GARMIN писал(а):Определение - выделение конкретного места хранения переменной, присвоение ей адреса в памяти.
s = 10;
v = 'h';
На сколько мне известно, это - присваивание переменной значения. А далеко не выделение под переменную памяти.
Или Вы считаете, что одного объявления переменной - int s; не достаточно для выделения ей "места хранения" ?

Какую то Вы, сударь, ерунду тут наговорили... :facepalm:

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:00:07
Аlex
ks0 писал(а):Из .с объявление выкинуть, а из .h выкинуть extern.
:facepalm:
Правильно, нафиг эта переменная вообще нужна - повыкидывать её к чертям, да и делов... :)))

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:02:29
ks0
Аlex писал(а):Правильно, нафиг эта переменная вообще нужна - повыкидывать её к чертям, да и делов... :)))
Не домысливайте, объявление char GlobalVar1 оставить, только модификатор extern убрать.

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:06:54
Аlex
ks0 писал(а):объявление char GlobalVar1 оставить, только модификатор extern убрать.
Вы валерьянки что-ли перепили ? Думайте что говорите. Ну или сходите литературку почитайте...

ЗЫ: Товарищи ! Думайте, перед тем, как что-то написать, вас читают начинающие !

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:09:19
ks0
Аlex писал(а):Вы валерьянки что-ли перепили ?
Да, аргумент!
А по существу?

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:14:57
Gudd-Head
Да, а по существу? Да так, чтобы чайникам было понятно :)

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:19:06
Аlex
Хорошо, по существу...
Вы предлагаете такой вариант :
Спойлерmodule.h

Код: Выделить всё

char var;     // Без extern

.......
module.c

Код: Выделить всё

include "module.h"

.......
main.c

Код: Выделить всё

include "module.h"

.......
В этом случае, в mai.c и module.c будут созданы отдельные экземпляры переменной var, с разными адресами !
Ибо это равносильно такому варианту :
Спойлерmodule.c

Код: Выделить всё

char var;

.......
main.c

Код: Выделить всё

char var;

.......
Т.к. include - это обычное включение в файл кода, находящегося в другом файле.

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:26:54
ks0
Для этого в начале и конце каждого заголовочного файла пишется следующая директива препроцессора

Код: Выделить всё

#ifndef _MODULE_H
#define _MODULE_H

// объявления

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

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:29:29
Аlex
Не поможет Вам эта директива. Что с ней, что без неё будет одинаковый результат.
что файл обрабатывается компилятором лишь единожды
Заблуждение !
Она лишь гарантирует, что один и тот же хидер не будет подключен многократно в одном модуле !

ЗЫ: И по вышеприведённой ссылке всё написано правильно. Там писал человек, уровнем выше некоторых тут присутствующих на несколько голов.

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:52:51
ks0
Это же легко проверить

Изображение

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 15:58:59
ARV
я, возможно, скажу слегка не так, как говорят всякие гранды Си, потому что люблю сам для себя формулировать определения наиболее понятно и непротивречиво.

так вот. каждый элемент программы в Си может иметь:
1. объявление или описание
2. определение или реализация
3. использование

объявление - это информация компилятору о наличии некоей сущности с характерными свойствами. для переменной - это ее тип, для функции кроме типа еще и типы ее параметров.

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

использование - это, само собой, использование сущности в алгоритме.

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

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

Код: Выделить всё

extern int var;
int var;
// тут нет никаких ошибок!
а вот попытка в хидере определить переменную - это крайне порочная практика, такая же, как подключение директивой include исходника на Си #include "myfile.c".

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 16:07:44
Аlex
ks0 писал(а):Это же легко проверить
Изображение
Понятия не имею, что Вы этим "проверили"...

http://os24.org/files/books/Brian_Kerni ... age-RU.pdf стр. №89 , п. 4.11.1
Процитирую один момент, о котором я уже выше говорил :
Любая строка вида
#include "имя-файла"
заменяется содержимым файла с именем имя-файла.
. Т.е. , как уже было сказано выше, include - всего-лишь вставляет текст подключаемого файла в код !

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 16:16:50
ks0
ARV писал(а): что касается extern. объявление переменной с этим префиксом - правильный вариант для многофайловых проектов, он гарантирует, что при использовании одного хидера вы всегда будете иметь доступ к нужной переменной. тот факт, что при подключении хидера к модулю с реализацией этой переменной возникает как бы двойное описание - не проблема, это разрешено стандартом.

Код: Выделить всё

extern int var;
int var;
// тут нет никаких ошибок!
Удивился этому изврату, протестировал, оказывается работает... Но дело вообще вот в чем. Каждый файл .с (как и .h) компилируется отдельно, на его основе создаются некие промежуточные файлы .o (объектный). Затем проходит компоновщик и связывает это все в один исполняемый файл. Вот если у вас некая переменная объявлена в одном .с файле, и вы хотите её использовать и в другом, то нужен способ как-то на нее сослаться. Если вы просто попытаетесь использовать её по имени, компилятор, при обработке выругается, т.к. ничего не знает о существовании того файла, где она была объявлена (они же проходится независимо). Вот тут и используется extern, мы как бы говорим компилятору "Мамой клянусь, где-то есть такая глобальная переменная". Он соглашается. Потом проходит компоновщик, и находит её в другом объектов файле, и вставляет на нее ссылку. А если не находит, то ругается уже компоновщик, и программа не собирается.

Поэтому extern редкоиспользуемый костыль, если есть .h файл, то достаточно переменную объявить там.

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 16:29:21
Аlex
ks0 писал(а):Вот тут и используется extern, мы как бы говорим компилятору "Мамой клянусь, где-то есть такая глобальная переменная". Он соглашается. Потом проходит компоновщик, и находит её в другом объектов файле, и вставляет на нее ссылку
Дак вот для этого они (переменные) и описываются в .h-файле с квалификатором extern, чтобы при его подключении, в модуле появлялась ссылка на эти переменные, которые находятся в другом модуле. Какой же это костыль ?
Ещё раз говорю: подключение файла с помощью директивы #include - это всего-лишь вставка в файл текста из подключаемого файла, не более того ! Отсюда следует логический вывод - если Вы напишите объявление переменной в подключаемом .h-файле, то это будет равносильно тому, что Вы объявите эти переменные во всех файлах, в которых подключали этот .h-файл.
Естественно, после подобных манипуляций, во всех файлах создадутся совершенно разные переменные (с разными адресами), просто с одинаковым именем.

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 16:32:05
ks0
Аlex писал(а):Понятия не имею, что Вы этим "проверили"...
Ну Вы сказали, что "будут созданы отдельные экземпляры переменной var, с разными адресами"
А получился один экземпляр, и с одним адресом.
Аlex писал(а):Т.е. , как уже было сказано выше, include - всего-лишь вставляет текст подключаемого файла в код !
Вы или неправильно понимаете, или там так неудачно сформулировано.
Вот в более новых языках программирования существует такое понятие как "пространство имен", в классическом Си его нет, или под ним понимается что-то другое. Пространство имен (namespace) собирает все определения созданные внутри него в единое множество. Может быть несколько П.И. и они могут иметь одинаковые объявления, например int var в одном и int var в другом это абсолютно разные переменные. Если П.И. не задано, то используется некое глобальное П.И. Так вот в Си существует только одно глобальное пространство имен. Переменная с именем var это всегда одна и та же переменная (если только не объявлена внутри функции).

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 17:26:28
ks0
Аlex, вероятно Вы правы все-таки. Только тогда разобраться надо почему GCC это лопает.

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 17:29:37
ARV
что лопает? объявление одноименных локальных переменных в разных модулях? так это по стандарту можно. вот как программист потом разберется в них - это другой вопрос :)

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 17:45:28
ks0
ARV писал(а):что лопает? объявление одноименных локальных переменных в разных модулях?
По объявлению в .h создает одну переменную, а не две. См. картинку выше. Компоновщик не ругается. Книжки по С++ однозначно такую конструкцию запрещают. В Си все должно быть еще однозначнее :\
Короче пойду умных людей подопрашиваю. GCC вообще уже не первый раз меня удивляет.

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 18:02:18
ARV
ks0 писал(а):
ARV писал(а):что лопает? объявление одноименных локальных переменных в разных модулях?
По объявлению в .h создает одну переменную, а не две. См. картинку выше.
картинка выше ничего не показывает, т.к. отладчик ловит контекст и показывает переменную по контексту. посмотрите map-файл - вот если там действительно память будет под одну переменную - тогда на самом деле странно...

Re: Вопросы по С/С++ (СИ)

Добавлено: Чт окт 02, 2014 18:14:14
ks0
ARV писал(а):картинка выше ничего не показывает, т.к. отладчик ловит контекст и показывает переменную по контексту. посмотрите map-файл - вот если там действительно память будет под одну переменную - тогда на самом деле странно...
Да одна, и дизассемблер по одному адресу отработку показывает.