指针:

指针乃C、C++的灵魂之所在,所以有必要好好的复习复习。什么是指针?一句话来概括:“指针是一个变量,它的值是一个地址。”,其中指针变量的声明有如下三种形式:

其中第一种是被推荐的写法。

其中还需要注意:在声明指针时如果未赋值,则是一个野指针【也就是有可能指向了一个不能被使用的地址从而造成程序的错误】,所以在声明时一定要赋值,如下:

那如果想取变量的地址则可以用“&”符,如下:

那如果想获取指针指向变量地址的值则需要用“*”解引用的操作,如下:

下面来看一下p指针占用了几个字节:

需要注意的是:由于目前是在64位系统上运行的,所以是8个字节,如果是在32位运行则长度是4个字。

有了指针之后就可以用它去操纵内存,下面来通过指针的形式来修改变量的值,如下:

指针是可以进行++、--操作的,比如用指针来遍历数组,下面来看下:

其中“*array_p1++”是先取了值,然后再对其指针进行++,如果是写成"*++array_p1",则是先对指针进行加加,然后再取值,最终输出就会漏掉一个,如下:

其中还有一种直接通过数组来进行相加也能达到遍历的目的,如下:

要取其数组的内容则需要解引用:

另外还有一个细节:为啥数组取地址时木有加“&”符号:

这是因为在C中数组名就是数组的首地址,下面来看下:

下面有个概念需要弄清楚:“数组指针”和“指针数组”,这个在面试可能会经常变问到,下面来看下:

其中指向的数组的元素个数为3,如果咱们想要通过数组指针array_p2来获得第二维的55,如何来写呢?

首先肯定得要将数组的指针+1,来定位到第二维的数组,所以array_p2+1,然后再取出它的值则是*(array_p2+1),接着这个值是一个数组,所以还得数组名+1来将指针移到要输出的第二个元素上来,所以此时为*(array_p2+1)+1,最后再解引用取出指针的值,所以整个的式子如:*(*(array_p2+1)+1),下面来验证一下:

接下来更绕的来了,先把代码写出来:

我去!!什么鬼~const char~~char const~~搞死人的节奏~~但是在学C时必须要理解它的,下面一个个来理解,在理解之前,先记着这个原则:“从右往左看 const 修饰谁 谁就不可变”:

意味着不能通过p2来修改tem的值,如下:

因为const是修饰的char,而非p2变量,所以p2的内容可以被更改,如下:

继续来理解下一个:

这个跟上一个效果是一模一样的,为啥?因为const只能修饰char,不能修饰*。

继续看下一个:

还是按照从右往左的原则,const这次修饰的是变量p4,也就是说p4的内容是不允许修改的,如下:

但是可以通过指针修改指向地址的值,如下:

好,继续,下面两个是啥都不能变了,如下:

拿p5举例,既不能修改p5指针的值,如下:

下面再来看一个跟指针相关的东东---多级指针:

解引用则为:

函数:

函数声明:

C中的函数跟Java的方法基本类似,但是在C中的函数需要注意:我们使用的函数必须在之前声明,否则会编译不过,如下:

可以在之前做一个声明既可:

所以一般函数都声明在头文件中,然后一.c文件中头部进行include,这样就如同上面的声明一样了。

函数传参:

  • 传值:把参数的值给函数,如下:

    也就是说不会改变原有变量的值。

  • 传引用:

    也就是可以通过指针来修改原值,有了这个特性,那么多级指针就变得非常有意义了,如下:

可变参数:

在Java中我们知道可变参数是由...来弄的,其实在C中也类似,其中我们经常打印的printf()函数就接收一个可变参数,查看一下源码便知:

所以咱们也来弄一个可变参数:

呃~~报错了~~参数中不能只有可变参数,必须要有一个确定参数,所以修改如下:

接着问题来了,如何来取出可变参数的值呢?看下面:

然后接着进行遍历,根据类型:

注意:其确定参数给NULL值是可以的,反正是要有一个,什么类型的都可以,不能没有确参,如下:

函数指针:

定义:指向函数的指针。举个例子:

其中"void (*p) (char*)"就是一个函数指针,void表示该函数无返回值;(char*)表示函数的参数列表,目前只接收一个参数;(*p)表示指向函数的指针。

接着咱们来调用一下:

其实也就相当于Java中的方法回调的意思,另外可以将函数的声明定义成一个typedef,如下:

可以用函数指针模拟HTTP请求,如果成功就执行某个函数,失败则执行某个函数,如下:

预处理器:

预处理器主要是完成文本替换的,常用的预处理器如下:

下面具体来看一下:

  • #include:这个就不多说了。
  • #if、#elif、#else、#endif:在实际代码编写中会遇到这样的写法,如下:

    假如不想要这段代码了,则直接更改条件既可:

    适用的场合就是假如写的代码不想要了,则不用注释掉了。

  • #define、#ifdef、#ifndef:这里可以配合#define的宏定义来配合上面的一些条件来使用,如下:

    其中定义的宏是可以被取消的,如下:

    其中#define宏定义分为两种:宏变量和宏函数,具体如下:

    这样在代码中就可以使用I来表示1了,如下:

    而在之前说过预处理其实也就是做文本替换用的,所以代码中所有的I就会被预处理器替换为1。
    接下来看一下宏函数:

    此时就可以在代码中进行调用了,如下:

    但是宏函数也有陷阱需要注意,看下面这个:

    如果修改一下:

    期望的结果应该是(1 + 10)* (10 + 10) = 220,但是运行看:

    居然变成了:1 + 10 * 10 + 10了,所以需要特别注意,可以加个括号解决:

    下面来看一下宏函数有哪些优缺点:
    优点:它只是文本替换,使用到宏函数的地方会执行替换,不会有函数调用的开销(将参数压栈,释放栈之类的)。
    缺点:1、不会对我们的代码执行检查,不像普通的函数在编写阶段就会给出相印的错误提示。2、假如宏函数是一个非常复杂的函数,那么每个调用它的地方就会完全替换,造成代码冗余使得最终生成的目标文件(如so)增大了,比如:

    如果代码中调了两次它,如下:

    实际上文本替换之后就是:

    其实内联函数跟宏函数的执行模式是一样的,也是执行代码替换,但不是一个概念,内联函数在编写时会做检查,另外它里面的代码不能编写过于复杂的代码,如使用了switch、while等复杂控制逻辑,否则会将内联函数降级为普通函数,那何为内联函数呢?其实就是inline关键字,如下:

  • #pragma:这个用得较少,在VS中在头文件中会自动有一个如下东东:

    它表示该头文件只能被引用一次,其实通用的写法是用它:

    其效果都是一样的。

ndk学习之C语言基础复习----指针、函数、预处理器的更多相关文章

  1. ndk学习之C语言基础复习----虚拟内存布局与malloc申请

    在这一次中来学习一下C语言的内存布局,了解它之后就可以解释为啥在用malloc()申请的内存之后需要用memset()来对内存进行一下初始化了,首先来了解一下物理内存与虚拟内存: 物理内存:通过物理内 ...

  2. ndk学习之c++语言基础复习----C++线程与智能指针

    线程 线程,有时被称为轻量进程,是程序执行的最小单元. C++11线程: 我们知道平常谈C++线程相关的东东基本都是基于之后要学习的posix相关的,其实在C++11有自己新式创建线程的方法,所以先来 ...

  3. ndk学习之c++语言基础复习----C++容器、类型转换、异常与文件流操作

    继续来复习C++,比较枯燥,但是这是扎实掌握NDK开发的必经之路,不容小觑. 容器: 容器,就是用来存放东西的盒子. 常用的数据结构包括:数组array, 链表list, 树tree, 栈stack, ...

  4. ndk学习之C语言基础复习----基本数据类型、数组

    关于NDK这个分类在N年前就已经创建了,但是一直木有系统的记录其学习过程,当然也没真正学会NDK的技术真谛,所以一直也是自己的一个遗憾,而如今对于Android程序员的要求也是越来越高,对于NDK也是 ...

  5. ndk学习之c++语言基础复习----面向对象编程

    关于面向对象编程对于一个java程序员那是再熟悉不过了,不过对于C++而言相对java还是有很多不同点的,所以全面复习一下. 类 C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程 ...

  6. ndk学习之C语言基础复习----结构体、共用体与C++开端

    自己实现sprintf功能: 关于C中的系统函数sprintf在上次[https://www.cnblogs.com/webor2006/p/7545627.html]学习中已经用到过了,这里再来回顾 ...

  7. MySQL学习笔记_8_SQL语言基础复习

    SQL语言基础复习 一.概述 SQL语句注释方式 1)以"#"开头直到行尾的所有内容都是注释 2)以"--"(--后还有一个空格)开头直到行尾的所有内容都是注释 ...

  8. GO学习-(10) Go语言基础之指针

    Go语言基础之指针 区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针. 要搞明白Go语言中的指针需要先知道3个概念:指针地址.指针类型和指针取值. Go语言中的指针 任何程序数 ...

  9. 嵌入式-C语言基础:指针函数

    指针函数:返回指针的函数,即函数返回一个地址.例如:int * a(int x,int y);由于()的优先级比*高,因此a先与()结合,a(int x,int y)显然是一个函数,函数前面带一个in ...

