使用C从文件中读取字节

时间:2013-09-09 18:48:13

标签: c pointers

我在C中编写了一个程序,它将从自己的地址空间读取特定内存地址的字节。

它的工作原理如下:

  1. 首先从文件中读取DWORD。
  2. 然后它使用此DWORD作为内存地址,并从当前进程的地址空间中的此内存地址读取一个字节。
  3. 以下是代码摘要:

    FILE *fp;
    char buffer[4];
    
    fp=fopen("input.txt","rb");
    
    // buffer will store the DWORD read from the file
    
    fread(buffer, 1, 4, fp);
    
    printf("the memory address is: %x", *buffer);
    
    // I have to do all these type castings so that it prints only the byte example:
    // 0x8b instead of 0xffffff8b
    
    printf("the byte at this memory address is: %x\n", (unsigned)(unsigned char)(*(*buffer)));
    
    // And I perform comparisons this way
    
    if((unsigned)(unsigned char)(*(*buffer)) == 0x8b)
    {
        // do something
    }
    

    当这个程序工作时,我想知道是否有另一种方法从特定的内存地址读取字节并执行比较?因为每一次,我都需要编写所有类型的铸件。

    此外,现在当我尝试使用以下语法将字节写入文件时:

    // fp2 is the file pointer for the output file
    fwrite(fp2, 1, 1, (unsigned)(unsigned char)(*(*buffer)));
    

    我收到警告:

    test.c(64) : warning C4047: 'function' : 'FILE *' differs in levels of indirectio
    n from 'unsigned int'
    test.c(64) : warning C4024: 'fwrite' : different types for formal and actual para
    meter 4
    

    感谢。

3 个答案:

答案 0 :(得分:1)

注意fwrite

的定义
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

这意味着问题最后部分的警告是因为你应该从字符指针写入而不是写出字符的实际值。

您可以通过将从文件中读取的指针指定给另一个正确类型的变量来删除额外的类型转换。

考虑的例子:

#include <stdio.h>
int main() {
  union {
    char buffer[8];
    char *character;
    long long number;
  } indirect;
  /* indirect is a single 8-byte variable that can be accessed
   * as either a character array, a character pointer, or as
   * an 8-byte integer! */
  char *x = "hi";
  long long y;
  char *z;
  printf("stored in the memory beginning at x: '%s'\n", x); /* 'hi' */
  printf("bytes used to represent the pointer x: %ld\n", sizeof(x)); /* 8 */
  printf("exact value (memory location) of (pointed to by) the pointer x: %p\n", x); /* 4006c8 */
  y = (long long) x;
  printf("%llx\n", y); /* 4006c8 */
  z = (char *) y;
  printf("%s\n", z); /* 'hi' */
  /* the cool part--we can access the exact same 8 bytes of data
   * in three different ways, as a 64-bit character pointer,
   * as an 8-byte character buffer, or as
   * an 8-byte integer */
  indirect.character = z;
  printf("%s\n", indirect.character); /* 'hi' */
  printf("%s\n", indirect.buffer); /* binary garbage which is the raw pointer  */
  printf("%lld\n", indirect.number); /* 4196040 */
  return 0;
}

顺便说一下,从记忆中读取任意位置似乎很令人担忧。 (你说你正在从程序自己的地址空间中的特定内存地址读取,但是你如何确定?)

答案 1 :(得分:1)

您可以使用C语言union构造来表示所示类型的别名

typedef union {
      char char[4];
      char *pointer;
   } alias;

alias buffer;

这假定采用32位架构(您可以在编译时调整4,但还需要更改fread()字节数。)

然后,您只需使用*(buffer.pointer)来引用内存位置的内容。

从您的问题来看,该应用程序并不清楚,并且该技术似乎容易出错。当事情发生变化时,您如何考虑内存中地址的移动?使用链接器映射来提取位置的符号信息以避免绝对地址可能有一些意义。

答案 2 :(得分:0)

    fp=fopen("input.txt","rb");

该文件的扩展名为.txt,您尝试将其作为二进制文件读取。请相应地命名文件。如果在Windows上,请使用.bin扩展名为二进制文件。在Linux文件扩展名上无所谓。

    // buffer will store the DWORD read from the file

    fread(buffer, 1, 4, fp);

如果要读取4个字节,请声明一个unsinged int变量并读入4个字节,如下所示

    fread(&uint, 1, 4, fp);

为什么要使用字符数组?这是不正确的。

    printf("the memory address is: %x", *buffer);

你想在这做什么? buffer是指向const char的指针,上面的语句打印数组中第一个字符的十六进制值。以上陈述等于

   printf("the memory address is: %x", buffer[0]);

   (*(*buffer)

这是如何工作的?是不是有任何编译器警告和错误?是Windows还是Linux? (* buffer)是一个char并再次取消引用它应该抛出和错误,除非正确转换,我发现你没有这样做。