char数组 和 char* 之间的关系

基础知识

char e[] = "question" 是一个包含 9 个字符的char类型数组

char* pe 是一个 char* 类型的指针

当对数组名e进行取地址操作时(即&e),会得到一个char(*)[9]的数组指针

当把这个数组指针(char(*)[9])赋值给 char* 类型的单个字符指针时,由于类型不匹配会出现报错

正确写法应该是将数组名 e 赋值给 char*pe ,即 char* pe = e;

  • 代码:
#include <iostream>
using namespace std;

int main(){
    char e[] = "question";
    char* pe = &e;

    cout << pe << endl;


    return 0;
}
  • 运行:
    报错,报错类型为类型不匹配
  • 修改:
     #include <iostream>
    using namespace std;
    
    int main(){
        char e[] = "question";
        char* pe = e;
    
        cout << pe << endl;
    
    
        return 0;
    }
    
  • 运行:
    question 因为 cout 会对 char* 类型做字符串处理

 

char 数组名、指针、数组首元素地址的关系

pe ≡ e ≡ &e[0],其中这三个输出的数值相同(均为question),类型有差异。

pe:是个 char* 指针,存着 e 数组开头的地址。

&e[0]:明确取了 e 数组第一个元素的地址,类型也是 char*

e(单独用作表达式):它本质上是 char[9] 数组。但当 cout 要打印它时,e自动变成 char* (指向 e[0])。

cout 看到 pee&e[0] 时,它们在 cout 眼里都暂时是 char*,所以都按字符串来打印(输出结果:question)。但只有 e原始类型是数组。

  • 代码:
    #include <iostream>
    using namespace std;
    
    int main(){
        char e[] = "question";
    
        char* pe = e;
    
        cout << pe << endl;
        cout << e << endl;
        cout << &e[0] << endl;
    
    
        return 0;
    }
    
  • 运行:
    question question question

 

char*的解引用与访问char数组首元素的不同方式

char*类型指针名解引用、char数组名解引用、数组首元素取地址并解引用、数组首元素,这些输出的结果和类型都相同(均为char类型数值)

  • 代码
    #include <iostream>
    using namespace std;
    
    int main(){
        char e[] = "question";
        char* p = e;
    
        cout << *p << endl;
        cout << *e << endl;
        cout << e[0] << endl;
        cout << *(&e[0]) << endl;
    
        return 0;
    }
    
  • 运行
    q
    q
    q
    q

 

sizeof() 运算符与数组大小

sizeof(e):返回整个数组的大小,char e[] = "question";,返回的结果是 9

"question" 这个字符串有 8 个字母。但 C++ 会自动在字符串末尾加一个空字符 \0 来表示结束。所以,'q', 'u', 'e', 's', 't', 'i', 'o', 'n', '\0' 一共是 9 个字符,每个 char 占 1 个字节,所以总大小就是 9 字节。

  • 代码:
#include <iostream>
using namespace std;

int main(){
    char e[] = "question";

    cout << sizeof(e) << endl;

    return 0;
}
  • 运行:
    9

 

&对数组名的作用

&e:返回整个数组的地址(类型为 char(*)[9]),意思是“指向一个包含 9 个 char 元素的数组的指针”。

  • 代码:
    #include <iostream>
    using namespace std;
    
    int main(){
        char e[] = "question";
    
        cout << &e << endl;
    
        return 0;
    }
    
  • 运行:
    输出该数组指针在内存中的地址,这是一个数组指针

 

char*char(*)[9] 运算偏移的差异

char*(如 pe*(pe + 1),移动 1 字节(指向 e[1])。

char(*)[9](如 &e&e + 1,移动 9 字节(指向下一个 char[9] 数组)。

  • 代码
    #include <iostream>
    using namespace std;
    
    int main(){
        char e[] = "question";
        char* pe = e;
    
        cout << *pe << endl;
        cout << *(pe+1) << endl;
    
        cout << &e << endl;
        cout << &e+1 << endl;
    
        return 0;
    }
    
  • 运行
    q
    u
    数组指针 e 的地址
    数组指针 e 偏移9个字节的地址

 

指针、数组名与首元素地址的关系

(void*)pe 输出的地址既是首元素 e[0] 的地址,也是数组 e 的起始地址(数值相同)。

cout 会对 char* 默认按字符串输出,所以需要强制转换为 void* 显示地址。其他指针类型(如 int* )默认输出地址。

  • 代码
    #include <iostream>
    using namespace std;
    
    int main(){
        char e[] = "question";
        char* pe = e;
    
        cout << (void*)pe << endl;
        cout << (void*)e << endl;
        cout << (void*)&e[0] << endl;
    
        return 0;
    }
    
  • 运行
    三个相同的地址

 

地址值相同类型不同

地址数值相同,类型不同pe&e[0]e&e 的地址值相同,但类型影响指针运算。

  • 代码

    #include <iostream>
    using namespace std;
    
    int main(){
        char e[] = "question";
        char* pe = e;
    
        cout << (void*)pe << endl;
        cout << (void*)e << endl;
        cout << (void*)&e[0] << endl;
        cout << &e << endl;
    
        return 0;
    }
    
  • 运行
    四个地址数值相同,但是指针类型不同

    前面三个 ((void*)pe(void*)e(void*)&e[0]) 都是void* 类型。

    &e 的类型是char(*)[9]

 

记忆技巧

数组名隐式转换指向数组首元素地址的指针:除了 sizeof 和 &数组名都是指向数组首元素地址的指针(存储的是首元素地址)。

cout对char* 特殊待遇cout 对char*按字符串处理,其他指针按地址处理

地址数值相同,类型不同:数组首元素、数组名取地址、数组名的地址值相同,但指针类型不同,会影响指针运算。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

( ̄▽ ̄).

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值