指针是一块内存地址的首地址,这其中包含两个概念:
1.指针是内存地址;
2.指针还包括内存大小,void指针占用一个指针大小。
比如:int *a指的是内存地址a,大小为int的内存块。
1.普通指针和数组指针
#includeint main() { char a[4]; char (*pa)[4],*pb; pa=&a; pb=&a[0]; printf("pa占用内存大小是:%dn",sizeof(*pa)); printf("pb占用内存大小是:%dn",sizeof(*pb)); printf("pa是:%pn",pa); printf("pa+1是:%pn",pa+1); printf("pb是:%pn",pb); printf("pb+1是:%pn",pb+1); return 0; }
pa占用内存大小是:4 pb占用内存大小是:1 pa是:0x7ff7b425df18 pa+1是:0x7ff7b425df1c pb是:0x7ff7b425df18 pb+1是:0x7ff7b425df19
在上面的案例中,&a和&a[0]都表示char型数组a的首地址,但是他们的类型并不相同。
&a[0],a先和[0]结合,所以&a[0]是一个元素的大小,在这里是1字节;
&a,本质上是char *(&a)[4],是数组指针,此时&a表示的是char *[4]类型指针,是4字节;
根据开头的原理,指针是内存块,指针的值是内存块的首地址,指针的类型是内存大小。
因此,指针的递增(+1)指的是类型大小的递增。
指针数组和数组指针的概念参考:c语言进阶笔记
2.不同指针间的类型转换
不同类型指针的强制转换会造成内存变化,但首地址不会变。
int main()
{
int a=12345678;
int *pa=&a;
char *pb=(char *)&a;
printf("pa:%pn",pa);
printf("pa_value:%dn",*pa);
printf("pb:%pn",pb);
printf("pb_value:%dn",*pb);
return 0;
}
pa:0x7ff7b0ebaf18 pa_value:12345678 pb:0x7ff7b0ebaf18 pb_value:78
同时可以发现,这个内存模型是大端对齐。
指针与字符串通过指针定义的字符串形式如下:
char *str="hello";
此时str具有只读属性,不能被修改:
#includeint main() { char *a="hello"; *(a+1)='B'; printf("%sn",a); return 0; }
此时编译会成功,但执行会崩溃,因为通过指针定义的字符串在内存中具有只读属性。
如果指针指向的字符串不具有只读属性,那么就可以对其进行修改:
#includeint main() { char a[20]="abc"; char *p; p=a; *(p+1)='2'; printf("%sn",p); return 0; }



