【问题标题】:assigning c++ array to pointer将 c++ 数组分配给指针
【发布时间】:2020-07-14 14:10:13
【问题描述】:

在这段代码中,我们创建了一个 const char 指针 id,因为它是一个 char,所以它应该只存储一个元素地址。但是在默认构造函数中,我们为该 id 分配了“NULL”,该 id 是如何保存 4 个字符的? 在参数化构造函数中,我们传递 i[] 数组并将值分配给 id,同样 char id 是如何保存完整数组的? 进一步为什么我们需要 const char?

class Employee
{
    public:
        string name;
        const char *id;
        int age;
        long salary;

        Employee ()
        {
            name = "NULL";
            id = "NULL";
            age =0;
            salary = 0;
        };

        // Employee(string n, char id[], int a, long s): name(n), id(id), age(a), salary(s)
        // {};
        Employee (string n,const char i[], int a, long s)    //const use krne k baighar warning a rhe
        {
            name = n;
            id = i;
            age = a;
            salary = s;
        };
        void getData()
        {
            cout<< "Employee ID: "<< id <<endl;
            cout<< "Employee Name: "<< name <<endl;
            cout<< "Employee Age: "<< age <<endl;
            cout<< "Employee Salary: "<< salary <<endl;
        };

};

我很困惑,如果 id 是 char 那么它是如何保存 5 个字符的字符串文字的。 CHAR 类型只能存储单个字符,但如果我将其设为指针,则它包含多个字符。请清除这一点,我很困惑它是如何工作的。

【问题讨论】:

  • id 是一个指针,它唯一“持有”的是一个对象的地址——它并不“持有”整个数组
  • 你怎么知道它有多少个字符?
  • 如果您将std::string 用于name,为什么idchar *
  • 是的,它有趣的。在 C 和 C++ 中,指向单个字符的指针也用于指向整个数组中的第一个(或任何一个!)字符。从语言上无法断定是哪一个,你得看代码和文档。如果使用指针指向数组中的第一个元素,通常会有一个长度,因为没有其他通用方法可以知道在第一个元素后面存储了多少元素。 (对于可打印字符,我们可以(标准库函数也可以)查找终止的零字节,但对于二进制数据则失败。)
  • @drescherjm 请注意,id 本身不是 const,它指向 const。您可以更改它在程序中指向的内容。事实上,如果它是 const ,即使在构造函数中也不能赋值;你必须初始化它。顺便说一句,它指向 const 并不妨碍您分配非常量字符(数组)的地址!它只是表明它所指向的内容的内容不会被类更改。

标签: c++ arrays pointers


【解决方案1】:

字符串文字"NULL" 是一个由 5 个chars 组成的数组(第五个是表示字符串结束的空字符)。 C++ 中的数组在内存中按顺序排列。这意味着如果你有一个指向数组的第一个元素的指针,你可以使用简单的算术找到后面的元素。

因此,C++ 中的数组可以隐式转换为指向其第一个元素的指针。当您编写id = "NULL" 时,id 将被分配为指向该 5 个字符数组的第一个字符("NULL" 开头的'N')。您的对象将在内存中布局如下:

Employee
+--------+
| name   |
|        |
+--------+
| id     |
|    +----------+
+--------+      |
| age    |      v
|        |    +-+-+---+---+---+----+
+--------+    | N | U | L | L | \0 |
| salary |    +---+---+---+---+----+
|        |
+--------+

由于其余字符在内存中是按顺序排列的,因此您只需在存储在id 中的地址上添加一个字节即可找到'U',然后通过添加两个字节等方式找到第一个'L'。您可以继续添加一个,直到找到一个 '\0' 字符,这表示您已到达字符串的末尾。

【讨论】:

  • 因为我们没有明确地增加指针。编译器会隐含地这样做以指向下一个字符,直到 '\0' 到达?
  • 适用于 C 风格字符串的字符串操作函数(例如 strcpycout&lt;&lt; 运算符重载 const char*)在内部完成。
【解决方案2】:

这是因为编译器被告知分配一个 const char 并指向一个长度为 5 的 char 数组类型的对象(因为 NULL 的长度为 4,不包括空终止符)并且它被初始化为字符串文字。

在取消引用之前一切都很好。当你这样做时,你只会得到N char 打印,而不是完整的字符串。但是它们连续存储在内存中,因此它们会被打印,直到字符串文字 \0 的空终止符出现在 std::cout 中,以终止之后读取字符串。

另外,请注意,一旦它们被指向,您就无法更改它们的值,它们不再是可替换的。


当您可以简单地使用 std::string 在 C++ 中广泛处理这些字符串时,您不需要使用 const char *

【讨论】:

  • Err... "NULL" 是一个由 5 个字符组成的数组,违反直觉。它也不同于NULL(在某些系统上可能已定义并且大小为 4 字节)。
  • @Peter-ReinstateMonica 哦,是的,错误现已修复,谢谢!
  • "length of 4 including null-terminator" 比以前更糟——要么是 5 包括空终止符,要么是 4 不包括空终止符;-)。
  • @RohanBari char* 可以保存任意长度的 char[] 或字符串的地址吗?然后按顺序保存该字符串或数组中所有字符的地址?
  • @LittleStar 几乎相似,但 std::stringchar * 是不同的东西。 char *可以容纳char[]任意长度的地址是对的。
猜你喜欢
  • 1970-01-01
  • 2018-10-06
  • 1970-01-01
  • 2011-04-02
  • 1970-01-01
  • 1970-01-01
  • 2019-05-18
  • 2021-11-29
  • 2015-07-05
相关资源
最近更新 更多