[英]C char pointer vs pointer to char array, increment dynamic allocation
我是 C 的新手,我很難理解下面的代碼塊不起作用的原因。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *src = "http://localhost";
/* THIS WORKS
char scheme[10];
char *dp = scheme;
*/
//DOESN'T WORK
char *dp = malloc(10);
while (*src != ':') {
*dp = *src;
src++;
dp++;
}
*dp = '\0';
/* WORKS
puts(scheme)
*/
//DOESN'T WORK
puts(dp);
}
預期的 output 是http
到標准輸出。 在這兩種情況下, dp
都應該是指向 char 指針數組(char **)
的指針。 但是,當使用malloc
方法時,它什么也不打印。 我通過 GDB 運行代碼,我的src
和dp
一次被刪除 1 個字符。 如果我將while
循環包含在 function 中,則調用它可以工作。 我認為原因是因為參數被評估為副本。 但是,然后我讀到 arrays 是異常並作為指針傳遞。 現在我很困惑。 我可以解決這個問題,但我試圖理解為什么這種方式行不通。
您正在循環內更改dp
dp = malloc(10);
假設dp
的值為0x42000000
while () {
dp++;
}
假設循環進行了 4 次,所以dp
的值為0x42000004
*dp = 0;
現在你把一個 null 字符放在dp
指向的地址
puts(dp);
然后你嘗試打印 null :)
保存dp
並打印保存的值
dp = malloc(10);
saveddp = dp;
/* ... */
puts(saveddp);
free(saveddp); /* for completeness */
它適用於scheme
,因為scheme
是一個數組,您無法更改該地址!
循環結束后, dp
指向分配字符串的結尾。 您需要在malloc
之后立即保存dp
並增加副本,而不是原始指針指向開頭。
在循環開始之前, dp
指向您分配的 memory 的開始。 在每次迭代中,您將src
指向的字符復制到dp
的當前指向的位置,然后前進一個dp
指向的 memory 位置。 在循環的末尾, dp
指向 memory 位置,就在您分配了'\0'
的字符p
之后。 當您嘗試使用puts (dp)
打印字符串時,因為dp
的內容已更改並且現在指向復制的最后一個字符之后的位置,它將從該位置開始打印。 它將打印一個空字符串,因為dp
指向的第一個位置是 null 字符。
+----------+
| src |
+----------+
|
|
V
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
| h | t | t | p | : | / | / | . . . ? | ? |
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
+----------+
| dp |
+----------+
|
|
V
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
| | | | | | | | . . . | |
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
+----------+
| src |
+----------+
|
|
V
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
| h | t | t | p | : | / | / | . . . | ? |
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
+----------+
| dp |
+----------+
|
|
V
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
| h | t | t | p | \0 | | | . . . | |
+-----+-----+-----+-----+-----+-----+-----+---- ----+----+
注意puts (dp)
將從上面指出的位置開始打印 print。 這不會得到預期的 output。 也因為你沒有保存你實際分配的dp
的原始地址。 您無法在循環后恢復它。
+----------+
| 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; /* Backup the base address */
while (*src != ':')
{
*dp = *src;
src++;
dp++;
}
*dp = '\0';
dp = db_bak; /* Restore the base address */
puts (dp);
實際上,如上所述,“scheme”是指向字符串開頭的指針,而 dp 是迭代器。
char *scheme = malloc(10), *dp = scheme;
...
看跌期權(方案);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.