C语言基础(四)(指针)

来源:互联网 发布:linux编写shell程序 编辑:程序博客网 时间:2024/05/29 18:04

一、指针基础

1、定义、绑定、和解引用

  • 定义一个指针变量p,类型是int* ,指向一个int型的数据 :
int *p = NULL;///NULL代表指向空,即什么都不指向,等同于int类型的0;避免野指针。
  • 绑定一个int型变量a:
int a = 0;int *p = &a;//指针变量内存储的是地址,故绑定非地址变量时需要使用取地址符号&
  • 指针的解引用
int a = 0;int *p = &a;*p = 6;     ///将p指向的地址,即a的值赋值为6。*为解引用符号。

2、指针的相减

  • 1、指针变量只能相减,不能加乘除。
  • 2、两指针变量相减,结果为int类型,数值为两指针指向的地址之差除以sizeof(变量类型),变量类型为指针所指向的数据的类型。
  • 3、若相减的两指针在同一数组中,贼相减的结果 == 两指针指向的元素的下标之差。

3、野指针

  • 野指针的危害(从低到高):
    1、直接指向内核区,即当前进程所使用的区域,可以随意修改。
    2、指向可用也没有别的数据的区域 。
    3、最严重,可用但有别的数据 ,会修改其他正在运行中的进程的数据。

在定义一个野指针时随机发生以上情况的其中一种,所以在编程中,野指针应尽量避免

二、指针的应用

1、指针函数

#include<stdio.h> void func(unsigned  short *a);int main(void) {    unsigned  short a = 0x11ff;    func(&a);    printf ("%x\n", a);} void func(unsigned  short *a)//在传输参数时,传来的是指针,即a的地址,所以在子函数中,*a的运算改变的是a所指向的地址的值,故可以影响到主函数的值(可以直接对数组进行赋值也是一个道理)。{    unsigned  short b = *a;    *a = *a << 8;    b = b >> 8;    *a += b;} 

2、函数指针

#include<stdio.h> void func(unsigned  short *a);int main(void) {    unsigned  short a = 0x11ff;    void (*p)(unsigned  short *a) = &func;//&func 或 func都可以。    (*p)(&a);                          //(*p)(&a) 或 p(&a)都可以。    printf ("%x\n", a);} void func(unsigned  short *a){    unsigned  short b = *a;    *a = *a << 8;    b = b >> 8;    *a += b;} 

3、指针数组

  • 即定义一个数组,该数组的每一个元素都是一个指针。
#include<stdio.h> int main(void) {    int arr[5] = {1, 2, 3, 4, 5}, i = 0;    int *p_arr[5] = {};  ///指针数组。    for (i=0; i<5; i++)        p_arr[i] = &arr[i];    printf("%d.\n", *p_arr[2]);} 

4、数组指针

  • 定义一个指针,该指针指向的数据是一个数组型的数据。(即自加一会越过整个数组)
#include<stdio.h> int main(void) {    int arr[2][3] = {1, 2, 3, 4, 5, 6};    int (*p)[3] = &arr[0] + 1; ///数组指针    printf("%d.\n", **p);     //输出为a[1][0]的值:4} 

三、相关命令

1、malloc函数

  • 头文件: #include <stdlib.h>
  • 命令格式:int *p = (int *p)malloc(数字)//申请时默认返回void *
  • 堆内存也是内存的一种,需要程序员自己手动申请malloc,手动释放 。
    编译器不会自动回收,申请的内存伴随整个程序 。
    malloc申请的空间,默认是有最小分配的。
    流程:申请,判断成功,初始化,使用,释放,指针设置为空 。

2、typedef

  • typedef的作用是定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。
  • typedef可以在全局定义,也可以在函数中定义。
typedef int my_int//将int重命名为my_int typedef char * my_char_p//将char *重命名为my_char_p typedef (void (*p)(void)) my_func//将void * void 类型的函数重命名为my_func 

3、const 关键字

  • const 修饰的变量是常数,不可更改,只能初始化一次;但可以用指针解引用修改。
#include <stdio.h>void main(void){        const int a = 0;        a = 3;           //错误,不可以直接修改内容        int *p = &a;        *p = 2;          //正确,可以通过指针更改内容        printf ("%d", a);        return;}  

四、二维数组

  • 定义:
int a[2][3];   //代表定义一个int型的二行三列的数组。
  • 二维数组的变量名是首元素首地址{arr[0], arr[1]}
  • &arr代表第一维数组的首地址。
  • &arr[0]、arr 代表第一维数组的首元素首地址,第二维数组的首地址。
  • &arr[0][0]、arr[0] 代表数组的第二维数组是首元素首地址。

五、二重指针

  • 二重指针指向的是一重指针的地址,一重指针不能指向一重指针的地址。
  • 二重指针的使用:
#include <stdio.h>void func (int **p);void main (void){    int **q = NULL, *p = NULL;    int a = 11;    p = &a;    q = &p;    func (q);    printf("*p = %d\n", *p);   // *p = 22     printf("**q = %d\n", **q); // **q = 0}void func (int **p){    int a = 22;    *p = &a;}
原创粉丝点击