IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> JNI常用的C语言知识 -> 正文阅读

[C++知识库]JNI常用的C语言知识

一、指针和数组

1、普通指针

指针是存储变量的内存地址,他有类型,地址没有类型。

int main(int argc, char const* argv[]) {
    //定义变量
    int i = 90;
    //定义指针p,对变量i取地址符( &i)
    int *p = &i;

    float fi = 0.8f;
    float *fp = &fi;
    
    double j = 44.7;
    //想通过四字节的指针复制给八字节的指针行不通,下面的是错误的
    p = &j;

    //空指针,访问内存地址NULL操作系统不允许,默认值是0
    int *pp = NULL;

    return 0;
}

2、二级指针

指针保存的是变量地址,保存这个变量还可以只指针变量。

int main(int argc, char const* argv[]) {
    //定义变量
    int i = 90;
    //定义指针p,对变量i取地址符( &i)
    int* p1 = &i;
    int** p2 = &p1;
    //加一个*是p1的地址,再加一个*是p1指针对应的值i
    **p2 = 93;

    printf("p1:%p,p2:%p\n", p1, p2);//【p1:0x7ffeef4145bc,p2:0x7ffeef4145b0】
    printf("%d",i);
    return 0;
}

3、数组指针

int main(int argc, char const* argv[]) {
    //数组在内存中是连续的
    int ids[] = {33, 44, 55, 66};
    printf("%p\n", ids);
    printf("%p\n", &ids);
    printf("%p\n", &ids[0]);
    //指针变量
    int *p = ids;
    printf("%d\n",*p);
    printf("p的地址:%p\n", p);
    //指针加法
    p++;
    printf("%d\n",*p);
    printf("p的地址:%p\n", p);
    return 0;
}

打印结果:

int main(int argc, char const* argv[]) {
	//开辟连续的内存空间
    int ids[5];
    int i = 0;
    for (; i < 5; i++) {
        ids[i] = i + 10;
        printf("%d\n", ids[i]);
    }
    printf("%d\n", *ids);
    return 0;
}

打印结果:

4、函数指针

void msg(const char* title) {
    printf("%s", title);
}

int main(int argc, char const* argv[]) {
    // msg("xxx");
    void (*func)(const char* msg) = msg;
    func("函数指针");
    return 0;
}

?二、动态内存分配

栈内存:windows下,分配确定的常数2M,自动分配自动释放。
堆内存:程序员手动分配,可以分配操作系统的80%的内存,需要手动释放。

1、静态内存分配

//栈内存
void stackFun() {
    int a[1024];
}

//堆内存
void heapFun() {
    //开辟
    void *p = malloc(1024 * 1024 * 10 * sizeof(int));
    //释放
    free(p);
}

//main函数
int main(int argc, char const* argv[]) {
    stackFun();
    heapFun();
    return 0;
}

?2、动态内存分配

数组的长度是动态的。
(1)重新分配内存:

//开辟
void* p = malloc(1024 * 1024 * 10 * sizeof(int));
//原来的内存不够用,需要重新分配,
void* p2 = realloc(p, sizeof(int) * 1024);

// p2分配的内存缩小,会导致数据丢失,p2分配的内存扩大内容,如果p后面扩展的有用,这连续扩展,还是原来的即p==p2,
//如果p后面存在了,分配的不连续,会将原来的数据复制到新的内存区域,则返回新的内存地址p!=p2,如果复制到新的内存区域还是不够放置
//数据,则返回NULL,开辟失败,原来的p还在

//这里只需要释放p2就可以了,p不需要释放
 if (p2 == NULL) {
    free(p2);
    p2 = NULL;
 }

(2)释放时候需要加上判断,给指针置空,标志释放成功

 if (p == NULL) {
    free(p);
    p = NULL;
 }
 if (p2 == NULL) {
    free(p2);
    p2 = NULL;
 }

(3)内存泄露问题 : P重新赋值之后在free,并没有释放

//40M
void* p1 = malloc(1024 * 1024 * 10 * sizeof(int));
free(p1);//重新赋值之前需要释放掉
//80M
void* p1 = realloc(p, 1024 * 1024 * 10 * sizeof(int)*2);

(4)不能多次释放

free(p);
free(p);

三、结构体的写法

1、方法一

struct Man {
    int age;
    char name[20];//表示字符数组,还可以char *name二者是有区别的
};

