可以创建匿名的非const char数组吗?

时间:2016-09-19 00:30:13

标签: c++ arrays char const

我正在使用其STL中没有std::to_string(...)的旧C ++编译器。我想将整数字符串化,所以我认为我已经被char* itoa (int value, char* str, int base)困住了。我想避免创建一个名为char[]的用作itoa()的第二个参数。可以这样做吗?

我知道我能做到

itoa(5, "abcd", 10)

但这实际上是错误的,因为" abcd"实际上是一个const char[],我怀疑最终的行为最多是未定义的。当然,抛弃常量是不可接受的。

有没有办法将参数列表中的匿名非const char []传递给函数?我在各种尝试中使用了语法,但无法想出任何东西。我在网上看了很多,包括StackOverflow,并没有遇到任何覆盖这个问题的Q& A。

感谢您的指导。

更新

我在原帖中忽略了:我还需要char []在堆栈上,即new ing / malloc一个char []不是一个选项这个练习。

更新2:

我已经收到了一些上下文请求,所以这里有:

重申:我坚持使用不支持std::to_string(...)的旧编译器

我希望这样做:

std::string foo(std::string(itoa(42, < *** non-const stack-allocated char[] *** > , 10)))

即。我真正想做的就是构造一个带有整数字符串化的std::string

为什么呢?好的,更多的背景:

我试图创建一个命名信号量,并将其命名为pid。所以这个电话理论上看起来像是:

sem_open(std::string(typeinfo(*this).name()).append(std::string(itoa(getpid(), < *** non-const stack-allocated char[] *** >, 10))))

我为什么要这样做?

  

在我看来,这可能是错过森林树木的情况

也许。这部分是学术练习,我只是想知道它是否在C ++语法中执行此操作。但除此之外,通过避免堆分配有一个代码卫生元素:我可能会忘记在我的析构函数中delete[] char。而且,我的假设char[]的生命周期实际上只需要用于创建信号量。难道从语法上保证它只能在需要的时间内存活吗?这就是RAII毕竟是什么,所以最终这个问题是RAII是否可以针对这种特定情况实施。

再次感谢您的回答和评论。

更新3

谢谢大家的回答。我认识并理解所给出的答案,但我希望找到一个也避免包装函数的答案。这是我的疏忽,我在最初的问题中没有提到这一点。这个问题可能从一开始就措辞得很厉害;我应该首先揭示上下文是为了创建一个信号量,这可能也引导了评论者的不同。我试图简洁而准确地表达我的问题,但我试图简化问题陈述最终留下了相关的背景;抱歉...

但是,我已经对自己做了一个不敬虔的回答。我可能已经正式潜入IOCCC领域,但是:

sem_open(std::string(typeinfo(*this).name()).append(static_cast<std::ostringstream&>(std::ostringstream() << getpid()).str().c_str()))

4 个答案:

答案 0 :(得分:3)

在我看来,这可能是错过森林树木的情况。

据我了解你的问题,你正在尝试实现std::to_string的替换,因为你的编译器没有它。

并且您希望将其用于简单int转换的用例。

让你的包装函数充分调整std::vector<char>,将其用于转换的char *缓冲区,然后从缓冲区构造一个std::string,替换函数返回。

而且,对于纯C ++解决方案:

std::string int_to_string(int n)
{
    std::ostringstream o;

    o << n;

    return o.str();
}

答案 1 :(得分:2)

您不能获取匿名临时地址并将其保持活动状态,但可能存在一些涉及命名引用的黑客,但这些不适用于数组。

因此,您基本上需要使用命名数组。但是,您可以将其包装在 function 调用中,无论如何都会返回std::string

std::string my_to_string(int val, int base)
{
    /* Big enough buffer for base=2. */
    char buf[sizeof(int) * CHAR_BIT + 1];
    (void)itoa(val, buf, base);
    return buf;
}

答案 2 :(得分:1)

您可以动态分配字符串。

char *result = itoa(5, new char[5], 10);

但是你必须记得使用:

delete[] result;

答案 3 :(得分:0)

由于您需要避免动态分配,因此您无法使用std::string,除非您确定所有相关编译器都使用短缓冲区优化,并且对于所有相关编译器而言,固定缓冲区足够大所有可能的用例。但是,我们只能说,你不能使用std::string

然后创建基于堆栈的缓冲区很容易。 std::numeric_limits<int>告诉您最大小数位数。但是,由于您使用的是较旧的编译器,因此它可能不支持constexpr。因此,只需使用<limits.h>中的静态已知值进行计算。添加1表示符号,您有最大字符数。添加1表示零终止,并且缓冲区大小为N.

现在创建一个类Stringified,其内部缓冲区为N char,构造函数将int(可能还有一个基数)作为参数。

您可以使用该类创建临时(它持续到完整表达式的结尾)或创建变量,在两种情况下都完全基于堆栈,例如像这样:

#include <stdio.h>
//#include <limits>
#include <limits.h>
#include <stdexcept>
#include <string>

bool hopefully( bool const condition ) { return condition; }
bool fail( std::string const& s ) { throw std::runtime_error( s ); }

int const n_digits_of_int =
    //std::numeric_limits<int>::digits10() + 1;
    1+ 3*CHAR_BIT*sizeof( int )/10;

class Stringified
{
private:
    enum{ buffer_size = n_digits_of_int + 2 };
    char    buffer[buffer_size];
public:
    char const* c_str() const { return buffer; }

    explicit Stringified( int const value )
    {
        int const n_chars = sprintf( buffer, "%d", value );
        hopefully( n_chars > 0 )
            || fail( "Stringified::<init>: failed to convert value" );
    }
};

int main()
{
    printf( "%s\n", Stringified( 42 ).c_str() );
}