C语言指针笔记

本文详细探讨了C语言中的指针概念,包括指针变量的声明、赋值和使用,以及指针与数组的关系。文中提到了指针在多级指针、数组指针、二维数组和字符串中的应用,并强调了指针在内存管理和类型转换中的重要性。此外,还讨论了常量指针和指针常量的区别以及在不同内存区域(如ROM和RAM)中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

红叶何时落水

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
#if 0
    //告诉编译器该如何翻译这个指针 void* 百搭,自动转换
    char *s = "abcd";//char 是来形容该指针的指向的类型,而指针变量的类型是固定的
    char **s2 = &s; 
    printf("sizeof(s) = %d s = %s\n", sizeof(s), s);
    printf("sizeof(s2) = %d *s2 = %s\n", sizeof(s2), *s2);
    int i = 1;
    int *p = &i;
    unsigned int *p2 = &p;
    printf("p = %p\n", p);
    printf("&p = %p\n", &p);
    printf("*p2 = %p\n", *p2);
    //printf("**p2 = %x\n", *(*p2));//没法使用,多级指针的意义所在,不可以链表的形式实现多级指针
    int *P_null = NULL;//空指针,为了防止野指针(没有初始化的指针)
    printf("P_null = %p\n", P_null);


#endif

#if 0
//指针与数组
    int arr[3] = {1,2,3};
    int *p = arr;
    //注意p++与p+1;p++很危险p为左值;p+1中为右值
    printf("*(arr + 0) = %d\n", *(arr + 0));
    printf("p[0] = %d\n", p[0]);//注意p[0]与arr[0]本质区别,arr是常量(ROM),p是变量(RAM)
    printf("p[0] = %d\n", (p+1)[0]);//=>arr[1] == 2

    printf("*p = %d *p++ = %d\n", *p, *p++);
    printf("*p = %d *p++ = %d\n", *p, *p++);
    printf("*p = %d *p++ = %d\n", *p, *p++);//由此可以看出,printf的参数执行是从右边开始的
    int *p2 = (int [3]){1,4,3} + 1;//没毛病
    int *p3 = p2 - 1;
    int y = ++(*--p2);//*p返回的是一个左值,因为*p = 2;成立可以再次赋值
    printf("y = %d\n", y); // y = *(p2 - 1) + 1;
    printf("p3[0] = %d\n", p3[0]);// 上面的 ++ 将 *(p2 - 1) 由 1 => 2 这就是说那个式子里有三个左值 y p2 *(p2 - 1)
#endif
#if 0
//指针与二维数组

    int arr[2][3] = {{1,2,3},{4,5,6}};
    int *p = arr;//这种情况不可以,该式右值的属性与左值属性不同,一个是数组,一个是指针
    printf("sizeof(arr) = %d\n", sizeof(arr));
    printf("sizeof(arr[0]) = %d\n", sizeof(arr[0]));
    printf("arr = %p\n", arr);
    printf("arr+1 = %p\n", arr + 1);
    printf("p = %p\n", p);
    printf("p + 1 = %p\n", p + 1);//以上是指针与数组的区别
    printf("**(arr + 1) = %d\n", **(arr + 1));//指针降级
    printf("*(arr + 1) = %p\n", *(arr + 1));//指针降级
    printf("arr + 1 = %p\n", arr + 1);//指针降级
    printf("*arr + 1 = %p\n", *arr + 1);//指针降级,添加"*"后,数组名会变成指针的方式访问内存
    int *p2 = *arr;//合理,加“*”降级为普通指针类型访问内存
    printf("*p2 = %d\n", *p2);
    printf("*(p2 + 1) = %d\n", *(p2 + 1));
    printf("*p2[4] = %d\n", p2[4]);
#endif
#if 0
//数组指针
    int (*p)[3];//=>int[3] *p; p+1的存储移动为int*3
    int arr[2][3] = {{1,2,3}, {4,5,6}};
    p = arr;//注意,虽然p访存方式和arr一致,但是arr是地址常量,p是指针变量
    printf("arr + 1 = %p\n", arr + 1);
    printf("p + 1 = %p\n", p + 1);
    printf("**(p + 1) = %d\n", **(p + 1));//"*"指针访存方式降级
    printf("**(arr + 1) = %d\n", **(arr + 1));

#endif
#if 0
//字符数组
    char *str_p = "hello";//注意"hello"是一个字符串,他储存在ROM区,是只读的,而RAM区的指针指向"hello"所在的地址,从ROM中访存读取,不可以再次修改
    char str_arr[] = "world";//数组则是在RAM的栈中开辟了一块空间,可读可写
    printf("sizeof(str_arr) = %d strlen(str_arr) = %d\n", sizeof(str_arr), strlen(str_arr));//数组大小
    printf("sizeof(str_p) = %d strlen(str_p) = %d\n", sizeof(str_p), strlen(str_p));//指针大小//区别一
    //区别二 这里的指针中所存储的地址是只读的,而数组名代表的那个地址是可读可写的
    strcpy(str_arr, "hello world");//可以成功赋值
    puts(str_arr);
    // strcpy(str_p, "hello world");//出错,无法修改ROM区段
    // puts(str_p);
    strcpy(&str_p, "hello world");//当然,这样可以,因为&str_p所代表的地址位于RAM,
    puts(&str_p);//这里也反映了C语言的危险性,这里毁掉了str_p这个指针,同时已发生了内存溢出
    //上面那个例子仅仅是为了区分ROM地址与RAM地址,无任何使用以及操作正确性

#endif
#if 0
//const访存修饰符 先修饰左边,后修饰右边,只能修饰一个
//#define的数据是存在于指令中的,而const是要占用ROM的
//当变量处于函数中,它储存在栈空间,可以通过地址指针间接改变
    const float PI = 3.14;
    float *p = &PI;
    *p = 3.1415;
    printf("PI = %f\n", PI);
//常量指针 const int *p;或int const *p; *p不可以变化 p可以重新赋值(指向新地址)
//指针常量 int *const p; *p可以变化,p不可以变化

//注  keil环境
//    float PI_font = 1;//经过验证,const为局部变量的话,是处于栈空间,但是编译器禁止将他的地址赋值给指针,
//                      //尽管间接改变了他地址上的值,依旧不影响程序,应该是程序将其以宏定义的方法进行了优化
//    const float PI = 3.14;
//    float *p = &PI_font;
//    p--;
//    *p = 3.1415;
//    printf("&PI = %p PI = %f \n p = %p *p = %f\n", &PI, PI, p, *p);//&PI = 2000c9f8 PI = 3.140000 
//                                                                   //p = 2000c9f8 *p = 3.141500
//    static const int PI = 3;//&PI = 08005308 PI = 3 加上static就定义到了FLASH区
//    printf("&PI = %p PI = %d\n", &PI, PI);
#endif
#if 0
//数组指针(指向数组的指针int (*p)[3] => int[3] *p) 常量指针(指向常量的指针) 函数指针(指向函数的指针)
//指针数组 int* arr[3]; 存放指针的数组,数组元素是指针 arr依旧是一个地址常量,上面的那三个是指针变量
    int *arr_p[3];
    int i = 1;
    int j = 3;
    char *str_arr_p[3] = {"word1", "word2", "word3"};
    arr_p[0] = &i;
    arr_p[1] = &j;
    puts(str_arr_p[0]);
    puts(str_arr_p[1]);
    puts(str_arr_p[2]);
    printf("*arr_p[0] = %d\n", *arr_p[0]);
    printf("*arr_p[1] = %d\n", *arr_p[1]);
#endif
#if 1
//多级指针 *相当于升级,取该地址的值,&相当于降级,取该值的地址,添加一个“*”,就是升一级,少一个“*”就降一级, 初始化中的星号用来说明他最高有几级
    int **p;//=> int** p;在初始化赋值时,是赋值给p,而非*p,或**p,
    // &左值 得到一个地址右值
    // *左值/右值 得到一个左值 可以存放新的右值
    int *p1;
    int i = 3;
    int j = 5;
    p = &p1;
    p1 = &i;
    printf("**p = %d *p = %p p = %p\n*p1 = %d &p1 = %p &i = %p\n", **p, *p, p, *p1, &p1, &i);
    *p = &j;
    printf("*p1 = %d\n", *p1);
#endif
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红叶落水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值