C语言小知识点总结

  • *a是指“a指向的变量”,而不仅是“a指向的变量所拥有的值”。理解这一点相当重
    要。例如,*a = *a + 1就是让a指向的变量自增1。甚至可以把它写成(*a)++。注意不要写
    成*a++,因为“++”运算符的优先级高于“取内容”运算符“*”,实际上会被解释成*(a++)。
  • gdb中显示程序收到了SIGSEGV信号——段错误。这太让人沮丧了!眼看本章就要结束
    了,怎么又遇到一个段错误?别急,让我们慢慢分析。我保证,这是本章最后的难点。
    你有没有想过,编译后产生的可执行文件里都保存着些什么内容?答案是和操作系统相
    关。例如,UNIX/Linux用的ELF格式,DOS下用的是COFF格式,而Windows用的是PE文件格
    式(由COFF扩充而来)。这些格式不尽相同,但都有一个共同的概念——段。
    “段”(segmentation)是指二进制文件内的区域,所有某种特定类型信息被保存在里面。
    可以用size程序 (5) 得到可执行文件中各个段的大小。如刚才的factorial.c,编译出a.exe以后执
    行size的结果是:
    D:\>size a.exe
    text data bss dec hex filename
    2756 740 224 3720 e88 a.exe
    此结果表示a.exe由正文段、数据段和bss段组成,总大小是3720,用十六进制表示为
    e88。这些段是什么意思呢?
    提示4-19:在可执行文件中,正文段(Text Segment)用于储存指令,数据段(Data
    Segment)用于储存已初始化的全局变量,BSS段(BSS Segment)用于储存未赋值的全局
    变量所需的空间。
    是不是少了点什么?调用栈在哪里?它并不储存在可执行文件中,而是在运行时创建。
    调用栈所在的段称为堆栈段(Stack Segment)。和其他段一样,堆栈段也有自己的大小,不
    能被越界访问,否则就会出现段错误(Segmentation Fault)。
    这样,前面的错误就不难理解了:每次递归调用都需要往调用栈里增加一个栈帧,久而
    久之就越界了。这种情况叫做栈溢出(Stack Overflow)。
    提示4-20:在运行时,程序会动态创建一个堆栈段,里面存放着调用栈,因此保存着
    函数的调用关系和局部变量。
    那么栈空间究竟有多大呢?这和操作系统相关。在Linux中,栈大小是由系统命令ulimit
    指定的,例如,ulimit -a显示当前栈大小,而ulimit -s 32768将把栈大小指定为32MB。但在
    Windows中,栈大小是储存在可执行文件中的。使用gcc可以这样指定可执行文件的栈大小:
    gcc -Wl,--stack=16777216 (6) ,这样栈大小就变为16MB。
    提示4-21:在Linux中,栈大小并没有储存在可执行程序中,只能用ulimit命令修改;
    在Windows中,栈大小储存在可执行程序中,用gcc编译时可以通过-Wl,--stack=<byte
    count>指定。
    聪明的读者,现在你能理解为什么在介绍数组时,建议“把较大的数组放在main函数
    外”了吗?别忘了,局部变量也是放在堆栈段的。栈溢出不一定是递归调用太多,也可能是
    局部变量太大。只要总大小超过了允许的范围,就会产生栈溢出。
  • CPU每秒运算速度月1e8/s  IO:scanf/printf 1e6/s    非标准方式可能到1e7
  • 素数密度n/ln(n)
  • 枚举回文数一般枚举前半
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值