• 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"
    

    是看不到的,除非单独查看那一位的字符

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

    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("
    file offset: %ld
    ", ftell(fp));
        if (ferror(fp)) {
            perror("ferror");
            exit(1);
        }
      
        fclose(fp);
      
        return 0;
    } 
    /* output:
    lin
    file offset: 3                                                              
    */
    

      

  • 相关阅读:
    清除浮动的集中方式
    css动画
    [Asp.net]c#中的斜杠和反斜杠
    C# ASPX页面做上传提示:超过了最大请求长度,解决方法
    在asp.net中用客户端上传控件上传文件( 需要注意的)
    jquery clone 与 clone(true) 的区别
    【转载】用div+css模拟表格对角线
    .net2.0中的Json序列化数据
    jquery操作checkbox的选中与不选中,解决只有一次有用。
    转:不同服务器数据库之间的数据操作[含远程数据库备份]
  • 原文地址:https://www.cnblogs.com/Harley-Quinn/p/6492565.html
Copyright © 2020-2023  润新知