我正在使用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终止的字符串。
无论如何,gforth
在hello_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
的调用将指向正确的东西?
答案 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
,然后正常退出。