1. 1. C
    1. 1.1. 编译运行
    2. 1.2. 头文件
      1. 1.2.1. #include中 <>和””的区别
    3. 1.3. C 的变量
      1. 1.3.1. int 长度
      2. 1.3.2. 自动变量、外部变量extern
      3. 1.3.3. const限定符
      4. 1.3.4. 人们通常把变量和函数的 extern 声明放在一个单独的文件中(习惯上称之 为头文件),并在每个源文件的开头使用#include 语句把所要用的头文件包含进来。后缀 名.h 约定为头文件名的扩展名。
      5. 1.3.5. define 指令可以把符号名(或称为符号常量)定义为一个特定的字符串:
      6. 1.3.6. 条件包含
    4. 1.4. C 是指针世界
      1. 1.4.1. 指针为什么需要类型
      2. 1.4.2. 无权限函数,参数,指针作为参数
      3. 1.4.3. 2级指针、多级指针,应用场景(以后你就懂了)
      4. 1.4.4. 函数指针
    5. 1.5. 动态内存分配
      1. 1.5.1. 内存分配的几个注意细节:
    6. 1.6. 字符操作
      1. 1.6.1. 字符数组,字符指针。
    7. 1.7. 结构体——C语言中结构化数据类型的核心
    8. 1.8. 类型别名
    9. 1.9. 文件IO编写步骤:
  2. 2. C++
    1. 2.1. 命名空间
      1. 2.1.1. using声明
    2. 2.2.
    3. 2.3. 构造函数、析构函数、拷贝构造函数
  3. 3. JNI
    1. 3.1. JNI概念及开发流程
      1. 3.1.1. 基本概念
      2. 3.1.2. 交叉编译
    2. 3.2. C 调用Java对象的构造方法
  4. 4. NDK
    1. 4.1. 使用Android Studio编写NDK
  5. 5. 调试

C

编译运行

在 UNIX 操作系统中, 首先必须在某个文件中建立这个源程序,并以“.c”作为文件的扩展名,例如 hello.c,然
后再通过下列命令进行编译:
cc hello.c
如果源程序没有什么错误(例如漏掉字符或拼错字符),编译过程将顺利进行,并生成一个可 执行文件 a.out。然后,我们输入:
a.out
即可运行 a.out,打印出下列信息:
hello, world
在其它操作系统中,编译、加载、运行等规则会有所不同。

头文件

编写C的时候 , 首先我们需要引入头文件 , 就像我们写JAVA的时候 , 需要引入包一样 , 但C语言他不会帮你自动引入 , 所有头文件 , 必须你自己手动引入, 最常用的两个头文件是

1
2
#include <stdio.h>
#include <stdlib.h>

C语言中的xxx.h的头文件 , 里面只有函数声明 , 没有函数实现 , 函数实现都在xxx.c里面 。

#include中 <>和””的区别

尖括号,表示编译器只在系统默认目录或尖括号内的工作目录下搜索头文件,并不去用户的工作目录下寻找,所以一般尖括号用于包含标准库文件,例如:stdio.h,stdlib.h。 双引号”xxx.h”,表示编译器先在用户的工作目录下搜索头文件,如果搜索不到则到系统默认目录下去寻找,所以双引号一般用于包含用户自己编写的头文件。
因此,所该头文件由自己编写,位于工作目录下,就一定要用双引号;若属于标准库文件,则两者都可以,不过最好使用尖括号。

C 的变量

C语言中的变量类型 , 和变量大小 。
和JAVA不同的是 ,

  1. C语言变量的大小 , 是随着操作系统变化而变化的 , 不同的操作系统 , 变量的大小可能不一样 。
  2. 在 C 语言中,所有变量都必须先声明后使用。声明通常放在函数起始处,在任何可执行 语句之前。

int 长度

四个字节只是在x86上面 大多数编译器的一种做法,目的自然是操作内存更方便;
int是最基本的类型,一般和CPU的字宽一致。,提高处理速度。。。
不一定是 4个字节的 和你操作系统有关系
是intel设计cpu时的规定,做16位cpu 8086时是这样的(ax寄存器可分为2个8位的ah和al),
在做32位嫌太麻烦,就没做.比如eax寄存器,可拆分为ax,ah,al使用,
高16位得通过特殊的方法使用.
如果想知道底层的实现 看看汇编相关数据吧!
一般地,short类型为半个机器字(word)长,int类型为一个机器字长,而long类型为一个或两个机器字长(在32位机器中,int类型和long类型通常字长是相同的)。
其实这是个历史遗留问题,16位时期 long就是32位的,为了兼容。而int应该是最适合当前机器的字长,所以也是32位的

自动变量、外部变量extern

const限定符

任何变量的声明都可以使用 const 限定符限定。该限定符指定变量的值不能被修改。对 数组而言,const 限定符指定数组所有元素的值都不能被修改:
const double e = 2.71828182845905; const char msg[] = “warning: “;
const 限定符也可配合数组参数使用,它表明函数不能修改数组元素的值: int strlen(const char[]);
如果试图修改 const 限定符限定的值,其结果取决于具体的实现。

人们通常把变量和函数的 extern 声明放在一个单独的文件中(习惯上称之 为头文件),并在每个源文件的开头使用#include 语句把所要用的头文件包含进来。后缀 名.h 约定为头文件名的扩展名。

define 指令可以把符号名(或称为符号常量)定义为一个特定的字符串:

