初始化char*与int*的区别

19

在 C++ 中是可能的:

const char* ch = "hello";

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

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

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

我知道我们可以使用

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

但这不是问题所在。


8
在 C 和 C++ 中,字符字面值(如"hello")是特殊的实体。 - πάντα ῥεῖ
2
你不应该使用字符串字面量来初始化 char * 。应该使用 const char * - Robert Allan Hennigan Leahy
char* ch = "hello"; 这是有效的 C 代码,但在 C++ 中无效(尽管它曾经也是有效的)。请适当标记您的问题。 - user743382
1
@WhozCraig 这是有效的 C 代码,但无效的 C++ 代码。不清楚 OP 感兴趣的编程语言是什么。 - user743382
1
你混淆了 charchar* - Lightness Races in Orbit
显示剩余7条评论
3个回答

15
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;

通常情况下,定义一个单独的数组变量会更容易一些,但在某些情况下,使用这样的模板会更有帮助。
注释中指出,可以更普遍地定义该模板,使其适用于任意类型和任意长度的数组,但需要一个更新的编译器,并且对当前版本的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;

能否编写一个可变参数版本的模板? - Karoly Horvath
有一种特殊的语法用于字符串字面量,因为它们被如此频繁地使用,并且在许多情况下不希望用虚拟变量来混淆代码。 - async

4

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


哦,我现在明白了,基本上引号可以被想象成“初始化列表”或字符数组。 - codekiddy
@codekiddy "hello" 是类型为 const char[6] 的字符串常量。表达式赋值所做的就是将任何“数组”分配给适当类型的指针,即表示第一个元素的地址。它不是某个初始化列表。它是一个数组,你正在保存它的第一个元素地址。唯一进行的初始化是使用该地址初始化指针。 - WhozCraig

3
字符字面量会被编译成二进制文件中数据段中的一块初始化存储器,而 const char * 是指向该存储器的指针。
实际上,如果您有一个内存块的地址,也可以对 const int * 进行同样的操作。您可以使用内联汇编(但我从未尝试过)指定一个 .data 段来实现此操作。

在C99及以后的版本中,您可以拥有其他类型的数组文字;不太确定为什么C ++没有做类似的事情。 - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接