Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 生成整数对数的常量数组的项值_C++_Algorithm_C Preprocessor - Fatal编程技术网

C++ 生成整数对数的常量数组的项值

C++ 生成整数对数的常量数组的项值,c++,algorithm,c-preprocessor,C++,Algorithm,C Preprocessor,我似乎无法理解这段用c++编写的代码: static const char LogTable256[256] = { #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6), LT(7), LT(7), LT(7), LT(7),

我似乎无法理解这段用c++编写的代码:

static const char LogTable256[256] = 
{
 #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
 LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
 LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};
如何使用循环生成相同的数组

\define
行可以出现在代码中的任何地方,只要它们的用法遵循它们。由于它们是预处理器指令,因此以下各项之间没有区别:

static const char LogTable256[256] = 
{
 #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
 LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
 LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};

如果第二个对您有意义,那么请放心,就编译器和程序的行为而言,第一个同样好。第一种可能会误导读者认为宏是在变量声明的范围内定义的,这是不正确的

如何使用循环生成相同的数组

不能使用循环来实现这一点,因为char数组是
const

该算法所做的是,它用从-1到7的数字填充一个char数组,从1开始,每个数字插入的频率是之前的两倍。这可以通过两个简单的嵌套循环完成,或者一个循环,
pow
memset
。但要使其工作,字符数组不能是常量。

预处理器指令的位置在技术上并不重要,除非它在使用它定义的
LT
宏之前。更传统的格式将把它放在数组定义之前。它不限于定义的范围:宏不尊重范围

要定义数组而不使用宏,可以使用单例,例如Meyers的单例

一次性初始化是构造函数的工作,我就是这样做的,一个Meyers的单例,带有类类型对象,其构造函数计算数组项值:

auto logarithms()
    -> std::array<signed char, 256> const&
{
    struct Wrapper
    {
        std::array<signed char, 256> items_;

        static void append( int const n, int const value, signed char*& p )
        {
            for( int i = 1; i <= n; ++i ) { *p++ = value; }
        }

        Wrapper()
        {
            items_[0] = -1;
            signed char* p = &items_[1];
            for( int i = 0; i < 8; ++i ) { append( 1 << i, i, p ); }
            assert( p == &*items_.end() );
        }
    };

    static Wrapper const the_array;
    return the_array.items_;
}
自动对数()
->std::数组常量&
{
结构包装器
{
std::数组项;
静态void append(int const n、int const value、有符号字符*&p)
{

对于(int i=1;i您甚至可以使用
constexpr
,当
constexpr
对象初始化时可以调用它。填充数组是可能的,但是
std::array
缺少一些
constexpr
声明,这些声明将在
C++17
中引入将其rt到一个
std::array
,带有一个辅助函数
到\u array
,该函数也将添加到标准/tr2中

#include <array>
#include <algorithm>
#include <cassert>

// this is from cppreference

namespace detail {
template <class T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
    to_array_impl(T (&a)[N], std::index_sequence<I...>)
{
    return { {a[I]...} };
}
}

template <class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N])
{
    return detail::to_array_impl(a, std::make_index_sequence<N>{});
}

constexpr auto make()
{
    int a[256] = {-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,};

    for(size_t i=4, n=16, start=16; i <= 7; ++i, n *= 2)
    {
        for(size_t j=0; j != n; ++j)
        {
            a[start + j] = i;
        }

        start += n;
    }

    return to_array(a);
}

int main() {
    static const int LogTable256[256] = 
{
 #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
 LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
 LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};

    auto constexpr a = make();
    assert( std::equal( std::begin(a), std::end(a), std::begin(LogTable256) ) );    
    return 0;
}

将这么多代码复制到一个空文件中,并运行(如果可用)此命令“
g++-E file.cpp>file\u preprocessed.cpp
”,您可能会看到
LT(n)
macro会在每个实例中将其替换为16个n-s。似乎有人正在使用这种基于ascii的值存储
char
。对于循环,没有系统的方法来生成此序列,因此最好保持如上所述。LT(n)每个将被值n替换8次。因此,对于i>4,您可以简单地使用for循环;最好您自己尝试并向我们展示您的progress@RamandeepPunia实际上是16次。结果是-1,然后是一个255个值的列表,从0到7,你总能找到n的2^n个实例。@TinyT,是的,你是对的。这是16次。不知怎的,我“第一个也一样好”,不,不是。它将宏定义隐藏在其他文本中,表示程序员错误地认为宏仅限于它定义的范围。源代码是关于与人通信的。@RSahu这有助于我理解数组是如何创建的,但我还需要用python重现相同的代码,我不知道就我所知,python没有任何类似于C预处理器的东西。然而,python是一种动态语言。你很有可能完成你想做的事情。请随意提问另一个问题,并提供所有细节。-1“使用循环无法做到这一点,因为char数组是
const
”是错误的(在公平的解释意义上)或是正确的,但没有意义(在完全字面意义上)。最后的断言“但要想做到这一点,char数组不能是const”是错误的™.这里有两个主要问题:(1)代码不使用Visual C++ 2015编译,因为它是非常C++ 14的特定代码,(2)复制,我不确定它是否一定会被优化掉。作为成本,这种方法购买了在编译时表达式中使用对数的能力。我不认为我会做这种交易。;-)@阿尔夫。我没有检查VC++,只是GCC 6.1。我认为可以通过创建一个<代码> CONTXPRP<代码>类来避免复制。它初始化了构造函数中的表。这也可以用VC++编译。我在更新2上看到了y,我想我已经看到了更新5。(更新3中引入了邪恶的呼叫总部潜力的主要原因是,为生成的可执行文件配备了这一功能,所以我停止了更新。我希望微软不要被黑暗面所操纵!)Alf这是我问题的一个很好的答案。但是如果我只是动态分配数组而不是使用内置的std::array,不是更好吗?@MuhammadAliQadri:对于静态大小常量数组,几乎不管大小,动态分配(即使用
std::vector
)这只是一个无用的开销。这就是
std::array
的用途。此数组的空间在程序加载的映像中。您可以使用内置的原始数组,而不是
std::array
,但是返回类型规范变得有点复杂,
->符号字符常量(&)[256]
。使用C++03函数声明语法甚至更不可编程。
#include <array>
#include <algorithm>
#include <cassert>

// this is from cppreference

namespace detail {
template <class T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
    to_array_impl(T (&a)[N], std::index_sequence<I...>)
{
    return { {a[I]...} };
}
}

template <class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N])
{
    return detail::to_array_impl(a, std::make_index_sequence<N>{});
}

constexpr auto make()
{
    int a[256] = {-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,};

    for(size_t i=4, n=16, start=16; i <= 7; ++i, n *= 2)
    {
        for(size_t j=0; j != n; ++j)
        {
            a[start + j] = i;
        }

        start += n;
    }

    return to_array(a);
}

int main() {
    static const int LogTable256[256] = 
{
 #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
 -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
 LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
 LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};

    auto constexpr a = make();
    assert( std::equal( std::begin(a), std::end(a), std::begin(LogTable256) ) );    
    return 0;
}
class LogTable
{
public:
    constexpr LogTable()
    {
        for(size_t i=4, n=16, start=16; i <= 7; ++i, n *= 2)
        {
            for(size_t j=0; j != n; ++j)
            {
                a[start + j] = i;
            }

            start += n;
        }
    }

    constexpr int operator[](size_t i) const
    {
        return a[i];
    }
private:
    int a[256] = {-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,};
};

int main() {
    static const int LogTable256[256] = 
    {
     #define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
     -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
     LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
     LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
    };

    LogTable constexpr l;
    for(auto i=0; i != 256; ++i)
    {
        assert(LogTable256[i] == l[i]);
    }

    return 0;
}