Logo

inspiratune

  • 关于我
  • 免责声明
  • 版权声明
  • Archive
  • RSS
  • 向我提问吧~

C语言标准库函数——头文件索引

  • <assert.h> 断言
    定义assert调试宏。
  • <ctype.h> 字符类函数
    包含有关字符分类及转换的名类信息(如isalpha和toascii等)。
  • <errno.h> (部分)库函数的错误代码
    定义错误代码的助记符。
  • <float.h> 浮点数运算
    包含有关浮点运算的一些参数和函数。
  • <limits.h> 检测整型数据类型值范围
    专门用于检测整型数据数据类型的表达值范围。
  • <locale.h> 本土化
    语言支持本地化设定,如本地格式时间和货币符号。
  • <math.h> 数学函数
    说明数学运算函数,还定了HUGE VAL宏, 说明了matherr和matherr子程序用到的特殊结构。
  • <setjmp.h> 非局部跳转
    定义longjmp和setjmp函数用到的jmp buf类型,并说明这两个函数。
  • <signal.h> 信号
    定义SIGIGN和SIGDFL常量,并说明rajse和signal两个函数。
  • <stdarg.h> 可变参数列表
    定义读函数参数表的宏。(如vprintf,vscarf函数)。
  • <stddef.h> 一些常数,类型和变量
    定义一些公共数据类型和宏。
  • <stdio.h> 输入和输出
    定义Kernighan和Ritchie在Unix System V 中定义的标准和扩展的类型和宏。
    还定义标准I/O 预定义流:stdin,stdout和stderr,说明 I/O流子程序。
  • <stdlib.h> 实用功能
    说明一些常用的子程序:转换子程序、搜索/ 排序子程序等。
  • <string.h> 字符串函数
    说明一些串操作和内存操作函数。
  • <time.h> 时间和日期函数
    定义时间转换子程序asctime、localtime和gmtime的结构,ctime、 difftime、 gmtime、 localtime和stime用到的类型,并提供这些函数的原型。
    • #C语言
    • #头文件
    • #标准
    • #库函数
    • #C Programming Language
    • #Library
    • #functions
    • #include
  • 9 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

C语言基本保留知识(二)

流

C语言将数据的输入输出看作是数据的流入和流出,(不管是磁盘文件或者是物理设备),而与物理结构无关。流式模型很利于编程,具有相当的通用性。

C语言在实现I/O功能做的相当底层:将所有的文件操作符都抽象成了字节流,没有对于从文件随机位置读取的直接支持,只能创建一个文件流,将文件指针指向到文件的中间部分,然后从文件流中按顺序读取一个又一个字节。

标准流

标准流是一种程序介面(注意:不是界面),在程序运行时所链接的频道。这三个频道是事先规定好的,他们分别是:标准输入(stdio)、标准输出(stdout)、标准错误输出(stderr)

  • 标准输入(stdio)
    在0号频道,用来将资料数据输入程序,通常为“读”运算,在未做重定向时,资料来源是键盘,即从键盘缓冲区内都入数据;
  • 标准输出(stdio)
    在1号频道,用来将结果数据输出,通常为“写”运算,在未做重定向时,输出到终端(打印到屏幕上)
  • 标准错误输出(stderr)
    在2号频道,用于输出错误信息或诊断。也可以被重定向。

文件

一个文件通常就是磁盘上的一段命名的存储区,C语言将文件看成是连续的字节序列,其中每一个字节都可以单独地读取。

文本文件是基于字符编码的文件,通常是定长的,译码较容易,可读性较好,存储要花费转换时间,常见的编码有ASCII编码,UNICODE编码等。

二进制文件是基于值编码的文件,变长编码(可以看作是自定义编码),译码较难,可读性较差,存储不存在转换时间。

    • #C语言
    • #基本保留知识
  • 9 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

操作系统内存浅析

程序调用

一般情况下程序存放在ROM(只读存储器)或FLASH中,运行时需要拷到RAM(随机存储器)中执行,RAM会分别存储不同的信息。

页与区

内核把物理页作为管理内存的基本单位。

内存管理单元(MMU,管理内存并把虚拟地址映射为物理地址)通常以页为单位进行处理,页就是内存管理的最小单位。体系结构不同,支持页大小也不同,标准32位机器(大多数)支持4KB的页,64位机器支持8KB的页。页面结构和物理页相关,并非与虚拟页相关。

由于硬件限制,内核并不是对所有的页一视同仁,有些页位于内存中特定的物理位置上,由于存在这种限制,所以内核把页划分为不同的区,内核使用具有相似特性的页进行分组。

某些硬件只能用一些特定的内存地址来执行DMA,一些体系结构的内存的物理地址寻址范围比虚拟地址寻址范围大,而且大很多,因此会有一些内存不能永久的映射到内核空间。

区的实际使用和分布体系结构相关。*nix-like系统体系结构把页划分为区,形成不同的内存池,这样就可以根据用途进行分配了。区的划分没有任何意义,只不过是内核为了管理页而采取的一种逻辑上的分组。某些分配需要从特定的区中获取,而某些分配却可以从多个区中获取页。不是所有的体系结构都定义了全部区,内核中使用struct_zone()表示区。

栈内存

栈内存是由系统自动分配,用来存放基本类型类型及其内容、函数参数、对象句柄。栈是向低地址扩展的数据结构,是一块连续的内存的区域。栈顶的地址和栈的最大容量是系统预先规定好的。系统栈的内容由编译器编译时决定并分配。在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用。用户栈在程序执行期间可以动态扩展和收缩。开辟和调用速度较快。但程序员是无法控制的。

堆内存

由程序控制分配的用户态内存块,编译器不受理。如果程序没有释放掉,在程序结束后,操作系统会自动回收。堆可以动态的扩展和收缩。

堆是向高地址扩展的数据结构,系统是用链表来存储的空闲内存地址的,是不连续的内存区域,遍历方向是由低地址向高地址。一般速度比较慢,容易产生内存碎片。

内存对齐

字,双字,和四字在自然边界上不需要在内存中对齐。(对字,双字,和四字来说,自然边界分别是偶数地址,可以被4整除的地址,和可以被8 整除的地址。)无论如何,为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;然而,对齐的内存访问仅需要一次访问。

一个字或双字操作数跨越了4字节边界,或者一个四字操作数跨越了8字节边界,被认为是未对齐的,从而需要两次总线周期来访问内存。一个字起始地址是奇数但却没有跨越字边界被认为是对齐的,能够在一个总线周期中被访问。某些操作双四字的指令需要内存操作数在自然边界上对齐。如果操作数没有对齐,这些指令将会产生一个通用保护异常。双四字的自然边界是能够被16整除的地址。其他的操作双四字的指令允许未对齐的访问(不会产生通用保护异常),然而,需要额外的内存总线周期来访问内存中未对齐的数据。
缺省情况下,编译器默认将结构、栈中的成员数据进行内存对齐。

缺省情况下,编译器默认将结构、栈中的成员数据进行内存对齐。

——《C语言深度剖析》

内存对齐的作用:

在设计不同硬件结构的通信协议时,避免不同的编译器生成的代码不一样;

程序提供API,但无统一标准时

取消内存对齐:

使用预处理#pragma pack (n),C编译器将按照n个字节对齐。

使用预处理#pragma pack (),取消自定义字节对齐方式。

__attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对

__attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

内存溢出(out of memory)

在申请内存时,没有足够的内存空间供其使用,比如申请了一个int,但给它赋予了long才能存下的数。

栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。

内存泄露(memory leak)

在申请内存后,无法释放已申请的内存空间

1. 常发性的:发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。

2. 偶发性的:发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的(也许)变成常发性的。

3. 一次性的:发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。

4. 隐式的:程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。对于长周期运行的应用程序(如服务器级应用,超过数月不关闭)不及时释放内存也可能导致最终耗尽系统的所有内存。

    • #操作系统
    • #内存
    • #operating system
    • #memory
  • 9 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

C语言基本保留知识(一)

复合赋值与普通赋值的区别
对于x = x + 1,表达式 x 被计算了两次,对于复合运算符 x += 1,表达式 x 仅计算了一次。对于O0优化的程序而言,是有区别的,而当优化为O1,O2,O3时,由于编译器的优化,是没有区别的。当赋值对象含有下标且是函数时,编译器并不能确定每次函数都返回相同的值(即是否有副作用),所以编译器不能对此优化,因此也就会调用两次函数,O0,O1,O2,O3都是如此。因此我们应尽量使用复合赋值操作符。

连续赋值的应用
对于x += x *= x /= x-6,
第一步:x = x / (x - 6),x 的值传递给第二步;
第二步:x = x * x,x 的值传递给第三步;
第三步:x = x + x,x 的最终结果在这里;
实际堆栈展开:
第一步 x = x + (x *= x /= x - 6)
第二部 x = x + (x = x * (x /= x - 6))
第三步 x = x + (x = x * (x = x / (x - 6)))

变量的赋值与初始化的区别
在变量声明中,不允许连续给多个变量赋初值,而赋值语句允许连续赋值。对于基本类型进行赋值时进行强制转换,但复合类型时则不进行。

