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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

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

Какую то Вы, сударь, ерунду тут наговорили... :facepalm:
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

ks0 писал(а):Из .с объявление выкинуть, а из .h выкинуть extern.
:facepalm:
Правильно, нафиг эта переменная вообще нужна - повыкидывать её к чертям, да и делов... :)))
Реклама
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

Аlex писал(а):Правильно, нафиг эта переменная вообще нужна - повыкидывать её к чертям, да и делов... :)))
Не домысливайте, объявление char GlobalVar1 оставить, только модификатор extern убрать.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

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

ЗЫ: Товарищи ! Думайте, перед тем, как что-то написать, вас читают начинающие !
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

Аlex писал(а):Вы валерьянки что-ли перепили ?
Да, аргумент!
А по существу?
Реклама
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Сообщение Gudd-Head »

Да, а по существу? Да так, чтобы чайникам было понятно :)
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Реклама
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение А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 - это обычное включение в файл кода, находящегося в другом файле.
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

Для этого в начале и конце каждого заголовочного файла пишется следующая директива препроцессора

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

#ifndef _MODULE_H
#define _MODULE_H

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

#endif
Это гарантирует, что файл обрабатывается компилятором лишь единожды, и никаких дубликатов объявлений не появляется. А без этой конструкции компилятор просто выругается и тоже никаких дубликатов не будет.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

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

ЗЫ: И по вышеприведённой ссылке всё написано правильно. Там писал человек, уровнем выше некоторых тут присутствующих на несколько голов.
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

Это же легко проверить

Изображение
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18673
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

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

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

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

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

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

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

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

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

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

Мой уютный бложик... заходите!
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

ks0 писал(а):Это же легко проверить
Изображение
Понятия не имею, что Вы этим "проверили"...

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

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

Сообщение ks0 »

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

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

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

Поэтому extern редкоиспользуемый костыль, если есть .h файл, то достаточно переменную объявить там.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

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

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

Сообщение ks0 »

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

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

Сообщение ks0 »

Аlex, вероятно Вы правы все-таки. Только тогда разобраться надо почему GCC это лопает.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18673
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

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

Мой уютный бложик... заходите!
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

ARV писал(а):что лопает? объявление одноименных локальных переменных в разных модулях?
По объявлению в .h создает одну переменную, а не две. См. картинку выше. Компоновщик не ругается. Книжки по С++ однозначно такую конструкцию запрещают. В Си все должно быть еще однозначнее :\
Короче пойду умных людей подопрашиваю. GCC вообще уже не первый раз меня удивляет.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18673
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

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

Мой уютный бложик... заходите!
Аватара пользователя
ks0
Прорезались зубы
Сообщения: 238
Зарегистрирован: Чт фев 28, 2013 14:16:10

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

Сообщение ks0 »

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

Вернуться в «Разные вопросы по МК»