随机推荐

  1. 【VS开发】【数据库开发】libevent入门

    花了两天的时间在libevent上,想总结下,就以写简单tutorial的方式吧,貌似没有一篇简单的说明,让人马上就能上手用的.首先给出官方文档吧: http://libevent.org ,首页有个 ...

  2. HTTP网页请求状态码

    我们平时在打开一些网页的时候,会遇到打不开的情况,页面提示404错误,这个404就是http状态码.如果我们可以正常打开网页,这时也会有http状态码的,这个状态码就是200,只不过这时我们是无法通过 ...

  3. java23种设计模式之九: 抽象工厂方法模式

    一.抽象工厂定义 上一讲我们说了一下工厂方法,那么我们如何对工厂进行抽象. 因为工厂是生产产品的,现在我们需要工厂抽象,只生产抽象产品,不生产具体的产品,这同时也体现了java的多态. 现在有2个抽象 ...

  4. MapReduce的shuffle过程详解

    [学习笔记] 结果分析:shuffle的英文是洗牌,混洗的意思,洗牌就是越乱越好的意思.当在集群的情况下是这样的,假如有三个map节点和三个reduce节点,一号reduce节点的数据会来自于三个ma ...

  5. 如何用IDEA创建springboot(maven)并且整合mybatis连接mysql数据库和遇到的问题

    一.New->Project 二.点击next 三.在Group栏输入组织名,Artifact就是项目名.选择需要的java版本,点击next 四.添加需要的依赖 在这里我们也可以添加sql方面 ...

  6. Laravel安装和composer安装

    下载地址:https://getcomposer.org/download/ 他会自动找到你的php目录,如果没有记得手动修改  一直点下一步,即可. 如果安装不成功,可能是之前安装过composer ...

  7. GB2312、GBK、GB18030 这几种字符集的主要区别

    1 GB2312-80 GB 2312 或 GB 2312-80 是中国国家标准简体中文字符集,全称<信息交换用汉字编码字符集·基本集>,又称 GB 0,由中国国家标准总局发布,1981 ...

  8. python学习-45 模块

    模块 -----模块包括三种: ····python标准库 ····第三方模块 ····应用程序自定义模块 -------应用程序自定义模块 1.建立两个py文件,一个是定义函数用的cal.py de ...

  9. scratch少儿编程第一季——06、人在江湖混,没有背景怎么行。

    各位小伙伴大家好: 到上期我们学习了动作模块的全部指令.接下我们用动作模块做一个小小项目,来总结我们前面学的内容. 在做项目之前我们先来换一个背景. 在左下角舞台区,点击打开背景库,选择自己所需要的背 ...

  10. python练习:函数2

    习题: 定义一个方法get_num(num),num参数是列表类型,判断列表里面的元素为数字类型.其他类型则报错,并且返回一个偶数列表:(注:列表里面的元素为偶数). def get_num(num) ...