所以我正在实现你可以说C编译器的子集,并且有一个让我头疼的功能。所以我想了解如何解决它。
在我的编程中。 language是通过值传递的所有参数,包括字符串,其声明如下:
string str;
我的问题是,正如你所看到的,我在声明时不知道字符串大小(与C的区别),所以当我生成程序集时,我不知道在堆栈上为它创建多大的空间。 如果我有这样的代码:
string str;
int number;
str = something;
我不知道如何为字符串str分配正确的空间,以后可以实际分配任意字符。最后一个条件是,我不能使用堆。
谢谢,抱歉我的英语不好。
编辑:
感谢您的回答。从我看来的响应来看,最大的问题是重新分配字符串,如果它在堆栈上变得更大,以防这个字符串背后已有东西,我认为最简单的解决方案是在堆栈上创建新空间而旧旧的空间应该是直到局部范围将被处理......这将是浪费,是的
答案 0 :(得分:0)
您可以从零长度字符串开始。
由于您未提前知道大小,因此在执行分配或串联字符串,重新分配后,您必须在运行时中动态分配和取消分配字符串存储范围等。
答案 1 :(得分:0)
由于它是您自己的语言,我假设您还可以控制代码的生成方式。所以你可以分配足够的堆栈空间并在那里复制字符串。 我在我自己的函数中使用了这样一种方法,它附加了两个未知长度的路径部分(basepath和filename作为参数),因为我不想打扰malloc和free。唯一需要注意的是堆栈的对齐,因为它必须保持均匀。
当然,这取决于你的程序有多大,因为对于足够复杂的程序,堆栈很快就会变得很大。
答案 2 :(得分:0)
我假设您有某种dup_string
例程,它会复制新内存块中的字符串。该dup例程必须知道源字符串具有未知的长度,该长度仅在执行复制时确定,如:
char *dup_string (char *s)
{
char *d = realloc(strlen(s)+1);
memcpy (d, s, strlen(s)+1);
return d;
}
所以你可以在你的来电代码和你的calle epilog中使用它来透明地使用这个功能,就像这样......
/* Source code: your programming language */
str s;
s = "whatever...";
func (s);
生成的汇编代码将是这样的(使用IA32代码和C调用约定的示例):
[Caller: this block repeated for every string passed as parameter to a function]
push offset s
call dup_string ;string copy pointed by EAX
add esp,4 ;get rid of parameter
push eax
call func
add esp,4 ;get rid of parameter
...
...
[Callee]
push ebp
mov ebp,esp
mov esi,[ebp+8] ; ESI = pointer to string
...use string in ESI...
...
...
EPILOG
(this block repeated for every string passed as argument):
mov esi,[ebp+8] ;8 because in this example, it's the first argument.
call free /* standard free() function */
mov esp,ebp
ret