【问题标题】:Initializing char* vs int*初始化 char* 与 int*
【发布时间】:2014-08-16 10:54:50
【问题描述】:

这在 C++ 中是可能的:

const char* ch = "hello";

但是这样的事情是不可能的:

int* i = { 1, 2, 3 };

char *chint* i 都是普通指针。为什么char* 可以分配多个字符,而int* 不能分配多个整数?

我知道我们可以使用

int x[] = {1, 2, 3};

但这不是问题。

【问题讨论】:

  • 字符文字 ("hello") 是 c 和 c++ 中的特殊野兽。
  • 你不应该用字符串初始化char *const char *.
  • char* ch = "hello"; 是有效的 C,但无效的 C++(尽管它曾经在那里也有效)。请适当标记您的问题。
  • @WhozCraig 那是有效的 C 和无效的 C++。目前尚不清楚 OP 对哪种语言感兴趣。
  • 你混淆了charchar*

标签: c++


【解决方案1】:
const char* ch = "hello";

有点像

static const char string_literal[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
const char* ch = &string_literal[0];

除了每个相同的字符串文字不一定指向内存中的不同位置。

其他类型也可以这样:

static int integer_list[] = { 1, 2, 3 };
int* i = &integer_list[0];
// or equivalently, just int* i = integer_list;

现在,i[0]1i[1]2i[2]3

字符串字面量有一种特殊的语法,因为它们被频繁使用,而且在不希望将代码与虚拟变量混淆的上下文中如此频繁。

如果您有很多代码使用静态分配的整数类型的只读数组,您可以使用模板隐藏样板:

template <int a, int b, int c>
struct int_array { static const int values[3]; };
template <int a, int b, int c>
const int int_array<a, b, c>::values[] = { a, b, c };

您只需要定义一次模板,然后每个不同的用户都可以将该模板用于用户感兴趣的特定值。

const int* i = int_array<1, 5, 6>::values;

通常,简单地定义一个单独的数组变量会更容易,但在某些情况下这样的模板会有所帮助。

如 cmets 中所述,可以更通用地定义模板,以便它适用于任意类型和任意长度的数组,但它需要一个对当前版本的 C++ 有良好支持的最新编译器(对于 GCC 和 clang,当前版本很好,但请确保传递 -std=c++11-std=gnu++11 选项以启用 C++11 功能):

template <typename T, T... v>
struct static_array {
  static const T values[sizeof...(v)];
};

template <typename T, T... v>
const T static_array<T, v...>::values[sizeof...(v)] = { v... };

现在,这个数组的用户的语法是

const int* i = static_array<int, 1, 2, 3, 4>::values;
const unsigned* j = static_array<unsigned, 1, 2, 3, 4, 5>::values;

【讨论】:

  • 是否可以编写可变参数版本的模板?
  • “字符串字面量有一种特殊的语法,因为它们被频繁使用,并且在不希望将代码与虚拟变量混淆的上下文中如此频繁。”谢谢!
【解决方案2】:

字符串文字是一个字符数组。请注意,ch 只是指向单个字符的指针,因此它实际上并不指向整个字符串,而只是指向其基地址(第一个字符的地址)。初始化列表(即{1, 2, 3}不是数组,因此不能用于初始化指针。

【讨论】:

  • 哦,我现在明白了,所以基本上可以将引号想象为“初始化列表”或字符数组。
  • @codekiddy "hello" 是 const char[6] 类型。表达式赋值的作用与将任何“数组”赋值给正确类型的指针一样;表示为第一个元素的地址。它不是一些初始化列表。它是一个 array,并且您正在保存它的第一个元素地址。唯一正在进行的初始化是使用所述地址初始化指针。
【解决方案3】:

字符文字被编译为二进制数据段中的一块初始化存储。 const char * 是指向该存储的指针。

事实上,应该可以对const int * 做同样的事情,只要你有一个内存块的地址。您可以使用内联汇编器(但我从未尝试过)指定.data 段来执行此操作。

【讨论】:

  • 在 C99 及更高版本中,您可以拥有其他类型的数组字面量;不完全确定为什么 C++ 没有做类似的事情
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-12
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
相关资源
最近更新 更多