电商论坛网站模板,wordpress建站速度提升,深圳企业500强,网站开发证书是什么指针与数组 指针与数组指针数组数组指针 多维数组数组名的保存 结构体定义结构体定义结构体变量使用typedef简化结构体声明访问结构体成员结构体内存分配字节对齐位域定义位域位域的限制示例 指针与数组 指针数组和数组指针是两个不同的概念#xff0c;它们涉及到指针和数组的… 指针与数组 指针与数组指针数组数组指针 多维数组数组名的保存 结构体定义结构体定义结构体变量使用typedef简化结构体声明访问结构体成员结构体内存分配字节对齐位域定义位域位域的限制示例 指针与数组 指针数组和数组指针是两个不同的概念它们涉及到指针和数组的组合使用。 指针数组
定义 指针数组是一个数组其中的每个元素都是一个指针。示例 int *ptrArray[5]; 声明了一个包含5个元素的指针数组每个元素都是一个指向整数的指针。用途 指针数组常用于存储一组指针每个指针可以指向不同类型的数据或不同位置的数组。
#include stdio.h
int main()
{char a[5] {a, b, c, d, e};char *p[5];printf(sizeof(a) %d\n, sizeof(a));printf(sizeof(p) %d\n, sizeof(p));return 0;
}输出
cd e:\CProject\output
PS E:\CProject\output .\指针数组.exe
sizeof(a) 5
sizeof(p) 40可以看到指针数组的大小是个数*对应类型的指针的大小
举例2
#include stdio.h
int main() {int a 1, b 2, c 3;int *ptrArray[3] {a, b, c};// 打印指针数组中每个元素指向的值for (int i 0; i 3; i) {printf(%d , *ptrArray[i]);}return 0;
}输出
PS E:\CProject\output cd e:\CProject\output
PS E:\CProject\output .\指针数组.exe
1 2 3 在这个例子中ptrArray 是一个包含3个指针的数组每个指针分别指向整数变量 a、b 和 c。
数组指针
定义 数组指针是一个指针它指向一个数组。示例 int (*ptr)[5]; 声明了一个指针指向包含5个元素的整数数组。用途 数组指针常用于处理二维数组或作为指向动态分配数组的指针。
#include stdio.h
int main() {int arr[3][5] {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}};int (*ptr)[5] arr;// 打印数组指针指向的数组中的元素for (int i 0; i 3; i) {for (int j 0; j 5; j) {printf(%d , ptr[i][j]);}printf(\n);}return 0;
}在这个例子中ptr 是一个指针指向包含5个元素的整数数组它被初始化为指向二维数组 arr 的第一行。
总体而言指针数组和数组指针提供了在数组和指针之间灵活切换的方式依赖于实际需求选择使用哪一种形式。 多维数组
数组名的保存
定义一个指针指向int a[10];的首地址定义一个指针指向int b[5][6];的首地址
#include stdio.h
int main()
{int a[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int b[3][4];int *p1 a;int **p2 b; // 这样是错误的二维数组和二维指针没有关系return 0;
}这样是错误的二维数组和二维指针没有关系 二维数组是一行一行读取的一次就读取4列的数据
二维指针是存储线性的地址
正确的读取方式
#include stdio.h
int main()
{int a[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int b[3][4] {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};int *p1 a;int(*p2)[4] b; // 每次读4个printf(%d\n\n, *p1);printf(%d\n, *p2[0]);printf(%d\n, *p2[1]);printf(%d\n, *p2[2]);return 0;
}举例2
int c[2][3][4];
int (*p)[3][4]; //T结构体
C语言中的结构体struct是一种用户自定义的数据类型它允许你将不同类型的数据组合在一起。这使得你可以创建更复杂的数据结构来表示现实世界中的实体。一个结构体可以包含多个成员member每个成员都有自己的数据类型和名称。
下面是一些关于C语言结构体的基本概念和用法
定义结构体
要定义一个结构体你需要使用struct关键字后跟结构体的标签可选接着是花括号包围的一系列成员声明最后以分号结束。
struct Point {int x;int y;
};定义结构体变量
一旦定义了结构体就可以声明该结构体类型的变量。有两种方式来做这件事
在定义结构体的同时声明变量
struct Point pt1, pt2;先定义结构体然后在其他地方声明变量
struct Point;// ... 之后某个地方struct Point pt1, pt2;如果你给结构体指定了标签如上面例子中的Point那么可以在后续代码中仅使用struct Point来声明新的变量。
使用typedef简化结构体声明
为了简化结构体变量的声明通常会与typedef一起使用
typedef struct {int x;int y;
} Point;这样以后可以直接使用Point作为类型名来声明结构体变量而不需要再写struct Point。
访问结构体成员
结构体成员通过点运算符.来访问
pt1.x 10;
pt1.y 20;如果结构体是指针则使用箭头运算符-来访问成员
Point *p pt1;
p-x 30; // 等价于 (*p).x 30;结构体内存分配
结构体变量的内存是在声明时分配的。如果你需要动态分配结构体的内存可以使用malloc()或calloc()函数。
Point *p (Point *)malloc(sizeof(Point));
if (p ! NULL) {p-x 40;p-y 50;
}
// 使用完后记得释放内存
free(p);字节对齐
#include stdio.hstruct student
{char x; // 4 字节对齐int roll; // 4float marks; // 4
};
int main()
{struct student s1;printf(struct size: %d\n, sizeof(s1));return 0;
}字节对齐为了效率希望牺牲一点空间换取时间的效率 分别看一下定义的顺序不同占用的空间大小
#include stdio.hstruct student
{char x; // 2short y; // 2int roll; // 4
};struct stu
{char x; // 4int roll; // 4short y; // 4
};
int main()
{struct student s1;printf(struct size: %d\n, sizeof(s1));struct stu s2;printf(struct size: %d\n, sizeof(s2));return 0;
}由于定义的顺序不同占用的空间大小也不同 第一种定义方式里char剩余3bytes可以给short类型的变量使用如下图所示 第二种定义的顺序在内存中的分布如下 位域
位域bit-fields是C语言中的一种特殊结构体成员它允许你定义一个特定宽度的字段以位为单位。位域主要用于需要紧凑存储或与硬件通信的场合比如嵌入式系统编程。
在位域中你可以指定每个成员占用的位数这可以减少内存的使用量。然而使用位域也可能会导致代码的可移植性问题因为不同的编译器可能对位域的实现有所不同包括它们如何打包和对齐数据。
定义位域
位域通过在结构体成员声明后添加冒号和位宽来定义。以下是位域的一个简单例子
struct packed_struct {unsigned int f1 : 1; // 1 bitunsigned int f2 : 3; // 3 bitsunsigned int f3 : 4; // 4 bits
};在这个例子中packed_struct包含三个位域成员f1、f2 和 f3分别占据1位、3位和4位。请注意位域成员必须是整数类型如int、unsigned int等并且不能是数组或指针。
位域的限制
位域的大小位域的最大宽度取决于底层整型的大小。例如在大多数系统上unsigned int通常是32位所以你不能创建超过32位的位域。匿名位域有时会看到不带名称但带有宽度的位域这样的位域用于填充或者对齐。例如unsigned int : 2;将占用2位但没有关联的变量名。不可寻址性由于位域是由多个位组成的因此不能取位域成员的地址。端序依赖不同体系结构上的字节顺序大端或小端会影响位域的实际布局。
示例
这里有一个更完整的示例展示了如何使用位域
#include stdio.hstruct Flags {unsigned int flag1 : 1;unsigned int flag2 : 1;unsigned int : 6; // 匿名位域用于填充或对齐unsigned int flag3 : 1;
};int main() {struct Flags flags;flags.flag1 1;flags.flag2 0;flags.flag3 1;printf(flag1: %d\n, flags.flag1);printf(flag2: %d\n, flags.flag2);printf(flag3: %d\n, flags.flag3);return 0;
}这个程序定义了一个Flags结构体其中包含了三个标志位每个都只占用了1位。注意我们还插入了一个6位的匿名位域用于确保后续的位域从一个新的字节开始假设编译器按照8位边界对齐。
请记住尽管位域提供了一种节省空间的方法但在编写代码时应该考虑到它的可移植性和潜在的复杂性。如果你不需要精确控制位级别的数据通常最好使用普通的结构体成员。 【嵌入式C语言】 https://www.bilibili.com/video/BV1RW411G7cr/?p44share_sourcecopy_webvd_source8af85e60c2df9af1f0fd23935753a933