C - 结构内静态字符数组的 sizeof() - 不可能吗?

发布于 2024-11-25 21:24:46 字数 1047 浏览 2 评论 0原文

我需要为每个数组元素存储两个项目 - 两个 char 数组,其中可能包含空字节 - 然后仍然能够使用 sizeof() 来获取它们的长度。由于这些值在执行过程中不会改变,我认为 GCC 应该能够处理这个问题。

代码如下:

#include <stdlib.h>
#include <stdio.h>

struct name_data {
    char *name;
    char *data;
} name_bins [] = {
    { "John", "\xAA\xAA\x00\xAA" },
    { "Mark", "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05" },
};

char bin_test[] = "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05";

int main () {
    printf("sizeof(bin_test) = %lu\n", sizeof(bin_test));
    printf("sizeof(name_bins[1].data) = %lu\n", sizeof(name_bins[1].data));
    exit(0);
}

该代码的输出为:

sizeof(bin_test) = 11
sizeof(name_bins[1].data) = 8

然而,bin_test 在内容上等同于 name_bins[1].data — 尽管类型定义不同 — bin_test 是一个 char[]names_bins[1].data 是一个 char*

有没有办法用 char[] 来定义 name_bins 数组? 有没有办法强制 GCC 将此值识别为静态常量,并使用 sizeof() 返回实际内容大小 - 它已经在编译时计算过了?

I need to store two items per array element — two arrays of char, which might contain null bytes — and then still be able to use sizeof() to get their length. Since these values will not change during execution, I think GCC should be able to handle this.

Here's the code:

#include <stdlib.h>
#include <stdio.h>

struct name_data {
    char *name;
    char *data;
} name_bins [] = {
    { "John", "\xAA\xAA\x00\xAA" },
    { "Mark", "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05" },
};

char bin_test[] = "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05";

int main () {
    printf("sizeof(bin_test) = %lu\n", sizeof(bin_test));
    printf("sizeof(name_bins[1].data) = %lu\n", sizeof(name_bins[1].data));
    exit(0);
}

The output of this code is:

sizeof(bin_test) = 11
sizeof(name_bins[1].data) = 8

However, bin_test is equivalent to name_bins[1].data in content — although the type definition is different — bin_test is a char[] and names_bins[1].data is a char*.

Is there a way to define the name_bins array with char[]s instead?
Is there a way to force GCC to recognize this values as static constants and return the real content size with sizeof() — which it already calculates at compile time?

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

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

发布评论

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

评论(3

爱的十字路口 2024-12-02 21:24:46

不,这是不可能的。 struct 的大小是常量(任何对象 name_datasizeof 始终相同)。如果可能的话,您可以拥有两个相同类型、不同大小的对象。

No, this isn't possible. The size of the struct is constant (sizeof any object name_data is always the same). If it were possible, you could have two objects of the same type, with different sizes.

淡淡的优雅 2024-12-02 21:24:46

您几乎可以通过将 data 的大小存储为单独的条目来完成您想要的操作:

struct name_data {
    char  *name;
    char  *data;
    size_t data_size;
} name_bins[] = {
    {
        "John",
        "\xAA\xAA\x00\xAA",
        sizeof("\xAA\xAA\x00\xAA")
     }, {
         "Mark",
         "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05",
         sizeof("\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05")
     }
};

然后:

printf("sizeof(bin_test) = %lu\n", sizeof(bin_test));
printf("sizeof(name_bins[1].data) = %lu\n", (unsigned long)name_bins[1].data_size);

然后您只需确保您的 name_bins 初始化是正确的。不过,您可以在其中添加一个宏以避免重复:

#define BIN(x,y) { (x), (y), sizeof(y) }

struct name_data {
    char  *name;
    char  *data;
    size_t data_size;
} name_bins [] = {
    BIN("John", "\xAA\xAA\x00\xAA"),
    BIN("Mark", "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05")
};

You can almost do what you want by storing the size of data as a separate entry:

struct name_data {
    char  *name;
    char  *data;
    size_t data_size;
} name_bins[] = {
    {
        "John",
        "\xAA\xAA\x00\xAA",
        sizeof("\xAA\xAA\x00\xAA")
     }, {
         "Mark",
         "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05",
         sizeof("\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05")
     }
};

And then:

printf("sizeof(bin_test) = %lu\n", sizeof(bin_test));
printf("sizeof(name_bins[1].data) = %lu\n", (unsigned long)name_bins[1].data_size);

Then you'd just have to make sure your name_bins initialization was right. You could toss a macro in the mix to avoid repeating yourself though:

#define BIN(x,y) { (x), (y), sizeof(y) }

struct name_data {
    char  *name;
    char  *data;
    size_t data_size;
} name_bins [] = {
    BIN("John", "\xAA\xAA\x00\xAA"),
    BIN("Mark", "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05")
};
源来凯始玺欢你 2024-12-02 21:24:46

如果您稍微思考一下您要求编译器在这里做什么,您可能会意识到您所要求的并不现实。

为了让编译器确定 sizeof(name_bins[1].data)11,它必须确保通向该行的每个可能路径包含 sizeof 的代码在涉及 name_bins[1].data 对象时具有完全相同的状态。

在您给出的简单示例中,您可能期望编译器能够以某种方式解决这个问题。但如果您的应用程序变得更加复杂怎么办?编译器如何知道 name_bins[1].data 仍然包含 "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05"

编辑:根据评论,您可以创建一个新类型来保存数据和大小:

typedef struct ConstByteString {
    const unsigned char* data;
    size_t length;
} ConstByteString;

然后使用它:

struct name_data {
    const char* name;
    ConstByteString data;
} name_bins [] = {
    { "John", { "\xAA\xAA\x00\xAA", sizeof("\xAA\xAA\x00\xAA") } },
    { "Mark", { "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05", sizeof("\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05") } },
};

If you think for a bit about what you're asking the compiler to do here, you'll probably realize that what you're asking is not realistic.

In order for the compiler to figure out that sizeof(name_bins[1].data) is 11, it would have to make sure that every possible path that leads to the line of code containing the sizeof has the exact same state when it comes to the name_bins[1].data object.

In the simple example you gave, you might expect the compiler to be able to somehow figure that out. But what if your application becomes more complex ? How will the compiler know that name_bins[1].data still contains "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05" ?

EDIT : Following up from the comments, you could create a new type that holds both the data and the size :

typedef struct ConstByteString {
    const unsigned char* data;
    size_t length;
} ConstByteString;

and then use that :

struct name_data {
    const char* name;
    ConstByteString data;
} name_bins [] = {
    { "John", { "\xAA\xAA\x00\xAA", sizeof("\xAA\xAA\x00\xAA") } },
    { "Mark", { "\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05", sizeof("\xFF\x0A\x00\x33\x01\x01\x03\x04\x04\x05") } },
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文