我有以下程式,它是通過創建新的字符指標 (newRow)、為新指標分配記憶體、將第一個字符設定為 'a'、復制先前的更新字串到新字串中 'a' 之后的位置,然后將原始字串重新分配給新的字符指標。但是,有兩件事不像我預期的那樣作業。
首先,我希望對于每次迭代,newRow 的地址應該改變,因為它是由 malloc 新創建的(并且前一個還沒有被釋放),然后一旦 newRow 被分配給 row,row 的地址應該是以前的迭代newRow,但事實并非如此。
其次,在第 18 次迭代之后,額外的字符被附加到字串的末尾,我不知道為什么。
下面是在 Linux 上編譯的源代碼gcc -Wall -Wextra -pedantic -std=c99 -g c_programs/playground.c,以及運行程式的輸出。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char lineBuf[] = "hello";
char *row = (char *)malloc(strlen(lineBuf) 1);
strcpy(row, lineBuf);
for (size_t i = 0; i < 40; i )
{
char *newRow = (char *)malloc(strlen(row) 1);
printf("%ld: &row: %p, &newRow: %p, len: %ld", i, (void *)&row, (void *)&newRow, strlen(row));
newRow[0] = 'a';
strcpy(newRow 1, row);
printf(", string is: %s\n", newRow);
row = newRow;
}
}
0: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 5, string is: ahello
1: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 6, string is: aahello
2: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 7, string is: aaahello
3: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 8, string is: aaaahello
4: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 9, string is: aaaaahello
5: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 10, string is: aaaaaahello
6: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 11, string is: aaaaaaahello
7: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 12, string is: aaaaaaaahello
8: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 13, string is: aaaaaaaaahello
9: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 14, string is: aaaaaaaaaahello
10: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 15, string is: aaaaaaaaaaahello
11: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 16, string is: aaaaaaaaaaaahello
12: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 17, string is: aaaaaaaaaaaaahello
13: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 18, string is: aaaaaaaaaaaaaahello
14: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 19, string is: aaaaaaaaaaaaaaahello
15: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 20, string is: aaaaaaaaaaaaaaaahello
16: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 21, string is: aaaaaaaaaaaaaaaaahello
17: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 22, string is: aaaaaaaaaaaaaaaaaahello
18: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 23, string is: aaaaaaaaaaaaaaaaaaahello
19: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 25, string is: aaaaaaaaaaaaaaaaaaaahello1
20: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 26, string is: aaaaaaaaaaaaaaaaaaaaahello1
21: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 27, string is: aaaaaaaaaaaaaaaaaaaaaahello1
22: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 28, string is: aaaaaaaaaaaaaaaaaaaaaaahello1
23: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 29, string is: aaaaaaaaaaaaaaaaaaaaaaaahello1
24: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 30, string is: aaaaaaaaaaaaaaaaaaaaaaaaahello1
25: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 31, string is: aaaaaaaaaaaaaaaaaaaaaaaaaahello1
26: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 32, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaahello1
27: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 33, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaahello1
28: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 34, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1
29: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 35, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1
30: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 36, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1
31: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 37, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1
32: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 38, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1
33: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 39, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1
34: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 41, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1A
35: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 42, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1A
36: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 43, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1A
37: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 44, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1A
38: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 45, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1A
39: &row: 0x7fff662312f8, &newRow: 0x7fff66231300, len: 46, string is: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaahello1A
uj5u.com熱心網友回復:
strcpy(newRow 1, row);失敗,因為newRow指向記憶體不足(減 1)。
這會導致未定義的行為(UB)。
// char *newRow = (char *)malloc(strlen(row) 1);
char *newRow = (char *)malloc(strlen(row) 1 1);
// ^ ^
// new character \0
uj5u.com熱心網友回復:
您列印的指標值不會改變,因為您列印的是指標本身的地址,而不是它的值。嘗試使用:
printf("%zu: row: %p, newRow: %p, len: %zu", i, row, newRow, strlen(row));
(%zu是 a 的正確格式說明符size_t,它是strlen()回傳的內容,以及i變數是什么)
至于額外的字符,您沒有為新字串分配足夠的記憶體:
char *newRow = (char *)malloc(strlen(row) 1);
應該是 2因為您需要為另外一個字符和一個終止的空字符留出空間,這strlen()不算數。
還有幾點:
- 您不需要也不應該強制轉換 的回傳值
malloc(),正如 John Bollinger 指出的那樣,您應該檢查回傳值以確保malloc()成功 main()不使用命令列引數時的首選簽名int main(void)不是int main()(替代方案可能可用,但由實作定義)#include <string.h>使用時strcpy()
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/336485.html
上一篇:輸入的微小變化使程式發瘋
下一篇:在輸入中找到兩個最大的數字
