LINUX.ORG.RU

блин ..
1) ты должен вызывать функцию, а не указатель на нее,
   array_name[i](paraments) это попытка вызвать хз что ..
2) какие проблемы вызывать функцию?

APPX:
void
test1(int a)
{
    printf("a1 = %d\n", a);
}

void
test2(int a)
{
    printf("a2 = %d\n", a);
}

void
test3(int a)
{
    printf("a3 = %d\n", a);
}

int
main()
{
    void (*fpa[3])();

    fpa[0] = test1;
    fpa[1] = test2;
    fpa[2] = test3;

    (*fpa[0])(1);
    (*fpa[1])(2);
    (*fpa[2])(3);

    /*
     * !!! кто нибудь объясните что это и почему это работает
     * это gcc такой мудь или это какой то там стандарт?
     * мне кажеться во время компиляции надо выдавать сообщение
     * типа "can't call uncallable object"
     * т/к fpa[0] это нифига не функция, а указатель на нее
     */
    fpa[0](11);
    fpa[1](12);
    fpa[2](13);
}

lg ★★
()

то что надо, спасибо

NikZ
() автор топика

2lg - г-н Б.С. относительно указателей на функцию в С++ пишет примерно вот что: "компилятор распознает - fpa[x] (в нашем случае) является указателем и вызовет ф-цию, на которую он указывает....разыменование указателя на ф-цию является необязятельным... необязательно испольльзовать & для получения адреса ф-ции" Думаю ввиду того что С++ является "надстройкой" над С, выше указанное верно и для С.

PETER ★★
()

Должен сказать, что как C так и С++ в подавляющем большинстве

контекстов treat функции и указатели на функции *одинаково* -- 

т.o. при наличии таких объявлений:

void func(int a)

{

}



void (*pfunc)(int) = func;

void (*arrfunc[1])(int) = { func; };



все следующие варианты кода правильны и эквивалентны:



func(1);

pfunc(1);

(*pfunc)(1);

(arrfunc[0])(1);

(*arrfunc[0])(1);





aa5779
()

блин фигня .. из-за этого кала у меня в коде и написано
fpa[0] = test1; когда писать то надо
fpa[0] = &test1; !!!

мне думается что правильнее было бы все таки сделать запрет конструкций когда у тебя функция и указатель на функцию фактически эквиваленты за исключением лишь той разницы что нельзя иметь массив функций.

lg ★★
()

lg какой запрет? зачем? имя функции есть адрес ее. добраться до тела функции в языке никак нельзя, ну и зачем городить лишний огород?

PS. вас же не смущает, что имя массива это указатель на первый элемент без всяких там &

anonymous
()

имя функции это не ее адрес! по имени лишь можно узнать ее адрес.
что значит "добраться до тела"?

меня совсем не смущает что массив это и есть указатель на первый элемент.
только ведь функция(имя функции) не является ни переменной ни чем то там еще. Что с функцией можно сделать? Только вызвать ее и получить ее адрес! - ВСЁ.

Если бы имя функции было бы ее адресом то почему нельзя делать так:
int a = 0x80484e8;
a(40);

Во! компилятор выдал:
called object is not a function - то что я и хотел чтобы он писал когда пытаешься вызвать указатель на функцию ..

> Плохому танцору ..
плохому танцору мешает лужа на краю сцены

lg ★★
()
Ответ на: комментарий от lg

lg Читай Страуструпа:) он все популярно объясняет. "Дизайн и эволюция языка С++" например очень полезная книжка, после ее прочтения обычно возникают более глубокие вопросы:)

kiv
()

lg

> имя функции это не ее адрес!

А что это тогда ??? :-)))) Ты чего, перегрелся ?? Это именно оно и есть (по крайней мере для С) и именно так и должно быть, исходя из парадигмы этого языка. Точно так же как инициализированный указатель определяет область памяти, имя функции определяет начало последовательности исполняемых инструкций. Не забывай - С это такой переносимый макроассемблер :-)))))) В плюсах уже другая парадигма, и там уже вопрос более тонок.

> когда писать то надо fpa[0] = &test1; !!!

Слава богу, ты не принимал участия в создании языка :-)))))

> правильнее было бы все таки сделать запрет конструкций когда у тебя функция и указатель на функцию фактически эквиваленты

И чем же, по-твоему, они должны отличаться ??? :-))))

> Если бы имя функции было бы ее адресом то почему нельзя делать так:

Потому что средствами языка не предусмотрено прямое обращение с адресами исполняемого кода. Что вполне логично, учитывая, что это _портабельный_ макроассемблер. :-))) По той же причине не может быть и адресной арифметики применительно к функциям. По той же причине исключили прямое присваивание целого указателю и обратно, бывшую изначально у K&R.

> плохому танцору мешает лужа на краю сцены

Учитывая, что на эту лужу никто до сих пор не жаловался, и мешает она исключительно тебе, может тебе сцену сменить ?? :-)))) Это не в порядке наезда :-))) Это в порядке предложения - есть масса хороших языков, где ни о каких указателях и адресах думать не надо :-)))

LamerOk ★★★★★
()

(lg)
>> Если бы имя функции было бы ее адресом то почему нельзя делать так:
>> int a = 0x80484e8; 
>> a(40); 
>> Во! компилятор выдал: 
>> called object is not a function 

Ну да ведь called object действительно is not a function. Он же
английским языком объявлен как int. А вот так -- можно:

int (*a)(int) = (int (*) (int)) 0x80484e8; 
a(40); 

Скомпилирует и не поперхнется. И даже работать будет, если, конечно,
адрес осмысленый.

(LamerOk)
> Потому что средствами языка не предусмотрено прямое обращение с 
> адресами исполняемого кода.

Ну здрасте пожалуйста. Еще как предусмотрено.

vnp
()

> Читай Страуструпа:)
в жопу C++

> А что это тогда ??? :-)))) Ты чего, перегрелся ?? Это именно оно и есть (по крайней мере для С) и именно так и должно быть, исходя из парадигмы этого языка.
не парь мне мозг .. имя функции нифига не ее адрес .. это просто набор каких то символов по которым ты можешь выяснить адрес и если надо прыгнуть на него.
Вообще я не знаю что такое парадигма и нехочу знать. Расскажи как из этой парадигмы вытекает что имя функции это ее адрес?

Возможно народ хочет сказать(но не совсем корректно выражается коворя что "имя функции это ее адрес") что компилятор во время прохода по коду и обнаружив ссылку(не вызов) на имя функции автоматически преабразует это дело в адрес функции? Вот я тоже запретил бы(да разве тут запретишь что, пишим компиляторы как хотим) если бы принимал участие в создании языка.

И вооще что такое имя функции с точки зрения конечного кода? правильно это некоторая метка. А что такое метка? адрес?

> int (*a)(int) = (int (*) (int)) 0x80484e8;
> a(40);
посмотрим что такое у нас a - a это указатель на какую-то функцию[или куда то там](НО НЕ ФУНКЦИЯ). Так какого же хрена тут компилятор не пишет что "called object is not a function" ведь called object действительно is not a function а указатель на нее.

как бы это не было я останусь при своем мнении и буду в коде писать:
void (*a)() = &test1;
(*a)(40);

APPX:
Breakpoint 1, main () at m.c:24
24 fpa[0] = &test1;
(gdb) n
25 fpa[1] = &test2;
(gdb) p fpa[0]
$1 = (void (*)()) 0x8048494 <test1>
(gdb) p *fpa[0]
$2 = {void ()} 0x8048494 <test1>
(gdb) p test1
$3 = {void (int)} 0x8048494 <test1>
(gdb) p &test1
$4 = (void (*)(int)) 0x8048494 <test1>
(gdb) p $3 == $4
$5 = 1
(gdb)


PS: вообще на меня можно не обращать внимания .. я в последнии пару дней не конструктивно настроен :(

lg ★★
()
Ответ на: комментарий от kiv

kiv (*) (2002-12-18 00:34:18.056):
> читай Страуструпа:) он все популярно объясняет.
Страуструп - графоман. Читабельный текст он пишет обычно с 3 попытки. Мозги у
него - набекрень.

Die-Hard ★★★★★
()

vnp

> Ну здрасте пожалуйста. Еще как предусмотрено.

Грешен, каюсь. Лажанулся. Чего-то меня с недосыпу переклинило.

lg

> это просто набор каких то символов по которым ты можешь выяснить адрес и если надо прыгнуть на него.

Во внутреннем представлении компилятора во время компиляции. А семантически это именно адрес памяти, по которой располагается исполняемый код.

> как бы это не было я останусь при своем мнении и буду в коде писать: ...

Тогда нужно быть последовательным до конца и отказаться от классово чуждых нам переменных :-)) Ведь что такое переменная ? "Это просто набор каких то символов по которым ты можешь выяснить адрес и если надо" взять его значение !!! :-)))) И пользоваться только указателями :-))))))

LamerOk ★★★★★
()
Ответ на: комментарий от Die-Hard

Почему то мне часто встречаются люди, которые делают громкие голословные заявления и чтоб набрать популярности, не прочь облить грязью других. Вот когда, Вы, дружок, напишите пару, тройку книжек, пользующиеся спросом, и в которых будут изложены Ваши мысли, реализованные на практике, тогда можно будет написать "Страуструп - графоман, а я хороший человек" :)

PETER ★★
()
Ответ на: комментарий от PETER

