如何做免费网站制作,做直播网站找哪个网站,2023推广平台,人才共享网站的建设方案怎么写目录 什么是指针#xff1f;
与指针相关的运算符
指针类型的意义 指针的大小
初始化
将指针直接指向一个已经存在的变量或内存地址#xff1a;
使用malloc函数动态分配内存#xff0c;并将指针指向新分配的内存#xff1a;
使用calloc函数动态分配内存#xff0c;并…目录 什么是指针
与指针相关的运算符
指针类型的意义 指针的大小
初始化
将指针直接指向一个已经存在的变量或内存地址
使用malloc函数动态分配内存并将指针指向新分配的内存
使用calloc函数动态分配内存并将指针指向新分配的内存同时将内存初始化为0
使用静态初始化
赋值
直接赋值操作符
使用malloc函数分配内存并赋值给指针
使用calloc函数分配内存并赋值给指针
解引用
指针和整数相加
指针和整数相减
递增指针
递减指针
指针求差
指针关系运算
空指针
const与指针
指向常量的指针
常量指针
指向常量的常量指针
二级指针 什么是指针
C语言中的指针是一个变量用于存储另一个变量的内存地址。
通过指针可以间接访问和修改变量的值。
我们口语中的指针是指的是指针变量指针变量的值是个地址
指针变量的声明需要指定所指向的变量类型例如int、char等。
指针变量的声明格式为
指针变量所指向的变量类型 *指针变量名;*和指针名之间的空格可有可无
与指针相关的运算符
通过取址操作符可以获得变量的内存地址。
例如对于一个整型变量x可以通过x表示其内存地址。
解引用操作符*
*指针名代表该指针指向的地址
比如 int*ab;*a就代表变量b的地址
指针类型的意义
1指针类型决定了指针在被解引用时访问几个字节
比如
int*的指针被解引用时只能访问一个int类型的大小即4个字节
char*的指针被解引用时只能访问一个char类型大小即1个字节
2.指针类型决定了指针加减操作时跳过几个字节
比如
char*a则a1时跳过1个字节
int*a则a1时跳过4个字节
我们可以看个例子
int n[2] { 1,2 };
int* w n;
printf(%d %d, *w, *(w 1));
运行结果
1 2 指针的大小
在C语言中不同类型的指针在内存中占用的大小是相同的即指针的大小不依赖于指向的数据类型。
无论是指向char、int、float或其他类型的指针在32位系统上占用4个字节32位即x86在64位系统上占用8个字节64位即x64。 printf(%zd\n, sizeof(int*));printf(%zd\n, sizeof(char*));printf(%zd\n, sizeof(float*));
在64位上是
8
8
8
这是因为指针的作用是存储另一个变量的内存地址而内存地址的大小是由系统的位数决定的。
指针存储的是一个地址值不论指针指向的数据类型的大小如何指针本身的大小都是固定的。
指针大小的固定性使得在C语言中可以实现通用的指针操作和类型转换。
需要注意的是指针变量本身的大小是固定的但指针所指向的内存区域的大小取决于指针指向的数据类型。对于一个指向int类型的指针它所指向的内存区域大小是sizeof(int)。指针的大小只是存储指针所需的内存空间而不是指针所指向的数据的大小。 初始化
在C语言中指针可以通过以下方式进行初始化 将指针直接指向一个已经存在的变量或内存地址 int num 10;
int *ptr num; // 将指针ptr指向变量num的地址使用malloc函数动态分配内存并将指针指向新分配的内存 int *ptr (int*)malloc(sizeof(int)); // 分配一个整型变量所需的内存使用calloc函数动态分配内存并将指针指向新分配的内存同时将内存初始化为0 int *ptr (int*)calloc(1, sizeof(int)); // 分配一个整型变量所需的内存并将内存初始化为0使用静态初始化 int *ptr NULL; // 将指针初始化为空指针需要注意的是在使用指针之前应该确保指针已经初始化并且指向了有效的内存地址。
否则就将指针指向NULL
赋值
在C语言中可以使用以下方式将一个指针赋值给另一个指针 直接赋值操作符 int *ptr1;
int *ptr2;
int num 10;ptr1 # // 将ptr1指向num的地址
ptr2 ptr1; // 将ptr2赋值为ptr1即ptr2也指向num的地址使用malloc函数分配内存并赋值给指针 int *ptr1;
int *ptr2;ptr1 (int*)malloc(sizeof(int)); // 分配内存并将其地址赋值给ptr1
*ptr1 10; // 给ptr1指向的内存赋值ptr2 ptr1; // 将ptr2赋值为ptr1两者指向同一块内存使用calloc函数分配内存并赋值给指针 int *ptr1;
int *ptr2;ptr1 (int*)calloc(1, sizeof(int)); // 分配内存并将其地址赋值给ptr1内存初始化为0
*ptr1 10; // 给ptr1指向的内存赋值ptr2 ptr1; // 将ptr2赋值为ptr1两者指向同一块内存需要注意的是在进行指针赋值操作时应确保指针指向的内存是有效的并且在使用指针之前进行了初始化。同时指针赋值只是将指针指向的内存地址进行了复制而不是复制内存中的内容。
解引用
在C语言中指针解引用是指通过指针获取指针所指向的变量的值。
可以使用*运算符来对指针进行解引用操作。
下面是使用指针解引用的示例
int num 10; // 定义一个整型变量 num
int *ptr # // 定义一个指向 num 的指针 ptrprintf(num 的值为%d\n, num); // 直接输出 num 的值
printf(ptr 所指向的变量的值为%d\n, *ptr); // 通过指针解引用输出 num 的值在上面的示例中通过*ptr可以获取指针ptr所指向的变量num的值。在将指针解引用后可以像操作普通变量一样使用解引用后的值。
需要注意的是在对指针进行解引用之前应确保指针指向的内存是有效的。否则解引用无效的指针可能会导致程序崩溃或未定义的行为。
指针和整数相加
在C语言中指针和整数是可以进行相加的。
当一个指针和一个整数相加时指针的地址值会根据整数的值进行偏移。偏移的单位是指针所指向类型的字节大小。
例如如果一个指针指向一个整型变量该整型变量占用4个字节则相加操作会根据整数值乘以4来改变指针的地址值。
下面是一个示例
int arr[] {1, 2, 3, 4, 5}; // 定义一个整型数组
int *ptr arr; // 定义一个指向数组的指针初始指向数组的第一个元素// 将指针向前移动两个元素
ptr ptr 2;printf(ptr 所指向的值为%d\n, *ptr); // 输出 ptr 所指向的值即数组的第三个元素ptr2和arr[2]等价
在上面的示例中ptr指向整型数组arr的第一个元素。通过将ptr与整数2相加可以使指针向前移动两个元素的偏移量即指向数组的第三个元素。通过对指针进行解引用可以获取到新的位置的值。
需要注意的是指针与整数相加时结果的类型仍然是指针类型。根据指针所指向的数据类型的大小相加的整数会根据数据类型的大小进行调整。
指针和整数相减
在C语言中指针减去一个整数的操作被称为指针的算术运算。其规则如下
当一个指针减去一个整数时整数的值将乘以指针指向的数据类型的大小然后将所得结果从指针的值中减去。最终的结果是一个新的指针指向原来指针所指向的位置减去整数的大小。
例如假设有一个指针p指向一个int类型的数据它的地址是0x1000那么p - 2的结果将是一个新的指针指向地址为0x1000 - 2 * sizeof(i的位置。nt)
看个例子 int arr[] { 1, 2, 3, 4, 5 }; // 定义一个整型数组int* ptr arr[2]; // 定义一个指向数组的指针初始指向数组的第一个元素// 将指针向前移动两个元素ptr ptr -2;printf(ptr 所指向的值为%d\n, *ptr);
这里ptr-2相当于arr[0]
运行结果是
ptr 所指向的值为:1
同样需要注意进行指针的算术运算时必须确保指针指向的内存是有效的否则结果是未定义的。此外指针的算术运算还要遵守指针的合法性和边界条件以避免访问非法内存。
递增指针
在C语言中可以使用递增操作符来递增指针。
递增指针会使指针指向下一个元素或下一个位置。
示例代码如下所示
int arr[5] {1, 2, 3, 4, 5};
int *ptr arr; // 指向数组的第一个元素ptr; // 递增指针指向数组的第二个元素printf(%d\n, *ptr); // 输出2在上述示例中开始时指针ptr指向数组的第一个元素。通过递增操作符指针ptr的值增加了一个元素的大小假设int类型占4个字节指针现在指向了数组的第二个元素。
需要注意的是递增操作符不仅可以递增指针还可以递增指向数组、字符串或者任何连续内存块的指针。另外递增操作也可以应用于指针变量本身而不仅仅是指向的内容。
示例代码如下所示
int x 10;
int *ptr x; // 指向整型变量xptr; // 递增指针指向下一个整型变量的地址printf(%d\n, *ptr); // 输出未定义因为ptr指向了未经初始化的内存在上述示例中指针ptr开始时指向整型变量x。通过递增操作符指针ptr的值增加了一个整型变量的大小假设int类型占4个字节指针现在指向了未经初始化的内存。因此对指针解引用会产生未定义的行为。
递减指针
在C语言中可以使用递减操作符--来递减指针。递减指针会使指针指向上一个元素或上一个位置。
示例代码如下所示
int arr[5] {1, 2, 3, 4, 5};
int *ptr arr[4]; // 指向数组的最后一个元素ptr--; // 递减指针指向数组的倒数第二个元素printf(%d\n, *ptr); // 输出4在上述示例中开始时指针ptr指向数组的最后一个元素。通过递减操作符--指针ptr的值减少了一个元素的大小假设int类型占4个字节指针现在指向了数组的倒数第二个元素。
需要注意的是递减操作符--不仅可以递减指针还可以递减指向数组、字符串或者任何连续内存块的指针。另外递减操作也可以应用于指针变量本身而不仅仅是指向的内容。
示例代码如下所示
int x 10;
int *ptr x; // 指向整型变量xptr--; // 递减指针指向上一个整型变量的地址printf(%d\n, *ptr); // 输出未定义因为ptr指向了未经初始化的内存在上述示例中指针ptr开始时指向整型变量x。通过递减操作符--指针ptr的值减少了一个整型变量的大小假设int类型占4个字节指针现在指向了未经初始化的内存。因此对指针解引用会产生未定义的行为。
指针求差
在C语言中可以使用减法操作符-来计算两个指针之间的差值。这个差值表示两个指针之间相隔的元素个数而不是它们之间的字节数。
具体用法如下
int arr[5] {1, 2, 3, 4, 5};
int *ptr1 arr[1]; // 指向数组的第二个元素
int *ptr2 arr[4]; // 指向数组的最后一个元素int diff ptr2 - ptr1; // 计算指针之间的差printf(%d\n, diff); // 输出3在上述示例中ptr1指向数组的第二个元素ptr2指向数组的最后一个元素。通过将ptr2减去ptr1可以得到它们之间的差值即3。这表示从ptr1移动到ptr2需要3个元素的距离。
需要注意的是两个指针只有在指向同一数组或数组的结尾位置中的元素时才能进行指针相减操作。否则结果将是未定义的。
另外指针相减的结果是一个整数类型表示两个指针相差的单位个数并不是指向元素的实际大小。
指针关系运算
在C语言中指针比较的规则如下 相等性比较使用运算符可以比较两个指针是否指向同一个内存地址。如果两个指针指向同一个内存地址比较的结果为真1否则为假0。 不等性比较使用!运算符可以比较两个指针是否指向不同的内存地址。如果两个指针指向不同的内存地址比较的结果为真1否则为假0。 大小比较使用、、和等运算符可以比较两个指针所指向的内存地址的大小关系。这里的比较是基于内存地址的值的大小。 如果两个指针指向数组中的不同元素那么比较的结果取决于它们指向的元素在数组中的相对位置。如果两个指针指向同一个数组中的不同元素那么比较的结果取决于它们指向的元素在数组中的索引位置。如果两个指针都指向不同的数组那么它们之间的比较没有定义。
需要注意的是指针比较操作只有在指针指向的内存地址属于同一个数组或同一个对象时才有意义。否则比较的结果是未定义的。因此在进行指针比较之前应该确保指针引用的对象是有效的。
下面是一些C语言中指针关系运算的例子
判断两个指针是否相等
int* p1 NULL;
int* p2 NULL;
if (p1 p2) {// 两个指针相等
}判断两个指针是否不相等
int* p1 NULL;
int* p2 NULL;
if (p1 ! p2) {// 两个指针不相等
}比较两个指针的大小关系
int arr[5] {1, 2, 3, 4, 5};
int* p1 arr[0];
int* p2 arr[2];
if (p1 p2) {// p1指向的元素在p2指向的元素之前
}
if (p1 p2) {// p1指向的元素在p2指向的元素之后
}
if (p1 p2) {// p1指向的元素在p2指向的元素之前或相等
}
if (p1 p2) {// p1指向的元素在p2指向的元素之后或相等
}判断指针和NULL之间的关系
int* p NULL;
if (p NULL) {// 指针为空
}
if (p ! NULL) {// 指针不为空
}这些例子演示了C语言中指针关系运算符的用法。需要注意的是在进行指针关系运算之前必须确保指针是有效的即它指向的内存是有效的。否则结果是未定义的。
空指针
在C语言中空指针是指没有指向任何有效对象或函数的指针。空指针用NULL宏表示其实质是一个整型常量0。
以下是一些关于空指针的常见用法
声明空指针
int* ptr NULL;
char* str NULL;这里将指针ptr和str声明为空指针即它们暂时不指向任何有效的内存地址。
判断指针是否为空
if (ptr NULL) {// 指针为空
}可以使用相等运算符将指针与NULL进行比较来判断指针是否为空。
传递空指针到函数
void foo(int* ptr) {if (ptr NULL) {// 指针为空}// 其他操作
}int main() {int* ptr NULL;foo(ptr);return 0;
}可以将空指针作为参数传递给函数并在函数内部判断指针是否为空。
需要注意的是对空指针进行解引用操作如*ptr是非法的会导致程序崩溃或未定义行为。因此在使用指针之前应始终确保它不为空。
const与指针
在C语言中const关键字可以与指针结合使用用于声明指向常量的指针或常量指针。
指向常量的指针
使用const修饰指针所指向的内容表明指针所指向的内容是不可修改的。
const int* p; // 指向常量的指针p指向的内容不可修改但p本身可修改
int num 5;
p num; // 合法
*p 10; // 非法指针指向的内容不可修改p可改*p不可改
常量指针
使用const修饰指针本身表明指针本身是不可修改的。即指针指向的地址不可修改。
int* const p; // 常量指针p本身不可修改但p指向的内容可修改
int num 5;
p num // 非法不可改变指针指向
*p 10; // 合法指针指向的内容可修改p不可改*p可改
指向常量的常量指针
既不允许修改指针本身也不允许修改指针所指向的内容。
const int* const p; // 指向常量的常量指针p本身和p指向的内容都不可修改
int num 5;
p num // 非法指针本身不可修改
*p 10; // 非法指针指向的内容不可修改p和*p都不可改
通过使用const关键字可以灵活地控制指针所指向的内容是否可修改以及指针本身是否可修改。常量指针和指向常量的指针在函数参数传递中特别有用可以避免不必要的修改。
二级指针
在C语言中二级指针double pointer也称为指向指针的指针。它本质上是一个指针变量存储的是另一个指针的地址。
语法上二级指针的声明和使用方式如下
int** ptr2; // 声明一个二级指针int main() {int num 10;int* ptr1 # // 声明一个指针并将其指向变量num的地址ptr2 ptr1; // 将指向ptr1的地址赋给二级指针ptr2printf(Value of num: %d\n, **ptr2); // 通过二级指针访问变量num的值printf(Address of ptr1: %p\n, *ptr2); // 通过二级指针访问指针ptr1的地址return 0;
}在上面的例子中我们声明了一个二级指针ptr2它存储了指向ptr1的地址。
通过二级指针ptr2可以访问ptr1所指向的地址和值。通过两次解引用操作**ptr2我们可以获得指向的变量num的值。通过一次解引用操作*ptr2我们可以获得指针ptr1的地址。
二级指针通常用在需要传递指针的地址作为参数的函数中可以通过传递二级指针来修改原始指针的值。