1
2
3
#define 名字 替换文本
#define LOWER 0
#define UPPER 300

条件包含

编译过程中根据计算所得的条件值选择性地包含不同代码。
例如,为了保证 hdr.h 文件的内容只被包含一次,可以将该文件的内容包含在下列形式 的条件语句中:

1
2
3
4
#if !defined(HDR)
#define HDR
/* hdr.h 文件的内容放在这里 */
#endif

C 语言还专门定义了两个预处理语句#ifdef 与#ifndef,它们用来测试某个名字是否已经 定义。上面有关#if 的第一个例子可以改写为下列形式:

1
2
3
4
#ifndef HDR
#define EDR
/* hdr.h 文件的内容放在这里 */
#endif

C 是指针世界

C语言的世界就是一个指针的世界 , 就如同JAVA的世界就是一个对象的世界一样 , 两者都是其各自的核心 , 所以我们一定要把指针弄懂 , 学透 。

指针为什么需要类型

指针是存储的地址是开始读取的位置 , 类型是读取的长度 , 操作类型必须一致 。
下面的代码段说明了如 何在程序中声明指针以及如何使用运算符&和*:

1
2
3
4
5
6
int x = 1, y = 2, z[10];
int *ip; /* ip is a pointer to int */
ip=&x; /*ipnowpointstox*/
y=*ip; /*yisnow1*/
*ip=0; /*xisnow0*/
ip = &z[0];/* ip now points to z[0] */

无权限函数,参数,指针作为参数

2级指针、多级指针,应用场景(以后你就懂了)

函数和java中的方法类似 , 只是缺少了访问控制符 , 二级指针也就是指针的指针 , 指针里面存储的是指针的地址 , 可以通过*操作符不断往上追溯 , 然后通过内存地址操作内存空间 。场景可以先不管,以后用到自然懂了。

函数指针

定义指向函数得指针,这个指针还可作为函数的参数。
void(*func_p)() = &message;

1
2
int *f(); /* f: function returning pointer to int */
int (*pf)(); /* pf: pointer to function returning int */

动态内存分配

栈区,堆区,全局区或静态区,程序代码区。
http://www.jianshu.com/p/93db7c692d1b

内存分配的几个注意细节:

1.不能多次释放
2.释放完之后 , 给指针置NULL,标志释放完成
3.内存泄漏 (p重新赋值之后 , 再free , 并没有真正释放 , 要在赋值之前释放前一个内存空间)

字符操作

字符数组,字符指针。

http://www.jianshu.com/p/b7e6fc094087
字符指针与字符数组 , 最大的区别是一个定义了就不可以修改 , 一个可以任意修改里面的字符 , 就和String和StringBuilder一样 , String定义了就无法增加或修改里面的内容 , 一个是可以增加和修改里面的内容 。
字符串函数附录

结构体——C语言中结构化数据类型的核心

如果说类是java中结构化数据类型的核心 , 那么结构体就是C语言中结构化数据类型的核心 。
在学习C语言的结构体的时候 , 我们可以类比成java中的类 , 只是这个类比较特殊,结构体中只有声明 , 函数没有实现 , 属性也不能初始化 , 一般定义在头文件中 。就好比声明了一个抽象类 , 里面什么动作也不做 , 属性只是声明一样 , 都需要继承或是外部去赋值 。

类型别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*类型别名 关键字:typedef*/
/*
1.不同名称代表在做不同的事情typedef int jint;
2.不同情况下,使用不同的别名
3.书写简洁
*/

// 简单别名

typedef char* Name;

// 结构体别名
typedef struct ImageInfo {
char* name;
int size;
char* path;
}ImageInfo , *ImageInfo_P;

文件IO编写步骤:

1.使用fopen函数 , 得到文件指针
2.指定fopen的操作模式r,w (指定输入输出流)
3.创建缓冲区 , 缓存读写数据(将流数据读入到内存或写入到磁盘)
3.关闭流 (关闭文件流)

C++

命名空间

增加了命名空间/namespace;

using声明

1
using std::cout;

与C 只有结构体相比,增加了类,权限修饰符。使用类与使用结构体 , 用法并无二致 , 只是结构不能使用new而类可以使用 , new出来的是一个对象指针 。

构造函数、析构函数、拷贝构造函数

JNI

JNI概念及开发流程

基本概念

  1. JNI是?
  2. 用JNI是为了?
  3. 基本类型
  4. 栈、堆的知识

    交叉编译

  5. 交叉编译是?
  6. 交叉编译的工具?
    JNI的开发流程 , .h头文件的分析 , 生成头文件javah命令 , 以及java类型在C语言中的表现形式 , 值得注意的是 , java中的所有引用类型都是jobject类型 , native生成的函数 , 以Java全类名方法名表示,包名的.以_表示 。
    以ijk为例,进行简单过程介绍:https://www.jianshu.com/p/aa6efea4ef35

C 调用Java对象的构造方法

NDK

使用Android Studio编写NDK

随着Android Studio的越来越完善 , 我们编写NDK就会越来越方便,使用Android Studio 2.2 RC2 , 编写NDK的时候 , 不需要使用javah命令来生成头文件 , 创建一个native方法 , 使用alt + enter会提示要你创建一个JNI函数 , C/C++语法提示也相对比较完善了, 减少了一些重复代码的编写。
http://www.jianshu.com/c/a25bf14495d7

调试

符号表
adds2line工具
ndkstace工具
env–>ExceptionCheck()
env–>ExceptionOccurd()