突然我想查看每个字符的值,于是看到的是这个
啊,突然想起来,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:
file offset: 3