gforth用字符串调用C函数printf

时间:2018-08-11 06:18:50

标签: c gforth

我正在使用printf字符串调用C函数S" ...",并且遇到无效的内存地址。将指针传递到在Forth端创建的以N结尾的字符串的正确方法是什么。

这是gforth中的hello world的两个版本,一个使用专用语法写出文字字符串,另一个使用type将字符串存储为值(虽然很小) >

这里是helloworld.fs

#! /usr/bin/env gforth
.( Hello, world!)
CR
bye

helloworld2.fs

#! /usr/bin/env gforth
S" Hello, world!" type
CR
bye

据我所知,语法S" Hello, world"在Forth运行时内部的某个全局区域中创建了一个新字符串,并将指向其的指针压入堆栈。它也可能是一个比这更丰富的对象,我不知道Forth是否使用以null终止的字符串。

无论如何,gforthhello_world_c.fs中公开了一些用于调用C函数的单词

#! /usr/bin/env gforth
\c #include <stdio.h>
c-function printf- printf a -- n

S" hello" printf-
CR

bye

我希望该脚本在运行时先打印hello,然后再打印换行符。函数printf的原型为a -- n ... ...表示它需要一个地址并返回与int相同大小的内容。单一格式的字符串绝对是传递给printf的可接受参数集合。

但是,它会产生错误:

$ ./hello_world_c.fs
ar: `u' modifier ignored since `D' is the default (see `U')

in file included from *OS command line*:-1
hello_world_c.fs:5: Invalid memory address
S" hello" >>>printf-<<<
Backtrace:
$7F3A14D65018 call-c
$763A14D64F50 execute

我猜这里的问题是由于S" hello"并不是指针,而是其他东西。有没有一种方法可以将其转换为指针,以便对printf的调用将指向正确的东西?

1 个答案:

答案 0 :(得分:0)

事实证明,S"不会创建以空值结尾的字符串,也不会专门将地址压入堆栈。

S"创建一个临时位置(该位置至少在下一次调用S"之前一直存在)并将长度和地址压入堆栈。

调用S"后,长度位于堆栈的顶部,此顺序很重要。

这是一个带有gforth的示例交互式会话,其中添加了注释和提示(>),以使内容更加清晰。

$ gforth
> S" a"                  ( define a new string, push length and addr )
> .s                     ( display size of stack and contents of stack )
<2> 22565888 1
> .                      ( print and drop top item of stack ) 
1
> .s                     ( display size and contents of stack again )
<1> 22565888
bye 

s\"一词类似于S",只是它遵循C样式的字符串转义符。它与S"一样劫持“阅读器”,但是执行一些翻译。

请牢记所有这些,这是脚本的一种实现,可以正确调用printf-

#! /usr/bin/env gforth

\c #include <stdio.h>
c-function printf- printf a -- n

( synonym for drop for documentation purposes.
  remove the initial length of a length, bytes pair created by
  S" or s\" )
: drop-cstr-length drop ;

s\" hello world\n\0" drop-cstr-length
printf-

bye

将显示hello world,然后正常退出。