C语言核心概念详解:指针的解引用,基本指针运算`*p++` 和 `(*p)++` 的区别

一、字符数组:字符串的存储容器

字符数组是用来存储字符串数据的重要数据结构。

基本定义与初始化

c 复制代码
#include <stdio.h>

int main() {
    // 方式1:逐个字符初始化
    char ch[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
    
    // 方式2:字符串直接初始化
    char str[] = "Hello";
    
    printf("ch: %s\n", ch);
    printf("str: %s\n", str);
    
    return 0;
}

内存布局

| | |
|------|-------|-------|-------|-------|-------|
| 字符数组 | H | e | l | l | o |
| 索引 | [0] | [1] | [2] | [3] | [4] |

自动大小计算

c 复制代码
#include <stdio.h>

int main() {
    char name[] = "张三";  // 编译器自动计算大小(包含\0)
    char city[20] = "北京";
    
    printf("姓名: %s\n", name);
    printf("城市: %s\n", city);
    printf("欢迎%s来到%s!\n", name, city);
    
    // 查看数组大小
    printf("name数组大小: %zu\n", sizeof(name));
    printf("city数组大小: %zu\n", sizeof(city));
    
    return 0;
}

输出结果:

makefile 复制代码
姓名: 张三
城市: 北京
欢迎张三来到北京!
name数组大小: 7
city数组大小: 20

二、字符串的整行输入输出

问题:scanf遇到空格就停止

c 复制代码
#include <stdio.h>

int main() {
    char text[50];
    
    printf("请输入带空格的文本: ");
    scanf("%s", text);  // 遇到空格就停止
    
    printf("输出结果: %s\n", text);  // 只会输出空格前的部分
    
    return 0;//如输入abc  defg只会输出abc要注意
}

解决方案:使用 %[^\n]

c 复制代码
#include <stdio.h>

int main() {
    char sentence[100];
    
    printf("请输入一句话: ");
    scanf("%[^\n]", sentence);  // 读取直到换行符
    
    printf("你输入的是: %s\n", sentence);
    
    return 0;
}

三、指针:直接内存访问的利器

指针的重要性

  • 直接内存访问能力
  • 高效的数据操作
  • 动态内存管理
  • 复杂数据结构的实现
  • 系统级编程支持

指针基础

c 复制代码
#include <stdio.h>

int main() {
    int a = 10;        // 开辟一块内存空间
    int *p = &a;       // 使用&取变量a的地址
    
    printf("变量a的值: %d\n", a);
    printf("变量a的地址: %p\n", &a);
    printf("指针p的值(存储的地址): %p\n", p);
    printf("通过指针p访问的值: %d\n", *p);
    
    return 0;
}

四、指针的解引用

指针的解引用(Dereferencing)是使用指针访问或修改其所指向内存中数据的操作。解引用操作使用 * 运算符。

c 复制代码
#include <stdio.h>

int main() {
    int num = 42;
    int *ptr = &num;  // ptr指向num
    
    // 解引用:通过指针访问指向的值
    printf("num的值: %d\n", num);
    printf("通过指针访问的值: %d\n", *ptr);  // 解引用
    
    // 通过指针修改值
    *ptr = 100;  // 解引用并赋值
    printf("修改后num的值: %d\n", num);
    
    // 验证修改
    printf("再次通过指针访问: %d\n", *ptr);
    
    return 0;
}

五、指针的算术运算

指针的算术运算是C语言中一个强大但需要谨慎使用的特性。与普通算术运算不同,指针运算的结果取决于指针所指向的数据类型。

基本指针运算

c 复制代码
#include <stdio.h>

int main() {
    int arr[5] = {10, 20, 30, 40, 50};
    int *ptr = arr;  // 指向数组第一个元素
    
    printf("初始位置:\n");
    printf("ptr = %p, *ptr = %d\n", ptr, *ptr);
    
    // 指针加法
    ptr = ptr + 1;  // 移动到下一个int元素
    printf("ptr + 1:\n");
    printf("ptr = %p, *ptr = %d\n", ptr, *ptr);
    
    ptr = ptr + 2;  // 再向后移动两个int元素
    printf("ptr + 2:\n");
    printf("ptr = %p, *ptr = %d\n", ptr, *ptr);
    
    // 指针减法
    ptr = ptr - 1;  // 向前移动一个int元素
    printf("ptr - 1:\n");
    printf("ptr = %p, *ptr = %d\n", ptr, *ptr);
    
    return 0;
}

六、*p++(*p)++ 的区别

*p++ - 指针移动

  • 先计算 *p(获取当前指针指向的值)
  • 然后执行 p++(指针向后移动一个元素位置)
  • 返回之前获取的值
c 复制代码
#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40};
    int *p = arr;
    
    printf("*p++ = %d\n", *p++);   // 输出:10
    printf("当前 *p = %d\n", *p);   // 输出:20(指针已移动)
    printf("arr[0] = %d\n", arr[0]); // 输出:10(原值未变)
    
    return 0;
}

(*p)++ - 值修改

  • 先计算 *p(获取指针指向的值)
  • 然后对该值执行 ++(将指针指向的内存位置的值加1)
  • 返回之前获取的值
  • 指针位置不变
c 复制代码
#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40};
    int *p = arr;
    
    printf("(*p)++ = %d\n", (*p)++); // 输出:10
    printf("当前 *p = %d\n", *p);       // 输出:11(值已改变)
    printf("arr[0] = %d\n", arr[0]);   // 输出:11(原数组被修改)
    
    return 0;
}

使用场景:

  • *p++ - 关注指针移动(常用于遍历数组)
  • (*p)++ - 关注值的修改(修改指针指向的内容)
相关推荐
开心就好202510 分钟前
Charles抓包工具使用方法 Charles抓包分析、配置教程、网络排查技巧与手机抓包步骤
后端
sheji341615 分钟前
【开题答辩全过程】以 基于springboot游泳馆管理系统为例,包含答辩的问题和答案
java·spring boot·后端
5***r93518 分钟前
SpringBoot 与 SpringCloud的版本对应详细版
spring boot·后端·spring cloud
在人间负债20 分钟前
昇腾 RAG SDK 从入门到实战:技术解析与部署实操
后端·算法
天天摸鱼的java工程师28 分钟前
MySQL 的锁机制和数据隔离:一个 Java 老兵的实战总结
java·后端
undsky33 分钟前
【RuoYi-SpringBoot3-Pro】:若依企业级增强版 —— 让开发更安全高效
spring boot·后端
踏浪无痕34 分钟前
准备手写Simple Raft(四):日志终于能"生效"了
分布式·后端
程序员西西38 分钟前
SpringBoot 隐式参数注入:告别重复代码,让 Controller 更优雅
java·后端
嘻哈baby39 分钟前
Ansible自动化运维:从入门到批量管理100台服务器
后端
用户3458482850539 分钟前
dict.fromkeys()和OrderedDict.fromkeys()的底层实现原理是什么?
后端