C++复合类型的使用:void*指针,bool变量与指针,指针数组与数组指针,C风格字符串的处理,多维数组的多种遍历方式

目录

Void类型的指针

Void指针的重要性质

Void*的用法

神奇的bool型变量

指针的隐式转换

指针的显式转换

如何创建指针的引用?

指针的引用与引用的指针

代码示例

数组指针与指针数组的区别

区别说明

代码示例

C风格字符数组的操作

C风格字符串处理函数简介

代码示例

轻松访问数组的开头与结尾

易错点解析

代码示例

For函数的新用法

For函数中参数的不同类型

代码示例

多维数组

多维数组简介

三种多维数组遍历方式

重点:指针遍历解析

重点:为何for新用法遍历中会出现“int (&row)[4]而不是int row[4]”?


Void类型的指针

Void指针的重要性质

① void*可以通过static_cast转化为其他任何类型的指针;

② void*类型的指针不可以使用解引用运算符*使其指向对应的内存;

③ void*类型的指针虽然可以和非void指针相互强制类型转换,但是最好不要从void*转化为非void指针。

Void*的用法

// C++复合类型.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。  
//  
  
#include <iostream>  
#include <string>  
using namespace std;  
  
void ShowInf(void* Data)  
{  
    const char* StringData = static_cast<const char*>(Data);  
    cout << StringData << endl;  
}  
                                                            
int main()  
{  
    string Name{ "45s4a54ad" };  
    ShowInf((void*)Name.c_str()); // 用void*作为形参进行参数传递  
  
    int var = 9;  
    void* ptr = &var;  
    //cout << *ptr << endl; //不可以对于void*类型的指针使用解引用操作  
    //ptr++; //不可以进行指针的偏移  
    cout << static_cast<int*>(ptr) << endl; // 强制类型转换(但这样不太安全)  
}  

神奇的bool型变量

当bool型变量用于指针时,可以判断指针是否非空。

指针的隐式转换

#include <iostream>  
using namespace std;  
  
int main()  
{  
    void* ptr = nullptr;  
    if (ptr) // 此时ptr隐式转换为布尔型变量,即true/false  
    {  
        cout << "指针为空" << endl;  
    }  
}  

指针的显式转换

#include <iostream>  
using namespace std;  
  
int main()  
{  
    void* ptr = nullptr;   
    bool trueorfalse = ptr;  
    if (trueorfalse) // 此时ptr转化为了布尔型变量,即true/false  
    {  
        cout << "指针为空" << endl;  
    }  
}  

如何创建指针的引用?

指针的引用与引用的指针

我们要明确两点:

① 指针指向的是一个内存区域;

② 引用是不分配内存的,变量的引用就相当于生成一个该变量的别名。

因此,存在指针的引用,但是不存在引用的指针(引用没有内存区域,指针无从下手)。

代码示例

#include <iostream>  
using namespace std;  
  
int main()  
{  
    int var = 10;  
    int* ptr = &var;  
    int* &ptr1{ ptr }; // 指针的引用  
    cout << *ptr1 - *ptr << endl;  
}

  

数组指针与指针数组的区别

区别说明

指针数组指的是数组内部的元素全为指针型变量;

数组指针指的是指向特定形式数组的指针。

代码示例

#include <iostream>  
using namespace std;  
  
int main()  
{  
    int *arr[10] = { nullptr };  
    int(*arr1)[10]; // 必须指向有10个元素的数组  
    int arr2[10] = { 0 }, arr3[3] = { 0 };  
    //arr1 = &arr3; // 指向的数组不符合要求  
    arr1 = &arr2; // 指向的数组符合要求  
} 

​​​​​​​ 

C风格字符数组的操作

C风格字符串处理函数简介

函数调用格式

函数功能

Int Strcmp(const char* var1, const char* var2)

比较字符型数组var1与var2

Const char* Strchr(const char* var1, const char var2)

在var1中查找特定字符var2并返回地址

Char* Strcpy(char* var1, const char* var2)

