C语言知识总结

* 各个类型的变量输出的方式:

double float 用 %f ,char 用 %c(打印字符) 和 %d(打印编码),int 用 %d,字符串用 %s,指针用 %p 打印

* 定义变量不初始化,直接使用,并不会报错,结果输出这个变量是随机的。

* 定义数组不初始化,分两种情况,有加 { } ,输出的值初始化默认是 0 ,而不是随机的;没加 { } ,则是随机的:

a[3] = {1,2,3} //完全初始化

a[3] = {};        //不完全初始化

a[3] = {1};      //不完全初始化

a[3];              //无初始化

a[3] = {[0] = 1,[2] = 100};    //gcc 特有的初始化 ,指定位置数据

a[3] = {1,[2] = 100};    //gcc 特有的初始化 ,指定位置数据

这样定义数组,输出为:

0 0 0

1 0 0

随机 随机 随机 

1 0 100

1 0 100

============================================================================

指针:

(1)

int a = 11;   //定义 int 类型变量为 a

int *p ;    //定义一个“指针类型”变量为 p,指向 int 类型数据(指针本身是一种类型)【可以写成:int * p 、int* p 都可以】

p = &a;     // & 表示内存地址,这里表示把 a 的内存地址赋值给指针 p

*p = 22;    //给指针类型p 赋值为 22 

输出 a 等于:

22      //最终就相当于修改了a的内存地址的值为 22

(2)

int a[5] = {55,44,33,22,11};

int *p;

----

p = &a;  //编译警告,但执行结果正确,打印 55【数组类型不能直接赋值给int类型的指针】

p = &a[0];   //编译正常,执行正常,打印 55【这样表示“数据首元素”的首地址,意思和下面不同,但是值一样】

p = a;    //编译正常,执行正常,打印 55【对于数组来说,直接使用变量 a,表示的是“整个数组的首地址”,和上面意思不一样,但是打印值一样】

----

数组的两种表示方式,利用指针也可以来表示数组:

例如有:

int a[5] = {55,44,33,22,11};

int *p;

p = a;

依次输出:

第一种:a[0]  a[1]  a[2]  a[3]  a[4]

第二种:*p  *(p+1)  *(p+2)  *(p+3)  *(p+4)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void main() {
    printf("===========\n");
    int a[5] = {11,22,33,44,55};
    int *p;
    p = a;
     
    for(int i=0;i<5;i++){
        printf("*p = %d \n",*(p+i));
    }
    printf("===========");
}
打印出:
===========
*p = 11
*p = 22
*p = 33
*p = 44
*p = 55
===========

指针在子函数中的使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <stdio.h>
 
int exchange1(int a,int b);
int exchange2(int *a,int *b);
 
void main() {
    printf("===========\n");
     
    int x = 3,y = 5;
    printf("begin param x = %d,y=%d\n",x,y);
     
    //exchange1(x,y);
    exchange2(&x,&y);
     
    printf("begin param x = %d,y=%d\n",x,y);
     
    printf("===========");
}
 
int exchange1(int a,int b){
    int t;
    t = a;
    a = b;
    b = t;
    return 0;
}
 
 
int exchange2(int *a,int *b){
    int t;
    t = *a;
    *a = *b;
    *b = t;
    return 0;
}
 
//调用 exchange1 输出:
===========
begin param x = 3,y=5
begin param x = 3,y=5
===========
//调用 exchange2 输出:
===========
begin param x = 3,y=5
begin param x = 5,y=3
===========

结构体:(就类似 java 的对象)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
 
//定义一个结构体,struct 是关键字
struct User{
    char name[20];  //姓名
    int num;        //编号
    int sex;        //性别
};
 
 
void main(void) {
    printf("===========\n");
     
    struct User s;
    s.name[0] = 'M';
    s.name[1] = 'o';
    s.name[2] = 'n';
    s.name[3] = 'g';
    s.name[4] = 'o';
     
    s.num = 38;
    s.sex = 1;
     
    //字符输出用 %s
    printf("name = %s,num = %d,sex = %d\n",s.name,s.num,s.sex);
     
    printf("===========");
     
}
输出:
===========
name = Mongo,num = 38,sex = 1
===========

结构体初始化两种方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
方式一:struct User u = {x1,x2,x3,x4,x5};
 
方式二:struct User u = {
 
  .a = x1,  //用逗号隔开,a前面的点不可省略
 
  .b = x2,
 
  .c = x3,
 
  .d = x4,
 
  .e = x5
 
};  //最后的分号不可省略

