【问题标题】:Why can we say ' char *c = "Hello"; ' in C++为什么我们可以说 ' char *c = "Hello"; ' 在 C++ 中
【发布时间】:2019-04-11 02:20:48
【问题描述】:

当我这样做时-

#include <iostream>

int main(){
    char *p = "Hello";
}

它工作正常,但正在做

#include <iostream>

int main(){
    char *p = 'H';
    // OR
    int *x = 5;

}

给出错误:从 'char' 到 'char*' [-fpermissive] / 'int' 到 'int*' 的无效转换

【问题讨论】:

  • char *p = "Hello"; 不应该编译。如果您使用 gcc,请在编译时使用 -pedantic-erros 以关闭编译器扩展。 (我真的希望这是默认开启)。
  • 未定义的行为 = 有时可以正常工作,但仍然是未定义的行为
  • 两个不同的引号做不同的事情。双引号:"A string of characters" 包含一个字符串,其类型为char const*,而单引号:'X' 包含一个字符,其类型为char
  • @Brian True,但 C++ 标签指的是当前标准 (C++17),所以我的评论是正确的。
  • @Dimfred 因为"Hello"const char[N],其中N 是字符数加上空终止符。执行char* foo = "hello"; 会从字符串文字中去除const,因此它应该无法编译,因为删除const 的唯一方法是使用c 样式转换或const_cast

标签: c++ pointers


【解决方案1】:

这里的问题是 C++ 是一种强类型语言。您必须确保 = 右侧的类型与左侧的类型相同(或者有一些明确定义的转换允许编译器在类型之间进行转换)。

所以我们需要知道字面量是什么类型:使用双引号会创建char const[] 类型的字符串字面量,而使用单引号会创建char const 类型的字符字面量。

const 部分,您将不得不忍受我。这使讨论变得更加复杂,因此我们将在开始时对其进行掩饰。

我们还需要知道,当在表达式中使用数组时,它们很容易衰减为指针。所以大多数情况下char const[] 的类型会衰减为char const*

这应该可行:

char const* p = "Hello";    // This is valid.
                            // Both left and right sides have the same type.
                            // After you consider the array decay into a pointer.

另一方面

char const* p = 'H';        // The type on the right is `char const'
                            // While the type on the right has a pointer in it.

现在这里有一些自动转换。
在最初的 C++03 中,允许编译器将字符串文字从 char const* 自动转换为 char*。这是旧 C 语言的遗物,在类型检查方面不像现在 C++ 那样严格。这允许这样做:

 char*       p = "Hello";    // Because there is an auto conversion
                             // the compiler is allowed to make 
                             // the conversion from one type to another

请注意,在更高版本的 C++ 中,此转换已被弃用。所以编译器会警告你这是危险的(因为你已经从允许修改它的类型中删除了 const,但是底层对象不能被修改,所以如果你尝试它会炸毁程序)。

那么为什么可以将char const 分配给char

char  x = 'X';

在这里,您将原始对象char const 复制到char 类型的对象中,这是完全有效的。你不能改变或改变文字,但你可以复制它。因此,您可以轻松删除赋值表达式中的外部 const

 char const* const y = "Hello";
 char const*       z = y;        // We remove the outer const
                                 // from a pointer. But the inner
                                 // const (of the object being pointed
                                 // at) can not be removed so easily.

                                 // This works because z is allowed to 
                                 // to be changed but hold a value a pointer
                                 // to a value that can not be changed.

查看您的评论:

#include <iostream>
void test(char *str)
{
    std::cout << str << std::endl;
}

int main()
{
    test("Hello");           // This is allowed in C++
                             // Deprecated still means valid.
                             // Just not a good idea

                             // There is a allowed conversion from
                             // char const* to char* for string literals.


    char const* x = "test";
    test(x);                 // This is NOT allowed.
                             // You can not cast away this const.
}

注意:从技术上讲,字符串文字是char const[]。即一个const char数组。 但是在表达式数组中使用时很容易衰减为指针,因此有时将它们视为char const* 更简单,但这种想法是抽象的,您应该知道底层的确切类型。

【讨论】:

  • 那么这样做也被丢弃了(不使用const)? - #include &lt;iostream&gt; void test(char *str){ std::cout &lt;&lt; str &lt;&lt; std::endl; } int main(){ test("Hello"); }
  • discarded 是错误的词。仔细选择你的话。从char const*char* 的自动转换允许编译器应用于string literals。这在这里有效。它不适用于泛型类型的对象。
  • double quote creates a string literal of type char const* 错误,其他基于此假设的解释也是错误的。
  • @SergeyA 需要解释一下吗?我很确定这是字符串文字的正确类型。或者你是说字符串文字是char const[].
  • @SergeyA 在第一次提及时添加了注释,并在底部添加了确切定义。
猜你喜欢
  • 2015-06-02
  • 1970-01-01
  • 2019-02-01
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-25
  • 2010-09-09
相关资源
最近更新 更多