C语言基础

来源:互联网 发布:mysql work导出数据库 编辑:程序博客网 时间:2024/05/22 15:02

Data:

%#o, %#x, %#X -> 0, 0x, 0X:产生对应的八进制,十六进制前缀

要使一个小的常量被当做long,可以在后面添加l或L,如7L

打印unsigned int使用%u;h可以用作short类型的前缀,如%hd等

当char和short作为参数被传入一个函数时会被自动转换成int型,float会被转换成double

compiler默认会将浮点数作为double型,要想将一个浮点数作为float,需要在其后添加f或F,如2.3f

使用%e可将浮点数以指数形式打出

使用%p打印地址

sizeof()是获得数据的byte数,类型是size_t,C99和C11使用%zd表示sizeof获得的数据(C的byte是指char的大小,在某些系统中char大于8bit)

char的大小是一个byte

printf输出的数据首先被送到buffer中,当buffer满了,或有newline,或即将进行输入时,buffer中的数据会被送至屏幕

typedef new_type int -> 可以用new_type定义新变量

C的Bool类型:_Bool(在包含了stdbool.h头文件后,可以使用bool)



Formatted Input/Output

当用scanf获得string时,假设name[20],则scanf("%s", name)。注意scanf使用的是地址,所以用name

之所以#define不需要使用分号,是因为替换机制是由预处理器完成的,不是一个C语句

%10d表示打出的数据占10位,在最右。如果想从左边开始的话,应使用%-10d

%5.3d表示数据占5位,3是补零的宽度,即至少显示3位,不够的补零

%24.5s表示打印24位长度的字符串,但仅打出5个字符

printf会返回打印的字符数,若出现错误则返回一个负值

scanf中的数字表示最大域宽度。当输入字符数达到最大域宽度或遇到空格键时输入停止

当读到非法数据时,scanf会将其放回,这样当下次程序再读取输入时,会从上次被拒绝处读起

如果使用%s,除了空格之外的字符都会被接受

例:scanf("%d,%d", &n, &m); 这种情况下,由于逗号紧跟在%d之后,所以输入时必须也如此;因为scanf会跳过整数前的空格,所以可以在逗号后输入空格

scanf中的空格表示跳过下一个输入项目之前的所有空格。除了%c之外,scanf会自动跳过输入值前的空格,所以sanf("%d%d", &n, &m)的效果和scanf("%d %d", &n, &m)的效果是一样的

scanf()会返回成功读取的项目数

printf("%*d", width, number):其中width用于表明输出整型数的宽度,number才是真正输出的整型数。"%*.*f"同理。

scanf("%*d %d", &n):"*"在scanf中表示跳过对应的输入项,在本例中若输入1 99,则n的值为99



Expressions and Statement

Parameter:形参

Argument:实参

在C语言中,每个表达式都是有值的

for的条件检查在执行完初始化后就就开始执行了,也就是说可能循环一次都没有执行过

整个逗号表达式(",")的值是最右边的值

例:x = (y = 3, (z = ++y + 2) + 5);  首先执行y=3,再执行右边的表达式,最后将右边表达式的值赋给x

但如果是var = 249, 500; 则var变成249,整个表达式的值变成500(因为"="的优先级更高)

由于getchar()和putchar()只处理字符,所以比通用的scanf()和printf()更快速和紧凑

整个的if..else..语句是一个表达式

C保证逻辑表达式是从左到右进行判断

switch语句括号中的测试表达式必须是整数值



I/O

C程序通过流(stream)处理文件,而不是直接处理文件。流是真实的输入和输出映射到的理想化的数据流。

getchar()的返回值是int型(EOF通常被定义为-1)



Function

递归函数中,递归调用前的语句是按照递归函数的调用顺序执行的;递归调用后的语句按照递归函数调用语句的逆序执行

递归会占用更多的内存,stack中的空间限制会制约递归的次数,并且每次调用自身都会花费时间

main()也可以递归调用,或者被其他函数调用


int main(int argc, char *argv[]);

大部分环境,包括Unix和DOS,都允许将多个单词用双引号括在一起而成为一个参数



位运算

C和其他高级语言不同的一点是C可以单独访问一个整数中的bit

位运算符的优先级低于"=="

按位取反:~

按位异或:^

左移:<< (空位补零,高位丢失,并且变量自身并不改变)

右移:>> (对于unsigned型,左边补零;对于signed型,左边补0还是1取决于具体的机器实现)


bit field

进行位处理的另一个方法是bit field,它是在一个signed int或unsigned int中相邻的bit(C99和C11还额外允许类型_Bool)。bit field的创建类似结构体的声明方式,要给每一个field命名并决定它的宽度,例:

struct bf {   unsigned int a : 1;   unsigned int b : 1;   unsigned int c : 2;};

变量bf存储在int大小的内存空间中,但是本例中只用了4个bit。bit的范围从0开始,例如若有8个bit,则范围是[0-7]。如果声明的bit数超过了类型的大小,以unsigned int为例,则下一个unsigned int的存储空间将会被使用,但一个field不能横跨两个unsigned int。可以给每个field赋值,如bf.a = 1;,注意不要超过field所能容纳的范围。

可以用未命名field来填充field结构,还可以使用宽度为0的未命名field强制使用下一个变量空间(如unsigned int)。例:

struct {   unsigned int field1 : 1;   unsigned int        : 2;   unsigned int filed2 : 1;   unsigned int        : 0;   unsigned int filed3 : 1;} stuff;

filed是从左向右使用还是从右向左使用取决于具体的机器。由于类似的原因,bit field的可移植性并不好。然而,bit field其实通常用于非可移植性的目的,如将数据以某个特定硬件所使用的格式存放。

bit-field结构的初始化可以用结构体相同的语法,如:struct bf bf_1 = {1, 0, 3};


对齐(Alignment)特性(C11)

C11的对齐特性更接近byte处理而不是bit处理。这里的对齐是指object是怎样在内存中被放置的。大多数情况下都不需要考虑使用对齐,但在一些特殊情况,如将数据从一个硬件位置传送到另一个硬件位置或使用同时处理多个数据的指令时,对齐处理会带来优势。

_Alignof操作符可以给一个类型产生对齐要求,通过在该关键字后添加被括号括起的类型可以实现:size_t d_align = _Alignof(float);

比如,当d_align的值是4的时候表示float object的对齐要求是4,也就是说存储float型的连续地址之间的byte数是4。通常,对齐的值应该是非负数,且应该是2的整数次幂。越大的对齐值叫做越严格(stricter)或越强(stronger),越小的称作越弱(weaker)


可以使用_Alignas标识符给一个变量或类型要求特定的对齐,但是不能要求比这个类型的基础对齐更弱的对齐。比如,对齐是8的意思是这个类型的地址可被8整除。它用在声明中,后接对齐值或一个类型,例:

_Alignas(double) char c1;_Alignas(8) char c2;char _Alignas(long double) c_arr[sizeof(long double)];

包含"stdalign.h"头文件可以让你用alignas和alignof代替_Alignas和_Alignof,同时也符合C++关键字。C11还在stdlib.h库中提供了能够设定对齐要求的空间分配函数,它的prototype是:void* aligned_alloc(size_t alignment, size_t size);

第一个参数表明对齐要求,第二个参数指明需要的byte数,第二个参数必须是第一个参数的整数倍


通常,使用上述bit特性的程序主要是面向某一种硬件平台或操作系统,并不强调可移植性


0 0
原创粉丝点击