C语言 指针
C语言 指针
最近接触到C语言的一个项目,碰到一些关于指针的问题,在这总结一下,以供以后学习
指针的本质
指针可以简单理解为内存地址。在代码中常说的指针变量,其含义是指向某一种变量的在内存中的地址,实质表现为。但同时也需要注意,指针本身也是一种变量,所以也存在指针的指针,即指向某一指针变量的地址。
案例1:
#include <stdio.h>
int main() {
int a=1;
int *p;
int **pp;
p=&a;
pp=&p;
printf("0x%x\n",p);
printf("size:%d\n",sizeof(p));
printf("0x%x\n",pp);
printf("size:%d\n",sizeof(pp));
return 0;
}
输出:
0x61fe14
size:8
0x61fe08
size:8
从案例1中可以看出,对于int类型a,使用符号‘&’获取变量a的地址,并赋值给指针变量p。同理,获取指针变量p的指针,复制给pp,即指针变量的指针。、
对于指针变量本身来说,其存储在C语言编译器的栈空间中,指向的是堆空间。且由于C语言本身的特殊性,其指针空间的大小与编译机器有关,与指向的类型无关(指针在栈中独占一行,而栈的大小受编译机器相关)。比如案例1中,使用的是64位win11,其指针大小是4个字节,即64比特位。
运用
指针的运算
指针变量也能参与运算,且其运算过程主要用于指针地址之间的上移或者下移,以及通过上下移动统计特定类型数据的个数。
案例2:
#include <stdio.h>
int main() {
int nums[]={1,2,3,4,5};
int *p1=&nums[0];
int *p2=&nums[4];
char str[]={"hello world"};
char *q1=&str[0];
char *q2=&str[10];
//指针移动
printf("p1:%p\n",p1);
printf("p1+1:%p\n",p1+1);
printf("*p1:%d\n",*p1);
printf("*(p1+1):%d\n",*(p1+1));
printf("q1:%c\n",*q1);
printf("q2:%c\n",*q2);
printf("q1+2:%s\n",q1+2);
//指针移动
printf("p2-p1:%d\n",p2-p1);
printf("q2-q1:%d\n",q2-q1);
}
输出:
p1:000000000061FDE0
p1+1:000000000061FDE4
*p1:1
*(p1+1):2
q1:h
q2:d
*(q1+2):llo world
p2-p1:4
q2-q1:10
从案例2中可以看出,指针除了指定变量的内存地址之外还能衍生出另外三个作用:
- 通过对指针加减,让指针指向另外的数据。在案例2中,对于数组元素nums和str,在指向数组头的时候,可以对指针使用加法,从而让指向变化到临近的元素。(需要注意的时,对指针使用加减法,不是对于内存地址直接加减法,而是相对于指针的类型,一次性加减相对于指向类型的字节数。比如对于int类型,p1+1相当于p1向下移动4个字节(int的大小))
- 对于字符串数组来说,当使用指针来输出字符串时,可以使用指针来确定输出字符串的起始点。在案例2中,对字符指针q2,在加2的情况下,使用printf("q1+2:%s\n",q1+2)输出字符串,可以看到输出字符串是从字符串指向位置开始,直至‘\0’结束。
- 由第一个作用,可以从指向同一数组的指针中,判断两个指针之间的距离或者说是两个指向位置之间元素个数。比如案例2中,printf("p2-p1:%d\n",p2-p1),可以判断出两个指针中有多少元素。
字符串使用
对于字符串,即字符数组,在使用指针的时候有一些特殊情况。
案例3:
#include <stdio.h>
#include<stdlib.h>
int main() {
char str[]={"hello world"};
char *p=str;
char *q1=&str[0];
char *q2;
q2=(char *)malloc(sizeof(char));
//str=&str[0]??
if(p==q1){
printf("true\n");
}else{
printf("false\n");
}
//以指针输入和输出、
//注意:q2要提前声明存储空间
scanf("%s",q2);
printf("%s",q2);
}
输出:
true
121212
121212
注意:
- 对于字符数组来说,其数组名是一个地址,且指向的是数组的第一个元素。在案例3中,可以发现str=&str[0]成立。
- 对于字符串的输入和输出,均是以数组名,即指针为实参。
指针数组
由指针组成的数组。
定义:element *数组名[]
#include <stdio.h>
#include<stdlib.h>
int main()
{
int *p[2];
int a=1;
int b=2;
p[0]=&a;
p[1]=&b;
for (int i = 0; i < 2; ++i) {
printf("%d\n",*p[i]);
}
return 0;
}
数组指针
指向数组的指针。主要用在二维数组。
定义:element (*指针名)[]
#include <stdio.h>
#include<stdlib.h>
int main()
{
int (*p)[2];
int a[2]={1,2};
p=&a;
for (int i = 0; i < 2; ++i) {
printf("%d\n",*(*p+i));
}
return 0;
}
结构体使用
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
struct Student
{
int age;
char firstname[10];
char *secondname;
};
int main()
{
//不使用指针
struct Student A;
A.age=10;
strcpy(A.firstname,"Wu");
strcpy(A.secondname,"Yanzu");
printf("%s ",A.firstname);
printf("%s\n",A.secondname);
//使用指针
struct Student *B;
B=(struct Student *)malloc(sizeof(struct Student));
strcpy(B->firstname,"liu");
//strcpy(B->secondname,"Yifei"); 错误用法
B->secondname="Yifei";
printf("%s ",B->firstname);
printf("%s",(*B).secondname);
return 0;
}
char * secondname和char firsrname[]是不一样的,具体看引用3。
注意:以下 3 种形式是等价的:
结构体变量.成员名。
(*指针变量).成员名。
指针变量->成员名。
还有一部分没写完。。。。
ref:
本文作者:weliars
本文链接:https://www.cnblogs.com/weliars/p/16631700.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步