int main() {
    //struct Man m1 = {20,"JSON"};
    struct Man m1;
    m1.age = 22;
    strcpy(m1.name, "Rouse");
    printf("%s,%d\n", m1.name, m1.age);
    return 0;
}

如果是字符数组可以在声明时候赋值:

struct Man m1 = {20,"JSON"};

但是不能这样赋值:

m1.name = "JSON";

只能导入头文件#include <string.h>拷贝操作:

strcpy(m1.name, "Rouse");

char name[20]:可以修改里面的内容,但是不能修改字符串:name[0]='x'可以
char *name:可以修改字符串,但是不能修改里面的内容如:name++,*name=x不行

2、方法二:结构体变量

struct Man{
    char name[20];
    int age;
} m1,m2,m3;

m1,m2,m3为结构体的别名。

struct Man{
    char name[20];
    int age;
} Man *Man;

Man结构体变量,*Man结构体变量的指针。在JNI中发现很多别名的结构体和名称一样。可以做到类似于JAVA的Man.age = 20的样子。

3、方法三:全局赋值

struct Man{
    char name[20];
    int age;
} Man = {"Jack",20};

4、方法四:匿名结构体

struct {
    char name[20];
    int age;
} m1;

5、方法五:结构体嵌套

struct Teacher {
    char name[20];
};

struct Student {
    char name[20];
    int age;
    struct Teacher t;
};

// struct Student{
//     char name[20];
//     struct Teacher{
//         int age;
//     } t;
// };

int main(int argc, char const* argv[]) {
    struct Student s1;
    s1.age =20;
    strcpy(s1.t.name,"json");
    return 0;
}

6、结构体大小

结构体大小,字节对齐,大小为最大数据类型的整数倍,不够的话会自动填充,如下为16(8X2)不是12(8+4);

struct Man{
    int a;
    double b;
};

7、结构体别名

取别名:

typedef int Age;
Age a = 9;

结构体取别名Man;WP为指针类型的别名:

typedef struct Man{
    char name[20];
} Man,*WP;

//简写也可以
 typedef struct Man *wp;
 typedef struct Man Man;

8、结构体函数指针成员

struct Girl {
    const char *name;
    int age;
    void (*sayHi)(const char*);
};

void sayHi(const char* text) {
    printf("%s\n", text);
}

int main() {
    struct Girl g;
    g.age = 20;
    g.name = "dd";
    g.sayHi = sayHi;
    g.sayHi("hellp");
    return 0;
}

9、结构指针的成员访问

typedef struct Girl {
    const char* name;
    int age;
    void (*sayHi)(const char*);
} Girl;

void sayHi(const char* text) {
    printf("%s\n", text);
}

typedef Girl* GirlP;

int main() {
	//Girl为结构体别名,用typedef struct修饰,不需要加struct
    Girl g;
    g.age = 20;
    g.name = "dd";
    g.sayHi = sayHi;
    g.sayHi("hellp");

    //传递指针可以直接传递,传递变量新开辟内存空间
    GirlP p = &g;
    p->sayHi("999"); //C语言中使用 -> 操作符来访问结构指针的成员
    return 0;
}

练习:

struct Song {
    char name[20];
    const char* singer;
} S, *SP;

int main(int argc, char const* argv[]) {
    S.singer = "张三";
    strcpy(S.name, "李四");
    printf("singer:%s , name:%s\n", S.singer, S.name);

    SP = &S;
    printf("singer:%s , name:%s\n", SP->singer, SP->name);
    return 0;
}

四、联合体

不同类型的变量共同占用一个内存,相互覆盖,互斥事件,目的是节省内存,大小为最大的成员所占用的字节数。

union MyTest {
	int a;
	int b;
	double c;
};

int main(int argc, char const* argv[]) {
    union MyTest t;
    t.a = 1;
    t.b = 2;
    t.c = 3;
    printf("%d,%d,%1f", t.a, t.b, t.c);
    return 0;
}

打印结果,只有t.c有数(0,0,3.000000)

五、枚举

固定的数据和java一样。

enum Day { SUN, MON, SEN };

int main(int argc, char const* argv[]) {
    enum Day d;
    d = SUN;
    return 0;
}

Day有默认值,相当于:

enum Day { SUN = 1, MON = 2, SEN = 3 };

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-24 10:21:36  更:2021-09-24 10:22:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:28:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码