当我在递增指针后使用 strlen() 时会发生什么?
What happens when I use strlen() after incrementing a pointer?
我已经对 strlen()
做了一些研究并有一个问题。
假设我有一个 50
元素数组和一个指向第一个元素的指针,意思是:
char A[50],*x;
gets(A);
x=&A[0];
据我了解,strlen(x)
应该会给出字符串的长度。
我的问题是,当我递增 x
时到底发生了什么?
首先,很抱歉跑题了,但是请不要使用过时的 gets()
函数。请改用fgets
。
在回答您的问题时,如果 x
是指向有效非空字符串的指针,则 strlen(x+1)
将始终等于 strlen(x) - 1
。
假设我们有这个字符串,x 指向它:
+---+---+---+---+---+---+
a: | H | e | l | l | o | [=10=]|
+---+---+---+---+---+---+
^
|
+---|---+
x: | * |
+-------+
即x
指向字符串的第一个字符。现在,strlen
所做的只是从 pointed-to 字符开始并计算字符数,直到找到终止的 '[=21=]'
.
所以如果我们增加 x
,现在它指向 'e'
(也就是说,它指向字符串 "ello"),像这样:
+---+---+---+---+---+---+
a: | H | e | l | l | o | [=11=]|
+---+---+---+---+---+---+
^
|
/
/
/
|
+---|---+
x: | * |
+-------+
所以 strlen
的长度会少一个。
脚注:我想起了一个我不止一次遇到的有趣错误。当您使用 malloc
为字符串分配 space 时,您始终必须记住包含 space 作为终止 '[=21=]'
。只是不要这样做:
char *p = malloc(strlen(str + 1));
我的co-worker就干过一次(不,真的,那是co-worker,不是我!),很难追查,因为太容易看有错误的代码,看不到它不是
char *p = malloc(strlen(str) + 1);
本应如此。
它给你一个更小的。 x += i
大致相当于伪代码 x = substr(x, i)
。 (请注意,如果 i
的长度超过 x
的长度,就会发生不好的事情。)
它将比以前少 return。在 C 中,字符串只是指向第一个字符的内存地址的指针,所以如果你的字符串是
"ABCDEF"
如果您增加指针,而不是指向 'A' 的指针,它将指向 'B',因此新字符串是
"BCDEF"
strlen("BCDEF")
是 5 而 strlen("ABCDEF")
是 6。
您的代码:
char A[50],*x;
gets(A);
x=&A[0];
strlen(x)
was supposed to give me the length of the string
what happens as I increment x?
Does strlen(x
) now give me the same
value as before or a smaller one and if so, why does it happen?
好吧,答案比人们想象的要复杂。答案是:视情况而定!
通过声明 A[50]
,编译器将在堆栈上分配 50
个字节 ,这些字节未初始化为任何值。
假设 A
的内容恰好是
A[50] = { '5', '1', '2', '3', 0 /*.............*/ };
然后考虑两种情况:
a) 用户输入:<enter>
b) 用户输入:'7'<enter>
数组的内容A
会有所不同
a) { 0, '1', '2', '3', 0 /*.............*/ };
b) { '7', 0, '2', '3', 0 /*.............*/ };
strlen
的结果可能会让您大吃一惊:
这是测试程序和结果:
#include <stdio.h>
#include <string.h>
int main(void)
{
char A[50] = { '5', '1', '2', '3', 0 };
char *x;
gets(A);
x=&A[0];
for (int i=0; i < 5; i++)
printf("%d: %02X\n", i, A[i]);
printf("strlen(x) = %zu\n", strlen(x));
printf("strlen(x+1)= %zu\n", strlen(x+1));
return 0;
}
测试:
<enter>
0: 00
1: 31
2: 32
3: 33
4: 00
strlen(x) = 0
strlen(x+1)= 3
7<enter>
0: 37
1: 00
2: 32
3: 33
4: 00
strlen(x) = 1
strlen(x+1)= 0
如您所知,strlen
计算从起始位置到遇到第一个 '[=27=]'
的字符数。如果起始字节等于 '[=27=]'
比 strlen(x)
=
0
.
对于场景 a) strlen(x)
,strlen(x+1)
将是 0
和 3
对于场景 b) strlen(x)
,strlen(x+1)
将是 1
和 0
.
请不要使用 gets
(Why is the gets function so dangerous that it should not be used?) 并且还要注意我以十六进制格式打印 ASCII
个字符,例如 '2' = 0x32
.
我已经对 strlen()
做了一些研究并有一个问题。
假设我有一个 50
元素数组和一个指向第一个元素的指针,意思是:
char A[50],*x;
gets(A);
x=&A[0];
据我了解,strlen(x)
应该会给出字符串的长度。
我的问题是,当我递增 x
时到底发生了什么?
首先,很抱歉跑题了,但是请不要使用过时的 gets()
函数。请改用fgets
。
在回答您的问题时,如果 x
是指向有效非空字符串的指针,则 strlen(x+1)
将始终等于 strlen(x) - 1
。
假设我们有这个字符串,x 指向它:
+---+---+---+---+---+---+
a: | H | e | l | l | o | [=10=]|
+---+---+---+---+---+---+
^
|
+---|---+
x: | * |
+-------+
即x
指向字符串的第一个字符。现在,strlen
所做的只是从 pointed-to 字符开始并计算字符数,直到找到终止的 '[=21=]'
.
所以如果我们增加 x
,现在它指向 'e'
(也就是说,它指向字符串 "ello"),像这样:
+---+---+---+---+---+---+
a: | H | e | l | l | o | [=11=]|
+---+---+---+---+---+---+
^
|
/
/
/
|
+---|---+
x: | * |
+-------+
所以 strlen
的长度会少一个。
脚注:我想起了一个我不止一次遇到的有趣错误。当您使用 malloc
为字符串分配 space 时,您始终必须记住包含 space 作为终止 '[=21=]'
。只是不要这样做:
char *p = malloc(strlen(str + 1));
我的co-worker就干过一次(不,真的,那是co-worker,不是我!),很难追查,因为太容易看有错误的代码,看不到它不是
char *p = malloc(strlen(str) + 1);
本应如此。
它给你一个更小的。 x += i
大致相当于伪代码 x = substr(x, i)
。 (请注意,如果 i
的长度超过 x
的长度,就会发生不好的事情。)
它将比以前少 return。在 C 中,字符串只是指向第一个字符的内存地址的指针,所以如果你的字符串是
"ABCDEF"
如果您增加指针,而不是指向 'A' 的指针,它将指向 'B',因此新字符串是
"BCDEF"
strlen("BCDEF")
是 5 而 strlen("ABCDEF")
是 6。
您的代码:
char A[50],*x;
gets(A);
x=&A[0];
strlen(x)
was supposed to give me the length of the stringwhat happens as I increment
x?
Doesstrlen(x
) now give me the same value as before or a smaller one and if so, why does it happen?
好吧,答案比人们想象的要复杂。答案是:视情况而定!
通过声明 A[50]
,编译器将在堆栈上分配 50
个字节 ,这些字节未初始化为任何值。
假设 A
的内容恰好是
A[50] = { '5', '1', '2', '3', 0 /*.............*/ };
然后考虑两种情况:
a) 用户输入:<enter>
b) 用户输入:'7'<enter>
数组的内容A
会有所不同
a) { 0, '1', '2', '3', 0 /*.............*/ };
b) { '7', 0, '2', '3', 0 /*.............*/ };
strlen
的结果可能会让您大吃一惊:
这是测试程序和结果:
#include <stdio.h>
#include <string.h>
int main(void)
{
char A[50] = { '5', '1', '2', '3', 0 };
char *x;
gets(A);
x=&A[0];
for (int i=0; i < 5; i++)
printf("%d: %02X\n", i, A[i]);
printf("strlen(x) = %zu\n", strlen(x));
printf("strlen(x+1)= %zu\n", strlen(x+1));
return 0;
}
测试:
<enter>
0: 00
1: 31
2: 32
3: 33
4: 00
strlen(x) = 0
strlen(x+1)= 3
7<enter>
0: 37
1: 00
2: 32
3: 33
4: 00
strlen(x) = 1
strlen(x+1)= 0
如您所知,strlen
计算从起始位置到遇到第一个 '[=27=]'
的字符数。如果起始字节等于 '[=27=]'
比 strlen(x)
=
0
.
对于场景 a) strlen(x)
,strlen(x+1)
将是 0
和 3
对于场景 b) strlen(x)
,strlen(x+1)
将是 1
和 0
.
请不要使用 gets
(Why is the gets function so dangerous that it should not be used?) 并且还要注意我以十六进制格式打印 ASCII
个字符,例如 '2' = 0x32
.