【C语言】

C语言

  • 1. C语言基础
    • 1.1 数据类型和占位符
    • 1.2 异或
    • 1.3 关键字
    • 1.4 const
    • 1.5 extern
    • 1.6 typedef
    • 1.7 static
    • 1.8 左值和右值
    • 1.9 位进行操作赋值
  • 2. C指针
  • 3. 二维数组和指针
  • 4. 函数传递二维数组
    • 4.1 形参给出第二维的长度。
    • 4.2 形参声明为指向数组的指针。
    • 4.3 形参声明为指针的指针。
  • 5. 二级指针传参数
    • 5.1 二级指针传参数,没有改变原始值
    • 5.2 二级指针传参数,改变原始值
  • 6 数组指针(也称行指针)
  • 7 指针数组
  • 8 指针变量
  • 9 函数指针&指针函数
    • 9.1 指针函数
    • 9.2 函数指针
  • 10 三维数组的传递
  • 11 计算公式最大值最小值和中间值

1. C语言基础

1.1 数据类型和占位符

在这里插入图片描述
在这里插入图片描述

1.2 异或

原则:110000101.
作用:交换两个整数的值而不必用第三个参数
a = 9;
b = 11;
a=a^b;  1001^1011=0010
b=b^a;  1011^0010=1001
a=a^b;  0010^1001=1011

1.3 关键字

设置表格对齐方式:

关键字描述
__asm用于内嵌汇编代码和直接访问底层硬件
__inline用于内联函数,以减少函数调用的开销
attribute用于定义变量或函数的属性,例如对齐方式、可见性、优化等级等
__packed用于取消结构体成员的对齐,以节省内存空间
__irq, __fiq用于定义中断服务函数的类型,以区分普通函数和中断函数
register用于将变量声明为寄存器变量,以提高访问速度
volatile告诉编译器该变量可能会被意外修改,从而避免编译器对该变量进行优化
__weak, __strong用于声明弱引用和强引用变量,在链接时进行符号重定向
__packed, attribute((aligned(n)))用于控制结构体和变量的对齐方式
ARM_ARCH_XX用于条件编译,根据处理器的不同选择不同的代码路径

1.4 const

请看下面三种定义:
const char p; const 修饰的是p 所以是p值不能更改。
char const p; const 修饰的是p 所以是
p值不能更改。
char * const p; const 修饰的是p 所以是p指针不能更改。

1.5 extern

在这里插入图片描述

1.6 typedef

作用是为一种数据类型定义一个新的名字。对于以上两种结构体定义形式,
typedef都可以为其创建别名。

1. 先定义结构体类型,再定义结构体变量
struct student{
    char no[20];      //学号
    char name[20];    //姓名
    char sex[5];      //性别
    int age;          //年龄
};             
struct student stu1,stu2;
//此时stu1,stu2为student结构体变量

2. 定义结构体类型的同时定义结构体变量。
struct student{
    char no[20];        //学号
    char name[20];      //姓名
    char sex[5];        //性别
    int age;            //年龄
} stu1,stu2;      
此时还可以继续定义student结构体变量如:
struct student stu3;

1. 先定义结构体类型,再定义结构体变量
struct{
    char no[20];      //学号
    char name[20];    //姓名
    char sex[5];      //性别
    int age;          //年龄
} stu1,stu2;

1.7 static

在这里插入图片描述

1.8 左值和右值

在这里插入图片描述

1.9 位进行操作赋值

可以对 u16Bit;数据类型中的每个位进行操作赋值,u16Bit.b1 = 1;。

typedef struct{                        
    union{
    struct {
      uint8_t b0:1;            
          uint8_t b1:1;            
          uint8_t b2:1;            
          uint8_t b3:1;            
          uint8_t b4:1;            
          uint8_t b5:1;            
          uint8_t b6:1;                
          uint8_t b7:1;
          uint8_t b8:1;            
          uint8_t b9:1;            
          uint8_t b10:1;            
          uint8_t b11:1;            
          uint8_t b12:1;            
          uint8_t b13:1;            
          uint8_t b14:1;                
          uint8_t b15:1;    
      };
      uint16_t byte;
   };
}u16Bit;

/*********************************定义uint32_t*******************************/
typedef struct {
    uint32_t b0:1;
}u200Bit;

u200Bit u200bit_t;
u200bit_t.b0=1;//赋值
qDebug() << "sizeof(u200Bit)=" << sizeof(u200Bit) << u200bit_t.b0 << endl; //sizeof(u200Bit)= 4 1 

 /*********************************定义uint16_t*******************************/
typedef struct {
    uint16_t b0:1;
}u200Bit;

u200Bit u200bit_t;
u200bit_t.b0=1;//赋值
qDebug() << "sizeof(u200Bit)=" << sizeof(u200Bit) << u200bit_t.b0 << endl; //sizeof(u200Bit)= 2 1 

 /*********************************定义uint8_t*******************************/
typedef struct {
    uint8_t b0:1;
}u200Bit;

u200Bit u200bit_t;
u200bit_t.b0=1; //赋值
qDebug() << "sizeof(u200Bit)=" << sizeof(u200Bit) << u200bit_t.b0 << endl;//sizeof(u200Bit)= 1 1 

2. C指针

main()
{
   int a[5]={1,2,3,4,5};
   int *ptr=(int *)(&a+1);
   printf("%d,%d",*(a+1),*(ptr-1));
}
  • &a + 1: 取数组a 的首地址,该地址的值加上sizeof(a) 的值,即&a + 5*sizeof(int),也就是下一个数组的首地址,显然当前指针已经越过了数组的界限。
    (int *)(&a+1): 则是把上一步计算出来的地址,强制转换为int * 类型,赋值给ptr。

  • *(a+1): a,&a 的值是一样的,但意思不一样,a 是数组首元素的首地址,也就是a[0]的首地址,&a 是数组的首地址,a+1 是数组下一元素的首地址,即a[1]的首地址,&a+1 是下一个数组的首地址。所以输出 (ptr-1): 因为ptr 是指向a[5],并且ptr 是int * 类型,所以(ptr-1) 是指向a[4] ,输出5。

在这里插入图片描述

3. 二维数组和指针

在这里插入图片描述

4. 函数传递二维数组

4.1 形参给出第二维的长度。

在这里插入图片描述
在这里插入图片描述

4.2 形参声明为指向数组的指针。

#include <stdio.h>
void func(int n, char*str)[5] )
{
 int i;
 for(i = 0; i < n; i++)
 printf("\nstr[%d] = %s\n", i, str[i]);
}
void main()
{
 char* p[3];
 char str[][5] = {"abc","def","ghi"};
 func(3, str);
}

4.3 形参声明为指针的指针。

