Автор вопроса: Neco | Web-сайт:neco.pisem.net | ICQ: 247906854
Вопрос в теме плюс непонятный прикол:
Был проект (не мой), я взял из него четыре файла - два заголовочных и два .c. Подключил их к моему проекту (тыкнул правой кнопкой на браузере Workspace и сделал "добавить файлы"), после этого начал юзать и добился 0 на 0 (ошибок и предупреждений) при компиляции.
Теперь непонятность: при нажатии f7 вылезла unresolved external symvol для тех функций, что я использовал. Ощущение такое что файлы .c хоть и видны в проекте, но оттуда не читается инфа (тыкание на "найти определение" для функции выдаёт диалог для поиска файлов).
Кстати вот код ошибки
main.obj : error LNK2001: unresolved external symbol "void __cdecl encode_frame(long *,unsigned long)" (?encode_frame@@YAXPAJK@Z)
Кроме того, когда я создаю свой собственный *.cpp файл и в наглую всё копирую туда, то в одной паре (*.h+new.cpp) всё проканывает, а в другой что-то кричит про разницу между Си и Си++ (что именно уже не помню, т.к. много что пробовал и тот проект уже удалил).
Вообще есть какая-нибудь разница в расширениях *.c & *.cpp? В свойствах файла эти два языка стоят через дробь - типа одно и то же, а так ли это?
И ещё. Когда я создал свой .cpp и удалил из проекта .с, то обнаружил ещё одну пакость: функции из файла .h всё ещё ссылались на тела функций в файле .с, хотя в проекте его уже не было, а вместо него был одноимённый .cpp. И чтоб показать мне эти тела, сишник открывал этот файл (.с) с диска и упрямо настаивал, что этот прототип ссылается именно на этот файл, а не на тот, что у меня в проекте. 8(
Объясните мне кто-нибудь, пожалуйста, что за хрень происходит! Ведь в том проекте, откуда я эти файлы взял всё работало на пять. Но правда там все файлы были .с, а у меня в проекте все .срр.
В чём разница и как выйти из положения?
void main(){
printf("number=%d\n",func(10));
get
}
Вот так не ругается, компилит, выдает ехе, правда при запуске вылетает, пока не понял почему. А "тыкание" на поиск (find definition) исправно выкидывает в файл "code.c"
В принципе, это эквивалентно тому, чтобы просто расположить свой main в файле .c, а не .cpp. Это что же выходит, сто Си и Сплюшка несовместимы? Имхо, такого не может быть.
Несовместимость тут ни при чём.
Ты пытаешься использовать функцию, которой нет в твоем проекте. Декларация есть (в файле "decl.h", а сам файл, в котором содержится функция ("code.c" ты не включил в проект.
Если смущает, что #include "code.c" указано в main.cpp, можешь перенести эту строку в decl.h. Главное, чтобы эта строка была.
Си и Сплюшка несовместимы?
Ты же видишь, что программа работает. Какая тут может быть несовместимость?
>Тебя же не удивляет, что в JavaScript нет функции void main()?
Мне проще - я не знаю джавы. 8)
>Ты пытаешься использовать функцию, которой нет в твоем проекте.
Функция есть в проекте - файл code.c виден в дереве, а это значит, что он учитывается компилятором. Вот если я при открытом проекте открою из проводника какой-нибудь сырец, то он отобразится у меня в моём открытом проекте. Но при этом он в него НЕ включится (он не будет ни компилироваться [если требует инклудов], ни ссылаться на мои функции) и НЕ будет виден в дереве проекта. А вот если я тыкну на него правой кнопкой и выберу Add to project ->MyPro, то он сразу очутится у меня в дереве и дальнейшая его успешность зависит от правильности написания.
Из этого я делаю вывод, что необязательно подключая к проекту файл инклудить его в главном. Тем более, что если переименовать файл code.c из моего примера на code.cpp (или main.cpp в main.c), то всё заработает на "ура". А всё дело я думаю в том, что "прототип функции" (в отличие от переменной) автоматом объявляется extern'ом (переменная же static'ом), а т.к. при этом необходимо, что в моём проекте было лишь одно одномённое с этим прототипом тело функции, то видать дело происходит так: процедура (к примеру, main) видит только прототип (который в инклуднутом *.h) и вызывает по нему функцию. Прототип "смотрит" из какого типа исходника (сишного или сплюшного) к нему обратились (точнее в каком типе расположен *.h) и ищёт тело в таком же. Если не находит, то unresolved external symvol, что видимо надо читать как "чувак, ты объявил external'ом эту хрень, а хреновины я не вижу".
Эту теорию я тока что опробовал включив в свой проект два почти одинаковых файла code.cpp и code.c. В одном моя func умножала аргумент на 2 перед возвратом, а в другом на 3.
Так вот когда я заключал инклуд в такие вот тиСки:
extern "C" {
#include "decl.h"
}
то она main печатала number=30, а когда я комментировал вот так:
//extern "C" {
#include "decl.h"
//}
то начинала печатать number=20.
В обоих случаях файлы .c или .cpp я не инклудил, т.к. раньше я пытался это делать, но потом обнаружил, что после этого шаг влево или вправо (при операциях с файлами - добавлении нового к примеру) вызывает redefenition, т.е. это надо дополнительно инструкции для препроцессора вводить, типа:
#ifndef MYDEF {
#define MYDEF
// и далее все объявления...
#endif
Короче, имхо, гимор это и для нормального исходника, видимо, надо транслировать нужный код, а для этого, млин, надо уяснить разницу между Си и СиПиПи.
---------------------------------
Запомните, дети! "Вилька" и "тарелька" пишутся без мягкого знака, а "сол" и "фасол" с мягким знаком. Что очень трудно понять.
---------------------------------
Вот такой же и этот Си. 8)
И даже того, что Java и JavaScript - разные языки?
Запомните, дети! "Вилька" и "тарелька" пишутся без мягкого знака, а "сол" и "фасол" с мягким знаком. Что очень трудно понять.
Для того, чтобы таких проблем не возникало, нужно для ознакомления с языком С/С++ прочитать какую-нибудь одну хорошую книжку по нему. Метод обучения "тыком", который очень неплохо работает в случае с VB, здесь не проходит. А то и получается, что аццы MFC не знают, что адрес массива обозначается его именем. После прочтения какой-нибудь достаточно хорошей книжки, Си(++) кажется крайне логичным и стройным языком. Это не просто слова, я через это проходил.
Функция есть в проекте - файл code.c виден в дереве, а это значит, что он учитывается компилятором
То, что он есть в дереве - ничего не значит. Учитывает его линкер или нет - видно по unresolved external symbol. А то что действительно учитывается в твоём проекте, можешь посмотреть в файле .dsp
Из этого я делаю вывод, что необязательно подключая к проекту файл инклудить его в главном
Вывод ни на чем не основанный. Необязательно в главном, но инклюдить - обязательно
В асме тоже так: файл в дереве отображается, но только отображается, не более. Нужно оговаривать include "myInclude.inc". Дерево - это всего лишь кусочек проводника, не более того.
Впрочем ладно, делай как хочешь...
Не мне ж на грабли наступать