简体   繁体   English

这段代码中指针运算的意图是什么?

[英]What is the intent of the pointer arithmetic in this code?

What does this line of code do, newnode -> item.string = (char *)newnode + sizeof(log_t);这行代码是做什么的, newnode -> item.string = (char *)newnode + sizeof(log_t); , in the below example? ,在下面的例子中?

int nodesize = sizeof(log_t) + strlen(data.string) + 1;
newnode = (log_t *)malloc(nodesize);
if (newnode == NULL) return -1;

// What is this line doing:
newnode -> item.string = (char *)newnode + sizeof(log_t);

strcpy(newnode -> item.string, data.string);

where newnode is the variable of type log_t ( log_t has a variable named item of type data_t ).其中newnode是类型的可变log_tlog_t具有可变的命名item类型的data_t )。 data_t has a property char *string . data_t有一个属性char *string

Is this code setting up the buffer size of string?这段代码是否设置了字符串的缓冲区大小?

newnode -> item.string = (char *)newnode + sizeof(log_t);

The right side will take the pointer newnode , cast it to a character pointer then add the size of an object to it.右侧将获取指针newnode ,将其转换为字符指针,然后向其添加对象的大小。

This gives a pointer n bytes beyond newnode , where n is the size of the log_t object.这给出了一个超出newnode的指针n字节,其中nlog_t对象的大小。

It then places this pointer value into the string member of the item member of the object pointed to by newnode .然后将该指针值放入newnode指向的对象的item成员的string成员中。

Without seeing the actual structures in use, it's a little hard to tell why this is being done but my best guess would be that it's to provide an efficient self-referential pointer.在没有看到实际使用的结构的情况下,很难说出为什么要这样做,但我最好的猜测是它提供了一个有效的自引用指针。

In other words, the pointer within newnode will point to an actual part of the newnode itself, or part of a larger memory block that was allocated which contains a newnode object at the start of it.换句话说, newnode的指针将指向newnode本身的实际部分,或已分配的较大内存块的一部分,该内存块在其开头包含一个newnode对象。 And, since you state that newnode is of the type log_t , it must be the latter case (a type cannot contain a copy of itself - it can contain a pointer to the type itself but not a actual copy).而且,由于您声明newnode的类型为log_t ,因此必须是后一种情况(类型不能包含自身的副本 - 它可以包含指向类型本身的指针,但不能包含实际副本)。


An example of where this may come in handy is an object allocation where small sizes are satisfied completely by the object itself but larger ones are handled differently, such as with an int -to- string map entry:这可能派上用场的一个例子是对象分配,其中小尺寸完全由对象本身满足,但较大尺寸的处理方式不同,例如使用int -to- string映射条目:

typedef struct {
    int  id;
    char *string;
} hdr_t;

typedef struct {
    hdr_t hdr;
    char  smallBuff[31];
} entry_t;

In the case where you want to populate an entry_t variable with a 500-character string, you would allocate the string separately then just set up string to point to it.如果您想用 500 个字符的字符串填充entry_t变量,您可以单独分配该字符串,然后只需设置指向它的string

However, for a string of thirty characters or less, you could just create it in smallBuff then set string to point to that instead (no separate memory needed).但是,对于 30 个字符或更少的字符串,您可以在smallBuff创建它,然后将string设置为指向它(不需要单独的内存)。 That would be done with:这将通过以下方式完成:

entry_t *entry = malloc (sizeof (*entry)); // should check for NULL.
entry->hdr.id = 7;
entry->hdr.string = (char*)entry + sizeof (hdr_t);
strcpy (entry->hdr.string, "small string");

The third line in that sample above is very similar to what you have in your code.上面示例中的第三行与您在代码中的非常相似。


Similarly (and probably more apropos to your case), you can allocate more memory than you need and use it:同样(可能更适合您的情况),您可以分配比需要更多的内存并使用它:

typedef struct {
    int  id;
    char *string;
} entry_t;

char *str = "small string";
entry_t *entry = malloc (sizeof (*entry) + strlen (str) + 1); // with extra bytes.
entry->id = 7;
entry->string = (char*)entry + sizeof (entry_t);
strcpy (entry->string, str);

I'm assuming the memory for newnode was allocated with additional space for the string.我假设为 newnode 的内存分配了额外的字符串空间。

The result is the same, but I'd personally write that as newnode->item.string = (char*) &newnode[1];结果是一样的,但我个人将其写为newnode->item.string = (char*) &newnode[1];

That is, the storage space for string is immediately after the log_t object.也就是说,string 的存储空间紧跟在 log_t 对象之后。 This is sometimes done when a single chunk of memory has been allocated in advance, and objects and their members all point to memory in this chunk.这有时是在预先分配了单个内存块时完成的,并且对象及其成员都指向该块中的内存。 It's been done in the past to cut down on the overhead of small memory allocations.过去已经这样做了,以减少小内存分配的开销。

If log_t is 32 bytes, and the string is 16 bytes long (including the nul terminator!), you could malloc 48 bytes, point the string member to the 32nd byte of this memory allocation and copy the string there.如果 log_t 为 32 字节,并且字符串长度为 16 字节(包括 nul 终止符!),您可以 malloc 48 个字节,将字符串成员指向此内存分配的第 32 个字节并将字符串复制到那里。

It's doing pointer arithmetic.它在做指针运算。 In C, when you add a value to a pointer, it moves the pointer by that value * the size of the type pointed to by the pointer.在 C 中,当您向指针添加值时,它会将指针移动该值 * 指针指向的类型的大小。

What this is doing is casting newnode to a char*, so that the pointer arithmetic is done assuming that newnode is a char*, thus the size of the data it points to is 1. It them adds the sizeof(log_t) which is the size of type log_t.这样做是将 newnode 强制转换为 char*,以便在假设 newnode 是 char* 的情况下完成指针算术,因此它指向的数据大小为 1。它们添加了 sizeof(log_t),它是log_t 类型的大小。 Based on your description of log_t, it looks like it contains a single char*, so its size would be the size of a pointer, either 4 or 8 bytes, depending on the architecture.根据您对 log_t 的描述,它看起来像是包含单个 char*,因此其大小将是指针的大小,4 或 8 个字节,具体取决于体系结构。

So, this will set newnode.item.string to be sizeof(log_t) bytes after address that newnode contains.因此,这将在 newnode 包含的地址之后将newnode.item.string设置为sizeof(log_t)个字节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM