【问题标题】:Why am I unable to cout a dereferenced char pointer?为什么我无法计算出取消引用的 char 指针?
【发布时间】:2020-04-21 01:16:36
【问题描述】:

当我尝试运行以下代码时,我没有收到任何错误或警告,但我的终端总是崩溃。为什么会这样,我该如何解决?

main.cpp

#include <iostream>
#include <cstdio>
#include "colours.hpp"

using namespace std;

int main()
{
    colour co(50,65,78);
    unsigned char *cp = co.getRGB();
    cout << *cp << endl;
    getchar();
    return 0;
}

colors.hpp

#ifndef COLOURS
#define COLOURS

class colour{
    public:
        colour(unsigned char r, unsigned char g, unsigned char b);
        unsigned char *getRGB();
    private:
        unsigned char red, green, blue;
};

#endif // COLOURS

colors.cpp

#include "colours.hpp"

colour::colour(unsigned char r, unsigned char g, unsigned char b) : red(r), green(g), blue(b) {
}

unsigned char *colour::getRGB(){
    unsigned char arr[3] = {red, green, blue};
    return arr;
}

【问题讨论】:

  • getRGB 中返回一个指向局部变量的指针,该变量在函数返回时被销毁
  • @M.M 哦,我明白了,arr[] 不在范围内。但如果不是错误,我的编译器至少不会发出警告吗?
  • 语言标准不需要针对这种情况发出警告,由各个编译器发出警告。有些人会。 Example
  • @MM 我明白了;我将 CodeBlocks 与 GCC 一起使用。为什么标准没有为此提供一些东西,因为我想不出一个可行的实例?
  • GCC 也会发出此警告,因此请考虑更改警告标志或升级编译器版本(默认情况下,代码块带有糟糕的 gcc 构建)。即使早在 gcc 4.1,我也看到没有额外标志的警告,也许有警告但你没有找对地方?

标签: c++ arrays char cout dereference


【解决方案1】:

您已在以下函数的堆栈中本地定义了一个数组:

unsigned char *colour::getRGB(){
    unsigned char arr[3] = {red, green, blue};
    return arr;
}

当函数返回时,堆栈递减并且数组不再有效(指向数组的指针也是如此)。这就是取消引用指针时程序崩溃的原因。

要解决此问题,您可以使用数组作为颜色,因为您在编译时就知道大小。

std::array<unsigned char, 3> colour::getRGB(){
    std::array<unsigned char, 3> color = {red, green, blue};
    return color;
}

另一种选择是在堆上分配,而不是在堆栈上,

unsigned char* colour::getRGB() {
    int size = sizeof(unsigned char) * 3;  // Get the size of 3 unsigned chars.
    unsigned char* color = (unsigned char*) malloc(size);
    color[0] = red;
    color[1] = green;
    color[2] = blue;

    return color;
}

这种方法有一些缺点。首先,您必须记住在完成后释放分配的内存。

colour a = colour(255, 0, 255);
unsigned char* rgb = a.getRGB();
// ---- DO STUFF ---
free(rgb);

其次,它很慢。以这种方式动态分配内存需要向操作系统请求更多内存,这需要一些时间。

第三,因为我们已经知道我们想要 3 个无符号字符,所以没有必要动态分配。这样做消除了编译器进行静态分析和优化代码的可能性。

【讨论】:

  • 这里也是std::tuple 的一个案例,以及一个typedef 来制作RGB 类型。
  • 我想我可以走的另一条路线是void colour::getRGB(unsigned char *cp){ *cp = red; *(cp+1) = green; *(cp+2) = blue;}。您的解决方案非常适合返回类型,这是理想的。
  • @thepufferfish 是的,这是另一种选择。但是,由于 RGB 始终是 3 个无符号字符,我建议您使用 C 或 C++ 静态类型检查来避免错误(并获得一些速度)。使用数组、元组或创建结构来保存值。
  • 我必须要问,为什么有小于大于符号用作括号?我想不出以前见过这样的东西。
  • @thepufferfish 这是一个模板参数。 C++ 引入了元编程和新语法。它允许您在编译时动态修改类定义。 std::array 类需要知道它应该包含什么类型以及它有多大,所以我们通过尖括号将它们传递给类。这允许编译器在构建程序时进行优化和类型检查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-23
  • 2014-03-30
相关资源
最近更新 更多