复制包含long的字符串

时间:2017-02-05 14:41:31

标签: c memcpy

我能够"打包"字符串长的数组。现在,如果我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

正如你所看到的,我能够阅读我在&#34; arr&#34;中存储的长值。但不是来自&#34; arr2&#34;。任何线索?

4 个答案:

答案 0 :(得分:2)

由于超出范围的缓冲区访问,

*((long *)arr + i) = f ; 将导致未定义的行为。 (long *)arr2 + i*sizeof(long)已在(long *)arr2 + i中编入索引。

所以你写了sizeof(long)的结尾,但只复制它的前40个字节。除此之外,对于未定义的行为没有任何理由。如果你幸运的话,它会崩溃,因此立即表明你做了一些非常错误的事情。

答案 1 :(得分:1)

问题是你将(衰变的)指针arrarr2强制转换为long*,然后你不再有一个数组ob字节而是一个{{1所以你的指针算术将不再正确(它假定指针是long的指针)。删除乘法,就像这样。

char

答案 2 :(得分:1)

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指针访问它,使用动态内存而不是堆栈分配的数组,或者通过在循环的每次迭代中将char字节memcp into临时long来解决这个问题(gcc可以采用提示和最后一个解决方案根本不会效率低下,尽管看似昂贵的函数调用。)

答案 3 :(得分:1)

您的问题出现在几个表达式中

*((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)