提问人:King Brain 提问时间:7/12/2023 最后编辑:Vlad from MoscowKing Brain 更新时间:7/16/2023 访问量:123
难以理解 CS50 中的 char* 和字符串
Trouble understanding char* and string in CS50
问:
所以我知道字符串只是连续存储在计算机内存中的字符数组。
我也知道,为了找出字符串的位置,你只需要转到第一个字符的位置,因为它是连续的,当程序或函数遇到 \0 字符时,字符串结束。
但我不明白的是:
-
char* s = "HI!";
它是否创建一个包含 4 个字符的数组?或者它只是指向起始角色位置的指针?还是两者兼而有之?
2.
char* name = "BEN";
printf("%c %c\n", *(name + 1), *name + 1);
为什么它们都给出两个不同的输出(E 和 C),而不是都给出 E?
答:
- in then 是字符串文字。 指向 .字符串文字长度为 4(包括终止)。另一种(非惯用的)看待它的方式:......这里是指向 .
char* s = "HI!";
"HI!"
s
H
char
\0
char(*s)[4] = &"HI!";
s
char[4]
- 在您的第二个示例中,它是关于您执行操作的顺序,即运算符优先级。
char* name = "BEN"; printf("%c %c\n", *(name + 1), *name + 1);
(name + 1)
添加到 中,因此您会得到一个指向 .之后,用 和 get 取消引用指针。1
char*
name
E
*
E
*name
取消引用指针,指针指向它,然后指向它,使其成为 .B
+ 1
C
这与这样做相同:
printf("%c %c\n", name[1], name[0] + 1);
在本声明中
char* s = "HI!";
将创建两个实体。
第一个是字符串文字,它具有静态存储持续时间和数组类型。(在C++中,它具有常量字符数组类型,与C相反。"HI!"
char[4]
const char[4]
您可以使用 printf 进行检查
printf( "sizeof( \"HI!\" ) = %zu\n", sizeof( "HI!" ) );
这里字符数组用作指针的初始值设定项。在这种情况下,它被隐式转换为指针的第一个元素,并且指针指向数组的第一个元素的地址。s
s
至于这个代码片段
char* name = "BEN";
printf("%c %c\n", *(name + 1), *name + 1);
由于指针算术,表达式具有类型并指向字符串文字的第二个字符 (thus )。取消引用指针表达式,就像获取表达式指向的字符串文本的符号一样。实际上,表达式与 .:) 相同name + 1
char *
"BEN"
'E'
*(name + 1)
*(name + 1)
name[1]
1[name]
至于这个表达式,取消引用指针,你会得到字符串文字的第一个符号。然后,将 1 添加到符号 'B''C'( *name + 1 )name[0] + 1' 的内部代码中。*name
name
'B'
( *name + 1 ), so the expression takes the value of the next symbol after
, which is
. The expression
is equivalent to the expression
使用下标运算符 like 和 使表达式更清晰。name[1]
name[0] + 1
我认为您知道可以仅使用原始字符串文字重写调用会很有趣。一些例子:printf
printf("%c %c\n", *( "BEN" + 1), *"BEN" + 1);
或
printf("%c %c\n", "BEN"[1], "BEN"[0] + 1);
甚至
printf("%c %c\n", 1["BEN"], 0["BEN"] + 1);
但我不明白的是:
char* s = "HI!";
它是否创建一个包含 4 个字符的数组?或者它只是指向起始角色位置的指针?还是两者兼而有之?
赋值的右侧提供了一个常量字符数组(4 个,包括 null 字符)。为这 4 个字符分配内存的位置/方式不是问题。编译器可以自由选择生存位置和生存时间。= "HI!";
"HI!"
赋值的左侧:在堆栈上声明一个本地指针,以指向数组的第一个字符(char *s =
'H'
)
char* name = "BEN";
printf("%c %c\n", *(name + 1), *name + 1);
为什么它们都给出两个不同的输出(E 和 C),而不是都给出 E?
name
是一个指针。它指向该字符串中字母的地址。B
name+1
是指向该字符串中过去一个字符的指针,在本例中为 .B
E
*name
是在 所指向的地址处保存的值。换句话说,字符 .name
'B'
*name + 1
与 或 或 相同。您在此表达式中将 1 添加到值中,而不是地址。(*name) + 1
'B' + 1
'C'
*(name + 1)
,计算结果为 引用的字符串中的第二个字符。或者正如你所期望的那样name
'E'
下一个:C 星号运算符使用
评论
char[4]
"HI!"
s
"HI!"
它本身就是一个由 4 个字符组成的数组。 然后指向它的第一个元素。char* s
cs50.h
typedef char *string;
cs50.h
string
typedef