可以创建匿名非const字符数组

Possible to create anonymous non-const char array?

本文关键字:const 字符 数组 创建      更新时间:2023-10-16

我正在使用一个较旧的c++编译器,它的STL中没有std::to_string(...)。我想对一个整数进行字符串化,所以我想我只能用char* itoa (int value, char* str, int base)了。我想避免创建一个名为char[]的参数,作为itoa()的第二个参数。这能做到吗?

我知道我可以做

itoa(5, "abcd", 10)

但这实际上是不正确的,因为"abcd"实际上是一个const char[],我怀疑所产生的行为充其量是未定义的。当然,抛弃常量是不可接受的。

是否有办法将参数列表中的匿名非const char[]传递给函数?我尝试了各种各样的语法,但什么也没得到。我在网上搜索了一下,包括StackOverflow,并没有遇到任何涵盖这一点的问题。

谢谢你的指导。

更新:

我忽略了在原来的帖子中提到:我还需要在堆栈上的char[],即new/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()))

在我看来,这可能是只见树木不见森林的情况。

正如我理解你的问题,你正试图实现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();
}

您不能获取匿名临时地址并使其保持活动,除非使用一些涉及命名引用的hack ,但这些不适用于数组。

基本上,你需要使用一个命名数组。但是,您可以将其包装在函数调用中,该函数无论如何都会返回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;
}

可以动态分配字符串

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

但是你必须记住使用:

delete[] result;

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

那么创建一个基于堆栈的缓冲区就很容易了。std::numeric_limits<int>告诉您十进制位数的最大数目。但是,由于您使用的是较旧的编译器,它可能不支持constexpr。因此,只需使用<limits.h>中的静态已知值来计算此值。符号加1,你就有了最大字符数。为0终止添加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( "%sn", Stringified( 42 ).c_str() );
}