简体   繁体   English

关于 C 中 printf() 的混淆

[英]confusion about printf() in C

I'm trying to hexdump a file with following code:我正在尝试使用以下代码对文件进行 hexdump:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define SIZE 16

void pre_process(char buffer[],int len);

int main(int argc, char **argv){
    if(argc == 2){
        char *file = argv[1];
        FILE *input = fopen(file,"r");
        char buffer[SIZE];
        char *tmp = malloc(4);
        while(!feof(input)){ 
            printf("%06X  ",ftell(input)); /*print file pos*/
            fread(buffer,1,SIZE,input); /*read 16 bytes with buffer*/
           
            for (int i=0;i<SIZE;i += 4){ /*print each 4 bytes with hex in buffer*/
                memcpy(tmp,buffer+i,4);
                printf("%08X  ",tmp);
            }
            printf("*");
            pre_process(buffer,SIZE); /*print origin plain-text in buffer. subsitute unprint char with '*' */
            printf("%s",buffer);
            printf("*\n");
        }
        free(tmp);
        fclose(input);
   }
}

void pre_process(char buffer[],int len){
    for (int i=0;i<len;i++){
        if(isblank(buffer[i]) || !isprint(buffer[i]))
            buffer[i] = '*';
    }
}

reading a slice from lord of ring,result as below: enter image description here从指环王那里读取切片,结果如下:在此处输入图像描述

so, why the hex code are all the same?那么,为什么十六进制代码都一样? It looks like something wrong with printf("%08X ",tmp); printf("%08X ",tmp);看起来有问题thx for your help.谢谢你的帮助。

The answer lies here:答案就在这里:

memcpy(tmp,buffer+i,4);
printf("%08X  ",tmp);

memcpy as you might already be aware, copies 4 bytes from buffer+i to where tmp is pointing to.您可能已经知道memcpy4个字节从buffer+i复制到tmp指向的位置。

Even though this is done in a loop, tmp continues to hold the address of a specific location, which is never changed.即使这是在循环中完成的, tmp仍会继续保存特定位置的地址,该地址永远不会改变。 The contents at that address/location in memory are updated with every memcpy() call.每次调用memcpy()都会更新 memory 中该地址/位置的内容。

In a nutshell, the house remains there only, hence the address remains the same but people change places, new people arrive as older ones are wiped out!简而言之,房子只留在那里,因此地址保持不变,但人们换了地方,新的人来了,老的人被消灭了!

Also, there is plenty to improve/fix here.此外,这里还有很多需要改进/修复的地方。 I recommend starting with enabling warnings by -Wall option with your compiler.我建议从编译器的-Wall选项启用警告开始。

tmp stores the address of a buffer; tmp存储缓冲区的地址 that address never changes.该地址永远不会改变。 What you want to print is the contents of the buffer that tmp points to .您要打印的是tmp指向的缓冲区的内容。 In this case, tmp point to a buffer of 4 char s;在这种情况下, tmp指向一个 4 char的缓冲区; if you write如果你写

printf( "%08X ", *tmp );

you'll only print the value of the first element - since tmp has type char * , the expression *tmp has type char and is equivalent to writing tmp[0] .您将只打印第一个元素的值 - 由于tmp的类型为char * ,因此表达式*tmp的类型为char并且等效于编写tmp[0]

To treat what's in those bytes as an unsigned int (which is what the %X conversion specifier expects), you need to cast the pointer to the correct type before dereferencing it:要将这些字节中的内容视为unsigned int (这是%X转换说明符所期望的),您需要在取消引用之前指针转换为正确的类型:

printf( "%08X ", *(unsigned int *) tmp );

We first have to cast tmp from char * to unsigned int * , then dereference the result to get the unsigned int equivalent of those four bytes.我们首先必须将tmpchar *转换为unsigned int * ,然后取消引用结果以获得这四个字节的unsigned int等价物。

This assumes sizeof (unsigned int) == 4 on your system - to be safe, you should write your malloc call as这假设您的系统上的sizeof (unsigned int) == 4 - 为了安全起见,您应该将malloc调用编写为

char *tmp = malloc( sizeof (unsigned int) );

and

for ( int i = 0; i < SIZE; i += sizeof (unsigned int) )
{
  memcpy( tmp, buffer + i, sizeof (unsigned int) );
  ...
}

instead.反而。

You should not use feof as your loop condition - it won't return true until after you try to read past the end of the file, so your loop will execute once too often.您不应该使用feof作为循环条件 - 在您尝试读取文件末尾之前它不会返回 true,因此您的循环会经常执行一次。 You'll want to look at the return value of fread to determine whether you've reached the end of the file.您需要查看fread的返回值以确定您是否已到达文件末尾。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM