c语言指针

1.取地址符&

  &用来取变量的地址

  输出变量的地址的时候使用:

    printf("%p",a)      //虽然有时候print("%d",&a)也能输出地址,但是这可能不是真正的a的地址,假如地址用8个字节表示,%d输出会默认向int类型转换,导致前面一部分数据丢失。

  &只能对变量操作,下面这些都是错误的:

    &(a+b)

    & (a++)

  对于数组  int a[50]

  &a=a=&a[0],数组a的地址连续分配,假如a[0]是 0000 0000,则a是 0000 0004

  

  在一个程序中,分配两个变量的时候,地址是从高到低分配的,因为这些变量存储在堆栈中,而堆栈是从上到下分配地址,例如

  int a,b;

  printf("%p     %p",a,b)    // 0001 0004       0001 0000

2.指针

  指针就是保存地址的变量,前面提到过%d输出地址的时候可能会导致部分数据丢失,而指针就不会。

  声明一个指针: 变量类型 *p 或者 变量类型* p  //注意*是修饰p的,而不是修饰变量类型的

  int *p,q  //表示声明了一个指针q和一个int型变量q

  int* p,q  //同上

3. * 作为单目运算符

  *p 作为单目运算符的时候表示取地址p指向的内容

  *p =26     可以通过这种方式改变指针p指向的变量的内容

  & 和 * 是两种相反的运算符,一个取地址,一个取地址所指向的变量的值

4. scanf("%d",i)

  编译的时候可能不会报错,因为某些电脑是32位的,地址就是32位的,跟int型变量的长度可能一样,因此scanf函数会把i的值当作地址,但是运行的时候就很可能出错了,因为i的值一般不大,而低地址在内存中往往是操作系统或者其他程序使用的。

5.指针的使用场景

  -swap交换两个变量的值

  -传给函数的参数实际是需要带回结果的变量,这样的返回值有多个,而函数return 语句只能返回一个变量

  -函数返回运算状态(成功/失败),指针返回运算结果。通常0表示成功,-1表示失败,当结果也可能取到-1/0时,就必须用指针返回,return 返回成功/失败的结果

  -当传递很大的数组或者结构体的时候,可以使用指针传递,当希望这些数组或者结构体不被修改的时候,可以使用 fun(int const * p)或者fun(const int a[])(这种只适用于数组)

6.指针最常见的错误

  -定义指针之后没有赋值就直接使用 ,即指针需要赋值之后才能使用 *指针 来读取指针所指向的变量,因为假如不初始化赋值指针,指针所在的内存单元存的值是未初始化的(随机的),因此指针指向的内存单元是未知的,运行的时候很有可能出错。

7.传入函数的数组的本质

  函数参数表中的数组实际是指针

  fun(int a[])、fun(int *a)、fun(int *)以及fun(int [])四种函数原型是等价的

  在函数fun里面使用sizeof(a)其实是指针变量的size,这里也就是8字节的长度,我的电脑是64位的。只有在main函数里面使用sizeof,才表示数组的长度x数据类型的长度

  int b[] =a    //a是数组,这里是非法的,因为int b[] 等价于 int * const b,即数组一旦创建,其地址是无法改变的,因为地址要分配一段连续的内存,如果改变,无法保证改变后的地址后续连续的地址可以使用。

8.指针与const    //这里的内容只适用于C99

  int * const p=&a;

  *p=26;  //OK

  p++;  //Error,这种情况是不能修改指针变量的值的

  const int *p=&a;

  *p=26;  //Error,这种情况是不能通过p修改a的,但是a可以修改

  a=26;  //OK

  p=&b;  //OK

  总结:判断哪个不能修改是看const是在*前面还是后面,如果在前面,表示不能通过指针修改变量的值,如果在后面表示不能修改指针,因此 int const * p 和const  int * p等价

9.const 数组

  const int a[5]={1,2,3,4,5}  //表示数组里面的每一个值都不能改变,而且数组必须通过这种初始化来赋值

原文地址:https://www.cnblogs.com/foodie-nils/p/13159348.html