C语言基础(十一)

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;  
}

运行结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值