1、指针:
C语言中的指针是一种非常重要的数据类型,可以直接访问和操作内存地址。指针存储变量的内存地址,而不是变量的值本身。通过使用指针,可以灵活地控制数据的存储和访问,实现复杂的数据结构如链表、树。
定义指针:
在C语言中,指针是通过在变量类型前加上星号(*)定义的。例如,int *ptr; 表示 ptr 是一个指向 int 类型数据的指针。
初始化指针:
使用指针之前,需要将其初始化为某个变量的地址或 NULL(表示指针不指向任何有效地址)。
例如,int var = 10; int *ptr = &var; ,&var 是取地址运算符,获取 var 的地址,并将其赋值给 ptr。
通过指针访问数据:
通过解引用指针(在指针前加星号),可以访问指针所指向的数据。例如,*ptr = 20; 将 var 的值修改为 20。
指针的算术运算:
指针的算术运算主要是指针的加减运算,以指针指向的数据类型的大小为单位进行。
例如,如果 ptr 是指向 int 的指针,ptr+1 将使 ptr 指向下一个 int 类型的存储位置。
指针的关系运算:
可以比较两个指针是否相等或不等,以及它们之间的顺序关系(前提是两个指针指向同一个数组的元素或指向数组之后的位置)。
指针的用途:
动态内存分配:通过 malloc、calloc 和 realloc 等函数,可以在堆(heap)上动态地分配内存,这些函数返回指向分配的内存的指针。
数组和字符串的访问:
在C语言中,数组名实际上是数组首元素的地址,因此可以使用指针遍历数组或字符串。
函数参数:
通过指针,可以将变量的地址传递给函数,允许函数修改传递给它的参数的值。
实现复杂数据结构:
如链表、树、图等,这些数据结构中的元素通常通过指针相互连接。
指针在使用前必须初始化,否则它们可能指向不确定的内存位置,导致程序崩溃或不可预测的行为。
指针运算时不要越界,即不要访问指针未指向的内存区域。
使用完动态分配的内存后,应通过 free 函数释放,以避免内存泄漏。
2、指针变量:
指针变量在C语言中是一种特殊的变量类型,用于存储内存地址而不是直接存储数据值。通过使用指针变量,程序可以间接地访问和操作存储在内存中的数据。指针变量提供了一种强大的机制管理内存,特别是在需要动态内存分配、数据结构操作或系统级编程时。
指针变量的定义
指针变量的定义包括指定指针所指向的数据类型。例如:int *ptr; 定义一个名为 ptr 的指针变量,它指向一个整型(int)数据。* 表示 ptr 是一个指针,而 int 指定了指针所指向的数据类型。
指针变量的赋值
指针变量可以被赋予两个类型的值:
地址:指针最常见的用途是存储某个变量的地址。通过取地址操作符 & 实现,例如 :ptr = &a; 将变量 a 的地址赋给指针 ptr。
另一个指针:指针也可以被赋予另一个同类型指针的值,从而实现指针的传递或赋值。
指针变量的间接访问
指针变量的主要操作是间接访问,即访问指针所指向的内存位置的值。通过解引用操作符 * 实现,例如: *ptr 表示访问 ptr 所指向的值。
指针变量的运算
指针变量支持几种特殊的运算,主要是指针算术运算:
指针加减:指针可以进行加减运算,但加减的不是指针本身的值,而是指针所指向类型的大小。例如,对于指向整型的指针 int *ptr,ptr + 1 实际上是将 ptr 的值增加了一个整型的大小(通常是4或8个字节,取决于编译器和平台)。
指针比较:两个指针可以进行比较运算,以检查它们是否指向内存中的相同位置或相对位置。
指针必须被初始化后才能使用,以避免指向不确定的内存位置。
指针解引用时,必须确保指针指向了一个有效的内存位置,否则可能会导致未定义行为,包括程序崩溃。
指针运算时,要注意指针所指向的数据类型,因为不同的数据类型在内存中占用的空间大小是不同的。
测试代码1:
#include "date.h"
#include <stdio.h>
int main() { int time = getTime();int var = 10; // 定义一个整型变量var int *ptr; // 定义一个指向整型的指针ptr // 将指针ptr指向var的地址 ptr = &var; // 打印var的地址 // %p 是打印指针(即地址)的格式说明符 printf("The address of var is: %p\n", &var); // 打印var的地址,将 &var 强转换为 (void*) printf("The address of var is: %p\n", (void*)&var); // 通过ptr打印var的地址(因为ptr已经存储了var的地址) printf("The address of var through ptr is: %p\n", ptr); // 通过ptr打印var的地址(因为ptr已经存储了var的地址),强转换为 (void*) printf("The address of var through ptr is: %p\n", (void*)ptr); return 0;
}
运行结果如下:
测试代码2:
#include "date.h"
#include <stdio.h>
//指针的访问
int main() { int time = getTime();int value = 10; // 定义一个整型变量value,并初始化为10 int *ptr; // 定义一个指向整型的指针ptr // 将ptr指向value的地址 ptr = &value; // 通过指针直接访问value的值,并打印出来// *ptr 表示直接访问 ptr 指针所指向的内存地址中的值。 printf("The value of value through pointer is: %d\n", *ptr); // 地址是这个 printf("The address is: %d\n", ptr); // 通过指针直接修改value的值 *ptr = 20; // value的值已经被修改 printf("The new value of value is: %d\n", value); return 0;
}
运行结果如下:
测试代码3:
#include "date.h"
#include <stdio.h> int main() { int tiem = getTime();// int 类型 int intVar = 10; int *ptrInt = &intVar; printf("The value of intVar through ptrInt: %d\n", *ptrInt); // char 类型(使用字符串) char str[] = "Hello, World!"; char *ptrChar = str; printf("The first character of the string: %c\n", *ptrChar); // 遍历字符串(指针运算) while (*ptrChar != '\0') { printf("%c", *ptrChar); ptrChar++; // 指针运算:移动到字符串的下一个字符 } printf("\n"); // float 类型 float floatVar = 3.14f; float *ptrFloat = &floatVar; printf("The value of floatVar through ptrFloat: %f\n", *ptrFloat); // float数组,指针的算术运算 float floatArr[] = {1.1f, 2.2f, 3.3f}; float *ptrFloatArr = floatArr; printf("The first element of floatArr: %f\n", *ptrFloatArr); ptrFloatArr++; // 指针运算:移动到数组的下一个元素 printf("The second element of floatArr: %f\n", *ptrFloatArr); return 0;
}
运行结果如下:
测试代码4:
#include "date.h"
#include <stdio.h> int main() { int time = getTime();int a = 10; // 定义一个整型变量a int b = 20; // 定义一个整型变量b int *ptrA = &a; // 创建一个指向a的指针ptrA int *ptrB = &b; // 创建一个指向b的指针ptrB // 输出a和b的地址 printf("Address of a: %p\n", (void *)&a); printf("Address of b: %p\n", (void *)&b); // 比较ptrA和ptrB(即a和b的地址)是否相同 if (ptrA == ptrB) { printf("Addresses of a and b are the same.\n"); } else { printf("Addresses of a and b are different.\n"); } // 大多数情况下,a和b会被分配在栈上的不同位置, // 通过某种方式(如数组元素),让它们共享相同的内存地址,比较就会返回true。 // 使用数组: int arr[2] = {10, 20}; int *ptrArrA = &arr[0]; // 指向arr的第一个元素 int *ptrArrB = &arr[1]; // 指向arr的第二个元素 // 比较ptrArrA和ptrArrB(即arr[0]和arr[1]的地址)是否相同 // 比较两个数组元素的地址,当然不同。 if (ptrArrA == ptrArrB) { printf("Addresses of arr[0] and arr[1] are the same. (This will not happen.)\n"); } else { printf("Addresses of arr[0] and arr[1] are different.\n"); } // 比较&arr[0]和&arr[0],则相同 if (&arr[0] == ptrArrA) { printf("Addresses of &arr[0] and ptrArrA are the same.\n"); } return 0;
}
运行结果如下: