C语言学习笔记整理2

本次主要整理的内容:

一、宏定义

二、内联函数

三、指针和数组以及指针和数组之间的联系

四、指针和函数的联系

五、野指针和段错误


一、宏定义

1、并不带参数的宏定义
#define MAX 10

2、带参的宏定义
#define add(x,y) (x)*(y) (注意要加小括号)

宏函数和带参的函数(自定义函数)的区别:

(1)宏函数毕竟是宏定义,在预处理阶段进行处理,只进行简单的替换。

         自定义函数不是在预处理阶段处理,是在编译的时候处理的!

带来的实质性差异是:宏函数是在程序里面原地展开的;而自定义函数在函数调用的时候跳转到函数中去执行,执行完毕之后再跳回来,需要一些形参的内存分配等开销。
(2)带参宏(宏函数)不需要进行参数类型检查的(所以就要求程序员自己传参时注意),返回值也不需要有返回值的类型。
自定义函数的参数是需要参数类型检查的(参数类型错误的话有警告),如有返回值,也需要检查返回值的参数类型。


二、内联函数

本质上也是函数!请求编译器在编译这个函数的时候,把他当成内联函数来编译。
定义方式:inline 函数返回值类型 函数名(参数列表) {  }
当编译器拒绝把它当成内联函数来编译的时候,这个函数就变成了自定义函数

#define 和 typedef
#define MAX 10    //不需要分号,在预处理阶段
typedef int INT;  //需要分号,不在预处理阶段


三、指针和数组以及指针和数组之间的联系

指针:指针的实质是变量,和其他的变量没有本质性区别!只不过指针变量里面保存的其他变量的地址。
char a;
char *p = &a;

数组和指针
对于int a[10];
a表示的是数组首元素的地址 &a表示数组的地址
a + 1跳过4个字节(一个int型变量占4个字节),&a + 1 跳过整个数组

*() = [ ];  <==>  *(a + 1) = a[1];

二维数组
a[i][j] = *(a[i] + j) = *(*(a + i) + j)

数组指针
int (*p)[3];
为了p + 1能够从第一行移动到第二行,所以,把p定义成数组指针的形式!
int (*p)[N];并且N跟二维数组的列数是一样的。

指针数组:
首先是个数组,数组里面保存的是指针。
例:char *str[3] = {"hello", "world", "Linux"};


四、指针和函数的联系

1、函数指针:首先它是个指针变量,保存的是什么地址?==》保存的是函数的地址!函数也是有入口地址的,否则如何跳到函数里面去执行相应的代码!
函数的地址怎么表示?==》函数的名字就是函数的地址
先记住:函数指针是我们调用函数的第二种手段!(用途)
如何调用:int function(int a);
第一种:通过函数的名字调用函数:function(2);
第二种:通过函数指针的方式来调用函数
1、函数指针怎么定义?    int (*p)(int);
2、既然函数指针已经定义完毕,接下来要做的事情就是给这个函数指针保存函数的地址
p = function;
给指针赋值,也就是把函数的地址保存到P所对应的空间。
上面这一步,可以理解为:给指针绑定到相应的函数上。
3、经过上面的两步,最后就是通过函数指针来调用相应的函数,用*p直接代替function

指针函数:首先是个函数,并且这个函数的返回值指针(也就是函数返回的是地址)

指针和字符串
1 以字符数组方式存储
char str[] = {"hello"};
char str[] = {'h', 'e', 'l', 'l', 'o'};

2 字符串常量方式存储==>在C语言里面没有字符串变量的说法 char *str = "hello";//以字符串常量的方式进行存储
指针变量str占四字节,用来保存字符串常量hello的首地址。字符串常量保存需要消耗:4 + 6 = 10个字节


五、野指针和段错误

野指针:指针指向了一个不确定地址空间或者是虽然指向了一个不确定的地址空间,但是引用这个地址空间的结果是不确定的。
野指针的危害:
1、段错误(其实就是地址错误)
2、没有结果,现在不会发生错误!这个时候错误很难找出来的!==》要避免野指针
3、发生连环错误!循环叠加,莫名其妙的错误

野指针产生的原因:
1、使用指针之前没有初始化或者没有指向明确的,可用的地址空间
2、不清楚某些指针空间的访问权限,试图修改这个空间里面的值!
char *str = "hello";  //字符串常量是只读的
*(str + 1) = 'w';     //这个操作就是错误的。没有修改的权限
3、有权限,但是超过人家给你的权限
int buf[4] = {1, 2, 3, 4};
*(buf + 4) = 10;   //可能成功,可能失败

如何避免野指针呢?
1、养成良好的编码习惯!定义指针的时候初始化为NULL;即使以后有段错误,也是有报警的。
2、使用指针变量之前,一定检查一下指针变量有没有指向确定的,有操作权限的空间。
3、当指针变量不使用的时候,你要把它指向NULL;

猜你喜欢

转载自blog.csdn.net/CSDN_JKing/article/details/81190358