2PETER (*) (2002-12-19 08:34:27.222):
"Почему то мне часто встречаются люди", которые, не имея своего мнения,
следуя моде, создают себе кумиров и яростно защищают их от любых нападок.
:-)

Ей-богу, когда в качестве библии предлагается трактат человека, который
лишь с 3 попытки сумел кое-как связать свои мысли, мне становится смешно:
kiv (*) (2002-12-18 00:34:18.056):
" ...очень полезная книжка, после ее прочтения обычно возникают более
глубокие вопросы"

> Вот когда, Вы, дружок, напишите пару, тройку книжек, пользующиеся спросом,
А почему мсье так уверен, что я НЕ написАл "пару, тройку книжек", пользующихся
спросом"? :0)

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> ...следуя моде, создают себе кумиров и яростно защищают их от любых нападок.

Не стоит искажать факты - в своем послании я никого не защищал.

> А почему мсье так уверен, что я НЕ написАл "пару, тройку книжек", пользующихся спросом"

Факты в студию. Думаю всем будет интересно.

PETER ★★
()
Ответ на: комментарий от PETER

PETER (*) (2002-12-19 18:29:29.127):
> Не стоит искажать факты - в своем послании я никого не защищал.
Стало быть, просто так меня дерьмом окатил? Просто, штоп жисть медом не казалась?

Понятно. Не защищал, а обосрал.

Конструктивно.
:-)

Die-Hard ★★★★★
()

Ребята! Хватит! Почитайте Кернигана и Ритчи! Они создатели зыка, и у них ясно написано что имя это указатель на нее, как имя массива указатель на его первый элемент... Прочтите эту книжку, написно доходчиво, простым языком. Это форум, а не место для флейма...

OxiD ★★★★
()
Ответ на: комментарий от OxiD

OxiD (*) (2002-12-19 21:29:55.892):
> Это форум, а не место для флейма...
Каюсь, грешен... Поддался на провокацию, более не повторится.

> Почитайте Кернигана и Ритчи! 
Да, и их книжка - ДЕЙСТВИТЕЛЬНО библия программиста (ok, один из Еванглиев).

> Они создатели зыка, ...
Страуструп - тоже создатель ЦеПП. IMHO язык и создатель друг друга стОят :)
(на комментарии не отвечу)

> ...имя это указатель на нее, как имя массива указатель на его первый элемент...
А хренушки!

#include <stdio.h>

void test1(int a)
{
   printf("a1 = %d\n", a);
}

void test2(int a)
{
   printf("a2 = %d\n", a);
}

int main(void)
{
void (*fpa[2])();
  fpa[0] = test1;
  fpa[1] = test2;

  /*Would it be an array? If so, the following code should fail:*/
  (*fpa[0])(1);
  (*fpa[1])(2);

  /* This is ok, if YOU are right:*/
  fpa[0](11);
  fpa[1](12);

  /* And, what do you think about the following?:*/
  fpa[0] = &test1;
  fpa[1] = &test2;

  fpa[0](21);
  fpa[1](22);
  return 0;
}
Any comments?

Приведенный код со швистом компилялся без единого ворнинга и работал 
на gcc  и Compaq C V6.4-014 on Compaq Tru64 UNIX V5.1A (Rev. 1885)

Кстати, в полном соответствии со стандартом.

Согласись, указатели на функции - одно из ... ТОНКИХ мест языка.
Це, а не ЦеПП. 

З.Ы.
BTW, Страуструп не имеет ни малейшего отношения к созданию Це.

Die-Hard ★★★★★
()

Die-Hard

> А хренушки!

sh-2.05$ make x && ./x cc x.c -o x a1 = 1 a2 = 2 a1 = 11 a2 = 12 a1 = 21 a2 = 22 sh-2.05$ gcc -v Reading specs from /usr/lib/gcc-lib/i386-slackware-linux/2.95.3/specs gcc version 2.95.3 20010315 (release) sh-2.05$

Ну и почему "хренушки" ? :-)))))))))

LamerOk ★★★★★
()

У K&R не написано что имя функции это указатель на нее!
Единственно что там подмечено как я и писал
k&r: "Если имя функции входит в выражение не в позиции имени функции,
      соответствующей обращению к ней, то генерируется указатель на эту функцию"

me: Возможно народ хочет сказать(но не совсем корректно выражается коворя
    что "имя функции это ее адрес") что компилятор во время прохода по коду
    и обнаружив ссылку(не вызов) на имя функции автоматически преабразует это
    дело в адрес функции

так что:
int (*fp)() = test1; писать вполне допустимо .. хотя мне все равно больше нравится &test1.
(Не возникает вопроса что за символ такой test1 и ты написав &test1 в точности
знаешь что это адрес чего то)

насчет вызова указателя на функцию у k&r насколько я помню ничего не написано.
Единственно вот что есть:

INT (*COMP)()
    говорит, что COMP является указателем на функцию, которая
    возвращает значение типа INT. Первые круглые скобки здесь
    необходимы; без них описание

INT *COMP()
    говорило бы, что COMP является функцией, возвращающей указа-
    тель на целые, что, конечно, совершенно другая вещь.
    Использование COMP в строке

IF (*COMP)(V[J], V[J+GAP]) <= 0)
    полностью согласуется с описанием: COMP - указатель на функ-
    цию, *COMP - сама функция, а

(*COMP)(V[J], V[J+GAP])

    - обращение к ней.

lg ★★
()

fpa[0](11); в C99 конечно, как все уже посмотрели, корректно. Но у меня 99% уверенность что в С89 не так.

dilmah ★★★★★
()
Ответ на: комментарий от lg

lg (*) (2002-12-20 10:39:43.96):

> int (*fp)() = test1; писать вполне допустимо .. хотя мне все равно больше нравится &test1. (Не возникает вопроса что за символ такой test1 и ты написав &test1 в точности знаешь что это адрес чего то)

Недавно наступал на такие грабли: Был у меня некий полиморфик, я там с целью оптимизации переприсваивал некоему методу ту или иную функцию, как ты и рекомендуешь, типа method=&fname; почти везде fname у меня была некая функция, все работало. Но в одной редко случающейся ветке fname оказался не именем функции, а указателем на нее.

Аля-улю. Прграмма вдруг сыпанулась при очередном вызове method(); хотя до этого все срабатывало раз 10. Дебагер мало помогал - дело было после 3-4 форков.

Короче, часа два я провозился, пока допер. И все из-за дурацкой особенности Це мешать в кучу имя функции, указатель на нее и ссылку.

Die-Hard ★★★★★
()

Die-Hard: есть такая мулька .. но все равно мне как-то больше глаз радуется на &fname; даже не знаю почему :) - хотя просматривая свой код, часто встречаю у себя и так и так .. вобщем все замешано - все перемешано :)

lg ★★
()

K&R : цитирую:
"В Си сама функцияне является переменной, но можно определить ее как указатель на функцию и работать с ним как с переменной..."
Вот и теперь выписка из ANSI
"В первой версии языка для именующего выражения функции допускался только тип "функция",..., ANSI стандарт поощряет практику существующих компиляторов, разрешающих иметь одинаковый синтаксис для обращения к функциям специфированным как указатели...
"
Посмотрети исходники qsort эта функция требует как параметр указатель на ф-цию, без всяких &!!

OxiD ★★★★
()

> Возможно народ хочет сказать ...

Именно об этом народ тебе и толкует :-))))

> но не совсем корректно выражается

Тебе как надо ? Как обрабатывается исходный текст компилятором, или как он воспринимается программистом ???

> Не возникает вопроса что за символ такой test1

А сделать ctr+] на этом загадочном test1 не проще, в случае сомнений ???

> и ты написав &test1 в точности знаешь что это адрес чего то

Вот именно, что ты точно думаешь, что раз используется операция взятия адреса, значит test1 - это __данные__. Ведь для функции это __избыточно__, а нормальные сишные программеры ничего избыточного не пишут. А тут подстава. Плавно переходящая в засаду.

LamerOk ★★★★★
()

2LamerOK:
нормальный Cишный программер будет писать:
main(){int a;if(a!=234) if(a==0) a=1;else a=2;} да?

и вообще хорошь гнать - ты сути того о чем я писал вообще не понимаешь ..

2OxiD: ANSI - тухлятина :)

lg ★★
()
31 декабря 2003 г.

помогите кто знает пожалуйста.
 У меня есть функция
double **f(double**){}
и в main`e я создаю массив указателей на функции
double (*A[2][2])(int,int)={f1,f2}
А тепреь вопрос. Как передать мой массив указателей на функцию в функцию f.

max-max
()

Плюсы КАЛ. Смывайте за собой

dilmah ★★★★★
()

С Новым Годом чуваки:)

dilmah ★★★★★
()
Ответ на: комментарий от max-max

> помогите кто знает пожалуйста.
> У меня есть функция
> double **f(double**){}
> и в main`e я создаю массив указателей на функции
> double (*A[2][2])(int,int)={f1,f2}
> А тепреь вопрос. Как передать мой массив указателей на функцию в
> функцию f.

Я бы с тайпдефами это писал..

typedef (*cruncher_f)( int, int );
cruncher_f A[2][2];

my_func( cruncher_f ARR[2][] );

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> typedef (*cruncher_f)( int, int ); > cruncher_f A[2][2];

> my_func( cruncher_f ARR[2][] );

ну то есть конечно:

typedef double (*cruncher_f)( int, int ); cruncher_f A[2][2];

int my_func( cruncher_f ARR[2][] );

dilmah ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.