2009-11-11 4 views
8

Я пытаюсь выяснить, что делает следующий код в C?Сложный C-литье объяснение

((void(*)())buf)(); 

где 'ЬиЙ' является char массивом.

+5

Ищите программу под названием «cdecl». Загрузить. Вставьте в него объявление. Будьте просветлены. –

+0

@Paul: Я попробую это и надеюсь, что он не убьет мою машину! –

+1

Этот код может обоснованно отображаться в JIT или в ОС в динамическом компоновщике/загрузчике. Как говорили другие, это страшно, но только если вы столкнулись с ним в типичном приложении. На своем месте, это не страшно, просто сложный материал. –

ответ

21

Давайте это один шаг за один раз.

void(*)() 

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

(void(*)())buf 

просто бросает buf в эту функцию указателя функции. Наконец,

((void(*)())buf)(); 

вызывает эту функцию.

Таким образом, весь оператор «интерпретирует buf как указатель на функцию void без аргументов и вызывает эту функцию».

+3

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

+0

Исправить меня, если я ошибаюсь, но разве это не значение указателя (адрес массива), которое рассматривается как функция, а не содержимое массива? «интерпретировать * значение * в buf» звучит немного похоже на то, что вы говорите, что содержимое интерпретируется как указатель на функцию. –

+3

-1 (не совсем): принимает неопределенные аргументы в C – pmg

9

Он отличает buf к указателю функции типа void(*)() (функция, возвращающая ничего/пустое и принимающая неуказанные аргументы) и вызывает его.

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

+0

Почему вы можете использовать массив для указателя функции? Есть ли статья, которая объясняет это? –

+0

Указатель - это всего лишь набор байтов, как и любое другое значение (которое может быть представлено на C как массив символов). Вероятно, вы обнаружите, что в другом месте программы обратное это было сделано: 'char * buf = (char *) function;' или что-то подобное. – Wernsey

+0

Вы можете сделать это, потому что это C - вы можете делать все, что хотите. Это ужасная идея, но вы можете это сделать. – Clyde

1

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

2

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

+1

-1 (не совсем): принимает неуказанные аргументы в C – pmg

+0

@pmg, спасибо. Я отредактировал ответ. –

4

Приводит buf к типу void (*)(), указателю на функцию, которая принимает неопределенные параметры и ничего не возвращает. Затем он вызывает функцию по этому адресу (две самые правые скобки).

+0

-1 (не совсем): принимает неуказанные аргументы в C – pmg

+0

@pmg, хорошая точка. –

0

вызывает указатель на функцию. функция не имеет аргументов.

Function Pointer - Wikipedia

+1

-1 (не совсем): функция имеет неопределенные аргументы в C – pmg

+0

Функция имеет (дана) аргументов. Тип функции имеет неуказанные параметры. –

+0

Конечно, учитывая другие ответы, я оставлю сообщение так, как есть. – segy

2
 
((void(*)())buf)(); 
\------------/   cast `buf` to 
\---------/   type: pointer to function accepting a fixed but 
           unspecified number of arguments and 
           returning void 
\----------------/  and call that "function" 
+0

+1 Вы правы относительно неопределенного количества параметров. Если бы вы разъяснили пример, вы, вероятно, получили бы больше признательности за свое понимание :) – Andomar

1

Возможно, вы найдете «экспертное программирование», хорошее чтение - распаковка такого рода в одной из глав, если я правильно помню. Прошло много времени с тех пор, как я прочитал его, но я помню, что в то время это стоило усилий. http://www.amazon.com/Expert-Programming-Peter-van-Linden/dp/0131774298

5

Как правило, я использую команду «cdecl», когда я сталкиваюсь с объявлением ума. Пример:

[[email protected]]$ cdecl 
Type `help' or `?' for help 
cdecl> explain (void(*)())buf 
cast buf into pointer to function returning void 

Хотя есть случаи, когда я желаю, что есть инструмент там, что объясняет выход «Cdecl»:/