关于为什么'h'之后的一切都消失了?:
char a[] = "children" ;
char *p = strchr(a, 'i') ;
*p = NULL";
-
有一个错字:应该是*p = NULL;(双引号"是错误的。)
-
p 的类型为 char*。应用取消引用运算符* 会产生指针类型。因此,表达式 *p 的类型为char。 (请不要将此与声明char* 类型的变量p 的声明 char *p 混淆。)NULL 旨在表示一个空指针。 (在 C 中,它可能被定义为 #define NULL (void*)0。在 C++ 中,nullptr 应该优于 NULL。)将空指针分配给 char 是……令人困惑,但 C 编译器(以及 C++编译器)可能会将其隐式转换回普通的0。
我用gcc -std=c11 和g++ -std=c++17 编译了这个。在这两种情况下,编译器都会发出警告,但会提供可执行的二进制文件:
-
C: Live Demo on coliru
输出:
warning: assignment to 'char' from 'void *' makes integer from pointer without a cast [-Wint-conversion]
*p = NULL;
-
C++: Live Demo on coliru
输出:
warning: converting to non-pointer type 'char' from NULL [-Wconversion-null]
*p = NULL;
所以,应该是*p = 0;,或者更清楚的是*p = '\0';,这在语义上是相同的,但更清楚地暴露了意图。
考虑到这一点,固定版本是:
char a[] = "children" ;
char *p = strchr(a, 'i') ;
*p = '\0';
它用\0 覆盖带有i 的元素,这是C 字符串中的字符串终止符。
char a[] 以前是:
{ 'c', 'h', 'i', 'l', 'd', 'r', 'e', 'n', '\0' }
在这个分配之后变成
{ 'c', 'h', '\0', 'l', 'd', 'r', 'e', 'n', '\0' }
因此,它仍然具有相同的长度,但将它与 C 字符串函数一起使用(例如 printf("%s", a);)将考虑第一个找到的字符串终止符。
因此,它只会打印ch。
演示演示:
#include <cstring>
#include <cstdio>
#include <iomanip>
#include <iostream>
int main()
{
char a[] = "children" ;
char *p = strchr(a, 'i') ;
*p = '\0';
// printing a c string
printf("a[]: '%s'\n", a);
// print a[] element wise
std::cout << "a[]: {";
const char *sep = " ";
for (char c : a) {
std::cout << sep << '\'';
if (c >= ' ' && c < '\x7f') std::cout << c;
else std::cout << '\\' << std::oct << (unsigned)(unsigned char)c << std::dec;
std::cout << '\'';
sep = ", ";
}
std::cout << " }\n";
}
输出:
a[]: 'ch'
a[]: { 'c', 'h', '\0', 'l', 'd', 'r', 'e', 'n', '\0' }
Live Demo on coliru
关于 OPs C/C++ 书籍的注释:
事实上,C++ 语言是从现有的 C 语言演变而来的。C 和 C++ 仍然相互关联。例如。 C++标准库采用了部分C标准库。
不过,这是两种独立的语言,有各自的标准。
- 有些 C 语句也适用于 C++。
- C 中的某些东西在 C++ 中的工作方式略有不同。
- C 中有些东西在 C++ 中不起作用,反之亦然。
最后的例子:
一个(诚然有点做作的)示例表明相同的源代码可能导致 C 与 C++ 中的不同语义:
auto a = 'a';
printf("sizeof a: %d\n", (int)sizeof a);
在 C11 中:
#include <string.h>
#include <stdio.h>
int main()
{
auto a = 'a';
printf("sizeof a: %d\n", (int)sizeof a);
}
输出:
sizeof a: 4
Live Demo on coliru
auto 是存储类。 auto a 中缺少一个类型。 C 编译器默认为int。
在 C++11 中:
#include <cstring>
#include <cstdio>
using std::printf; // pull printf() into global scope
int main()
{
auto a = 'a';
printf("sizeof a: %d\n", (int)sizeof a);
}
输出:
sizeof a: 1
Live Demo on coliru
auto 从其初始化中确定a 的类型。在 C++ 中,字符常量的类型为 char(与 C 相反,它们的类型为 int)。