указатель функции typedef?

<p>я учусь динамически загружать dll, но я не понимаю, что это за строка</p><pre><code>typedef void (*functionfunc)(); </code></pre><p>у меня есть несколько вопросов. если кто-то сможет ответить на них, я был бы благодарен.</p><ol> <li>почему используется <code>typedef</code>?</li> <li>синтаксис выглядит странно; после <code>void</code> не должно быть имени функции или чего-то еще? это похоже на анонимную функцию.</li> <li>создан ли указатель на функцию для хранения адреса памяти функции?</li> </ol><p>так что я в замешательстве в данный момент; вы можете уточнить вещи для меня?</p>

<p><code>typedef</code> - это языковая конструкция, которая связывает имя с типом.<br> вы используете его так же, как вы использовали бы, например, оригинальный тип</p><pre><code> typedef int myinteger; typedef char *mystring; typedef void (*myfunc)(); </code></pre><p>используя их как</p><pre><code> myinteger i; // is equivalent to int i; mystring s; // is the same as char *s; myfunc f; // compile equally as void (*f)(); </code></pre><p>как видите, вы можете просто заменить имя типа <em> </em> определением, приведенным выше.<br></p><p>сложность заключается в указателе на синтаксис функций и читаемость в c и c++, а <code>typedef</code> может улучшить читаемость таких объявлений. однако синтаксис является подходящим, поскольку функции - в отличие от других более простых типов - могут иметь возвращаемое значение и параметры, таким образом, иногда длинное и сложное объявление указателя на функцию.</p><p>читаемость может стать очень сложной с указателями на массивы функций и некоторые другие, даже более косвенные варианты.</p><p>чтобы ответить на ваши три вопроса</p><ul> <li> <p><strong>почему используется typedef?</strong> для облегчения чтения кода - особенно для указателей на функции или имена структур.</p> </li> <li> <p><strong>синтаксис выглядит странно (в указателе на объявление функции)</strong> этот синтаксис не очевиден для чтения, по крайней мере, в начале. использование объявления <code>typedef</code> вместо этого облегчает чтение</p> </li> <li> <p><strong>создан ли указатель на функцию для хранения адреса памяти функции?</strong> да, указатель на функцию сохраняет адрес функции. это не имеет ничего общего с конструкцией <code>typedef</code>, которая только облегчает написание/чтение программы; компилятор просто расширяет определение typedef перед компиляцией фактического кода.</p> </li> </ul><p>пример:</p><pre><code>typedef int (*t\_somefunc)(int,int); int product(int u, int v) { return u*v; } t\_somefunc afunc = &product; ... int x2 = (*afunc)(123, 456); // call product() to calculate 123*456 </code></pre>

<ol> <li> <p><code>typedef</code> используется для псевдонимов типов; в этом случае вы используете псевдоним <code>functionfunc</code> для <code>void(*)()</code>.</p> </li> <li> <p>действительно, синтаксис выглядит странно, взгляните на это:</p> <pre><code>typedef void (*functionfunc) ( ); // ^ ^ ^ // return type type name arguments </code></pre></li> <li> <p>нет, это просто говорит компилятору, что тип <code>functionfunc</code> будет указателем на функцию, а не <em>define</em>, например, так:</p> <pre><code>functionfunc x; void dosomething() { printf("hello there\n"); } x = &dosomething; x(); //prints "hello there" </code></pre></li> </ol>

<p>без слова <code>typedef</code> в c++ объявление объявляло бы переменную <code>functionfunc</code> типа указатель на функцию без аргументов, возвращая <code>void</code>.</p><p>с <code>typedef</code> вместо этого он определяет <code>functionfunc</code> как имя для этого типа.</p>

<p>если вы можете использовать c++ 11, вы можете использовать ключевые слова <code>std::function</code> и <code>using</code>.</p><pre><code>using functionfunc = std::function<void(int arg1, std::string arg2)>; </code></pre>

<pre><code>#include <stdio.h> #include <math.h> /* to define a new type name with typedef, follow these steps: 1. write the statement as if a variable of the desired type were being declared. 2. where the name of the declared variable would normally appear, substitute the new type name. 3. in front of everything, place the keyword typedef. */ // typedef a primitive data type typedef double distance; // typedef struct typedef struct{ int x; int y; } point; //typedef an array typedef point points[100]; points ps = {0}; // ps is an array of 100 point // typedef a function typedef distance (*distancefun\_p)(point,point) ; // type\_def distancefun\_p to be int (*distancefun\_p)(point,point) // prototype a function distance finddistance(point, point); int main(int argc, char const *argv[]) { // delcare a function pointer distancefun\_p func\_p; // initialize the function pointer with a function address func\_p = finddistance; // initialize two point variables point p1 = {0,0} , p2 = {1,1}; // call the function through the pointer distance d = func\_p(p1,p2); printf("the distance is %f\n", d ); return 0; } distance finddistance(point p1, point p2) { distance xdiff = p1.x - p2.x; distance ydiff = p1.y - p2.y; return sqrt( (xdiff * xdiff) + (ydiff * ydiff) ); } </code></pre>

<p>для общего случая синтаксиса вы можете посмотреть <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf">приложение a стандарта ansi c</a> .</p><p>оттуда в форме бэкуса-наура вы можете видеть, что <code>typedef</code> имеет тип <code>storage-class-specifier</code>.</p><p>в типе <code>declaration-specifiers</code> вы можете видеть, что вы можете смешивать множество типов спецификаторов, порядок которых не имеет значения.</p><p>например, правильно сказать,</p><pre><code>long typedef long a; </code></pre><p>определить тип <code>a</code> в качестве псевдонима для <code>long long</code>. итак, чтобы понять typedef для исчерпывающего использования, вам нужно обратиться к некоторой форме backus-naur, которая определяет синтаксис (есть много правильных грамматик для ansi c, не только для iso).</p><p>когда вы используете typedef для определения псевдонима для типа функции, вам нужно поместить псевдоним в то же место, где вы поместили идентификатор функции. в вашем случае вы определяете тип <code>functionfunc</code> как псевдоним для указателя на функцию, чья проверка типов отключена при вызове и ничего не возвращает.</p>