将var2拷贝至var1中并返回拷贝后的var2

Char* Strcat(char* var1, const char* var2)

将var2连接至var1中并返回连接后的var1

代码示例

#include <iostream>  
using namespace std;  
  
int main()  
{  
    const char name1[] = "sasasa", name2[] = "suaisais";  
    char name3[30], *CharPlace; // C风格字符串的劣势就在于"必须预留充分的空间供后续字符串操作使用"  
    int StringLength;  
    bool Comp;  
    strcpy(name3, name1); // 将name1复制到name3当中  
    cout << "拷贝后name3为" << name3 << endl;  
    strcat(name3, name2); // 将name2拼接至name3之后  
    cout << "拼接后的name3为" << name3 << endl;  
    StringLength = strlen(name3);  
    cout << "name3的长度为" << endl;  
    Comp = strcmp(name2, name1); // name2与name1比较  
    cout << "name2与name1谁更大:" << Comp << endl;  
    CharPlace = const_cast<char*>(strchr(name2, 's')); // 找出第一个s字符出现的位置并且返回指针地址  
    cout << "name2中第一个's'的相对地址为" << CharPlace - name2 + 1 << endl;  
}  

轻松访问数组的开头与结尾

易错点解析

Begin(数组首地址) 返回数组的第一个元素的地址

End(数组首地址) 返回数组最后一个元素地址的后一个地址

代码示例

#include <iostream>  
using namespace std;  
  
int main()  
{  
    int arr[5] = { 0,1,2,3,4 };  
    cout <<"数组的首元素为"<< *begin(arr) << endl;  
    cout << "数组的末尾元素为" << *(end(arr) - 1) << endl;  
}  

For函数的新用法

For函数中参数的不同类型

For(DataType var: 数组首地址arr)

数组元素采用值传递的方式将值传递给var

For(DataType &var: 数组首地址arr)

var变量是数组arr中元素的引用

代码示例

#include <iostream>  
using namespace std;  
  
int main()  
{  
    int arr[] = { 0,1,2,3,4,5 };  
    for (int var: arr) // 从begin(arr)遍历到end(arr)-1  
    {  
        cout << var << endl;  
    }  
}

​​​​​​​  

多维数组

多维数组简介

所谓所谓数组只不过是多个一维数组的组合,多维数组最大的难点就在于数组的遍历,这里给出三种数组遍历方式:指针遍历,引用遍历,for新用法遍历。

三种多维数组遍历方式

#include <iostream>  
using namespace std;  
  
int main()  
{  
    int arr[][4] = { 1,2,3,4,5,6,7,8 };  
  
    // 引用遍历  
    int(&arr2)[4] = arr[0]; // 使用引用的方式遍历第一行元素  
    for (int& var: arr2)  
    {  
        cout << var << endl;  
    }  
      
    // 指针遍历  
    int (*ptr)[4] = arr;  
    for (; ptr != arr+2; ptr++) // 行遍历  
    {  
        int* ptr1 = *ptr;  
        for (; ptr1 != (*ptr) + 4; ptr1++) // 列遍历  
        {  
            cout << *ptr1 << endl;  
        }  
    }  
  
    // for新用法  
    int(&row)[4] = arr[0];  
    for (int (&row)[4]: arr) // 行循环  
    {  
        for (int var: row) // 列循环  
        {  
            cout << var << endl;  
        }  
    }  
}  

重点:指针遍历解析

Int (*Ptr)[4] 定义了一个只能指向4个整形元素的数组指针,最外层的for循环是行循环每次++移动4个int变量占用的内存空间,最里层for循环为列循环在每行地址的基础上每次++一个int变量占用的空间。

重点:为何for新用法遍历中会出现“int (&row)[4]而不是int row[4]”?

因为我们知道静态数组不可以进行一次性赋值操作,因此我们用int &row[4]来引用arr数组的每一行,在在此基础上访问每一行的每一列元素。

猜你喜欢

转载自blog.csdn.net/weixin_45590473/article/details/108539541