* 共生体(类似 java 的父类)

============================================================================

* 宏定义 ://类似 java 的全局常量,命名全大写,下划线连接

#define NUM (10)    //数据要用括号包起来

#define SUM_NUM (NUM+10)     //后定义的可以使用上面先定义的,结合使用

//例子,使用宏定义表示一年的秒数

#define YEAR_SECOND (365*24*60*60)UL    //UL 表示强制赋值,不然默认为 int 类型,超出长度了,也可以简写成 U【UL 表示无符号类型】

============================================================================

* 枚举

enum week{

  SUN,

  MON,

  TUE,

  WEN,

  THU,

  FRI,

  SAT

}

============================================================================

* void 用法,类似 java 里面的 Object 类型,可以接纳所有类型

1
2
3
4
5
6
7
8
9
10
11
12
void main(void) {
    printf("===========\n");
     
    int a = 123;
    void *p;    //定义 void 类型的指针
    p = &a;
    printf("*p = %d\n",*(int *)p);      //正确
    printf("*p = %f\n",*(float *)p);    //错误
     
    printf("===========");
     
}

* C语言没有 bool 类型(C++ 有),需要使用的时候,用  int 代替,在C语言中,除了 0 ,其余正负 int 数据,都是 1 

* 全局变量和局部变量

  只是定义没有初始化的情况下,局部变量每次数据是“随机值”,全局变量默认是 0

静态局部变量和全局变量很像,可以累加使用,唯一的不同就是静态局部变量还是局部方法里面使用,全局是整个程序使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <stdio.h>
 
void fun1();
void fun2();
 
void main(void) {
    printf("===========\n");
    fun1();
    fun1();
    fun1();
     
    printf("-----------\n");
     
    fun2();
    fun2();
    fun2();
    printf("============");
     
}
 
void fun1(){
    int a = 1;
    a++;
    printf("a = %d\n",a);
}
 
void fun2(){
    static int b = 1;   //静态局部变量,只初始化一次,后续不再初始化
    b++;
    printf("b = %d\n",b);
}
输出:
===========
a = 2
a = 2
a = 2
-----------
b = 2
b = 3
b = 4
============

* 多文件的相互调用:

比如:a.c 和 b.c 有两个文件,在编译的时候,使用命令:gcc a.c b.c -o ab 即可把两个文件关联成一个项目。

如果两者之前的函数,变量要相互调用,必须在顶部声明:

(1)对于函数,和单独一个文件的声明方式一样,直接声明即可。【两个文件不能出现一样的函数名字】

(2)对于变量(只有全局变量),有两种方式来使用,

    ①间接使用,比如 a.c 文件中一个函数 fun 调用了,在 b.c 文件中调用函数 fun 即可间接使用该变量

    ②使用关键字:extern 来声明,比如:

a.c 文件中有一个全局变量 :int g_a = 11;

b.c 文件中要使用,则这样声明:extern int g_a; //不可再赋值

* 静态全局变量的理解:

普通全局变量,是整个项目都可以使用的,一旦定义,即使不同文件之前也不能再出现重名的;

静态全局变量,就是规定只在我当前这个文件中可以使用,另外的文件不可以使用。

* 常量(不会改变的值)

方式:

①宏定义就是一种常量的表现形式

②使用关键字:const 定义。例如:const int a = 1;

“常量”和“指针”结合的重点理解:

const int *p;      //p是一个指针,指针指向一个int类型的数据。p所指向的是一个常量

int const *p;      //p是一个指针,指针指向一个int类型的数据。p所指向的是一个常量

int *const p;      //p是一个指针,指针指向一个int类型的数据。p本身是常量,p所指向的是一个变量

const int *const p;  //p是一个指针,指针指向一个int类型的数据。p本身是常量,p所指向的也是一个常量

 * 回调函数:把整个函数当作参数传给另一个函数使用,需要用到指针来配合。

使用场景:当 A 函数的执行时间需要由 B 函数来决定时,可以把 A 函数当作参数,整个传给 B 函数,然后由 B 来执行。

 

 返回函数指针:

注意: typedef int (*opFunc)(int,int)  中 typedef 后面的 int 类型,取决于 add 和 sub 函数的返回类型!

 

 函数指针数组:

 * 堆的动态申请和释放

* 越界:

 

posted @   雪化山河  阅读(163)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示