zoukankan      html  css  js  c++  java
  • 【C++】指针和函数

    指针和函数

    标签:c++


    一、基本概念

    定义:

    也称作“指针变量”,大小为4个字节,内容代表一个内存地址

    指针的定义及使用:

    • 定义:

      int *p;//指向的变量类型为整型
      char *pc;
      
    • 赋值:

      int *p = (int *) 4000;//强制类型转换,让p = 4000
      char ch1 = ‘A’;
      char *pc = &ch1;
      *pc = ‘B’;
      char ch2 = *pc;
      pc = &ch2;
      

      注:指针定义后就要赋值,防止变成野指针

    二、指针的相互赋值

    不同类型的指针相互赋值要强制类型转换

    int *pn;
    char *pc;
    char c = 0x65;//e
    pn = pc;//编译出错,类型不匹配
    pn = &c;//编译出错
    pn = (int *) &c;//可以,但是&c只代表一个字节,pn代表四个字节,此时pn会占用&c后面的三个字节,导致错误
    int n = *pn;//n中的内容不是0x65
    

    因此,不要用不同类型的指针相互赋值

    三、指针的运算

    比较大小:

    两个同类型的指针p1, p2,如果地址p1<地址p2,则p1<p2,其余同理

    相减:

    p1 – p2 = (地址1-地址2)/sizeof(T)

    T为指针的类型

    加减整数类型变量或者常量:

    p + n 等价于:地址p + n * sizeof( T )

    p - n 等价于:地址p - n * sizeof( T )

    自增自减:

    同3

    下标运算符[ ]:

    p[ n ]等价于 *( p + n )

    四、空指针

    空指针NULL,即为地址0

    可以做条件表达式使用

    五、指针作为函数参数

    • 传递指针的方式依然是指传递,注意函数是在对指针操作还是对指针所指的内容操作,即函数只能改变指针指向地址中的内容,不能改变指针本身

      #include<iostream>
      using namespace std;
      void Swap(int *p1, int *p2)
      {
          int temp = *p1;
          *p1 = *p2;
          *p2 = temp;
      }
      int main()
      {
          int m = 4, n = 3;
          Swap(&m, &n);
          cout<<m<<','<<n;
      }
      结果:3,4
      
    • 使用指针作为函数参数时,应先判断指针是否为空,避免野指针对函数造成影响

    • 返回一个指针时,也要注意返回非空指针

    六、指针和数组

    数组的名字即为一个指针,作为函数形参时,T *pT p[ ]完全等价

    七、常量指针和指针常量

    常量指针

    const T* p

    特点:不能通过常量指针修改指向的内容,即内容可以修改,但是要用其他方法

    指针常量

    T *const p = p0

    特点:定义之后指针p就不能指向其他位置,但是可以通过指针对其指向内容修改

    八、字符串和指针

    普通字符串和指针的关系

    字符串常量的类型就是char *,字符数组的类型也是char *

    char name[20];
    char *pName = name;
    

    string对象和char *指针的关系

    • 可以用char *类型指针对string对象赋值

    • string对象有成员函数:const char *c_str(),返回的是字符串指针

    • 如果s是一个string对象,对其执行 const char *p = s.c_str(),当s的内容改变时,p可能会失效,因为s的位置可能发生改变

      #include<iostream>
      #include<cstring>
      #include<string>
      using namespace std;
      int main()
      {
          string s;
          char str1[20] = "the flower of war";
          char str2[20] = "hhh";
          char *p = str1;
          s = p;
          cout<<"s:"<<s<<endl;
          strcat(str2, s.c_str());
          cout<<"str2:"<<str2<<endl;
          return 0;
      }
      

    常用字符串操作库函数

    cstring中声明:

    char *strcat(char *dest, const char *src),返回dest

    char *strchr(const char *src, int c),寻找csrc中第一次出现的位置,找到则返回位置指针,否则返回NULL

    int strcmp(const char *s1, const char *s2),比较大小

    char *strcpy(char *dest, const char *src),复制

    int strlen(const char *src),求长度

    char *strlwr(char *str),字母转小写

    char *strupr(char *str),字母转大写

    char *strncat(char *dest, const char *src, int n),连接前n个字符到dest

    类似有:strncpy, strncmp

    cstdlib中声明:

    atoi:字符串转整数

    atof:字符串转浮点数

    itoa:整数转字符串,char *itoa(int value, char *string, int radix)

    九、 void指针和内存操作库函数

    定义及特点:

    指针的类型为void *

    • 可以用任何类型的指针对其初始化
    • 主要用于内存复制
    • sizeof()及各种指针运算不适用于空指针

    库函数

    cstring中声明

    void *memset(void *dest, int ch, int n),将ch复制到destn个字节中

    void *memcpy(void *dest, void *src, int n),将src的开始n个字节复制到dest

    示例

    #include<iostream>
    using namespace std;
    void *myMemcpy(void *dest, const void *src, int n)
    {
        char *pDest = (char *)dest;//必须先将形参进行强制类型转换
        char *pSrc = (char *)src;
        for(int i = 0; i < n; ++i)
            *(pDest + i) = *(pSrc + i);
    
        return dest;
    }
    int main()
    {
        char szName[10] = "abcdsedf";
        char destName[10];
        myMemcpy(destName, szName,5);
        cout<<szName<<endl;
        for(int i = 0; i < 5; ++i)
            cout<<destName[i];
    }
    

    十、 函数指针

    定义:

    类型名 (*指针变量名)(参数类型1,参数类型2,……)

    赋值及调用:

    • 可以用一个原型匹配的函数的名字给一个函数指针赋值

    • 调用格式:函数指针名(实参表)

      #include<iostream>
      using namespace std;
      void PrintMin(int a, int b)
      {
          if(a < b)
              cout<<a;
          else
              cout<<b;
      }
      int main()
      {
          int x = 4, y = 1;
          void (*pf)(int ,int) = PrintMin;
          pf(x, y);
          return 0;
      }
      

    应用

    qsort()函数

    原型:void qsort(void *base, int nelem, unsigned int width, int (*pfCompare)(const void *, const void *))

    其中比较函数的原型:int 函数名(const void *elem1, const void *elem2)

    注意:

    • 返回值必须是int
    • 两个参数的类型必须都是const void *
    • 假设是对int排序的话,如果是升序,那么就是如果a比b大返回一个正值,小则负值,相等返回0,其他的依次类推
    #include<iostream>
    #include <cstdlib>
    using namespace std;
    
    //比较函数可以根据自己的需求写,其作用相当但不限于
    //使用sort()时的运算符重载
    int myCompare(const void *elem1, const void *elem2)
    {
       unsigned int *p1, *p2;
       p1 = (unsigned int *)elem1;
       p2 = (unsigned int *)elem2;
       return (*p1 % 10) - (*p2 % 10);
    }
    const int NUM = 5;
    int main()
    {
       unsigned int a[NUM] = {8,123,11,10,4};
       qsort(a, NUM, sizeof(unsigned int), myCompare);
       for(int i = 0; i < NUM; ++i)
           cout<<a[i]<<endl;
       return 0;
    }
    

    十一、 指针域动态内存分配

    使用方法:

    指针类型 *p = new 指针类型(int *p = new int)

    指针类型 *p = new 指针类型[空间大小](int *p = new int[N]),分配到N*sizeof(T)的空间

    注意

    • 分配空间失败时,系统会抛出异常
    • 动态分配的内存使用结束后要释放,方法为:delete 指针delete [ ] 指针
    • 释放一个指针后,不会使指针的值变为NULL

    十二、 二阶指针

    指向指针的指针,大小永远为4字节,对应多维数组

    十三、指针数组

    定义:

    T *a[N]

    数组中每个元素的类型是T *a的类型是T **

    示例:

    #include<iostream>
    using namespace std;
    int main()
    {
        char **p = NULL;
        char *countries[] = {"China","USA","Japan","France"};
        p = countries;
        for(int i = 0; i < 4; ++i)
            cout<<*(p + i)<<endl;
        cout<<*((*p) + 1);
    }
    
  • 相关阅读:
    Node.js 0.12: 正确发送HTTP POST请求
    pm2 常用命令
    IntelliJ IDEA Configuring projects
    socket.io入门整理教程
    幂等函数
    Linux 下 ps 命令
    Linux 下 tail 命令
    Linux下chmod命令
    Linux下ll命令与ls -l
    Thrift——初学
  • 原文地址:https://www.cnblogs.com/vinnson/p/13451350.html
Copyright © 2011-2022 走看看