复制包含长整数的字符串

Copying strings containing longs

我能够 "pack" 长字符串数组。现在,如果我 memcpy 包含 long 数组的字符串,内容就会丢失。这里有我的代码:

#include <stdio.h>
#include <string.h>

int main() 
{
    unsigned char arr[40];
    unsigned char arr2[40];
    unsigned int i = 0 ;
    long f=0;

    for ( i = 0 ; i < 5 ; i++ ) {
        f = i + 1 ;
        *((long *)arr + i*sizeof(long)) = f ;
    }
    memcpy(arr2, arr, 40);
    for ( i = 0 ; i < 5 ; i++ ) {
        f = *((long *)arr2 + i*sizeof(long)) ;
        printf("f =%ld from arr2 sizeof %zu\n", f, (size_t)(i*sizeof(long)));
    }
    for ( i = 0 ; i < 5 ; i++ ) {
        f = *((long *)arr + i*sizeof(long)) ;
        printf("f =%ld from arr sizeof %zu\n", f, (size_t)(i*sizeof(long)));
    }
}   

这是输出:

f =1 from arr2 sizeof 0
f =0 from arr2 sizeof 8
f =1 from arr2 sizeof 16
f =140734674541394 from arr2 sizeof 24
f =140734674541702 from arr2 sizeof 32
f =1 from arr sizeof 0
f =2 from arr sizeof 8
f =3 from arr sizeof 16
f =4 from arr sizeof 24
f =5 from arr sizeof 32

如您所见,我可以读取存储在 "arr" 中但不能来自 "arr2" 的长值。有什么线索吗?

问题是你将(腐烂的)指针 arrarr2 转换为 long*,然后你不再有一个数组 ob 字节,而是一个 long 所以你的指针运算将不再正确(它假定指针是 char 的指针)。放弃乘法,只做例如

*((long *)arr + i) = f ;

(long *)arr2 + i*sizeof(long) 将由于越界缓冲区访问而导致未定义的行为。 (long *)arr2 + i 已经在 sizeof(long) 中编制索引。

所以你写的方式超过了 arr 的末尾,但只复制了它的前 40 个字节。除此之外,没有必要对未定义的行为进行推理。如果你幸运的话,它就会崩溃,从而立即表明你做错了什么。

1添加到指针psizeof(*p) == 8时,相当于将8添加到char指针。 换句话说,一旦你转换了指针,就没有必要再缩放索引了。

#include <stdio.h>
#include <string.h>

int main() 
{
    unsigned char arr[40];
    unsigned char arr2[40];
    unsigned int i = 0 ;
    long f=0;

    for ( i = 0 ; i < 5 ; i++ ) {
        f = i + 1 ;
        *((long *)arr + i) = f ;
    }
    memcpy(arr2, arr, 40);
    for ( i = 0 ; i < 5 ; i++ ) {
        f = *((long *)arr2 + i) ;
        printf("f =%ld from arr2 sizeof %zu\n", f, (size_t)(i*sizeof(long)));
    }
    for ( i = 0 ; i < 5 ; i++ ) {
        f = *((long *)arr + i) ;
        printf("f =%ld from arr sizeof %zu\n", f, (size_t)(i*sizeof(long)));
    }
}   

虽然从技术上讲,您的程序仍然是未定义,因为它违反了严格别名。您可以通过使用 long 数组并通过 char 指针访问它,使用动态内存而不是 stack-allocated 数组,或者通过在循环的每次迭代中将 char 字节 memcpying 为临时 long 来解决这个问题(gcc 可以接受提示,最后一个解决方案最终并没有变得效率低下,尽管看起来是一个看似昂贵的函数调用。

你的问题出在几个表达式上

*((long *)arr + i*sizeof(long))

您需要决定是对 char 指针还是 long 指针进行指针运算。

如果你想在 char 指针上做,你从 arr 开始,添加 i*sizeof(long),然后转换为 long 指针:

         arr
         arr + i*sizeof(long)
(long *)(arr + i*sizeof(long))

另一方面,您也可以先将arr转换为long指针。但是,您不必乘以 sizeof(long),因为 long 指针的算术以 sizeof(long) 为单位,而不是字节:

         arr
 (long *)arr
((long *)arr + i)