Android JNI--C语言基础

1,  #include

相当于java的导包操作 例如:#include <stdio.h>

<> 代表寻找系统的资源
“” 代表寻找我们自己写的资源
.h .hpp(声明文件 头文件)
.c  .cpp (实现文件)

2,代码结构

int main() {  // 函数的主入口printf("哈喽!");//打印getchar(); // 阻塞程序return 0;
}

3,基本数据类型

 int i = 100;double d = 200;float f = 200;long l = 100;short s = 100;char c = 'd';
上面这些基本数据类型与java一致
需要注意的是 字符串类型 java中是String  而C语言中是  char * str = "我是字符串";
sizeof获取字节数 下面是每个基本类型所占用的字节数 可以通过此api获取
sizeof(int)//int 占几个字节  == 4
sizeof(double)//double 占几个字节 == 8
sizeof(char)//char 占几个字节 ==1
sizeof(long)//long占几个字节 == 4
sizeof(short)//short占几个字节 == 2
sizeof(float)//float占几个字节 == 4bit——计算机的最小单位byte——1byte = 8bit       (byte就是字节)kb——1kb = 1024bytemb——1mb = 1024kbgb——1gb = 1024mbtb——1tb = 1024gbpb——1pb = 1024tb

4,打印

打印需要注意的是,不和java一样随便打印的,需要占位符

    printf("i的值是:%d\n", i); // d == 整形printf("d的值是:%lf\n", d); // lf == long floatprintf("f的值是:%f\n", f); // f == floatprintf("l的值是:%d\n", l); // d == 整形printf("s的值是:%d\n", s); // s == shortprintf("c的值是:%c\n", c); // c == charprintf("字符串:%s\n", str); // s == String

5,指针地址

在java中,万物皆对象。

在Linux中,万物皆文件

在C 语言中,万物皆指针

指针其实可以理解为地址

  & 代表取出地址 例如:

int number = 10;
printf("此number变量的地址是:%p\n", &number); // 地址 == 00B3FE90
* 代表取出地址所对应的值 例如:
int number = 100;
printf("number的值是:%d\n", *(&number));//100 &number代表number所对应的地址  *(&number)代表取number地址所对应的值 所以输出100
int * 代表int类型的指针 说明定义的是一个指针变量,就是一个变量而已,只不过是指针的变量而已

例如:

int a = 100;
int * b = &a;
printf("a的值是:%d\n", *b);输出100  因为b是a的指针,也就是a地址,
*b代表取地址所对应的值,也就是取a的地址所对应的值100

只要记住一句话,内存地址就是指针,指针就是内存地址

下面看一个错误的用法:

int i = 100;
int * p = i;这种写法是错误的,因为p只能接收指针,给它传一个100,显然是不行的

正确的写法应该是:

int i = 100;
int * p = &i;
指针变量 只能接收指针

如何通过指针修改变量值呢?举个例子:

int i = 100;
int * p = &i;
i = 200;
printf("*p的值是:%d\n", *p);输出200,因为i变为了200,p指向i,*p取得是i的值*p = 300;printf("i的值是:%d\n", i);输出300,因为*p代表i的地址所对应的值修改成300

6,函数

C语言不允许函数重载,Java可以,C++可以

函数需要先声明,再实现。 函数不能写在main函数的下面,会报错

下面来看一个简单的函数例子:

#include <stdio.h> //引入标准库void change(int * i); // 先声明  参数为指针变量int main() {int i = 100;change(&i);//传入指针printf("%d\n", i);//输出666return 0;//main函数返回值 也可以写为NULL
}// 再实现
// 使用指针 来修改
void change(int * i) {*i = 666;
}

由于C语言不支持函数重载,所以声明的函数,不需要写参数

例如:

void change();//不需要填写参数int main() {int a = 100;int b = 200;change(&a, &b);printf("交换完成后的效果:%d,%d\n", a, b);//200  100}// 只接收指针(内存地址)
void change(int * a, int * b) {int temp = *a;*a = *b;*b = temp;
}

7,多级指针:

直接看例子:

int num = 20;int * num_p = &num; // 取出num的内存地址给 num_p(一级指针)int ** num_p_p = &num_p; // 取出num_p的内存地址给  num_p_p(二级指针)int *** num_p_p_p = &num_p_p;//取出num_p_p的内存地址给 num_p_p_p (三级指针)printf("获取最终的值:%d\n", **num_p_p);//输出20printf("获取最终的值:%d\n", *** num_ppp);//输出20是几级指针,取值时,前面就加几个*

8,数组与数组指针

 定义数组int [] arr = {1,2,3,4}; 错误的写法int arr[]  = {1,2,3,4}; 正确写法
遍历数组
int i = 0;
for (i = 0; i < 4; ++i) {printf("%d\n", arr[i]); // 取值
}

