c - 指针、bison 和 yacc

标签 c pointers bison yacc

我正在学习 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_paircreate_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 在同一个地方。不像 pq ,它们必须在不同的地方,因为它们同时存在,这个旧的 p和新的p仅存在于不同时间,因此它们可能位于同一个地方。

这并不一定总是会发生。如果你的语法更复杂,Bison 可能会同时在堆栈中包含其他内容,而不是另一个(或者可能没有;Bison 生成的解析机可能不会那样工作;我不知道)。或者,如果另一个规则中有相同的代码,则处理该规则时堆栈可能会有所不同。

关于c - 指针、bison 和 yacc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14007588/

相关文章:

c# - 将 C 赋值/条件语句转换为 C#

冲突的类型与不兼容的隐式声明

c++ - 使用 malloc 分配空间给 list<int> 指针不工作

c++ - 指向 4 维数组的指针

C++排序数组是指向类的指针

c - 为什么我在这个 bison 语法中收到这么多 'useless rule/token' 警告?

c - 如何在 Codeblocks 中构建我的代码?Codeblocks IDE 停止工作

c - C 编译器使用此语句可能会产生什么结果?

parsing - Verilog 门级解析器

makefile - grub_script.yy.c :2354:13: error: 'yy_fatal_error' defined but not used