我们可以在联合中使用指针吗?

发布于 2024-10-13 04:27:04 字数 25 浏览 2 评论 0原文

如果没有为什么?联合优于结构的用途?

If no why? Uses of union over structure??

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

静赏你的温柔 2024-10-20 04:27:04

您可以在联合中使用任何数据类型,没有限制。

至于在结构上使用并集,结构将其数据按顺序排列在内存中。这意味着它们的所有子组件都是独立的。

另一方面,联合体对其所有子组件使用相同的内存,因此一次只能存在一个。

例如:

                                 ┌─────┬─────┐
struct { int a; float b }  gives │  a  │  b  │
                                 └─────┴─────┘
                                    ▲     ▲
                                    │     │
                 memory location:  150   154
                                    │
                                    ▼
                                 ┌─────┐
union { int a; float b }  gives  │  a  │
                                 │  b  │
                                 └─────┘

结构用于“对象”由其他对象组成的情况,例如由两个整数组成的点对象,这两个整数是 x 和 y 坐标:

typedef struct {
    int x;           // x and y are separate
    int y;
} tPoint;

联合通常用于对象可以是许多事物之一但一次只有一个,例如无类型存储系统:

typedef enum { STR, INT } tType;
typedef struct {
    tType typ;          // typ is separate.
    union {
        int ival;       // ival and sval occupy same memory.
        char *sval;
    }
} tVal;

它们对于节省内存很有用,尽管现在这往往越来越不受关注(除了像嵌入式系统这样的低级工作之外),所以你不需要看到很多。

You can use any data type in a union, there's no restriction.

As to the use of unions over structures, structures lay out their data sequentially in memory. This mean all their sub-components are separate.

Unions, on the other hand, use the same memory for all their sub-components so only one can exist at a time.

For example:

                                 ┌─────┬─────┐
struct { int a; float b }  gives │  a  │  b  │
                                 └─────┴─────┘
                                    ▲     ▲
                                    │     │
                 memory location:  150   154
                                    │
                                    ▼
                                 ┌─────┐
union { int a; float b }  gives  │  a  │
                                 │  b  │
                                 └─────┘

Structures are used where an "object" is composed of other objects, like a point object consisting of two integers, those being the x and y coordinates:

typedef struct {
    int x;           // x and y are separate
    int y;
} tPoint;

Unions are typically used in situation where an object can be one of many things but only one at a time, such as a type-less storage system:

typedef enum { STR, INT } tType;
typedef struct {
    tType typ;          // typ is separate.
    union {
        int ival;       // ival and sval occupy same memory.
        char *sval;
    }
} tVal;

They are useful for saving memory although that tends to be less and less of a concern nowadays (other than in low-level work like embedded systems) so you don't see a lot of it.

对风讲故事 2024-10-20 04:27:04

那么,根据 ISO/IEC 9899:TC3(C99 标准):

联合类型描述了一组重叠的非空成员对象,每个成员对象
它有一个可选的指定名称和可能不同的类型。

简而言之,联合成员的内存空间是重叠的,并且您赋予联合成员的名称允许您读取该位置的内存大小。考虑一下:

#include <stdio.h>
#include <stdint.h>

typedef union
{
    struct
    {
        uint8_t a;
        uint8_t b;
        uint8_t c;
        uint8_t d;
    };
    uint32_t x;
} somenewtype;

typedef union
{
    uint32_t* p;
    uint8_t* q;
} somepointer;

int main(int argc, char** argv)
{
    uint32_t r;
    uint8_t s;
    somenewtype z;
    somepointer p;
    r = 0x11223344; s = 0x11;
    z.x = 0x11223344;
    p.p = &r;
    p.q = &s;
    printf("%x%x%x%x\n", z.d, z.c, z.b, z.a);
    printf("%x %x\n", *(p.p), *(p.q));
}

在第一个 printf 中,我们正在做的是打印 32 位整数的 8 位部分。当然希望匿名结构中没有填充。

在第二个 printf 中?我必须逐步使用 gdb 才能理解,但我做到了:

p.p = (uint32_t *) 0x7fffffffde5c;
p.q =  (uint8_t *) 0x7fffffffde5b "\021D3\"\021P\337\377\377\377\177";
p.p = (uint32_t *) 0x7fffffffde5b;

当然,指针的大小都相同,因此分配 pq 会覆盖 pp 的地址。我强烈怀疑将 32 位整数的地址取消引用为 8 位指针会打印“该位置的内容 + 32 位大小”,这对我来说碰巧是 22334411.但我怀疑,在这一点上,行为是未定义的。

无论如何,这个小练习的目的是向您展示:

  • 联合可用于通过不同的“类型”修饰符访问相同的内存位置。
  • 您必须小心所做的事情并了解您正在使用的底层类型。如果您要使用指针,请注意它们的修改,因为您可能会开始指向谁知道什么。

我应该指出,我可以看到 somenewtype 的实际用途,但看不到 somepointer - 这是一个我很确定会破坏的人为示例。

Well, according to ISO/IEC 9899:TC3 (the C99 standard):

A union type describes an overlapping nonempty set of member objects, each of
which has an optionally specified name and possibly distinct type.

In short, the memory space of union members overlaps, and the names you give to union members allow you to read memory at that location in size. Consider:

#include <stdio.h>
#include <stdint.h>

typedef union
{
    struct
    {
        uint8_t a;
        uint8_t b;
        uint8_t c;
        uint8_t d;
    };
    uint32_t x;
} somenewtype;

typedef union
{
    uint32_t* p;
    uint8_t* q;
} somepointer;

int main(int argc, char** argv)
{
    uint32_t r;
    uint8_t s;
    somenewtype z;
    somepointer p;
    r = 0x11223344; s = 0x11;
    z.x = 0x11223344;
    p.p = &r;
    p.q = &s;
    printf("%x%x%x%x\n", z.d, z.c, z.b, z.a);
    printf("%x %x\n", *(p.p), *(p.q));
}

In the first printf, what we're doing is printing out 8-bit parts of the 32-bit integer. Hoping of course for no padding in that anonymous struct.

In the second printf? I had to step through using gdb to understand, but I did:

p.p = (uint32_t *) 0x7fffffffde5c;
p.q =  (uint8_t *) 0x7fffffffde5b "\021D3\"\021P\337\377\377\377\177";
p.p = (uint32_t *) 0x7fffffffde5b;

Well of course, pointers are all the same size, so assigning p.q overwrites the address of p.p. I suspect strongly that de-referencing the address of the 32-bit integer to an 8-bit pointer is printing "whatever is at that location + 32 bits in size" which co-incidentally for me happens to be 22334411. But I suspect, at that point, the behaviour is undefined.

Anyway, the point of that little exercise was to show you that:

  • unions can be used to access the same memory location through a different "type" modifier.
  • You have to be careful what you do and understand the underlying type you're using. If you're going to use pointers, beware their modification as you might start pointing to who knows what.

I should point out I can see the practical use for somenewtype but not for somepointer - that was a contrived example I was pretty sure would break.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文