|
Программирование >> Арифметические и логические операции
*this; int main() C1 c1, c2; c1 = c2; Некоторые считают, что здесь должен быть вызван дефолтный оператор присваивания C1::operator=(C1&) (а не C1::operator=(C0&)), который, собственно, уже вызовет C0::operator=(C0&). Понадобилось написать метод объекта на ассемблере, а Ватком строит имена так, что это невозможно - стоит знак : в середине метки, типа xcvvxx:svvsvv. Какие ключи нужны чтобы он такого не делал? class A; extern C int ClassMetod Call2Asm (A*, ...); class A int Call2Asm(...) return ClassMetod Call2Asm(this, ...); Сожрет любой Cpp компилятор. Для методов, которые вы хотите вызывать из asm - аналогично... Так можно произвольно менять генерацию имён в Watcom: #pragma aux var * ; И var будет всегда генериться как var. А ещё лучше в данном случае использовать extern C и для переменных также. После имени функции говорит о том, что Вaтком использует передачу параметров в регистрах. От этого помогает cdecl перед именем функции. Пример: extern C int cdecl my func(); Скажите почему возникает stack overflow и как с ним бороться? Причины: 1. Велика вложенность функций 2. Слишком много локальных переменных (или большие локальные массивы); 3. Велика глубина рекурсии (например, по ошибке рекурсия бесконечна) 4. Используется call-back от какого-то драйвера (например, мыши); В пунктах с 1 по 3 - проверить на наличие ошибок, по возможности сделать массивы статическими или динамическими вместо локальных, увеличить стек через stklen (для C++), проверять оставшийся стек самостоятельно путем сравнения stklen с регистром SP. В пункте 4 - в функции, использующей call-back, не проверять стек; в связи с тем, что он может быть очень мал - организовать свой. Любители Ваткома! А что, у него встроенного ассемблера нет что ли? Конструкции типа asm не проходят? Встроенного asma у него на самом деле нет. Есть правда возможность писать asm-функции через #pragma aux Например: #pragma aux DWordsMover = \ mov esi, eax , \ mov edi, ebx , \ jcxz @@skipDwordsMover , \ rep movsd , \ @@skipDWordsMover: , \ parm [ebx] [eax] [ecx] modify [esi edi ecx] void DWordsMover (void* dst, void* src, size t sz); При создании 16-bit OS/2 executable Watcom требует либу DOSCALLS.LIB. Причем ее нет ни в поставке Ваткома ни в OS/2. Что это за либа и где ее можно достать? Называют ее теперь по другому. В каталоге LIB286 и LIB386 есть такая OS2286.LIB. Это то, что вам нужно. Назовите ее DOSCALLS.LIB и все. BC не хочет понимать метки в ассемблерной вставке - компилятор сказал, что не определена эта самая метка. Пришлось определить метку за пределами ASM-блока. Может быть есть более корректное решение? Загляните в исходники RTL от C++ 3.1 и увидите там нечто красивое. Например: #define I asm ........ I or si,si I ]z m1 I mov dx,1 m1: I int 21h и т.д. Есть - компилировать с ключом -B (via Tasm) aka #pragma inline. Правда, при этом могут возникнуть другие проблемы: если присутствуют имена read и read (например), то компилятор в них запутается. Было замечено, что Борланд (3.1, например) иногда генерит разный код в зависимости от ключа -B. Как правило, при его наличии он становится осторожнее чинает понимать, что не он один использует регистры. Почему при выходе из программы под BC++ 3.1 выскакивает Null pointer assignment ? Это вы попытались что-то записать по нулевому адресу памяти, чего делать нельзя. Типичные причины: ♦ используете указатель, не инициализировав его. Например: char *string; gets(string); ♦ запрашиваете указатель у функции, она вам возвращает NULL в качестве ошибки, а вы этого не проверяете. Например: FILE *f = fopen( gluck , w ); putcCX, f); Это сообщение выдаётся только в моделях памяти Tiny, Small, Medium. Механизм его возникновения такой: в сегменте данных по нулевому адресу записан борландовский копирайт и его контрольная сумма. После выхода из main контрольная сумма проверяется и если не совпала - значит напорчено по нулевому адресу (или рядом) и выдаётся сообщение. Как отловить смотрите в HELPME!.DOC - при отладке в Watch поставить выражения: *(char*)0,4m (char*)4 потом трассировать программу и ловить момент, когда значения изменятся. Первое выражение - контрольная сумма, второе - проверяемая строка. При запуске программы из BC (Ctrl-F9) все работает нормально, а если закрыть BC, то программа не запускается. Что делать? Если вы используете BWCC, то эту либу надо грузить самому - просто среда загружает BWCC сама и делаёт её доступной для программы. Советуем вам пользоваться таким макросом: #define BEST EnableBWCC(TRUE); \ EnableCtl3d(TRUE); \ EnableCtl3dAutosubclass(TRUE) Потом в InitMainWindow пишете: BEST; и все будет хорошо. Вообще-то правильнее OWLевые экзепшены ловить и выдавать сообщение самостоятельно. Заодно и понятнее будет отчего оно произошло: int OwlMain(int /*argc*/, char* /*argv*/[]) int res; TRY res = App().Run(); CATCH((xmsg &s) Какие хочешь ексепшены MessageBox(NULL, Message , s.c str()); return res; Почему иногда пытаешься проинспектировать переменную в BC++ во время отладки, а он ругается на inactive scope? Вот пример отлаживаемой программы. Компилим так: bcc -v is.cpp === Cut === #include <iostream.h> void a() int b = 7; cout << b << endl; void main() a(); === Cut === Входим в TD. Нажимаем F8, оказываемся на строке с вызовом a(). Пытаемся inspect b. Естественно, не находим ничего. А теперь перемещаем курсор в окне исходника на строку с cout, но трассировкой в a() не входим и пробуем посмотреть b. И вот тут-то и получаем inactive scope. Были у меня две структуры подобные, но вторая длиннее. Сначала в функции одна была, я на ней отлаживался, а потом поменял на вторую, да только в mallocе, где sizeof(struct ...) старое оставил, и налезали у меня данные на следующий кусок хипа Для избегания подобной баги можно в С сымитировать Сиплюс-ный new: #define tmalloc(type) ((type*)malloc(sizeof(type))) #define amalloc(type, size) ((type*)malloc(sizeof(type) * (size))) Более того, в последнем define можно поставить (size) + 1, чтобы гарантированно избежать проблем с завершающим нулём в строках. Можно сделать иначе. Поскольку присвоение от malloc() как правило делают на стилизованную переменную, то нужно прямо так и писать: body = malloc(sizeof(*body)); Теперь вы спокойно можете менять типы не заботясь о malloc(). Ho это верно для Си, который не ругается на присвоение void* к type* (иначе пришлось бы кастить поинтер, и компилятор изменения типа просто не пережил бы). Вообще в С нет смысла ставить преобразования от void* к указательному типу явно. Более того, этот код не переносим на C++ - в проекте стандарта C++ нет malloc() и free(), а в некоторых компиляторах их нет даже в hosted с++ заголовках. Проще будет: #ifdef cplusplus # define tmalloc(type) (new type) # define amalloc(type, size) (new type[size]) #else # define tmalloc(type) malloc(sizeof(type)) # define amalloc(type, size) malloc(sizeof(type) * (size)) #endif Суммируя вышеперечисленное, можно отметить следующее. Необходимо скомбинировать все варианты: #ifdef cplusplus # define tmalloc(type) (new type) # define amalloc(type, size) (new type[size]) # define del(var) delete(var) #else # define tmalloc(type) ((type*)malloc(sizeof(type))) # define amalloc(type, size) ((type*)malloc(sizeof(type) * (size))) # define del(var) free(var) # define vmalloc(var) ((var) = malloc(sizeof(*(var)))) #endif Я не понимаю, почему выдаются все файлы, вроде указал, что мне нужны только c атрибутом директория? Можно, конечно, проверять ff attrib, что нашли findfirst и findnext, но это мне кажется не выход. Может я что не дочитал или не понял? done = findfirst( *.* , &onlydir, FA DIREC); while(!done) cout << onlydir.ff name << endl; done = findnext(&onlydir); Это не баг, это фича MS DOS. Если атрибут установлен, то находятся как файлы с установленным атрибутом, так и без него. Если не установлен, то находятся только файлы без него. И проверять ff attrib вполне выход. Вы не дочитал хелп про findfirst/findnext. Создается файл: fopen(FPtr, w ). Как может случиться, что структура пишется на диск некорректно? fopen (FPtr, wb ); Режим не тот... При печати функцией cprintf в позицию экрана x = 80, y = 25 происходит автоматический перевод строки (сдвиг всего экрана на строку вверх и очистка нижней строки) и это знакоместо так и остается пустым. Может кто знает, как вывести символ в это знакоместо? Нажмите Ctrl+F1 на слове wscroll в Борландовском IDE. Правда, printf это не вылечит, так как его вывод идёт не через борландовскую библиотеку. Как очистить текстовый экран в стандарте ANSI C? Никак, в ANSI C нет понятия экрана и текстового режима. В Turbo С так: #include <conio.h> void main(void) clrscr(); Можно также попробовать выдавать ANSI ESC-коды или сделать следующее: #include <stdio.h> #define NROWS 2*25 /*
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |