gpt4 book ai didi

将单个字节连接到字节序列

转载 作者:行者123 更新时间:2023-11-30 19:40:24 25 4
gpt4 key购买 nike

新来的,如果我没有适本地提出问题,请告诉我。

我正在尝试从文件数据动态创建字节序列。这是我遇到问题的代码(我意识到打印是一种糟糕的调试方式,但问题似乎微不足道,而且我在 gdb 中没有看到太多其他内容)。编辑以包含一个编译示例。实际代码要长得多,不想给任何人带来负担。

#include <stdio.h>
#include <stdlib.h>

int main() {
FILE *fpt;
unsigned char *file;
int file_size, i;

// File ops
fpt = fopen("test.txt", "rb");
fseek(fpt, 0L, SEEK_END);
file_size = ftell(fpt);
fseek(fpt, 0L, SEEK_SET);
file = (unsigned char *) calloc(sizeof(unsigned char), file_size);
fread(file, file_size, sizeof(unsigned char), fpt);
fclose(fpt);

int str_len = 1;
unsigned char *string = (unsigned char *)calloc(sizeof(unsigned char), str_len);
unsigned char *next_byte = (unsigned char *)calloc(sizeof(unsigned char),1);
i = 1;
*string = *file;

// Build byte sequence
while (i < file_size) {
*next_byte = *(file + i);
str_len++;
string = realloc(string, str_len);
if (i==1)printf("string+char = %04X\n", (*string << 8) | *next_byte);
*string = (*string << 8) | *next_byte;
if (i==1)printf("string+char = %04X\n", *string);
i++;
}
return 0;
}
// I realize I need to free memory

假设我的 test.txt 仅包含

ABC

用十六进制编辑器查看我会看到

41 42 43 0A

两次打印的输出是:

字符串+字符 = 4142 字符串+字符 = 0042

我的问题是为什么第一个打印给出了我想要的结果,而第二个打印却没有?我意识到 unsigned char 是一个字节,因此向左移动 8 位应该得到零。我不明白为什么直接打印位运算会得到我想要的结果。

是否有更好的方法将单个字节连接到字节序列?

最佳答案

这对我来说有点困惑。

我无法看出代码示例的行为与您预期的不同。
让我举例说明...

我在示例代码中添加了一些打印,请参阅下面的 concat.c 了解完整的程序,但让我们重点关注 while 循环的移位。仅供引用,到目前为止的所有内容(从“test.txt”等加载 4 个字节)似乎都按预期工作。

具体代码片段如下:

移位片段,原始

if (i==1)printf("string+char = %04X\n",  (*string << 8) | *next_byte);
*string = (*string << 8) | *next_byte;
if (i==1)printf("string+char = %04X\n", *string);

我认为带有 %04x 的 printf() 表明 *string 中的内容比实际存在的内容更多。

转变片段,修订

我修改了移位表达式,以使用一系列单独的变量来分解我认为它正在执行的操作,以便我可以查看每个变量的值。

       /* original:  *string = (*string << 8) | *next_byte; */
printf(" explicit shifting...\n");
unsigned char a = *string;
printf(" Lets print 'a' as %%x and %%04x just to verify zero padding doesn't change anything.\n");
printf(" a=%x a=%04x sizeof(a)=%ld\n", a, a, sizeof(a) );
unsigned char b = a << 8;
printf(" b=%x : b = a << 8 yielded all zero bits.\n", b);
unsigned char c = *next_byte;
printf(" c=%x : c = *next_byte as expected.\n", c);
unsigned char d = b | c;
printf(" d=%x : d bitwise-or of 0 w/c yields, well, c.\n", d);
// pick up with original...
// note that we're always overwriting string[0].
// the following is the same as saying:
// string[0] = d; // assuming 'd' is assigned as above.
*string = (*string << 8) | *next_byte;
// If you want to use shift and accumulate 4 bytes
// you probably want *string to be a long.
printf(" after shift: string[0]=%x, next_byte[0]=%x\n", string[0], next_byte[0] );
if (i==1) printf("string+char = %04X\n", *string);

轮类片段的输出,修订

以下是第一次执行 while 循环。
i = 1,next_byte = 0x42。
(完整输出见下文)

   explicit shifting...
Lets print 'a' as %x and %04x just to verify zero padding doesn't change anything.
a=41 a=0041 sizeof(a)=1
b=0 : b = a << 8 yielded all zero bits.
c=42 : c = *next_byte as expected.
d=42 : d bitwise-or of 0 & c yields, well, c.
after shift: string[0]=42, next_byte[0]=42
string+char = 0042

原始程序的最后一行显示 string+char = 0042 但这不是因为 printf 格式显示 printf("string+char = %04X\n",*字符串);?我的意思是... *string 的底层值只是 0x42,这就是它应该做的,是吗?

话虽如此,我认为这与“移位”无关,因为它不断地覆盖字符串的第一个字节,例如字符串[0]。

也许这就是实际的问题?

这是另一个输出片段,这是我在 while 循环之后添加的一些打印内容(再次参见下面的 concat.c)以获取完整代码。

After while loop.  just for fun, let's print out string...
string[0]=0a (string+0)=0x114d010
string[1]=00 (string+1)=0x114d011
string[2]=00 (string+2)=0x114d012
string[3]=00 (string+3)=0x114d013
done.
$

在这里你可以看到string的值非常空。
字符串实际上保留了最后一个字符,0x0a。
由于我不清楚的原因,字符串是用第一个字符“A”初始化的, while 循环开始之前。好歹...
在while循环期间,string已被重新分配多次。 (例如 string = realloc(string, str_len); - 为什么这样做,顺便说一句?)

那么...您是否想要通过移位和按位或将字符“ABC\n”级联到字符串

如果你有类似 long my4bytes; 而不是 string 我可以看到移位和按位 - 或者在收集各个字节时“有帮助”。
但是...字符串本质上是一个字节数组(好吧,无符号字符数组)。

假设您想将 string 保留为字节数组,我认为您最好这样做:string[i] = *next_byte;


所以。您可以通过多种方式来编写它; while 循环有点困惑,所以我把它留给你。 (这是可以理解的......我可以想象困惑是因为您将原始示例削减到足够小以发布在原始问题中)。


无论如何,这是否有助于为您指明有用的方向?
或者...我是否错过了最初问题的意图?

concat.c 的示例输出

$ cat test.txt 
ABC
$ hexdump -C test.txt
00000000 41 42 43 0a |ABC.|
00000004
$ gcc concat.c
$ ./a.out
file_size=4
file[0]=41 (file+0)=0x114d240
file[1]=42 (file+1)=0x114d241
file[2]=43 (file+2)=0x114d242
file[3]=0a (file+3)=0x114d243

--- Build byte sequence
while: i=1
file[i]=42 file=0x114d240
next_byte[0]=42 next_byte=0x114d030
string+char = 4142
before shift: string[0]=0041, next_byte[0]=0042
explicit shifting...
Lets print 'a' as %x and %04x just to verify zero padding doesn't change anything.
a=41 a=0041 sizeof(a)=1
b=0 : b = a << 8 yielded all zero bits.
c=42 : c = *next_byte as expected.
d=42 : d bitwise-or of 0 w/c yields, well, c.
after shift: string[0]=42, next_byte[0]=42
string+char = 0042
while: i=2
file[i]=43 file=0x114d240
next_byte[0]=43 next_byte=0x114d030
before shift: string[0]=0042, next_byte[0]=0043
explicit shifting...
Lets print 'a' as %x and %04x just to verify zero padding doesn't change anything.
a=42 a=0042 sizeof(a)=1
b=0 : b = a << 8 yielded all zero bits.
c=43 : c = *next_byte as expected.
d=43 : d bitwise-or of 0 w/c yields, well, c.
after shift: string[0]=43, next_byte[0]=43
while: i=3
file[i]=0a file=0x114d240
next_byte[0]=0a next_byte=0x114d030
before shift: string[0]=0043, next_byte[0]=000a
explicit shifting...
Lets print 'a' as %x and %04x just to verify zero padding doesn't change anything.
a=43 a=0043 sizeof(a)=1
b=0 : b = a << 8 yielded all zero bits.
c=a : c = *next_byte as expected.
d=a : d bitwise-or of 0 w/c yields, well, c.
after shift: string[0]=a, next_byte[0]=a

After while loop. just for fun, let's print out string...
string[0]=0a (string+0)=0x114d010
string[1]=00 (string+1)=0x114d011
string[2]=00 (string+2)=0x114d012
string[3]=00 (string+3)=0x114d013
done.
$

concat.c

#include <stdio.h>
#include <stdlib.h>

int main() {
FILE *fpt;
unsigned char *file;
int file_size, i;

// File ops
fpt = fopen("test.txt", "rb");
fseek(fpt, 0L, SEEK_END);
file_size = ftell(fpt);
printf("file_size=%d\n", file_size);
fseek(fpt, 0L, SEEK_SET);
//file = (unsigned char *) calloc(sizeof(unsigned char), file_size);
file = calloc( file_size, file_size);
fread(file, file_size, sizeof(unsigned char), fpt);
fclose(fpt);

int str_len = 1;
unsigned char *string =
(unsigned char *)calloc(sizeof(unsigned char), str_len);
unsigned char *next_byte =
(unsigned char *)calloc(sizeof(unsigned char),1);
i = 1;
//printf(" file[0]=%02x file=%p\n", file[0], file );
//printf("before: string[0]=%02x string=%p\n", string[0], string );
*string = *file;
//printf("after: string[0]=%02x string=%p\n", string[0], string );

for( int idx = 0; idx < file_size; ++idx ) {
printf(" file[%d]=%02x (file+%d)=%p\n", idx, file[idx], idx, (file+idx) );
}
printf("\n--- Build byte sequence\n");
while (i < file_size) {
printf("while: i=%d\n", i );
printf(" file[i]=%02x file=%p\n", file[i], file );
*next_byte = *(file + i);
printf(" next_byte[0]=%02x next_byte=%p\n", next_byte[0], next_byte );
str_len++;
string = realloc(string, str_len);
if (i==1) printf("string+char = %04X\n", (*string << 8) | *next_byte);
printf(" before shift: string[0]=%04x, next_byte[0]=%04x\n", string[0], next_byte[0] );
/* original: *string = (*string << 8) | *next_byte; */
printf(" explicit shifting...\n");
unsigned char a = *string;
printf(" Lets print 'a' as %%x and %%04x just to verify zero padding doesn't change anything.\n");
printf(" a=%x a=%04x sizeof(a)=%ld\n", a, a, sizeof(a) );
unsigned char b = a << 8;
printf(" b=%x : b = a << 8 yielded all zero bits.\n", b);
unsigned char c = *next_byte;
printf(" c=%x : c = *next_byte as expected.\n", c);
unsigned char d = b | c;
printf(" d=%x : d bitwise-or of 0 w/c yields, well, c.\n", d);
// pick up with original...
// note that we're always overwiting string[0].
// the following is the same as saying:
// string[0] = d; // ssuming 'd' is assigned as above.
*string = (*string << 8) | *next_byte;
// If you want to use shift and accumulate 4 bytes
// you probably want *string to be a long.
printf(" after shift: string[0]=%x, next_byte[0]=%x\n", string[0], next_byte[0] );
if (i==1) printf("string+char = %04X\n", *string);
i++;
}
printf("\nAfter while loop. just for fun, let's print out string...\n");
for(int idx = 0; idx < str_len; ++idx ) {
printf(" string[%d]=%02x (string+%d)=%p\n", idx, string[idx], idx, (string+idx) );
}
printf("done.\n");
return 0;
}
// I realize I need to free memory

附:打印实际上是解决问题的好方法;不要犹豫,继续添加它们,直到您的代码所做的事情变得显而易见。

关于将单个字节连接到字节序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35354728/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com