Форум программистов, компьютерный форум, киберфорум
Наши страницы
C для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.60/25: Рейтинг темы: голосов - 25, средняя оценка - 4.60
mappy89
2 / 2 / 2
Регистрация: 16.10.2011
Сообщений: 179
1

Ссылка goto из одной функции в другую

06.05.2012, 12:26. Просмотров 4539. Ответов 20
Метки нет (Все метки)

Доброго времени суток! Возник следующий вопрос: неужели имея в программе 2 функции, нельзя из одной из них методом goto перейти в другую функцию?

C
1
2
3
4
5
6
7
8
9
10
11
12
13
void main (void)
{
somefunction();
 
gohere:
printf('blah');
}
 
void newfunc(void)
{
...
goto gohere:
}
Либо как можно обойти эту проблему?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.05.2012, 12:26
Ответы с готовыми решениями:

Передача значений из одной функции в другую
Как сделать чтоб с этой функции: int string(char * ch) { int big=0,small=0,i; for(i=1;i<ch;++i)...

Перенос значения из одной функции в другую
Всем привет! :) Такая проблема: нужно сделать программу, которая считывает текст из некоего файла,...

Как перенести переменные из одной функции в другую?
Есть программа #include <stdio.h> #include <locale.h> #include <time.h> int date() {...

Передача значения массива из одной функции в другую
В функции re вводятся 2 строковые переменные Как передать их значения в другую функцию?

Переход goto от одной функций к другой
Всем добрый день! Почему в данном коде не получается перейти от одной функций к другой методом...

20
go
Эксперт С++
3637 / 1369 / 243
Регистрация: 16.04.2009
Сообщений: 4,527
06.05.2012, 13:13 2
Цитата Сообщение от mappy89 Посмотреть сообщение
Либо как можно обойти эту проблему?
Можно
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main (void)
{
    somefunction();
    goto gohere;
 
    gohere:
    printf('blah');
}
 
void newfunc(void)
{
    ...
    return ;
}
Только для чего?
0
mappy89
2 / 2 / 2
Регистрация: 16.10.2011
Сообщений: 179
06.05.2012, 13:41  [ТС] 3
Забыл пояснить, данный код писался в качестве примера и не более. Вопрос заключается в том, как обойти ограничение диапазона действия оператора goto с одной функции на несколько?
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10494 / 6202 / 1559
Регистрация: 25.07.2009
Сообщений: 11,806
06.05.2012, 14:54 4
mappy89, ничего не выйдет. Просто нельзя из тела одной функции перейти в тело другой. Есть тому объяснение, но сложное.
0
06.05.2012, 14:54
go
Эксперт С++
3637 / 1369 / 243
Регистрация: 16.04.2009
Сообщений: 4,527
06.05.2012, 15:24 5
mappy89, все возможно. Используйте глобальный переменные, а потом в самой функции прыгайте.

Добавлено через 56 секунд
Цитата Сообщение от easybudda Посмотреть сообщение
Просто нельзя из тела одной функции перейти в тело другой.
На прямую, без условно, нельзя. Но можно окольными путями.
0
mappy89
2 / 2 / 2
Регистрация: 16.10.2011
Сообщений: 179
06.05.2012, 17:13  [ТС] 6
Go, приведите пример реализации, не понимаю как это можно сделать с глобальной переменной
0
go
Эксперт С++
3637 / 1369 / 243
Регистрация: 16.04.2009
Сообщений: 4,527
06.05.2012, 17:17 7
mappy89, см. пост #2.
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10494 / 6202 / 1559
Регистрация: 25.07.2009
Сообщений: 11,806
06.05.2012, 18:42 8
Цитата Сообщение от go Посмотреть сообщение
mappy89, см. пост #2.
Ну и с какого бока там безусловный переход в тело функции? Нужно что-то вроде
C
1
2
3
4
5
6
7
void f1(void) {
    Label:
    printf("blah blah blah");
}
void f2(void) {
    goto Label;
}
а так работать ни за какие коврижки не будет.
0
Kastaneda
Jesus loves me
Эксперт С++
5042 / 3060 / 351
Регистрация: 12.12.2009
Сообщений: 7,736
Записей в блоге: 2
Завершенные тесты: 1
06.05.2012, 19:10 9
Цитата Сообщение от easybudda Посмотреть сообщение
а так работать ни за какие коврижки не будет.
если только за очень вкусные коврижки
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
 
void *ptr = NULL;
 
void* f0()
{
lbl:
    if (ptr != NULL) {
        printf("Hello\n");
    }
 
    return &&lbl;
}
 
void f1(void *exit)
{
    asm("pushl %0" :"=d"(exit));
    goto *ptr;
}
 
int main()
{
    ptr = f0();
    f1(&&exit);
 
exit:
    return 0;
}
только такие "коврижки" есть только в gcc/MinGW
0
Evg
Эксперт CАвтор FAQ
20034 / 7602 / 582
Регистрация: 30.03.2009
Сообщений: 21,232
Записей в блоге: 30
06.05.2012, 19:18 10
Цитата Сообщение от Kastaneda Посмотреть сообщение
если только за очень вкусные коврижки
Внимательно читай описание в gcc. Такой код если и заработает, то некорректно
0
easybudda
Модератор
Эксперт JavaЭксперт CЭксперт С++
10494 / 6202 / 1559
Регистрация: 25.07.2009
Сообщений: 11,806
06.05.2012, 19:22 11
Kastaneda, ну разве что вот так как-нибудь, но это мрак какой-то. Думаю цель была упростить задачу, а тут всё с точностью наоборот получилось. Мало того, какими-нибудь ещё более витиеватыми путями оно и под cl сделается, было бы, за чем...

ТС, а что в результате получить-то пытаетесь?
0
Evg
Эксперт CАвтор FAQ
20034 / 7602 / 582
Регистрация: 30.03.2009
Сообщений: 21,232
Записей в блоге: 30
06.05.2012, 19:24 12
Цитата Сообщение от easybudda Посмотреть сообщение
Kastaneda, ну разве что вот так как-нибудь, но это мрак какой-то
Да не будет это работать, не ссы
0
Kastaneda
Jesus loves me
Эксперт С++
5042 / 3060 / 351
Регистрация: 12.12.2009
Сообщений: 7,736
Записей в блоге: 2
Завершенные тесты: 1
06.05.2012, 19:29 13
Цитата Сообщение от easybudda Посмотреть сообщение
но это мрак какой-то
ну да
Цитата Сообщение от Evg Посмотреть сообщение
Такой код если и заработает, то некорректно
без ассемблерной вставки он работал, но в конце падал (я так понимаю, что на ret в f0()). А так работает.

Добавлено через 4 минуты
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[kastaneda@myhost ~]$ cat tmp.c
#include <stdio.h>
 
void *ptr = NULL;
 
void* f0()
{
lbl:
    if (ptr != NULL) {
        printf("Hello\n");
    }
 
    return &&amp;amp;lbl; // тут какой-то косяк при выводе в этом теге, не редактируется, но вы поняли, что там
}
 
void f1(void *exit)
{
    printf("Now will be write \"Hello\": ");
    asm("pushl %0" :"=d"(exit));
    goto *ptr;
}
 
int main()
{
    ptr = f0();
    f1(&&exit);
 
exit:
    return 0;
}
 
[kastaneda@myhost ~]$ gcc tmp.c
tmp.c: В функции «f0»:
tmp.c:12:5: предупреждение: функция возвращает адрес локальной переменной [по умолчанию включена]
[kastaneda@myhost ~]$ ./a.out 
Now will be write "Hello": Hello
[kastaneda@myhost ~]$
0
Evg
Эксперт CАвтор FAQ
20034 / 7602 / 582
Регистрация: 30.03.2009
Сообщений: 21,232
Записей в блоге: 30
06.05.2012, 23:48 14
Цитата Сообщение от Kastaneda Посмотреть сообщение
без ассемблерной вставки он работал
Он условно работает. goto передаёт управление в другую функцию, но при этом нет переключения контекста (стекового окна), а потому после такого перехода состояние стека в функции f0 соответствует стеку в функции f1
0
Nameless One
Эксперт С++
5793 / 3442 / 356
Регистрация: 08.02.2010
Сообщений: 7,448
07.05.2012, 07:39 15
Цитата Сообщение от mappy89 Посмотреть сообщение
Доброго времени суток! Возник следующий вопрос: неужели имея в программе 2 функции, нельзя из одной из них методом goto перейти в другую функцию?
Резонный вопрос: зачем? Ты уверен, что это тебе так уж и необходимо? Список «оправданных» применений goto в С довольно-таки ограничен, а от нелокального goto в твоем примере попахивает плохим кодом.

Вообще, в С аналогом нелокального goto является пара функций (или макросов) setjmp/longjmp; используются обычно для организации обработки ошибочных ситуаций. Надуманный пример:

C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
 
enum error
{
    E_NONE,
    E_ARGC,
    E_OPEN,
    E_READ
};
 
static jmp_buf env_buf;
 
void run(int argc, char* argv[])
{
    FILE* file;
    char buf[BUFSIZ];
    
    if(argc != 2)
        longjmp(env_buf, E_ARGC);
    
    if((file = fopen(argv[1], "r")) == NULL)
        longjmp(env_buf, E_OPEN);
 
    while(fgets(buf, BUFSIZ, file) != NULL)
        fputs(buf, stdout);
    
    if(ferror(file))
    {
        fclose(file);
        longjmp(env_buf, E_READ);
    }
 
    fclose(file);
}
 
int main(int argc, char* argv[])
{
    int ret = EXIT_SUCCESS;
    int err;
    
    if((err = setjmp(env_buf)) == 0)
        run(argc, argv);
    else
    {
        ret = EXIT_FAILURE;
        
        switch(err)
        {
        case E_NONE: /* не выполнится никогда, т.к. longjmp(env_buf, 0) == longjmp(env_buf, 1) */
            break;
 
        case E_ARGC:
            fprintf(stderr, "Usage: %s FILENAME\n", argv[0]);
            break;
            
        case E_OPEN:
            fprintf(stderr, "Can't open file %s\n", argv[1]);
            break;
            
        case E_READ:
            fprintf(stderr, "Error reading file %s\n", argv[1]);
            break;
            
        default:
            fprintf(stderr, "Unknown error was signalled\n");
            break;
        }
    }
    
    exit(ret);
}
0
Evg
Эксперт CАвтор FAQ
20034 / 7602 / 582
Регистрация: 30.03.2009
Сообщений: 21,232
Записей в блоге: 30
07.05.2012, 09:04 16
Цитата Сообщение от Nameless One Посмотреть сообщение
нелокального goto является пара функций (или макросов) setjmp/longjmp
С одним весьма существенным ограничением - переход должен быть "вверх" по стеку
0
Nameless One
Эксперт С++
5793 / 3442 / 356
Регистрация: 08.02.2010
Сообщений: 7,448
07.05.2012, 09:09 17
Evg, ну да, это следует из того, что при возврате из функции ее стековый фрейм становится недействительным
0
Evg
Эксперт CАвтор FAQ
20034 / 7602 / 582
Регистрация: 30.03.2009
Сообщений: 21,232
Записей в блоге: 30
07.05.2012, 09:13 18
Цитата Сообщение от Nameless One Посмотреть сообщение
Evg, ну да, это следует из того, что при возврате из функции ее стековый фрейм становится недействительным
Но новичкам это совсем неочевидно
0
mappy89
2 / 2 / 2
Регистрация: 16.10.2011
Сообщений: 179
07.05.2012, 10:08  [ТС] 19
easybudda, в данный момент я программирую контроллер и через goto хотел ссылаться на кусок кода, отвечающий за повторный вывод чисел на экран. Вывод находиться в main, goto находиться в функции-прерывании.
В принципе я уже решил эту задачу, но более громоздким вариантом, нежели простой вставкой goto

Всем спасибо за помощь =)
0
fasked
Эксперт С++
5001 / 2580 / 241
Регистрация: 07.10.2009
Сообщений: 4,311
Записей в блоге: 1
07.05.2012, 12:13 20
Цитата Сообщение от mappy89 Посмотреть сообщение
хотел ссылаться на кусок кода, отвечающий за повторный вывод чисел на экран
Этот кусок кода надо выделить в отдельную функцию, а уже ее вызывать из main и еще откуда-то.
0
07.05.2012, 12:13
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.05.2012, 12:13

Можно ли реализовать Goto из одной процедуры в другую?
1. Требуется реализовать следующий код dim a as integer for i = 1 to n b = 2*C if b &gt; 1000...

можно ли в с++ вызвать переменную из одной функции в другую т.е. мы переменну задали в одной функции а использовали в другой... и как это реализовать?
можно ли в с++ вызвать переменную из одной функции в другую т.е. мы переменну задали в одной...

Ссылка с одной стр на другую в нужное место текста.
Кто подскажет код, как пересылать посетителя на нужный конкретный участок текста находящийся на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru