GDB調試字符數組時指針和數組區別的體現


測試ftell函數時發現報錯,先貼源碼

// File Name: ftell.c                                                       
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char** argv)
{
    FILE* fp = fopen("myfile.in", "r");
    if (fp == NULL) {
        perror("fopen error");
        exit(1);
    }
    char buf[4];
    fgets(buf, 4, fp);
    if (fputs(buf, fp) == EOF) {
        perror("fputs error");
        exit(1);
    }
    if (ferror(fp)) {
        perror("ferror");
        exit(1);
    }
 
    return 0;
}

錯誤信息如下 

於是用GDB調試,在fputs處設斷點,輸出字符數組

突然我想查看每個字符的值,於是看到的是這個

啊,突然想起來,buf的類型並不是char*,雖然如果作為函數輸入參數的話會被當成char*,但是buf的實際類型是char (*)[4]

所以輸出的是4個char (*)[4],也就是buf開始的16個字符

但是我使用p &buf[0]@sizeof(buf)會報錯Only values in memory can be extended with '@'

想着可能需要類型轉換,加了(char*)后還是報錯,原來是因為只有值才能狗用@擴展,GDB會取得值的指針,然后用@往前移動

於是幾個調試如下

(gdb) p buf
$1 = "lin"
(gdb) p &buf[0]
$2 = 0x7fffffffde90 "lin"
(gdb) p &buf[0]@4
Only values in memory can be extended with '@'.
(gdb) p (char*)&buf[0]@4
Only values in memory can be extended with '@'.
(gdb) p *(char*)&buf[0]@4
$3 = "lin"
(gdb) p *buf@4
$4 = "lin"

\0是看不到的,除非單獨查看那一位的字符

(gdb) p (int)buf[3]
$5 = 0
(gdb) p buf[3]
$6 = 0 '\000'

OK,繼續解決fputs出錯的問題吧。

其實perror顯示的信息很完美了,錯誤原因是Bad file descriptor,在這里文件描述符藏在FILE*指向的對象里,錯誤也就是fp。

這里我是要把信息輸出到屏幕上,所以fputs的第二個輸入參數應該是標准輸出stdout,而不是我打開的文件指針fp。

由於fopen選擇了讀取模式,所以無法進行寫入。

試着把fopen第二個參數改成"r+",允許寫入,結果如下

該文本之前第1行是line 01,現在被改成了linlin1,因為讀取3個字符時偏移量是3(即'e'所在位置),然后又寫入了3個字符,所以"lin"替代的是"e 0"。

這里也可以發現,用"r"而不是"r+"來禁止寫入能夠檢查出一些容易忽視的錯誤。

修改后如下

// File Name: ftell.c   
#include <stdio.h>
#include <stdlib.h>
  
int main(int argc, char** argv)     
{ 
    FILE* fp = fopen("myfile.in", "r");
    if (fp == NULL) {
        perror("fopen error");      
        exit(1);
    }
    char buf[4];
    fgets(buf, 4, fp);
    if (fputs(buf, stdout) == EOF) {
        perror("fputs error");      
        exit(1);
    }
    printf("\nfile offset: %ld\n", ftell(fp));
    if (ferror(fp)) {
        perror("ferror");
        exit(1);
    }
  
    fclose(fp);
  
    return 0;
} 
/* output:
lin
file offset: 3                                                              
*/

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM