我正在学习 bison/yacc(并复习一些 c)并尝试构建一个 json 解析器作为简单的测试项目。
使用 http://www.json.org/ 上找到的术语我有一个表示字符串/值对的结构体对和一个表示具有成员字段的对象的结构体对象,该成员字段基本上包含指向对的链接列表的指针。
我有一个简单的 c 函数 (create_pair),它返回一个新的对。我注意到一个我无法解释的奇怪行为:
- 如果我从“main”调用此类函数并打印返回结构的内存地址,则它们的地址始终不同。
- 如果我在 Bison “ Action ”中调用完全相同的函数,我会发现我的函数返回一个恰好始终驻留在同一内存地址上的指针。
这有意义吗?
详细信息/代码如下:
这是代码(链接包含 4 个 Pastebin 链接的列表,指向“项目”中包含的四个不同文件):
你可以编译并运行它:
lex t.l
yacc -d t.y
cc y.tab.c lex.yy.c t.c
./a.out
如果您启动代码并使用以下输入运行它:
{ “名字”:“A”, “姓氏”:“B” }
你会看到:
1)在“main”中执行的代码(检查文件 t.y)创建四个不同的对对象,然后打印它们的内存地址,输出类似于(注意不同的地址):
p 0x7fff52476be8 //(<-memory address for pair p)
print pair: P, Hellov
q 0x7fff52476bc8 //(<-memory address for pair q)
print pair: Q, Hellox
2) 一旦我粘贴上面的 json 示例,我们就会两次点击“pair”规则,第一次是“firstName”:“A”,第二次是“lastName”:“B”,我创建了一个两种情况下都新建对并打印内存地址,它们是相同的:
Creating pair 0x7fff52475c88
print pair: firstName, A
Creating pair 0x7fff52475c88
print pair: lastName, B
为什么会发生这种情况?
最佳答案
你不应该关心pair
的地址是什么。是。这与与他们一起执行的工作无关,您看到的地址是偶然的,没有后果。
您的函数create_pair
不返回指针。它是用 pair create_pair(…)
声明的,所以它返回 pair
,按值。
在 main
,您定义 pair p = create_pair(l, v);
。这将创建一个自动对象 p
,通常是通过在堆栈上为其留出空间。然后它调用create_pair
。 create_pair
返回的值被复制到 p
。稍后,当您打印 &p
时,您正在打印 p
的地址,不是 create_pair
的地址返回。
同样,当您定义 pair q = create_pair(l, x);
时,您创建另一个对象 q
。因为这个对象的生命周期与p
的生命周期重叠。 ,他们一定在不同的地方,所以他们有不同的地址。当您打印&q
时,您会看到这个不同的地址。
接下来,考虑您放置在 Bison 规则中的代码 pair p = create_pair($<u_string>1, $<u_value>3);
。 Bison 在处理规则时执行此代码。它创建一个自动对象,然后您打印它的地址。然后执行就离开了这段代码的作用域,而 Bison 无疑会继续做其他事情,并且它会退出当前正在进行的处理。自动对象的生命周期结束,堆栈上的数据被弹出。后来,比森又回到了这条规则。此时,仅仅因为计算机是机械操作的,堆栈指针具有与之前相同的地址。所以,当一个新的p
创建后,它恰好与旧的 p
在同一个地方。不像 p
和q
,它们必须在不同的地方,因为它们同时存在,这个旧的 p
和新的p
仅存在于不同时间,因此它们可能位于同一个地方。
这并不一定总是会发生。如果你的语法更复杂,Bison 可能会同时在堆栈中包含其他内容,而不是另一个(或者可能没有;Bison 生成的解析机可能不会那样工作;我不知道)。或者,如果另一个规则中有相同的代码,则处理该规则时堆栈可能会有所不同。
关于c - 指针、bison 和 yacc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14007588/