#include <stdio.h>
void func(int n, char **str)
{
	int i;
	for(i = 0; i < n; i++)
	printf("\nstr[%d] = %s\n", i, str[i]);
}
void main()
{
	char* p[3];
	char str[][5] = {"abc","def","ghi"};
	p[0] = &str[0][0];
	p[1] = str[1];
	p[2] = str[2];
	func(3, p);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

char* arg[] = {
        "abc",
        "cde",
        "efg",
    };
//这种写法和上面的等价
char* b[3];
b[0] = arg[0];
b[1] = arg[1];
b[2] = arg[2];

int array[][3] = {
        {1, 2, 3},
        {2, 3, 4},
        {3, 4, 5},
    };

int* a[3];

a[0] = array[0];
a[1] = array[1];
a[2] = array[2];

在这里插入图片描述

5. 二级指针传参数

5.1 二级指针传参数,没有改变原始值

在这里插入图片描述

uis@ubuntu:~/text$ gcc zhizheng.c 
uis@ubuntu:~/text$ 
uis@ubuntu:~/text$ ./a.out 
&a=0x7ffe43789e08,&p=0x7ffe43789e0c
pp=0x7ffe43789e08,kk=0x7ffe43789e0c---&pp=0x7ffe43789e10,&kk=0x7ffe43789e18 
x=0x7ffe43789e10,y=0x7ffe43789e18---&x=0x7ffe43789dd8,&y=0x7ffe43789dd0,--- *x=0x7ffe43789e08,*y=0x7ffe43789e0c  
x=0x7ffe43789e10,y=0x7ffe43789e18---&x=0x7ffe43789dd8,&y=0x7ffe43789dd0,--- *x=0x7ffe43789e08,*y=0x7ffe43789e0c  
x=0x7ffe43789e10,y=0x7ffe43789e18---&x=0x7ffe43789dd8,&y=0x7ffe43789dd0,--- *x=0x7ffe43789e0c,*y=0x7ffe43789e0c  
x=0x7ffe43789e10,y=0x7ffe43789e18---&x=0x7ffe43789dd8,&y=0x7ffe43789dd0,--- *x=0x7ffe43789e0c,*y=0x7ffe43789e08  
a = 20 b = 10, a=10,b=20

5.2 二级指针传参数,改变原始值

在这里插入图片描述

uis@ubuntu:~/text$ gcc zhizheng2.c 
uis@ubuntu:~/text$ 
uis@ubuntu:~/text$ ./a.out 
&a=0x7ffc22703778,&p=0x7ffc2270377c
pp=0x7ffc22703778,kk=0x7ffc2270377c---&pp=0x7ffc22703780,&kk=0x7ffc22703788 
x=0x7ffc22703780,y=0x7ffc22703788---&x=0x7ffc22703748,&y=0x7ffc22703740,--- *x=0x7ffc22703778,*y=0x7ffc2270377c  
x=0x7ffc22703780,y=0x7ffc22703788---&x=0x7ffc22703748,&y=0x7ffc22703740,--- *x=0x7ffc22703778,*y=0x7ffc2270377c  
x=0x7ffc22703780,y=0x7ffc22703788---&x=0x7ffc22703748,&y=0x7ffc22703740,--- *x=0x7ffc22703778,*y=0x7ffc2270377c  
x=0x7ffc22703780,y=0x7ffc22703788---&x=0x7ffc22703748,&y=0x7ffc22703740,--- *x=0x7ffc22703778,*y=0x7ffc2270377c  
a = 20 b = 10, a=20,b=10

6 数组指针(也称行指针)

定义 int (*p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
 p=a;        //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
 p++;       //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]

所以数组指针也称指向一维数组的指针,亦称行指针。

7 指针数组

定义 int *p[n]; 
//这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,则p指向下一个数组元素,这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针
for(i=0;i<3;i++)
p[i]=a[i]
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。

8 指针变量

int *p;
*p = NULL;
同样,我们可以在编译器上调试这两行代码。第一行代码,定义了一个指针变量 p,其指向
的内存里面保存的是 int 类型的数据;但是这时候变量 p 本身的值是多少不得而知,也就是
说现在变量 p 保存的有可能是一个非法的地址。第二行代码,给*p 赋值为 NULL,即给 p
指向的内存赋值为 NULL;但是由于 p 指向的内存可能是非法的,所以调试的时候编译器可
能会报告一个内存访问错误。这样的话,我们可以把上面的代码改写改写,使 p 指向一块合
法的内存:
int i = 10;
int *p = &i;
*p = NULL;
在编译器上调试一下,我们发现 p 指向的内存由原来的 10 变为 0 了;而 p 本身的值, 即内
存地址并没有改变

9 函数指针&指针函数

在这里插入图片描述

9.1 指针函数

在这里插入图片描述
在这里插入图片描述

9.2 函数指针

在这里插入图片描述

10 三维数组的传递

11 计算公式最大值最小值和中间值

最大值
#define MAX(a, b)     (((a) > (b) ) ? (a) : (b))
最小值
#define MIN(a, b)     (((a) < (b) ) ? (a) : (b))
中间值
#define MID(a,b,c)     a>b?(a>c?(b>c?b:c):(a)):(a>c?(a):(b>c?c:b))

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何使用免费的 Vecteezy 旅行视频

网址&#xff1a;https://www.vecteezy.com/ Vecteezy 是一个提供免费和付费矢量图形、模板、视频和其他创意资源的网站。该网站拥有大量旅行视频&#xff0c;可用于各种目的&#xff0c;例如个人使用、商业用途或教育用途。 要下载 Vecteezy 的免费旅行视频&#xff0c;请按…

阿里云服务器u1和经济型e实例有什么区别?

阿里云服务器ECS经济型e实例和通用算力型u1实例有什么区别&#xff1f;如何选择&#xff1f;ECS经济型e实例是共享型云服务器&#xff0c;通用算力型u实例是企业级独享型云服务器&#xff0c;e实例性价比高&#xff0c;现在2核2G3M带宽一年99元&#xff0c;云服务器u1价格相对要…

什么是权限?(Linux篇)

前言 其实我们在学会运用一些简单的Linux指令之后&#xff0c;我们可以简单的用ls查看当前目录的文件有哪些啊&#xff0c;可以使用tree用树形结构查看目录&#xff0c;可以使用touch来创建文件&#xff0c;用mkdir创建目录&#xff0c;可以使用rm来删除目录和文件&#xff0c;…

C#,数值计算——多项式计算,Poly的计算方法与源程序

1 文本格式 using System; using System.Text; namespace Legalsoft.Truffer { /// <summary> /// operations on polynomials /// </summary> public class Poly { /// <summary> /// polynomial c[0]c[1]xc[2]x^2 ..…

高频SQL50题(基础题)-5

文章目录 主要内容一.SQL练习题1.602-好友申请&#xff1a;谁有最多的好友代码如下&#xff08;示例&#xff09;: 2.585-2016年的投资代码如下&#xff08;示例&#xff09;: 3.185-部门工资前三高的所有员工代码如下&#xff08;示例&#xff09;: 4.1667-修复表中的名字代码…

数据库恢复技术

事务 含义&#xff1a;用户定义的一个数据库操作序列&#xff0c;这些操作要么全做&#xff0c;要么全不做&#xff0c;是一个不可分割的工作单位 地位&#xff1a;恢复和控制并发的基本单位 区分事务和程序&#xff0c;一个程序中包含多个事务 定义事务 事务的开始与结束…

[linux网络实验] 多网卡绑定

聚合链路技术 什么是bonding 提供了一种将多个网络接口设备绑定到一个网络接口的方法。这可用于网络负载平衡和网络冗余&#xff1b; 实现将两个网卡虚拟成一个网卡。这种聚合设备看起来就像一个以太网接口设备。通俗地说&#xff0c;这意味着两个网卡拥有相同的 IP 地址&am…

PostgreSQL 机器学习插件 MADlib 安装与使用

MADlib 一个可以在数据库上运行的开源机器学习库&#xff0c;支持 PostgreSQL 和 Greenplum 等数据库&#xff1b;并提供了丰富的分析模型&#xff0c;包括回归分析&#xff0c;决策树&#xff0c;随机森林&#xff0c;贝叶斯分类&#xff0c;向量机&#xff0c;风险模型&#…

Leetcode刷题详解——黄金矿工

1. 题目链接&#xff1a;1219. 黄金矿工 2. 题目描述&#xff1a; 你要开发一座金矿&#xff0c;地质勘测学家已经探明了这座金矿中的资源分布&#xff0c;并用大小为 m * n 的网格 grid 进行了标注。每个单元格中的整数就表示这一单元格中的黄金数量&#xff1b;如果该单元格…

数据库表的设计——范式

目录 1. 设计数据表需要注意的点 2. 范式 2.1 范式简介 2.2 范式有哪些&#xff1f; 2.3 第一范式(1NF) 2.4 第二范式(2NF) 2.5 第三范式(3NF) 2.6 小结 1. 设计数据表需要注意的点 &#xff08;1&#xff09;首先要考虑设计这张表的用途&#xff0c;这张表都要存放什…

博捷芯BJCORE:国内划片机品牌优势

国内划片机品牌在半导体设备制造领域奋起直追&#xff0c;展现出以下几个优势&#xff1a; 1. 技术提升&#xff1a;国内划片机品牌在技术上持续取得突破&#xff0c;例如设备精准度和切割精度的提高&#xff0c;可以在短时间内完成大量加工&#xff0c;提高了生产效率。 2. 适…

【Python Opencv】Opencv画图形

文章目录 前言一、画图形1.1 画线1.2 画矩形1.3 画圆1.4 画椭圆1.5 添加文本 总结 前言 在计算机视觉和图像处理中&#xff0c;OpenCV不仅可以处理图像和视频&#xff0c;还提供了一组功能强大的工具&#xff0c;用于在图像上绘制各种形状和图形。这些功能使得我们能够在图像上…

centos利用find提权反弹shell

需要说明的是利用find命令进行提权的方式已经不存在了&#xff0c;因为Linux默认不会为find命令授予suid权限&#xff0c;这里只是刻意的制造出了一种存在提权的环境 首先我们先介绍一下find命令&#xff0c;find命令主要用来在Linux中查找文件使用&#xff0c;它可以进行最基础…

JVM如何运行,揭秘Java虚拟机运行时数据区

目录 一、概述 二、程序计数器 三、虚拟机栈 四、本地方法栈 五、本地方法接口 六、堆 &#xff08;一&#xff09;概述 &#xff08;二&#xff09;堆空间细分 七、方法区 一、概述 不同的JVM对于内存的划分方式和管理机制存在部分差异&#xff0c;后续针对HotSpot虚…

Brute Force

Brute Force "Brute Force"&#xff08;暴力破解&#xff09;指的是一种通过尝试所有可能的组合来获取访问、解密或破解信息的攻击方法。这种攻击方法通常是基于暴力和不断尝试的&#xff0c;不依赖漏洞或弱点。通常用于破解密码、破坏系统或获取未经授权的访问权限…

【数据结构】链表经典OJ题,常见几类题型(二)

目录 题型三&#xff1a;链表相交&#xff0c;找相交节点思路解析OJ题实例解题代码 题型四&#xff1a;链表带环&#xff0c;找入环节点思路解析OJ实例解题代码 题型三&#xff1a;链表相交&#xff0c;找相交节点 思路解析 看到这类题型首先要判断链表是否相交&#xff0c;而…

密钥安全存储方案探讨与实践

随着信息技术的迅猛发展和应用范围的不断扩大&#xff0c;我们日常生活中的许多方面已经与信息技术密不可分。而在信息安全领域中&#xff0c;密钥的安全存储显得尤为重要。本文将探讨密钥安全存储的必要性、相关技术和实践方案&#xff0c;并提出一些解决方案。 一、密钥安全存…

Redis 常用的类型和 API

前言 在当今的软件开发中&#xff0c;数据存储与操作是至关重要的一部分。为了满足日益增长的数据需求和对性能的追求&#xff0c;出现了许多不同类型的数据库。其中&#xff0c;Redis 作为一种基于内存且高性能的键值存储数据库&#xff0c;因其快速的读取速度、丰富的数据结…

进行 “最佳价格查询器” 的开发(多种并行方式的性能比较)

前置条件 public class Shop {private final String name;private final Random random;public Shop(String name) {this.name name;random new Random(name.charAt(0) * name.charAt(1) * name.charAt(2));}public double getPrice(String product) {return calculatePrice…

第4关:非递归实现二叉树左右子树交换

任务描述相关知识 栈的基本操作二叉树后序遍历编程要求测试说明 任务描述 本关任务&#xff1a;给定一棵二叉树&#xff0c;使用非递归的方式实现二叉树左右子树交换&#xff0c;并输出后序遍历结果。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.栈的基…