C

写一个C程序first.c

1,预处理 gcc -E first.c -o first.i -->first.

2,编译   gcc -c first.i-->first.o

3,连接         gcc first.o-o first -->first

gccfirst.c

 

sizeof()括号内的运算式不进行运算,只是推断一下大小

 

优先级:

1,()最高 =最低

2,单目运算符比双目运算符高

 

赋值运算符,和单目运算符是右结合的

其他的基本为左结合

 

与或非

1 && X = X

1 || X = 1

异或

1 ^ X = -X

0 ^ X = X

按位取反:

先加1,符号反转

 

两个数参与运算

1,小范围的数转成大范围的数

2,最小的计算单位是int

 

switch语句:

case后面一定要为常量表达式,而且不能重复

 

函数:

void fun() {}

当传参数时,可以随意传入参数,只不过没意义

如果不想函数里面传递参数,可以规定:void fun(void){}

调用函数之前,函数必须先声明或先定义,否则,C处理成隐式声明,返回int

尽量不要使用隐式声明

隐式声明, int函数名(根据实参推)

递归

1,退出

2,递归调用向已知靠近

3,效率低,内存消耗大

4,适合解决特别复杂的问题(这个复杂问题可以简化成若干简单问题)

 

全局变量如果没有初始化,会自动初始化为0,作用域是整个程序,可以在任何地方访问,前面没有默认的auto修师符,也不能加auto

 

 

指针:

int* p1, p2;是定义了一个int指针和一个int变量

 

注意:

a[i] ==*(a+i)

*(a+i) ==*(i+a)

*(i+a) ==i[a]

所以a[i] ==i[a]

指针和数组区别:

1,sizeof结果不同

2,数组名不可更改(数组a[],指针p++p可以,而++a错误)

其他数组和指针一样,可将数组名当指针用

数组名本身:

本身是常量,不可改变,sizeof可以获取整个这片内存的长度

自定义指针指向一片数组区域:

指针是变量,可以改变,sizeof结果为4

char*fa() {

//函数中返回字符串常量的地址是可以的(在代码区)

return"abcdef";        

}

 

char*fb() {

//static是在全局区,所以返回地址是可以的

static int x = 10;

return &x;        

}

 

int* fc(){

//这是不可以的

int x = 10;

return &x;        

}

 

char*fd() {

//这也不可以(在栈区分配的局部变量)

char str[] = "abcdef";

return str;

}

 

进程内存空间:

代码区 : 程序代码,只读区,不可改

全局区 : 全局变量

堆 : 程序员自己申请

栈 : 局部变量,函数形参...

main函数:

int main(void)

int main()

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

int maim(int argc, char** argv)

int main(int argc, char** argv, char** env)

#define

宏函数:#define 标识符(...) ...

注意:标识符和(之间不能有空格

宏函数:

1,所有参数应用()将其包含,否则使用表达式时可能错误

2,在调用宏函数时,不要使用++,--,否则不能保证结果正确

 

优点:

1,程序可能会稍微快一点

2,宏更"通用"

3,宏函数中的参数不检查类型

缺点:

1,编译后的代码通常会变大

2,宏参数没有类型检查

3,无法用一个指针指向宏

4,宏可能会不止一次地计算它的参数(n= MAX(i++, j);)

5,可读性差,错误很难查出

"#"运算符

只能出现在宏函数中,作用是将参数字符串化

#define PRINT_INT() printf(#n

"##"运算符

将两个标记连成一个标记,一般情况下,两个标记中的一个是参数

 

预定义宏

__LINE__ 源程序行号

__FILE__ 源程序文件名

__DATE__ 现在日期

__TIME__ 现在时间

__STDC__ 是否支持标准C,支持为1,不支持为0

 

注意:

在全局变量前面加上static是为了限制其范围,只能在本文件内访问此全局变量

在函数前面加static也是为了限制其访问权限,只能在本文件内访问此函数

 

给类型起别名的方法:

1,先用这种类型定义一个变量

2,在最前面加typedef

那个变量名就是类型的别名

Example: typedef int I10[10];

而不是 typedef int[10] I10;

预处理器 将///* */ 去掉

编译器将#.... 去掉

 

全局变量

extern 类型 变量名

静态全局变量

限制变量的访问

静态全局函数

限制函数的调用

 

结构体

p-> 相当于 (*p).

 

对齐,补齐

由于内存分配会将结构中的变量分配到内存的边界上,以方便访问。

所以每个成员放的位置是从本身长度的倍数位开始放。

但本身长度超过4时,以4计。此称为对齐。

char   1倍

short  2倍

int    4倍

double4倍                

整个结构变量的长度要保持内部最长成员(超过4以4计)的倍数。

如果不够,则补齐。

 

位段

本质是结构

struct Switch {

int s1 : 1    //1代表一个二进制位

int s2 : 1

int s3 : 1

int s4 : 1

int s5 : 1

};

 

函数指针

函数名其实是一个常量指针

为什么用函数指针

函数指针的应用比较广泛,函数指针是变量,

所以变量能出现的地方,函数指针就可以出现

比如,可以用数组保存很多函数,

可以把函数作为另外一个函数的参数进行传递,用一个函数返回一个函数

 

静态分配 :编译期间可以确定需要分配内存的大小

int x; : 在栈分配

动态分配 :编译期间不能确定所需要分配内存的大小,

只有程序运行时才能确定分配空间的大小.

   在堆空间中分配,堆空间内存分配比较自由,

                  分配空间和释放空间由程序员自己确定,堆区也叫自由区

malloc:

分配多少空间后在之后的一个空间位置设置一个标记,当free时从开始位置释放空间,直到遇到此标记时结束,因此如果越界访问可能会破坏此标记,引发内存错误,也可能产生段错误(超过页面大小)

malloc和calloc的功能相同,可以通用,唯一的区别就是calloc会将分配好的内存清零

mallco和calloc分配空间的首地址一定要保存下来,否则在free时会出现内存错误

realloc :函数调整分配后的大小

1,当扩展内存时,不会对增加的内存初始化

2,失败时返回空指针,原内存中的数据不会改变

3,第一个参数是空指针时,如同调用malloc

4,如果以0作为第二个参数,会释放原内存块

5,小心,realloc可能会将内存块移到别的地方去。

 

free:

1,参数需要释放空间的首地址,确定堆空间的结束标记没有被破坏

2,两次释放同一片空间会造成内存错误(double free)

3,当free掉一片空间后,应该立即把指向该空间的指针置零

4,谁申请的空间谁释放,否则可能造成悬空指针

 

数组指针

int n[10];

数组a的值是第一个元素的地址(下标0)的地址

a的类型int[10]实质上是int* const类型

所以*a 等同 a[0]

如果&a,则取到整个数组的首地址

与a[0]地址相同,但意义不同,类型为int (*pa)[10] = &a

inta[3][4],a是一个数组,数组里有3个元素,每个元素是int[4]类型的数组

a是第一个元素的地址,a的类型就是int[3][4],int(*)[4]

int(*pa)[4] = a;

 

stdout 和stderr的区别

1,stdout带缓冲区,stderr不带缓冲区

2,stdout可以重定向,stderr不能重定向

3,什么时候stdout缓冲区会清空:

1)缓冲区清空时,缓冲区的内容会送到显示器

2)当输出换行时会清空

3)当等待用户输入时会清空

4)当调用fflush函数时清空

5)当程序运行结束时清空

6)当缓冲区满时清空

 

sprintf:

可以将任何数据转成指定格式的字符串

 

va_list:处理步骤固定,如下

va_listva;                //1,声明一个va_list类型的变量,用来保存所有可变长参数

va_start(va,n);        //2,将所有的参数保存到va_list里

va_arg(va,i);        //3,从va_list中逐个取出参数进行处理

va_end(va);                //4,释放va_list

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值