循环开始前,
dp
指向你分配的内存的起始位置。每次迭代,将
src
指向的字符复制到
dp
指向的当前位置,并将
dp
向前移动一个内存位置。循环结束时,
dp
指向字符
p
的右侧内存位置,你在该位置赋值了
'\0'
。当你尝试使用
puts(dp)
打印字符串时,因为
dp
的内容已经改变,现在指向最后一个复制的字符的右侧位置,它将从该位置开始打印。由于
dp
指向的第一个位置是空字符,所以它将打印一个空字符串。
循环之前
+
| src |
+
|
|
V
+
| h | t | t | p | : | / | / | . . . ? | ? |
+
+
| dp |
+
|
|
V
+
| | | | | | | | . . . | |
+
循环后(使用dp = malloc(10))
+----------+
| src |
+----------+
|
|
V
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
| h | t | t | p | : | / | / | . . . | ? |
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
+----------+
| dp |
+----------+
|
|
V
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
| h | t | t | p | \0 | | | . . . | |
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
注意,puts (dp)
将从上面指向的位置开始打印输出。这不会得到预期的输出。因为您没有保存实际分配的dp
的原始地址。循环后您将无法恢复它。
循环后(使用dp = &scheme)
+----------+
| src |
+----------+
|
|
V
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
| h | t | t | p | : | / | / | . . . | ? |
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
+----------+
| dp |
+----------+
|
|
V
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
scheme[ | h | t | t | p | \0 | | | . . . | | ]
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
puts (scheme) will work because it still refers to the base of the array
puts (dp) will not work because it does not point to the base of the array
and currently points to a location pointing to null character
你上面的注释解决方案之所以有效,是因为你使用了scheme
数组来打印字符串。scheme
指的是你想要打印的数组,scheme
指的是数组的基地址,因为你没有修改它(也不能修改)。这就是为什么它从基地址开始打印,一直打印到循环后你分配的'\0'
。
你可以选择:
int i;
for (i=0; (src[i] != ':') && (src[i] != '\0'); i++)
{
dp[i] = src[i];
}
或者执行以下操作
char *dp_bak;
char *dp = malloc(10);
dp_bak = dp;
while (*src != ':')
{
*dp = *src;
src++;
dp++;
}
*dp = '\0';
dp = db_bak;
puts (dp);
char *const dp = malloc(10);
,这样编译器就不会让您犯这个错误了。 - Nemo