C指针分析详解

局部变量和全局变量初始化区别

  局部变量,在未初始化情况下,初值为随机值。C规范对该初值并没有做规定,具体实现由编译器决定。如VC/VS等编译器,会将初始值值为0xCCCCCCCC, 而GCC等编译器则是不可预知的随机值。

  全局变量和静态局部变量(带static修饰的局部变量)。即定义在函数外,不属于任何一个函数的变量。这两种默认初值为0.

 


 

指针:指针其实是一个地址。

指针赋值:一个地址的赋值。

空指针:即 int *p=NULL ;  //等于NULL

野指针:即 int *p;    //只声明,不定义(赋值)

指针变量:int  *p =&a;  //*p称为指针变量,无论是声明时候什么类型,指针变量只占有4个字节。

&:取地址符号

*:指针符号,指向一个储存空间,也可以取出存储空间的值

数字名:数组名是一个地址(首地址),是一个常量,不允许重新赋值   //第一个元素的地址。

  

对一级指针,二级指针进行操作:

其实:&与*是一个反运算符

一级指针:*p

  (*p)++:括号优先级大,所以直接执行(*p)操作,取出该指针所对应的值,然后对值进行加1操作。

  *p++:++与*优先级相同,从右往左操作:先执行p++,由于是“++”号是后加加号,所以会在整条语句执行完后再对P自加1,所以先输出*p,然后指针再+1。

  *(p+1):括号优先级大,与*p++类似。

  *p:直接取出指针所对应的数值。

  *++p:++与*优先级相同,从右往左操作:先执行++操作,再执行*。++p先把指针+1,然后再取加1后的值。

  *(++p):括号优先级大,与*++p类似。

 

#include<stdio.h>
int main(void){
    int a[]={1,2,3,4,5};
    int *p=a;

    printf("++(*p):%d \n",++(*p));//2
    printf("(*p)++:%d \n",(*p)++);//2
    printf("a[0]:%d\n",a[0]);//3
    
    printf("*p++:%d \n",*p++);//3
    printf("*(p++):%d \n",*(p++));//2
    printf("*p:%d \n",*p);//3
    
    p=a;//a指针重新回到a[0] 
    printf("a[0]:%d\n",a[0]);//3
    printf("*++p:%d \n",*++p);//2
    printf("*(++p):%d \n",*(++p));//3
    
    return 0;
}

 

 

 

二级指针:**p2

#include<stdio.h>
int main(void){
    int a=10;
    int *p=&a;
    int **pp;
    pp=&p;
    printf("&a:%p\n",&a);//000000000062FE4C
    printf("&p:%p\n",&p);//000000000062FE40
    printf("&pp:%p\n",&pp);//000000000062FE38
    printf("p:%p *p:%d\n",p,*p);//000000000062FE4C 10
    printf("pp:%p **p:%d %d\n",pp,**pp,*(*pp));//000000000062FE40 10 10
    printf("pp:%p  &p:%p  \n",pp,&p);//000000000062FE40  000000000062FE40
    printf("*pp:%p  p:%p \n",*pp,p);//000000000062FE4C 000000000062FE4C
    printf("**pp:%d  *p:%d\n",**pp,*p);//10  10
    return 0;
}

 

由图所示:

    p: p里面存储的是a的地址。

  *pp二级指针: 取一级指针的数值,也就是&a,但是&a是一个地址,所以取出来的是一个地址。

  **pp二级指针:可以看成*(*pp),先取*p里面的值,取出来之后是&a,接着就是*(&a),结果10。

 


 常量指针:int const *p;

1.通过该指针不可以修改它所指向的存储单元里面的值【只有读的权限,没有修改,如果要修改存储单元里面的值,需要用一个指针去修改】

2.指针指向地址可以被修改【指向地址】

 

 

#include<stdio.h> 
int main(void){
    int a=10;
    int b=9;
    int const *p =&a;
    *p=11;//常量指针报错,指向的存储单元的值,不可以被修改 
    p=&b;
    
    printf("p:%d",*p) ;
    
    return 0; 
}

 

 

 

指针常量:int * const p 

1.指针本身即地址不可以被修改。【用二级指针修改存储单元里面的值】

2.通过该指针可以修改它所指向的存储单元的值。

【与常量指针相反】

 

#include<stdio.h> 
int main(void){
    int a=10;
    int b=9;
    int *const p=&a;
    
    *p=11;
    p=&b;//报错,地址不能修改 
    
    printf("p:%d",*p);
    
    return 0; 
}

 

 

 

 

 

指向常量的指针常量:int const * const p

1.指针本身即地址不可以被修改。

2.通过该指针不可以修改他所指向的存储单元的值。

 

 

 

 

 

段的错误(常见问题):

a.操作了空指针

b.对野指针进行赋值(操作受保护的内存),也就是已经被占用的内存。

c.指针指向一个错误的内存(或者说是不存在的内存)。

d.修改常量区的内容。

 

转载于:https://www.cnblogs.com/tianjiale/p/9839133.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:C语言字节对齐问题详解中提到了C语言中的字节对齐问题。在结构体中,为了提高内存访问的效率,编译器会对结构体进行字节对齐。这意味着结构体的成员在内存中并不是紧凑排列的,而是按照一定的规则进行对齐。具体的对齐规则取决于编译器和编译选项。\[1\] 引用\[2\]:在C语言中,可以使用宏offsetof来获取结构体成员相对于结构体开头的字节偏移量。这个宏非常有用,可以帮助我们计算出每个结构体成员相对于结构体开头的偏移字节数。通过这个宏,我们可以更好地理解结构体的内存布局。\[2\] 引用\[3\]:在C语言中,指针和结构体的组合常常用于处理复杂的数据结构。指针可以指向结构体的成员,通过指针可以方便地对结构体进行操作。指针和结构体的组合可以实现更灵活的数据处理和内存管理。\[3\] 综上所述,C语言中的指针结构体组合可以用于处理复杂的数据结构,而字节对齐问题则是在结构体中为了提高内存访问效率而进行的优化。通过使用宏offsetof,我们可以更好地理解结构体的内存布局。 #### 引用[.reference_title] - *1* *3* [结构体指针,C语言结构体指针详解](https://blog.csdn.net/weixin_34069265/article/details/117110735)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [C语言之结构体详解](https://blog.csdn.net/m0_70749276/article/details/127061692)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值