C Note 20210708

指针

  • 指针:地址
  • 指针变量:存地址的变量。

基操

给函数传指针p,函数内直接修改*p相当于直接修改变量的内容

void test(int * p)
{
    *p = 23333;
}
int main(void)
{
    int * p;
    int a = 4;

    p = &a;
    printf("%d\n", a);   // a = 4
    test(p);
    printf("%d\n", a);   // a = 23333
}

指针的大小与类型无关,只与平台架构有关。32位为4字节,64位为8字节。
指针的类型决定了从起始地址向后读取的字节数。
与指针本身存储空间无关。
同时类型也决定了对指针的加减1时,加减的字节数。

    int a = 2000000000;
    int * p = &a;
    printf("p = %p\n", p);
    printf("p = %p\n", p+1);
    /*
    p = 0x7fffffffe50c
    p+1 = 0x7fffffffe510 增加了4字节
    */
    int a = 2000000000;
    short * p = &a;
    printf("p = %p\n", p);
    printf("p = %p\n", p+1);
    /*
    p = 0x7fffffffe50c
    p+1 = 0x7fffffffe50e  增加了2字节
    */

int *p;
*p = 1000;  //野指针

没有指向一个有效地址空间的指针,称为野指针

int *p;
int a = 20;
p = &a;

指针应该被赋予一个其他变量的地址。

稍微难一点

泛型指针

可以接收任意一种指针类型,但是使用时必须转换。

void * p;
int a = 4;
p = &a;
printf("%d", *((int *)p)); //不转换会报错

数组与指针

数组名是地址常量——不可修改。

int a[] = {1,2,3,4};
int b[4]; 
b = a; // Wrong!
int * p = a ;// Right!

指针和数组名等价

int a = {1,2,3,4,5,6,7};
int size = sizeof(a) / sizeof(a[0]);
int * p = a;

for (int i = 0; i < size; i++)
{
    printf("%d", a[i]);
    printf("%d", *(a+i));
    //a[i] == *(a+i)
    printf("%d", p[i]);
    printf("%d", *(p+i));
    //p[i] == *(p+i)
    
}

Const修饰

const int *p  //可以修改 p 不可以修改 *p
int const *p  //同上
int * const p //可以修改*p 不可以修改p
const int * const p   //都不可修改

const向右修饰,被修饰的部分为只读。
函数形参内常用,用来限制指针对应内存空间为只读。

指针的自增

p++ == (p = p + 1)

int arr[10] = {1,2,3,4,5,6,7,8,9,0};
printf("%p", &arr+1); //加过整个数组的大小

感觉这种比较容易玩砸,万一循环多一次啥的。。。

其他

当给函数传参的时候:

int fun(int arr[])
int fun(int * arr)

等价。


给函数传入一个数组,数组的长度信息会丢失,因为本质上来说是传入了数组的首地址。

参考

stackoverflow

Avatar photo 心有所向,日复一日,必有精进。 Twitter Tweet