赋值表达式和赋值语句的区别
赋值表达式可以出现在任何允许表达式出现的地方,而赋值语句则不能。
x=y+5 <—-赋值表达式
x=y+5; <—-赋值语句

    • #C语言
    • #基本保留知识
  • 9 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+
在被挤成相片之前,成功从西直门返回学校,在三线换乘的通道里,看着乌泱乌泱的人群,我顿时觉得十分乏力~~
今日地铁西直门站有感~~留念
    • #地铁
    • #有感
  • 10 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+
舒适的编码环境~~~我正在写自己的头文件~~
Pop-up View Separately

舒适的编码环境~~~我正在写自己的头文件~~

    • #留念
    • #舒适
    • #编码
    • #环境
    • #头文件
    • #自己
  • 10 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+
内核失败于2014-03-01,留念~~
想幸灾乐祸的同学,现在可以开始了~~
Pop-up View Separately

内核失败于2014-03-01,留念~~

想幸灾乐祸的同学,现在可以开始了~~

    • #内核
    • #失败
    • #留念
  • 10 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

到底会不会发生死循环?

如下代码会不会发生死循环

#include <stdio.h>

int main()
{
    int name[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    int i = 0;

    for (i = 0; i <= 10; i++)
    {
        printf(“name[%d] = %d \t”, i, name[i]);
        name[i] = 0;
        printf(“\t====>\tname[%d] = %d \t\t[ OK ]\n”, i, name[i]);
    }
    return 0;
}

我的电脑运行这段程序不光不会陷入死循环,而且还能通过基本代码机器审计~

image

一问才知道:这伙计用的还是VC++6.0 with SP2,这么老掉牙的东西,还能在这片神奇的土地上这么流行,真奇葩~

    • #C语言
    • #循环
    • #审计
    • #出错
  • 10 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

邮件回复:进程、线程、协程的关系

一位不知名的读者在昨天晚上22:23分给我发了一封邮件,询问了有关进程、线程、协程的关系,我个人认为这是一个比较容易混淆的知识点,在争得邮件发送者本人的同意下,此邮件公开回复

答:

  1. 进程(Process,又译作行程)为应用程序的运行实例,是一个具有独立功能的程序关于某个数据集合的一次运行活动。进程是由进程控制块、程序段、数据段三部分组成。在现代操作系统(面向线程设计的系统)中不是基本执行单位,而是线程的容器。
    即一个进程可以包含若干线程(Thread),线程可以帮助应用程序同时做几件事而互相不干扰。
    进程的状态可以划分为创建(new)、运行(running)、阻塞(等待,waiting)、就绪(ready)、结束(terminated)五种,并随一定条件而相互转化。

  2. 线程(thread)是操作系统能够进行运算调度的最小单位,被包含于进程中,一条线程指的是进程中一个单一顺序的控制流。
    同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。
    进程的状态可以划分为产生(spawn)、中断(block)、非中断(unblock)、结束(finish)四种,并随一定条件而相互转化。

  3. 协程(coroutine)是协作的例程(co-operative routines),又称微线程和纤程等。其与具有操作系统概念的线程不一样,协程是在用户空间利用程序语言的语法语义就能实现逻辑上类似多任务的编程技巧。
    协程避免了无意义的调度,由此可以提高性能,但也因此,程序员必须自己承担调度的责任,同时,协程也失去了标准线程使用多CPU的能力。


以上三种“程”的关系:

  • 进程拥有自己独立的堆和栈,与同类既不共享堆,也不共享栈,由操作系统调度。
  • 线程拥有自己独立的栈和共享的堆,与同类共享堆,但不共享栈,由操作系统调度。
  • 协程和线程一样共享堆,不共享栈,协程由程序员在协程的代码里显示调度。
    • #邮件
    • #回复
    • #进程
    • #线程
    • #协程
    • #关系
  • 10 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+

最优美的C语言代码

#include <stdio.h>
void main()
{
    double world;
    unsigned letter;
    short stay;
    long memories;
    printf(“I miss you.\n”);
}

非常优美的代码,用了C的基本保留关键字,一个简单的爱情故事,简单翻译一下:

两个世界

一封未署名的信

短暂的约会

长久的相思

留下一句:我想你了

    • #C语言
    • #代码
  • 10 months ago
  • Comments
  • Permalink
Share

Short URL

TwitterFacebookPinterestGoogle+
Page 1 of 2
← Newer • Older →

雁过留声

我在~...

  • nathanielben on github

Instagram

loading photos…

I Dig These Posts

See more →
  • RSS
  • 关于我
  • 免责声明
  • 版权声明
  • 向我提问吧~

除非另有声明,本网站和其下作品及一切知识劳动成果采用CC BY-NC-SA 4.0国际许可协议进行许可.

inspiratune © 2004-2014. Design by Nathaniel Lee