【问题标题】:How can a char variable parameter take in a string?char 变量参数如何接收字符串?
【发布时间】:2019-09-07 17:47:50
【问题描述】:

假设一个函数有一个const char* 类型的参数。当我在调用该函数时使用字符串时,没有任何问题!我希望您只能输入 ASCII 中包含的字符,例如 c 或 dec 68,但似乎并非如此。看看下面的代码...

void InitFunction(const char* initString)
{
  std::cout << initString;
}

int main()
{
  InitFunction("Hello!");
}

当您运行代码时,不会出现任何问题、警告或错误。从以下内容可以看出,我对此进行了更多测试...

void InitFunction(char initString)
{
  std::cout << initString;
}

int main()
{
  InitFunction("Hello!");    // compiler error on this line
}

由于无法将Hello! 转换为char,因此编译时出错。我尝试了另一个测试,但使用const char 作为函数参数类型。代码仍然编译错误。但是当我将* 添加到函数参数类型时,一切都编译得很好!在我看来,const 也是必要的。

根据我对指针的理解,该函数要求一个指针,并且该指针被标识为一个字符。但这给我带来了三个问题。

  • 首先,Hello! 不是指针的形式。我希望至少必须使用引用运算符 (&amp;)。

  • 其次,Hello! 不是char 类型。

  • 第三,为什么我们需要包含const

我在这里遗漏了什么吗?指针和字符是否以我不知道的方式工作?

【问题讨论】:

  • 你在用哪本书来学习 C++?
  • 你怎么知道的?萨姆斯自学。这实际上很容易理解,但我只是卡在这部分。
  • “我怎么知道”是什么意思? Here are the books we recommend.

标签: c++ parameters


【解决方案1】:

"Hello!" 是一个 const char 字符数组。数组被视为指针,当在函数调用中用作参数时,它们会衰减为指针。 C++ 标准对此进行了指定,以便与 C 语言标准指定处理数组的方式兼容。

顺便说一下,这个数组衰减到指针的方式发生在其他使用数组的情况下,其中可以使用指针或地址运算符,例如赋值语句。另见Arrays are Pointers?

所以"Hello!" 将作为指针放入InitFunction() 的参数列表中,该指针指向编译器存储添加了终止零字符的字符数组的位置。当编译器生成函数调用的代码时,指向用作函数参数的字符数组的指针是const char *,指向char 的指针是const,不应更改。

当函数原型为InitFunction(const char *) 时,编译器可以很好地调用InitFunction("Hello!"); 之类的函数。您正在做的是提供一个指向"Hello!"const char *

但是,如果您删除 const,那么由于 "Hello!"const,编译器会抱怨。编译器抱怨是因为在函数调用中使用了const 变量,其参数列表是非常量的,表明该函数可能会更改指针指向的内容。自从“你好!”不应该改,因为是const,编译器报错。

如果您删除星号,将const char * 更改为const char,那么由于"Hello!" 是一个char 数组,然后编译器会衰减为指向数组第一个元素的指针,编译器会报错正在尝试将指针用于不是指针的参数。在这个替代方案中,问题在于实际的数据类型,charchar * 是问题所在。

以下代码行也是可以接受的:

const char *p = "Hello!";  // create a pointer to an series of characters
char x1[] = "Hello!";      // create an array of char and initialize it.
char *p2 = x1;             // create a pointer to char array and initialize it.
char *p3 = x1 + 2;         // create a pointer to char array and initialize it with address of x1[2].

InitFunction (p);    // p is a const char *
InitFunction (x1);   // x1 decays to a char *
InitFunction (p2);   // p2 is a char *
InitFunction (p3);   // p3 is a char *

InitFunction (x1 + 3);  // called with address of x1[3].

另请注意,C++ 有一个实际的字符串类型string,它会生成一个动态字符串,其底层物理内存布局通常包括一个指向字符数组的指针。标记为字符串的 C 样式字符数组与 C++ string 类型不同。

【讨论】:

  • 干得好,只是数组指针转换的事情有点模糊。虽然“[arrays] 在函数调用中用作参数时衰减为指针”是完全正确的,但这并不是全部真理。数组被转换为指针在访问时 受到C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) 中包含的四个异常的影响。这将有助于避免“数组在哪里衰减到指针?”的挥之不去的问题?
  • @DavidC.Rankin 感谢您对 C 标准的引用的评论。这促使我进一步寻找 Stackoverflow 中类似问题的内容,其中包含许多经过大量阐述的答案。
  • 是的,我总是尝试并重新强调我记得的问题,“现在这到底是怎么回事?”关于的问题。 (顺便说一句,还有很多……)
【解决方案2】:

函数要求指针

正确。

并且指针被识别为一个字符

不,指针不是字符。指针是指针。该指针指向一个或多个字符,即一个字符数组。这正是您的字符串文字。

首先,您好!不是指针的形式。

是的,是的。字符串文字 "Hello!" 的类型为 const char[7],它会衰减为指针。

我希望至少必须使用引用运算符 (&)。

这是地址操作符。您并不总是需要它来获取指针。示例:this

第二,你好!不是 char 类型。

不,但每个组成字符都是。

第三,为什么我们需要包含 const?

因为字符串文字 "Hello!" 的类型为 const char[7]。删除const 会违反const-正确性,因此是不允许的。

这会引发一个错误,因为你好!不能转换成char。

没错。 char 是一个字节。字符串"Hello!" 不是一个字节。它是一个字符串。


C 字符串通常/按惯例/通常以 const char* 形式提供。

您应该阅读书中有关该主题的章节,因为它是该语言的基础。它与 ASCII 无关(文本编码与存储字节序列无关)。

【讨论】:

  • 哦,好吧。我明白。所以“Hello”会被当成一个字符串,但它也可以作为一个字符数组工作?
  • @FuzzySquid 两者有什么区别?字符串一个字符数组。一直都是。
  • 哦,好吧。最后一件事,const char[7]“衰减”到指针是什么意思?
  • 这意味着您可以将Ts 的数组传递给正在寻找指向T*s 的指针的函数。有一个内置的兼容性规则。如果您使用推荐的书,它将解释这一点。 (注意:一些不好的书错误地声称“数组是指针”,因为他们的作者被这个兼容性规则弄糊涂了。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-18
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多