LINUX.ORG.RU

Динамический goto


0

0

На ассемблере «динамический goto» реализовать можно так:

.data
	msg: .string "Hello world!"
 
.bss
	.lcomm p, 4

.text
.globl _start
_start:
	mov $L2, %eax
	mov %eax, p
	jmp *p
L1:
	push $0
	call exit
L2:
	push $msg
	call puts
	add $4, %esp
	jmp L1
Можно ли в C сделать что-нибудь аналогичное?

Пробовал ассемблерными вставками организовать - не получается.
C-шные метки ассемблер не признаёт.
Пробовал вместо них использовать asm volatile («L2:») - не работает.

Есть идеи?

Ещё в сторону longjump можно посмотреть.

Biga
()

Вообще тут будет на усмотрение компилятора, сделает ли он из switch вычисляемый goto. В gcc есть расширение:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  void* labels[] = { &&L1, &&L2 };

  int i = 0;

  goto *labels[i];

 L1:
  exit(0);

 L2:
  puts("1!");
  goto L1;
}
	.file	"foo.c"
	.section	.rodata
.LC0:
	.string	"1!"
	.text
.globl main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	movq	%rsp, %rbp
	.cfi_offset 6, -16
	.cfi_def_cfa_register 6
	subq	$32, %rsp
	movq	$.L2, -32(%rbp)
	movq	$.L3, -24(%rbp)
	movl	$0, -4(%rbp)
	movl	-4(%rbp), %eax
	cltq
	movq	-32(%rbp,%rax,8), %rax
	jmp	*%rax
.L2:
	movl	$0, %edi
	call	exit
.L3:
	movl	$.LC0, %edi
	call	puts
	jmp	.L2
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.ident	"GCC: (Gentoo 4.4.2 p1.0) 4.4.2"
	.section	.note.GNU-stack,"",@progbits
Begemoth ★★★★★
()

Если бы в си были лексические замыкания:

(defun bar (f) (funcall f))

(defun foo (&aux goto-closure)
  (tagbody
    (setf goto-closure (lambda () (go 1)))
    (bar goto-closure)
    0
    (return-from foo)
    1
    (go 0)))

У нас в CL еще есть динамический return, кстати:

(defun bar (tag)
  (throw tag "returned value"))

(defun foo (&aux (tag (make-instance 'standard-object)))
  (catch tag (bar tag)))
;=> "returned value"

Love5an
()

Я бы предложил подумать об указателях на функции.

Они решают если не сабжевую задачу, то хотя бы задачу «выполнить участок кода, а какой именно, станет ясно по ходу выполнения». И при этом позволяют иметь читаемый код.

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

ИМХО без массива более читаемый код:

#include <stdio.h>
#include <stdlib.h>

int main()
{
	void *label;

	label = &&L2;
	goto *label;

L1:
	return 0;
L2:
	puts("Hello world!");
	goto L1;
}

LinuxUser ★★★
() автор топика

А в чем соль динамического goto? Что такого можно с ним сделать, чего нельзя сделать «стандартными» средствами?

tarcar
()
Ответ на: комментарий от LinuxUser

а вот это уже неправомерное использование goto

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

не надо учить нубов ламерству

#include <stdio.h>
#include <stdlib.h>

int main()
{
  int target = 1;
  switch (target)
  {
  case 1:
    puts("1!");
  case 0:
    exit(0);
  }
} 

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

А в чем соль динамического goto? Что такого можно с ним сделать, чего нельзя сделать «стандартными» средствами?

Динамический goto даёт массу способов изящно выстрелить себе в ногу.

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

Но-но. По ссылке моей ходил? Неплохие такие корутины получаются, switch хуже. Человек на них ОС написал, и еще в FreeRTOS тоже они. Ну и еще компиляторописатели, которые в С компилят свои языки любят его. То есть у него есть свои применения и свои пользователи. А если просто в обычном коде использовать - то здесь я согласен, в ногу.

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