定义一个不带终止符的c++字符数组
Define a C++ char array without terminator
为什么这个程序在C语言中可以很好地编译?不支持c++吗?解释与C语言不同,c++语言不允许char
数组的初始化字符串长度不足以容纳结束的null字符。有没有一种方法来指定一个未终止的char
数组在c++中没有膨胀的字符串在源代码的四倍?
例如,在C和c++中,下列语句是等价的:
const char s[] = "Hello from Stack Overflow";
const char s[] = {'H','e','l','l','o',' ','f','r','o','m',' ','S','t','a','c','k',' ','O','v','e','r','f','l','o','w',' '};
因为字符串"Hello from Stack Overflow"
的长度是25,所以这就产生了一个包含26个元素的char
数组,就好像写了以下内容:
const char s[26] = "Hello from Stack Overflow";
const char s[26] = {'H','e','l','l','o',' ','f','r','o','m',' ','S','t','a','c','k',' ','O','v','e','r','f','l','o','w',' '};
仅在C语言中,程序可以排除终止null字符,例如如果字符串的长度在带外已知。(查找C99标准第6.7.9章中的"如果有空间,包括终止null字符")
const char s[25] = "Hello from Stack Overflow";
const char s[25] = {'H','e','l','l','o',' ','f','r','o','m',' ','S','t','a','c','k',' ','O','v','e','r','f','l','o','w'};
但是在c++中,只有后者是有效的。如果我知道我将使用std::strn
家族中的函数来操作数据,而不是std::str
家族,那么c++语言中是否有对应的C的速记语法?
我的动机不同于另一个关于c++中未终止的char
数组的问题。这样做的动机是,游戏中的多个道具名称存储在二维char
数组中。例如:
const char item_names[][16] = {
// most items omitted for brevity
"steel hammer",
{'p','a','l','l','a','d','i','u','m',' ','h','a','m','m','e','r'}
};
如果没有简写来声明一个不终止的char
数组,那么最大长度的名字将不得不一个字符一个字符地写,这使得它们比更短的名字更不容易读,更不容易维护。
这是可能的,但我同意Alan Stokes的"Why"
例如使用c++:宏可以展开"abc"分为'a', 'b', 'c'?它可以调整为允许对任何提供的数组进行操作,并将其长度限制为16。
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
template <unsigned int N>
constexpr char get_ch (char const (&s) [N], unsigned int i)
{
return i >= N ? ' ' : s[i];
}
#define STRING_TO_CHARS_EXTRACT(z, n, data)
BOOST_PP_COMMA_IF(n) get_ch(data, n)
#define STRING_TO_CHARS(STRLEN, STR)
BOOST_PP_REPEAT(STRLEN, STRING_TO_CHARS_EXTRACT, STR)
const char item_names[][16] = { // most items omitted for brevity
"steel hammer",
STRING_TO_CHARS(16, "palladium hammer"),
//{'p','a','l','l','a','d','i','u','m',' ','h','a','m','m','e','r'},
};
但是从长远来看,这会给你带来更多的麻烦。
c风格数组的缺点是它不能传递给函数或从函数返回(传递或返回char*可以给你一个char*数组,但最后不是char[]数组),我们可以使用std::array来绕过这个
c风格数组的优点是小字符串字面值可以用来初始化char[][]的初始化列表中较大的char[](如您的示例),对于std::数组,我们使用std::max来模拟这个
#include<array>
#include<utility>
#include<algorithm>
#include<iostream>
template<size_t string_length, typename T, T... ints, size_t string_literal_size>
constexpr std::array<char, string_length> generate_string_impl(std::integer_sequence<T, ints...> int_seq, char const(&s)[string_literal_size])
{
return { {s[ints]...} };
}
template<size_t string_length, size_t string_literal_size>
constexpr std::array<char, string_length> generate_string(char const(&s)[string_literal_size])
{
return generate_string_impl<string_length>(std::make_index_sequence<string_literal_size - 1>{}, s);
}
template<size_t ...string_literals_size>
constexpr std::array < std::array<char, std::max({ string_literals_size... }) - 1 > , sizeof...(string_literals_size) > generate_array_of_strings(char const(&...s)[string_literals_size])
{
return { generate_string < std::max({ string_literals_size... }) - 1 > (s)... };
}
int main()
{
constexpr auto array_of_string1 = generate_array_of_strings("1234", "12345", "123456");
//std::array<std::array<char,6>,3>{{
// {{ '1', '2', '3', '4', ' ', ' ' }},
// {{ '1', '2', '3', '4', '5', ' ' }},
// {{ '1', '2', '3', '4', '5', '6' }}
//}}
//std::array<std::array<char,6>,3> satisfies StandardLayoutType requirement
char const(&array_of_string2)[std::size(array_of_string1)][6] = reinterpret_cast<char const(&)[std::size(array_of_string1)][6]>(array_of_string1);
char const(*p_array_of_string2)[std::size(array_of_string1)][6] = reinterpret_cast<char const(*)[std::size(array_of_string1)][6]>(&array_of_string1);
for (int i = 0; i != 3; ++i)
{
for (int j = 0; j != 6; ++j)
{
std::cout << i << "," << j << " " << array_of_string2[i][j] << " " << (*p_array_of_string2)[i][j] << std::endl;
}
}
}
- OpenGL - 在抛出"__gnu_cxx::recursive_init_error"实例后终止调用?
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 我收到以下错误:抛出'std::bad_alloc'实例后终止调用
- 为什么这个 c++ 代码打印出长度 5,当我打印出字符串时,程序会自动终止?
- 当我在其中一个线程执行中(在activemq-cpp中)捕获到特定值时,我如何终止/停止所有其他线程
- llvm构建器向基本块添加终止符
- 如何使用隔离>终止执行来停止所有线程
- 用于将C++代码转换为 Web 程序集的脚本未终止
- C++应用程序 MySQL odbc 数据库连接错误:在引发"otl_tmpl_exception<>"实例后终止调用
- 终止 QProcess 不会终止子进程
- 运行代码时,c++ 会终止进程
- 检测到堆栈粉碎:已终止 中止(核心已转储)
- 在输入句子时终止 std::out_of_range
- 二进制搜索的终止点
- MPI:检查是否有任何进程已终止
- 英特尔 TBB 程序不会终止,可能会误用参考计数器
- 如何改进我的代码,使其不会因超时而终止?(黑客排名挑战)
- while 循环不以哨兵值终止
- C++ 程序不会因为内存而终止
- 在这个无限循环中,当输入 0 时终止,当输入 int 范围之外的任何内容时,程序行为不正常