数组的内存地址 等于第一个元素的内存地址,不是其他元素的地址

上面数组的内存地址可以写为:arr    &arr   &arr[0]

既然数组就是一个内存地址,那么

int * arr_p = arr;

数组可以用地址变量赋值

操作数组,就是对数组的指针进行操作。

int arr[]  = {1,2,3,4};将数组地址赋值给指针变量arr_p  此时指针默认指向第一个元素
int * arr_p = arr; printf("%d\n", *arr_p); //输出1 因为此时指针指向第一个元素的内存地址arr_p ++; // 指针挪动   此时指向元素二的内存地址了printf("%d\n", *arr_p); // 输出2 因为此时指针指向第二个元素的内存地址arr_p += 2;printf("%d\n", *arr_p); // 输出4 因为此时指针指向第四个元素的内存地址

数组是连续的内存空间,数组每次挪动4个字节

通过循环给数组赋值:

定义数组
int arr[4];赋值给指针变量arrP
int * arrP = arr;循环赋值操i作
int i = 0;
for (i = 0; i < 4; ++i) {// 1.拿到 元素一 元素二 元素三 元素四 的内存地址   (arrP + i)// 2.取出 元素一 元素二 元素三 元素四 的内存地址 所对应的值 * (arrP + i)* (arrP +i) = (i + 10001);
}

9,函数指针

void(*methid)(int,int) 函数指针 

void 返回值

(*methid) 函数名

(int,int)参数  可以随便写 这里只是举个例子

下面来看具体用法:

void add(int num1, int num2); // 先声明void opreate(void(*method)(int,int), int num1, int num2) {method(num1, num2);
}int main() { opreate(add,  10, 10);printf("main函数的 add指针是多少:%p\n", add);// &add和add是一样的值吗printf("%p, %p\n", add, &add); //  一样的return 0;
}// 再实现 使用
void add(int num1, int num2) {printf("num1 + num2 = %d\n", (num1 + num2));
}

10,C语言中的布尔类型

C语言和Java的不同就是,C语言没有true和false  只有0和非0

只要记住一句话即可,非0即true  0就是false

11,静态开辟

在函数局部内,创建的数据,在执行函数的时候会进栈操作,函数执行完毕,会执行弹栈。因此会释放栈内的成员,栈内的数据也称之为栈内成员,这种方式开辟的内存,称为静态开辟,执行完会弹栈。不会占用内存空间。

静态开辟,即在栈区开辟内存 
int a;
int arr[6];
char 'c';
等等操作都属于静态开辟内存
进栈
void staticAction() {int arr[5]; // 静态开辟 栈区 (栈成员)
} 
函数的末尾会弹栈(隐士):执行完毕会弹栈  会释放所有的栈成员
栈区:占用内存大小 最大值: 大概 2M  大于2M会栈溢出  平台有关系的
堆区:占用内存大小 最大值: 大概80%  40M没有任何问题,基本上不用担心 堆区很大的
大概80%: Windows系统 给我们的编译器给予的空间  的 百分之百八十

12,动态开辟

使用malloc函数,可以动态开辟内存,这种方式的空间属于在堆中开辟,函数执行完毕之后,不会释放堆空间,因此我们一定要手动释放free,并把指针指向NULL。避免悬空指针。

悬空指针:指针指向一块内存,如果这块内存稍后被操作系统回收(被释放),但是指针仍然指向这块内存,那么,此时该指针就是“悬空指针”

void *p = malloc(size);
assert(p);
free(p); 
// 现在 p 是“悬空指针”

正确的写法

void *p = malloc(size);
assert(p);
free(p); 
// 避免“悬空指针”
p = NULL;

野指针:是没有被初始化过的指针,所以不确定指针具体指向

void *p;  // 此时 p 是“野指针”

因为“野指针”可能指向任意内存段,因此它可能会损坏正常的数据,也有可能引发其他未知错误。在实际的C语言程序开发中,定义指针时,一般都要尽量避免“野指针”的出现,可通过赋初值方式解决:

void *p = NULL;
void *data = malloc(size);

下面再来讲讲动态开辟:

 int * arr = malloc(1 * 1024 * 1024); // 堆区开辟 4Mfree(arr); // 释放掉arr = NULL; // 重新指向一块内存地址00000
realloc:前面已经开辟的空间,使用realloc可以扩展空间大小,举例如下:
动态开辟一个大小为5的数组
int * arr = (int *) malloc(5);
for (int i = 0; i < 5; ++i) {arr[i] = (i + 10001); 
}//使用realloc 将arr扩展为大小为11的数组
int * new_arr = (int *) realloc(arr, 5+6);int j = 5; // 5开始
for (; j < (5+ 6); j++) { arr[j] = (j + 10001);
}别忘了释放
free(new_arr);
new_arr = NULL;

