green Я отвечал на вопрос Nafanya-и, почему f() является функцией с переменным числом параметров. Ответ, в Си любая _cdecl функция это функция с переменным числом параметров.
Для WinXP sp3 фурычит. Функция с переменным числом параметров, без именного аргумента, считает сумму пяти переданных аргументов. Вроде получилось без асм-вставок. Код (Text): #include <intrin.h> #include <stdio.h> int func() { int i; int arg,sum=0; int* Address =(int*) _AddressOfReturnAddress(); Address++; for(i=0;i<5;i++) { arg= *Address; Address++; sum=arg+sum; } return(sum); } int main(void) { printf("%d",func(1,2,3,4,5)); getchar(); return 0; } Согласен. Точно. Вот где истина то крылась.
вариант, что тебе предлагал GoldFinch надежнее, тк ты кучу всего не учитываешь, что в принципе учитывают ва_листы: Код (Text): va_start(va, *_AddressOfReturnAddress()); то, что предлагает GRRRLPower предназначен для людей, которые не удивляются, что это работает, а знают почему это работает...
Да ладн, ребят, зачем так вот пряма эта периносимость нужна. Подумаешь пару асм-вставок ничево, в этом таково страшново нет.
Чисто так к сведению: попробовал добавить в сорц Код (Text): int myfunc (...); cl не схавал. с хотя бы одним именованным параметром хавает.
Rel Ну что там не знать... он объявляет указатель на двойное слово ( int* stack затем пихает в него базу стекового кадра, затем относительно базы берет смещение +2 и +3 DWORD'а в сторону старших адресов по стеку (return *(stack + 2) + *(stack + 3) так как это и будут адреса аргументов,затем берет значения аргументов по адресам(разыменовывает указатели), затем возвращает сумму аргументов . Смещение +1 DWORD - адрес возврата из функции. Вариант GoldFinch'а более туманен, т.к. нет законченной реализации...
ну смотри... как минимум первый вопрос: как определить количество переданных параметров... вопрос с подвохом, ответ - никак... ну кроме каких-нить нетривиальных хаков... функция должна как-то понять, какие параметры были в нее переданы... поэтому в ней (как например в функции printf) должен быть как минимум один явный параметр, указывающий, какие параметры были переданы в функцию... поэтому с точки зрения компилятора и нормального программиста функция func(...) бессмысленна... далее, следующий вопрос: как быть с параметрами, размер которых не равен 4 байтам? предлагаю тебе написать аналогичный код для функции, которая будет принимать два параметра типа char, и для функции, которая будет принимать два параметра типа double и посмотреть результат... эти вопросы, как и проблема кроссплатформенности (по разрядности (x86/x64)), и проблема кросскомпиляции (хотя бы msvc/gcc-семейство) решены в реализации ва_листов... и кстати, я считаю вариант с ва_листами вполне переносимым, необходимо только написать переносимую функцию получения указателя на параметры на стеке... хотя еще раз: func(...) - лишена смысла...
Мой способ оказался более-менее переносимым, на виндовсе и на линуксе работает же, компилируется в gcc и msvc http://codepad.org/QAQhi93m Только вот кому нужны эти функции без формальных параметров вообще...
GRRRLPower Такие вопросы с подколом задают на собеседованиях(больше это нигде не нужно). Напишут бред и спросят типа компилятор выдаст ошибку или нет. Смотришь - вроде бред, говоришь выдаст ошибку. А они как подпрыгнут от радости - "А вот и нет, пропустит!" Вот вы сможете ответить - сколько байт памяти занимает объект пустого класса? И почему?
GRRRLPower Какая ж это переносимость, если у вас в фактически отдельный вариант кода для каждого компилятора? Кроме того, как насчёт корректной работы с ключом оптимизации -fomit-frame-pointer ? А как насчёт других аппаратных платформ? x64, скажем? Эти ф-ции нужны. В С это позволяет сделать развязку прототипа ф-ции и её реализации в случае, если интерфейс ф-ции неопределён на этапе компиляции. В С++ определения func(...) выступают как default case различных перегрузок func - позволяют обработать вызов ф-ции с непредусмотренным набором параметров. Широко используется в метапрограммировании.
На собеседованиях такие вопросы задают только идиоты, а на нормальных собеседованиях даются практические задачи, чтобы программист мог порассуждать, порешать ее на глазах у того, кто принимает собеседование. Вплоть до того, что программисту будет дан доступ в интернет. Вот зачем мне знать на практике, что объект пустого класса занимает 1 байт, и что связано это с адресацией? Вы уже доказали, что можно быть хорошим теоретиком, но быдлокодером Я могу задать Вам более практические вопросы по C++, на которые Вы не факт, что ответите. Да хреновая это переносимость Думаю, если бы существовало хорошее переносимое решение, оно бы уже было включено в компиляторы.
Если Вы сами задали вопрос про размер экземпляра пустого класса, подразумевается, что Вы знаете ответ) А если нет - в поисковиках достаточно ответов.
GRRRLPower Но несмотря на найденные Вами недочеты в том участке кода, он кроссплатформенный и тестировался под тремя осями Windows (VS), Linux(KDevelop) и ОСРВ QNX (QNX Momentics IDE). А оптимизация участков кода относящихся к ядру позволила снизить время обработки одной отметки втрое - с 1,5 ms до 428 us. (Информация снята с QNX Application Profiler)
как интерфейс функции может быть неизвестен на этапе компиляции? пример будьте добры... я помню втирал кому-то уже на эту тему... основной смысл в том, что по стандарту sizeof(..) > 0... сообщение #6: да... ва_листы... +1... именно поэтому надо рассматривать практическую составляющую, а не теоретическую... я помню как то раз ответил что-то вроде: "зачем мне знать алгоритм сортировки пузырьком, если я могу за минуту его нагуглить"...
Если бы Вы еще знали такую практическую составляющую, что создавать объекты на стеке во много раз быстрее, чем в куче, думаю, снизили бы еще... Быть может, если функция extern? Вроде того: main.c: Код (Text): #include <stdio.h> extern int func(); //Только линковщик может найти эту функцию, но не компилятор int main(void) { int a = 2, b = 3; printf("%u + %u = %u", a, b, func(a, b)); return 0; } func.c: Код (Text): int func(int a, int b) { return a + b; } Но они требуют наличия хотя бы одного формального параметра у функции
Rel Например вычисление факториала 5. Код (Text): #include <intrin.h> #include <stdarg.h> #include <stdio.h> int func() { va_list vl; int i; int arg,Z=1; va_start(vl,*(int *)_AddressOfReturnAddress()); for(i=0;i<5;i++) { arg=va_arg(vl,int); Z=arg*Z; } return(Z); } int main(void) { printf("%d",func(1,2,3,4,5)); getchar(); return 0; } Интересно если скомпилить для x64 то (int *) ,будет указателем на 32-бита или 64-бита? GRRRLPower Почему Вы не связываете main.c и func.c через h-ник?
Только не пишите такое вычисление факториала где-нибудь на собеседовании... И про _AddressOfReturnAddress уже говорили, что не переносим не то что между системами, а даже между компиляторами. Ну вот, значит Вы еще и об extern не знаете... Уже и недостаток теоретических знаний проявляется)