将 char[][] 转换为 char**?
Converting char[][] to a char**?
我正在根除 std::string
,转而使用我刚接触的 C 字符串。如何编译以下内容? g++
抱怨:cannot convert char(*)[16] to char**
#include <iostream>
void print(char** s, int n)
{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << '\n';
}
}
int main()
{
constexpr int n = 3;
char s[n][16]{ "Hello", "Bye", "Sky"};
print(s, n);
}
编译器无法从 char ** 中提取有关 char[16] 的信息。您需要定义一个类型 char[16] 并将指向该类型的指针传递给您的打印函数。
#include <iostream>
typedef char str_t[16];
void print(str_t* s, int n)
{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << std::endl;
}
}
int main()
{
int n = 3;
char s[n][16]{ "Hello", "Bye", "Sky"};
print(s, 3);
}
您创建了一个多维数组,而不是指针数组。通常一个数组可以说等同于一个指针,但是在这种情况下,c++ 需要知道数组第二维的大小。函数如下
void print(char s[][16], int n)`{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << std::endl;
}
}
可以理解,您可能希望使用指针传递函数,而不是制作二维数组的完整副本。我看到你提到你可以使用可变长度的字符串。字符串库支持该功能。您正在处理的 C 字符串根本不是字符串,而是字符类型的静态数组。使用动态内存定义这些 C 字符串恰好可以为您提供所需的行为,因为您可以用最简单的术语创建一个指针数组。
void print(char** s, int n)
{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << std::endl;
}
}
int main()
{
int n = 3, i;
char** s = new char*[n];
for (i = 0; i < 3; i++) {
s[i] = new char[16];
}
s[0] = "Hello";
s[1] = "Bye";
s[2] = "Sky";
print(s, n);
for (i = 0; i < 3; i++) {
delete [] s[i];
}
delete [] s;
s = NULL;
return 0;
}
由于您现在使用的是动态内存,因此您需要释放内存,这是最后一个循环所要做的。正如您所看到的那样,使用所有这些动态内存非常费力,使用经过优化的字符串库会比您可以更容易地完成更好的工作。如果您仍然不相信,您至少应该创建自己的字符串 class 来处理包含 char * 作为其私有成员的动态内存。在任何一种情况下,您都可以避免这种混乱,只需创建一个 zed class 对象数组,而根本不处理多维废话。没有人喜欢段错误和内存泄漏。
给定任何类型 T
,T arr[N];
声明类型 T[N]
的变量 arr
,它是 数组而不是指针。当您在几乎所有上下文中使用 arr
时,都会发生 array to pointer conversions,从而给人一种错误的错觉,即 arr
是 T*
.
类型的指针
char s[n][16] = { "Hello", "Bye", "Sky" };
将 s
声明为 n
类型 char[16]
元素的数组。现在,当数组到指针的转换发生时,s
会衰减为 char (*)[16]
类型的指针。因此,您的函数需要具有签名
void print(char (*s)[16], int n);
相当于
void print(char s[][16], int n);
[]
被编译器解释为指针。
为了使这些复杂类型更具可读性,可以使用类型别名。
using T = char[16];
void print(T s[], int n);
解决一些问题
正如评论中所指出的,std::string
几乎总是比 char
数组更受欢迎。如果您有性能问题,请在执行此操作之前进行基准测试。我真的怀疑在大多数情况下能否观察到性能提升。
声明一个长度为 n
的数组,它是一个 int
不是标准的 C++。它是编译器提供的扩展,不可移植,在大多数情况下没有必要。
int n = 3;
char vla[n]; // this is a variable length array
char arr[3]; // this is just an array
char* darr = new char[3]; // this is a pointer pointing to dynamically allocated memory
std::string str; // but instead, this is just better
我正在根除 std::string
,转而使用我刚接触的 C 字符串。如何编译以下内容? g++
抱怨:cannot convert char(*)[16] to char**
#include <iostream>
void print(char** s, int n)
{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << '\n';
}
}
int main()
{
constexpr int n = 3;
char s[n][16]{ "Hello", "Bye", "Sky"};
print(s, n);
}
编译器无法从 char ** 中提取有关 char[16] 的信息。您需要定义一个类型 char[16] 并将指向该类型的指针传递给您的打印函数。
#include <iostream>
typedef char str_t[16];
void print(str_t* s, int n)
{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << std::endl;
}
}
int main()
{
int n = 3;
char s[n][16]{ "Hello", "Bye", "Sky"};
print(s, 3);
}
您创建了一个多维数组,而不是指针数组。通常一个数组可以说等同于一个指针,但是在这种情况下,c++ 需要知道数组第二维的大小。函数如下
void print(char s[][16], int n)`{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << std::endl;
}
}
可以理解,您可能希望使用指针传递函数,而不是制作二维数组的完整副本。我看到你提到你可以使用可变长度的字符串。字符串库支持该功能。您正在处理的 C 字符串根本不是字符串,而是字符类型的静态数组。使用动态内存定义这些 C 字符串恰好可以为您提供所需的行为,因为您可以用最简单的术语创建一个指针数组。
void print(char** s, int n)
{
for (int i = 0; i < n; ++i)
{
std::cout << s[i] << std::endl;
}
}
int main()
{
int n = 3, i;
char** s = new char*[n];
for (i = 0; i < 3; i++) {
s[i] = new char[16];
}
s[0] = "Hello";
s[1] = "Bye";
s[2] = "Sky";
print(s, n);
for (i = 0; i < 3; i++) {
delete [] s[i];
}
delete [] s;
s = NULL;
return 0;
}
由于您现在使用的是动态内存,因此您需要释放内存,这是最后一个循环所要做的。正如您所看到的那样,使用所有这些动态内存非常费力,使用经过优化的字符串库会比您可以更容易地完成更好的工作。如果您仍然不相信,您至少应该创建自己的字符串 class 来处理包含 char * 作为其私有成员的动态内存。在任何一种情况下,您都可以避免这种混乱,只需创建一个 zed class 对象数组,而根本不处理多维废话。没有人喜欢段错误和内存泄漏。
给定任何类型 T
,T arr[N];
声明类型 T[N]
的变量 arr
,它是 数组而不是指针。当您在几乎所有上下文中使用 arr
时,都会发生 array to pointer conversions,从而给人一种错误的错觉,即 arr
是 T*
.
char s[n][16] = { "Hello", "Bye", "Sky" };
将 s
声明为 n
类型 char[16]
元素的数组。现在,当数组到指针的转换发生时,s
会衰减为 char (*)[16]
类型的指针。因此,您的函数需要具有签名
void print(char (*s)[16], int n);
相当于
void print(char s[][16], int n);
[]
被编译器解释为指针。
为了使这些复杂类型更具可读性,可以使用类型别名。
using T = char[16];
void print(T s[], int n);
解决一些问题
正如评论中所指出的,std::string
几乎总是比 char
数组更受欢迎。如果您有性能问题,请在执行此操作之前进行基准测试。我真的怀疑在大多数情况下能否观察到性能提升。
声明一个长度为 n
的数组,它是一个 int
不是标准的 C++。它是编译器提供的扩展,不可移植,在大多数情况下没有必要。
int n = 3;
char vla[n]; // this is a variable length array
char arr[3]; // this is just an array
char* darr = new char[3]; // this is a pointer pointing to dynamically allocated memory
std::string str; // but instead, this is just better