13,结构体

在C语言中,结构体相当于 java中的类

结构体的定义形式为


struct 结构体名
{成员列表(可以是基本的数据类型,指针,数组或其他结构类型)
};

例如:

struct Dog {// 成员char name[10];int age;char sex;};
必须要在最后写;
struct Dog dog;
这样写完,成员是没有任何初始化的,成员默认值 是系统值,乱码赋值操作strcpy(dog.name, "旺财");
dog.age = 3;
dog.sex = 'G';

第二种写法:

struct Person {// 成员char * name; // 字符指针 = "赋值"int age;char sex;
} ppp = {"zhangsan", 33, 'W'};

结构体指针

struct Cat {char name[10];int age;
};int main() { // 栈// 结构体struct Cat cat = {"小花猫", 2};// 结构体 指针    -> 调用一级指针成员struct Cat * catp = &cat;catp->age = 3;strcpy(catp->name, "小花猫2");printf("name:%s, age:%d \n", catp->name, catp->age);return 0;
}

结构体指针与动态内存开辟

struct Cat {char name[10];int age;
};int main() { // 堆// VS的写法:Cat * cat = (Cat *) malloc(sizeof(Cat));struct Cat *cat = malloc(sizeof(struct Cat));strcpy(cat->name, "金色猫");cat->age = 5;printf("name:%s, age:%d \n", cat->name, cat->age);// 堆区的必须释放free(cat);cat = NULL;return 0;
}

14,结构体取别名

struct Student_{char name[10];int age;char sex;
};typedef struct Student_Student_; // 给结构体取别名typedef Student_* Student; // 给结构体指针取别名

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/32339.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Rust 编程小技巧摘选(8)

目录 Rust 编程小技巧(8) 1. 取整函数 floor() 2. 取整函数ceil() 3. 取整函数 round() 4. 保留小数位数 5. 字符串转整数 unwrap() unwrap_or() Rust 编程小技巧(8) 1. 取整函数 floor() floor函数对浮点数进行向下取整 示例代码&#xff1a; fn main() {let x: …

[C++项目] Boost文档 站内搜索引擎(5): cpphttplib实现网络服务、html页面实现、服务器部署...

在前四篇文章中, 我们实现了从文档文件的清理 到 搜索的所有内容: 项目背景: &#x1fae6;[C项目] Boost文档 站内搜索引擎(1): 项目背景介绍、相关技术栈、相关概念介绍…文档解析、处理模块parser的实现: &#x1fae6;[C项目] Boost文档 站内搜索引擎(2): 文档文本解析模块…

PAT 1067 Sort with Swap(0, i)

Given any permutation of the numbers {0, 1, 2,…, N−1}, it is easy to sort them in increasing order. But what if Swap(0, *) is the ONLY operation that is allowed to use? For example, to sort {4, 0, 2, 1, 3} we may apply the swap operations in the followi…

0基础学习VR全景平台篇 第80篇:Insta360 影石如何直播推流

一、下载Insta360 Pro APP 1、手机进入Insta360官网Insta360 | Action Cameras | 360 Cameras | VR Cameras&#xff0c;页面往下滑动到Insta360 Pro2相机处&#xff0c;点击相机图片进入详情页。详情页继续下滑到到手机APP处&#xff0c;根据自己的手机系统选择对应的客户端进…

计算机网络(6) --- https协议

计算机网络&#xff08;5&#xff09; --- http协议_哈里沃克的博客-CSDN博客http协议https://blog.csdn.net/m0_63488627/article/details/132089130?spm1001.2014.3001.5501 目录 1.HTTPS的出现 1.HTTPS协议介绍 2.补充概念 1.加密 1.解释 2.原因 3.加密方式 对称加…

【Linux】网络基础1

文章目录 网络基础11. 计算机网络背景1.1 网络发展 2. 认识协议2.1 网络协议2.2 OSI七层模型2.3 TCP/IP五层&#xff08;或四层&#xff09;模型 3. 网络传输基本流程3. 1 数据报封装和分用 4. 网络中的地址管理4.1 认识IP地址 5. 认识MAC地址 网络基础1 1. 计算机网络背景 1…

Flink-串讲面试题

1. 概念 有状态的流式计算框架 可以处理源源不断的实时数据&#xff0c;数据以event为单位&#xff0c;就是一条数据。 2. 开发流程 先获取执行环境env&#xff0c;然后添加source数据源&#xff0c;转换成datastream&#xff0c;然后使用各种算子进行计算&#xff0c;使用s…

数据结构 | 树的定义及实现

目录 一、树的术语及定义 二、树的实现 2.1 列表之列表 2.2 节点与引用 一、树的术语及定义 节点&#xff1a; 节点是树的基础部分。它可以有自己的名字&#xff0c;我们称作“键”。节点也可以带有附加信息&#xff0c;我们称作“有效载荷”。有效载荷信息对于很多树算法…

【学习FreeRTOS】第5章——FreeRTOS任务挂起与恢复

1.任务的挂起与恢复的API函数 vTaskSuspend() ——挂起任务&#xff08;类似暂停&#xff0c;可恢复&#xff0c;但删除任务&#xff0c;无法恢复&#xff09;vTaskResume() ——恢复被挂起的任务xTaskResumeFromISR()—— 在中断中恢复被挂起的任务 1.1.任务挂起函数vTaskSu…

leetcode19. 删除链表的倒数第 N 个结点

题目&#xff1a;leetcode19. 删除链表的倒数第 N 个结点 描述&#xff1a; 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 思路&#xff1a; 让前面的节点比后面的节点先走n1步&#xff0c;因为从链表的尾节点的下一个节点开始&…

【BASH】回顾与知识点梳理(二十二)

【BASH】回顾与知识点梳理 二十二 二十二. Linux 账号管理22.1 Linux 的账号与群组使用者标识符&#xff1a; UID 与 GID使用者账号/etc/passwd 文件结构/etc/shadow 文件结构 关于群组&#xff1a; 有效与初始群组、groups, newgrp/etc/group 文件结构有效群组(effective grou…

传值与传址问题

传值与传址实例 2023年上半年软考真题&#xff1a; 22、设函数foo和hoo的定义如下图所示&#xff0c;在函数foo中调用函数hoo&#xff0c;hoo的第一个参数采用传引用方式(call by reference)&#xff0c;第二个参数传值方式(call by value)&#xff0c;那么函数foo中的print(a…

重温git和GitHub

1.初始化本地库:让git获取到这个目录的管理权 git init 查看文件夹的文件命令&#xff1a;ll 查看文件夹的隐藏的文件命令:ll -a 查看状态的命令&#xff1a;git status cat文件名&#xff1a;查看文件内容 工作区&#xff1a;当git status时&#xff0c;名字为红色则在工作区&…

go错误集(持续更新)

1.提示以下报错 Build Error: go build -o c:\Users\Administrator\Desktop__debug_bin2343731882.exe -gcflags all-N -l . go: go.mod file not found in current directory or any parent directory; see ‘go help modules’ (exit status 1) 解决办法&#xff1a; go …

Elasticsearch 与 OpenSearch:揭开性能差距

作者&#xff1a;George Kobar, Ugo Sangiorgi 对于任何依赖快速、准确搜索数据的组织来说&#xff0c;强大、快速且高效的搜索引擎是至关重要的元素。 对于开发人员和架构师来说&#xff0c;选择正确的搜索平台可以极大地影响你的组织提供快速且相关结果的能力。 在我们全面的…

opencv实战项目 实现手势跟踪并返回位置信息(封装调用)

OpenCV 是一个基于 Apache2.0 许可&#xff08;开源&#xff09;发行的跨平台计算机视觉和机器学习软件库&#xff0c;可以运行在Linux、Windows、Android和Mac OS操作系统上。 需要提前准备opencv 和 mediapipe库 pip --default-timeout5000 install -i https://pypi.tuna.tsi…

在react中,使用ref获子取组件实例

在 React 中&#xff0c;你可以使用 ref 来获取子组件的实例。以下是一些使用 ref 获取子组件实例的常见方法&#xff1a; 使用createRef 函数 import React, { createRef } from react;export default class ParentComponent extends React.Component {childRef createRef()c…

拂袖一挥,zipfile秒列zip包内容

使用wxpython列出文件夹中的zip文件及内容 最近在做一个文件管理的小工具,需要列出选择的文件夹下的所有zip压缩文件,并在点击某个zip文件时能够显示其中的内容。为此我使用了wxpython来实现这个功能。 1. 导入需要的模块 首先导入程序需要的模块: import wx import os imp…

HTML - Javascript - 原生的JS HTTP请求:实用主义的一篇文章

HTML - Javascript - 原生的JS HTTP请求&#xff1a;实用主义的一篇文章 前言 虽然现在使用JQuery等可以做到很方便的HTTP请求&#xff0c;但是这样做毕竟要引入一些JS文件。 如果想使用原生的JS进行HTTP网络请求应该怎样呢&#xff1f;可以使用XMLHttpRequest。 使用方法 …

设计模式之工厂模式

简单工厂 由一个工厂生产多个产品。 一般工厂 每个产品都有一个单独的工厂专门生产。 抽象工厂 不同工厂生产不同种类的产品&#xff0c;每个工厂生产的同类产品又可以再次分类。比如一个鼠标工厂和一个键盘工厂&#xff0c;他们可以为不同的品牌生产鼠标和键盘。