总结对指针的一些看法~~~~

本文深入探讨了C/C++中指针的基本概念及其与数组的关系,包括指针变量的值与类型、指针解引用的过程、数组与指针之间的联系等关键知识点。

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

c/c++中的指针一般是指指针变量,它与普通的变量不同的是他能根据指针变量的类型通过*来重新解析指针变量的值,比如 :

int i=3;

int *p=&i;

p=&i是给指针变量赋值,对于i编译器根据变量i的类型(int),在内存中划出了4个字节的空间&i~&i+3,以后对i的操作会映射到&i~&i+3这个字节中,比如i=4;编译器会根据编译时所获得类型信息,将4存储到&i~&i+3内存中。编译器给变量的赋值过程跟指针的解引(*)用过程是相似的。上面p=&i;是把i的地址值赋给p,也就是说p的值是编译器分配i变量对应的内存的起始地址值,现在p的类型是int*,当进行*p操作时,编译器认为p的值是某个int类型变量在内存的地址,于是编译器会从p的值对应的内存开始,往下涵盖四个字节,把这四个字节的内存里的数据按照一定的方式取出。指针变量与普通的变量的不同之处也在于此,指针变量能控制对内存数据的解析方式,如果

int i=3;

char *p=(char*)&i;

p的值还是i的首地址,但*p的内容不一样了,由于是char*现在*p只是i的首地址内存的数据。

 

所以对于指针变量有两点是至关重要的,首先是指针变量的值,然后是它的类型也就是它对指针变量值的解析方式,搞明白指针变量这两点基本对指针变量比较从容了~~~~

 

再谈一下数组和指针,一维数组如 int a[10]={0},那么编译器会在内存开辟10*sizeof(int)的连续空间,其中a用来标示这块连续内存的首地址,然后对a[0],a[1].....的访问自动回被转化为*(a+0),*(a+1)....指针形式的访问,因此可以认为a的值是一个编译期就确定下来的常量,默认被解析成对应类型的指针变量的一个值,所以可以赋给对应类型指针变量。因此像

int a[10]={0};

int b[10];

b=a;

这样的语句是编译器所拒绝的,因为编译器要靠b的值,来寻址b[0],b[1]...所以不能修改b的值。另外对于像b[0],0[b]在编译器眼里都会被解析成*(b+0),所数组下标可以为负数,但要注意越界。


  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     int a[10]={0};
  6.     0[a]=10;
  7.     cout<<a[0]<<endl;
  8.     int  *p=a;
  9.     p+=1;
  10.     cout<<(-1)[p]<<endl;
  11.     cout<<p[-1]<<endl;
  12.     system("pause");
  13.     
  14. }

 

对于二维数组,他们在内存也是连续的,如int c[10][10],c也可以认为是一个常量默认解析成一个(*)[10]类型,一个指向数组的指针变量的值。可能有人会问为什么不解析成一个二级指针变量的值,道理很简单比如如下代码:

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     int a[10][10]={10};
  6.     int **p=(int**)a;
  7.     cout<<*p<<endl;
  8.     system("pause");
  9.     **p=1;
  10.     
  11. }

a的值可以强制赋给p,但是*p时会把a对应的内存开始涵盖四个字节的数据取出,解析成一个int*变量的值,此时程序还没有问题*p的值是a[0][0](0x0000000a)的值,但**p操作会从地址值0x0000000a开始涵盖四个字节内存取其中数据组成一个int变量的值,而对0x0000000a访问,很容易非法,故程序挂掉。

  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5.     int a[2][2]={1,2,3,4};
  6.     int (*p)[2]=a;
  7.     cout<<**p<<endl;//->a[0][10]
  8.     cout<<*p[1]<<endl;//->*(*(p+1)+0)->a[1][0]
  9.     int *q=(int*)a;//验证二维数组在内存布局也是连续
  10.     for (int i=0;i<4;i++)
  11.     {
  12.          cout<<q[i]<<endl;
  13.     }
  14.     system("pause");
  15.     
  16. }

 

ps:个人见解,如有错误望不吝指教。(未完)

 

 

 

<think>好的,用户问的是C语言中指针声明 `int* p` 和 `int* p` 有什么区别。首先我需要确认自己对这个问题是否理解正确。这两种写法其实在语法上是没有区别的,都声明了一个指向整型的指针变量p。但可能在代码风格或可读性上有不同的看法。 接下来,我需要分析用户可能的背景。用户可能刚开始学习C语言,对指针的声明方式感到困惑,或者看到不同的代码风格产生了疑问。这时候需要明确解释两者的等价性,同时指出风格上的差异,以及可能带来的潜在问题。 首先,解释两种写法的语法等价性。C语言中,`int* p`和`int *p`都会被编译器识别为声明一个指针变量p。这里的`*`符号是类型修饰符,它作用于变量名而非类型名。因此,无论`*`靠近类型还是变量,效果是一样的。 然后,讨论代码风格的问题。`int* p`这种写法强调类型整体性,即“指向int的指针类型”,适合在单独声明变量时使用,使类型信息更集中。而`int *p`则更符合C的传统习惯,强调`*`是变量的一部分,这在同时声明多个指针时尤为重要,比如`int *p, *q;`,此时每个变量前都需要加`*`,避免错误。 接下来,需要举例说明两种写法在不同情况下的应用场景。例如,当声明多个指针时,如果使用`int* p, q;`,q会被误认为是int指针,而实际上是int类型。而使用`int *p, *q;`则明确两个都是指针。这可能就是为什么有些人更倾向于`int *p`的写法,以避免歧义。 此外,可能还需要提到团队协作中的编码规范问题。不同的项目可能有不同的风格指南,选择其中一种并保持一致即可。对于个人项目,可以根据可读性自行决定,但需要注意声明多个变量时的正确写法。 最后,总结两者的区别主要在于代码风格和可读性,语法上没有区别。需要提醒用户注意在多个变量声明时的正确用法,避免错误。 现在需要将这些思路组织成清晰的中文解释,先回答两种写法在语法上等价,然后讨论代码风格和潜在的陷阱,最后给出建议。同时,在相关问题部分,可以提出指针声明相关的问题,比如多级指针、多个变量声明、类型修饰符的位置等,以帮助用户进一步理解。</think><< `int* p` 和 `int *p` 在语法功能上完全等价,它们的区别仅体现在代码风格上: 1. **语法等价性** C语言编译器会将其解析为同一含义:声明一个指向 `int` 类型的指针变量 `p`。`*` 符号在声明中与变量名绑定,而非类型名。 2. **代码风格差异** - `int* p` 风格: 强调类型整体性("指向 int 的指针类型"),常见于面向对象编程背景的开发者。 ```c int* p; // 直观体现 p 的类型是 int 指针 ``` - `int *p` 风格: 强调 `*` 是变量修饰符,符合 C 语言传统习惯,尤其在多变量声明时更安全: ```c int *p, *q; // 明确声明两个指针 // 若写作 int* p, q; 则 q 是普通 int 变量! ``` 3. **潜在陷阱** `int* p, q;` 会被错误解析为 `int (*p), q;`(q 是普通 int),而 `int *p, *q;` 能正确声明两个指针。 **建议**:在团队开发中遵循项目规范;个人代码优先使用 `int *p` 风格以避免多变量声明错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值