C语言指针、动态数组、编译预处理总结

一、指针:

对于指针,我就不介绍概念了,很多教材讲的比我好的多。我在这里归纳一下指针操作需要注意的点:

1. 在进行函数传参时,数组传址,其它类型传值,但进行局部变量通过其它函数改变值时要传址。

    如int a=1;则函数形参应该写int *x; 传参时实参应该为&a;

    但传址时,函数中对形参指向进行改变,不影响原函数中实参的指向。

    比如原函数中实参a->地址1,传参时形参b->地址1,将b换值不影响a的指向。

2. 二维数组情况下,有下图关系(理解此图,指针基础操作不在话下): 

    

3. 二维数组作形参的三种方式:分别是int b[][6],int (*b)[6],int **b。其中前两种二维不能省略,第三种传参以后得到的实际上是一个一维数组,注意操作方式。

4. c储存字符串的两种方式:一是字符数组,而是字符指针。但这两种方式储存字符串的方式是不同的,字符数组每一个单元存放一个值,而字符指针存放的只是字符串的首地址。在系统编译时,字符指针只有一个4字节的空间用于存放地址,而字符数组则有一系列连续的空间存放值。

对于字符指针,可以像c++种string类型那样直接赋值,可以puts()输出,可以像字符数组一样用下标访问,可以和字符指针用等号进行赋值,但在使用字符指针一定要记得赋初值,否则指针的指向是未定的,使用野指针很危险。当然使用字符指针时,若不打算赋初值,也可以配合动态数组开辟一定的空间把地址给字符指针,但要注意此时字符指针的地址已经改变。

对于字符之间的赋值,字符指针之间可以之间用等号。但对于字符指针a和字符数组b,首先不能用等号是自然,其次对于字符复制函数,strcpy(a,b)不行,strcpy(b,a)则可以(这应该与编译原理有关),要进行第一种操作,应该写成a = &b[0]或者a=&b,或者给a开辟一定空间。

5. 函数的指针:首先函数名就是函数的首地址,函数名就是函数的指针。如有一个函数int max(int a,int b);  则指向这个函数的指针p应该定义为int (*p)(int,int),然后p=max。调用时(*p)(a,b)即可。

若要返回指针,对函数类型进行相应修改即可。

6. 指针数组:char * name[ ] = {"aaa", "bbb", "ccc"}; name中三个元素分别存放三个字符串首地址,puts(name[i]);可分别输出三个字符串。

7. 指针的指针:char * name[ ] = {"aaa", "bbb", "ccc"}; char **p;  p=name; puts(*(p+i)); 可分别输出三个字符串。

指针数组和指针的指针在字符串上的作用比较直接,其它情况类似,但目前遇到这些情况的实际应用,以后遇到再补充。

二、 动态数组:

1. int *p;  p=(int *)malloc(sizeof(int));       //开辟1块int大小的空间,将其强制转换为int型指针,地址给p。

2. int *p;  p=(int *)calloc(5,sizeof(int));     //开辟5块int大小的连续空间,将其首地址强制转换为int型指针,给p。

2. free(p);     //释放申请的空间,不释放容易造成内存泄漏。

三、 编译预处理:

1. 宏定义:#define PI  1e6+5

2. 文件包含:系统文件:#include <stdio.h>,自定义文件#include "gaoithe.h"。

3. 条件编译:

//第一种:如果标识符被定义,执行程序段1,否则执行程序段2

#ifdef 标识符
    程序段1
#else
    程序段2
#endif

//第二种:表达式值为真,执行程序段1,否则执行程序段2

#if 常量表达式
    程序段1
#else
    程序段2
#endif

4. 补充一个不是编译预处理但类似的,即变量名替换:typedef long long LL;

发布了34 篇原创文章 · 获赞 26 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/sinat_40471574/article/details/90213740
今日推荐