编译器:字符串常量vs动态分配的String对象

时间:2017-05-03 01:14:27

标签: compiler-construction

我正在编写一个小编译器,我无法处理字符串常量和字符串对象。

以下面的代码为例:

s : String = "Hello world"

由于字符串在程序中,编译器将识别该字符串,并生成字符串常量并将其放在.data段中。

.data

string_const1:
    .quad    2
    .quad    6
    .quad    String_dispatch_table
    .quad    int_const1
    .asciz    "Hello world"
    .align    8

然后可以通过以下方式访问实际的字符串:

leaq string_const1(%rip), %rax
addq $32, %rax

但是,如果我们要求用户输入字符串,则需要动态生成字符串对象。以下是字符串对象模板,该模板也放置在.data段中。

String_protoObj:
    .quad    2                        # tag              
    .quad    5                        # size
    .quad    String_dispatch_table    
    .quad    0                        # string length
    .quad    0                        # string content

# assume %rax contains the address of a copy of String_protoObj
# assume %rdi contains the address of user input string 

leaq String_protoObj(%rip), %rdi
callq malloc
movq user-input, %rdi
movq %rdi, 32(%rax)   # copy the new string into string content

然后稍后访问实际的字符串,我必须使用

32(%rax)  # read from memory

因此,从字符串常量访问字符串和动态分配的字符串对象之间存在差异,这需要在所有函数中使用不同的句柄

我显然可以在protoObject中添加另一个标记来指示这是一个已分配的对象而不是一个常量,但这需要接收字符串对象/常量的所有方法进行检查,这听起来并不优雅。 / p>

任何人都可以给我任何关于如何处理这种情况的建议吗?

1 个答案:

答案 0 :(得分:1)

就个人而言,我首先使常量看起来像一个字符串对象,这意味着第五个字将包含指向第六个字的指针。这是你明显愿意用字符串对象支付的价格。

更节省空间的策略是大多数现代C ++库使用的策略,其中有两个字符串布局:一个包含字符向量(短字符串),另一个带指针。你可以告诉他们除了长度,所以你不需要一个不同的标签,但当然你也可以使用不同的标签。

在实践中,大多数字符串都相当短,因此这种优化被认为是有用的。但是它的工作量更大,而且要编写更多测试,因此您可能希望将其保存以供日后使用。