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;
}
运行结果如下: