在编写Haskell作为之前接触过Lisp的程序员时,我注意到一些奇怪的事情,我无法理解.
编译好:
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ExistentialQuantification #-}
data Foo = forall a. Show a => Foo { getFoo :: a }
showfoo :: Foo -> String
showfoo Foo{getFoo} = do
show getFoo
Run Code Online (Sandbox Code Playgroud)
但这失败了:
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ExistentialQuantification #-}
data Foo = forall a. Show a => Foo { getFoo :: a }
showfoo :: Foo -> String
showfoo foo = do
let Foo{getFoo} = foo
show getFoo
Run Code Online (Sandbox Code Playgroud)
对我而言,第二个片段失败的原因并不明显.
问题是:
我是否因为haskell不是homoiconic这一事实而错过了某些内容或阻止了这种行为?
我的理由是,鉴于:
Haskell需要将记录模式匹配实现为编译器扩展,因为它可以选择使用语法而不是数据.
函数头或let子句中的匹配是两种特殊情况.
很难理解这些特殊情况,因为它们既不能实现也不能直接用语言本身查找. …
当我运行以下代码时,我正在观察奇怪的行为.我通过使用结构创建一个位域,我想使用52位,所以我使用long int.我的系统上long int的大小是64位,我在代码中检查它.不知怎的,当我尝试设置一位时,它设置了两位.其中一个是我想要设置的,第二个是第一个加上32的索引.任何人都可以告诉我,为什么?
#include <stdio.h>
typedef struct foo {
long int x:52;
long int:12;
};
int main(){
struct foo test;
int index=0;
printf("%ld\n",sizeof(test));
while(index<64){
if(test.x & (1<<index))
printf("%i\n",index);
index++;
}
test.x=1;
index=0;
while(index<64){
if(test.x & (1<<index))
printf("%i\n",index);
index++;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Sry忘了发布输出,所以我的问题基本上不可理解......它给出的输出如下:
8
0
32
我用gcc编译程序,然后在a.out文件上运行gcc。当我在gdb中运行programm时,出现此错误:
Program received signal SIGSEGV, Segmentation fault.
0xbffff118 in ?? ()
(gdb) backtrace
#0 0xbffff118 in ?? ()
#1 0x00000000 in ?? ()
Run Code Online (Sandbox Code Playgroud)
这是什么意思?同样在我之前,当试图正常运行程序时,我得到了这个错误:
*** stack smashing detected ***: ./benchmark terminated
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)
所以我读到这是对缓冲区溢出的保护,我仔细检查了所有内容,应该一切都很好,所以我使用了标志将其禁用:
-fno-stack-protector
Run Code Online (Sandbox Code Playgroud)
编辑:我不发布代码,因为我想弄清楚如何使用gdb而不是让我的代码正常工作。所以我是gdb的新手,但现在我成功使用了几次。我还是不知道是什么?? 意味着在什么情况下gdb不能指向我代码中的相应调用,这会导致错误,为什么帧1的地址为0x0?