c-memcpy(),通过引用而不是复制



上下文

学习记忆。是的,它是有效的,但如果我们能保留对我们感兴趣的数组的子部分的引用,而根本没有副本,那就太好了。

char a[] = "hello";
char b[20];
memcpy(b,a,strlen(a)-1)

问题

我们能在完全不复制的情况下,只使用指针算术来做同样的事情吗?

printf("my array is %sn",a..a+2)

例如?

该点不仅是printf,而且是代码中任何位置的任何引用,该引用由开头和结尾的指针表示。a..a+2(想想套接字,函数参数..(

对我来说,复制切片似乎有点奇怪,因为它应该是对父数组的引用。

您可以在printf中指定%s的长度,以仅显示您感兴趣的部分:

printf("my array is %.2sn", a);

您可以将原始字符串封装到某个结构中,该结构携带引用和长度:

typedef struct
{
    const char* ptr;
    size_t len;
} my_str_t;
char a[] = "hello";
my_str_t b = { a, 2 }; 
my_str_t c = { a+2, 3 }; 
send( sock, b.ptr, b.len, 0 );   // sends "he"
send( sock, c.ptr, c.len, 0 );   // sends "llo"
printf( "%.*sn", b.len, b.ptr );    // prints "he"

使用stdio.h中的fwrite,您可以随心所欲地打印C样式字符串的任何部分,因为fwrite将指针指向字符串中的任何字符,并希望您提供一个大小,而不是使用空字节终止。

fwrite的声明如下:

size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

另请参阅http://www.cplusplus.com/reference/cstdio/fwrite/

所以你可以写

const char* a = "foobarfoobar";
fwrite(a + 3, 6, 1, stdout);

它将把子字符串"barfoo"打印到stdout。

标准库中还有其他几个函数,它们采用指针和原始内存管理大小,如果您想处理子字符串,而不必复制原始字符串,只需在子字符串末尾插入一个空字节,就可以使用这些函数。与fwrite一样,这些函数允许您处理任意二进制数据,但也适用于字符串操作和处理。

当你编辑你的问题时,这里有一个关于传递数组部分的更一般的解释:

接受包含任意数据的数组的函数总是使用两个参数。一个指针指向数组,另一个指针表示数组的大小。当然,他们也可以接受额外的论点,但这两个是最低限度的。

void some_function(const void *ptr, size_t size);

如果您有一个数组const char[] foo = "some data",您可以使用指针算术来确定子部分的开始。CCD_ 4将生成指向数组的第n+1个元素的指针。因此,可以将foo + 2作为ptr传递给some_function,使ptr指向foo数组的第三个元素。在这种情况下,这是包含字符串"some data"的字母"m"的内存地址。从这个位置开始,您可以通过size参数告诉函数数组的大小。如果您选择大小为5,则可以将some_function称为some_function(foo + 2, 5);,这将使some_function有效地看到"me da"。

要比较两个子数组,可以使用string.h中的函数memcmp(http://www.cplusplus.com/reference/cstring/memcmp/)。这个函数也像some_function一样接受一个指针和一个大小参数。此外,它接受指向内存位置的第二个指针以与进行比较

const char[] foo = "some data";
const char[] bar = "same database";
memcmp(foo + 2, bar + 2, 7); // Will return 0 indicating equality as foo+2 -> foo+2+7 and bar+2 -> bar+2+7 both result in the substring "me data".

最新更新