memcpy()通过引用而没有副本?

时间:2014-08-01 09:36:24

标签: c arrays memcpy

上下文

学习memcpy。 是的它有效,但如果我们可以保持对我们感兴趣的数组的子部分的引用而没有任何副本,那将是很好的。

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

问题

我们可以做同样没有副本,只是指针运算吗?

printf("my array is %s\n",a..a+2)

例如?

关键点不仅是printf,而是代码中任何地方的任何引用都是由开头和结尾的指针引用的。 a..a + 2(认为套接字,函数参数..)

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

3 个答案:

答案 0 :(得分:5)

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

printf("my array is %.2s\n", a);

答案 1 :(得分:1)

您可以将原始字符串封装到一个带有引用和长度的结构中:

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( "%.*s\n", b.len, b.ptr );    // prints "he"

答案 2 :(得分:0)

使用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",你可以使用指针算法来确定子部分的开始。 foo+n将生成指向数组的第n + 1个元素的指针。因此,您可以将foo + 2作为ptr传递给some_function,使ptr指向foo数组的第3个元素。在这种情况下,这是包含字符串“some data”的字母“m”的内存地址。从该位置开始,您可以通过size参数告诉函数数组的大小。如果您选择的尺码为5,则可以some_function作为some_function(foo + 2, 5);,这会使some_function有效地看到“我”。

要比较两个子数组,可以使用string.h中的函数memcmphttp://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".