在结构中的静态字符数组上的C-sizeof()-不可能?
我需要为每个数组元素存储两个项目-两个在结构中的静态字符数组上的C-sizeof()-不可能?,c,arrays,struct,sizeof,C,Arrays,Struct,Sizeof,我需要为每个数组元素存储两个项目-两个char数组,可能包含空字节-然后仍然能够使用sizeof()获取它们的长度。由于这些值在执行期间不会改变,我认为GCC应该能够处理这个问题 代码如下: #include <stdlib.h> #include <stdio.h> struct name_data { char *name; char *data; } name_bins [] = { { "John", "\xAA\xAA\x00\xAA"
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);
}
但是,bin\u test
相当于name\u bin[1]。内容中的数据
虽然类型定义不同-bin\u test
是一个char[]
和names\u bin[1]。数据
是一个char*
有没有办法用char[]
s来定义name\u bin
数组?
有没有办法强迫GCC将这些值识别为静态常量,并使用
sizeof()
-返回它在编译时已经计算过的实际内容大小?不,这是不可能的。struct
的大小是恒定的(sizeof
anyobjectname\u data
总是相同的)。如果可能的话,您可以拥有两个相同类型、不同大小的对象。不,这是不可能的。struct
的大小是恒定的(sizeof
anyobjectname\u data
总是相同的)。如果可能的话,您可以有两个相同类型、大小不同的对象。如果您仔细考虑一下您在这里要求编译器做什么,您可能会意识到您所要求的是不现实的
为了让编译器计算出sizeof(name_bins[1].data)
是11
,它必须确保指向包含sizeof
的代码行的所有可能路径在到达name_bins[1].data时都具有完全相同的状态
在您给出的简单示例中,您可能希望编译器能够以某种方式理解这一点。但是,如果您的应用程序变得更复杂怎么办?编译器如何知道name\u bins[1]。数据仍然包含“\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") } },
};
如果您仔细考虑一下您在这里要求编译器做什么,您可能会意识到您所要求的是不现实的
为了让编译器计算出sizeof(name_bins[1].data)
是11
,它必须确保指向包含sizeof
的代码行的所有可能路径在到达name_bins[1].data时都具有完全相同的状态
在您给出的简单示例中,您可能希望编译器能够以某种方式理解这一点。但是,如果您的应用程序变得更复杂怎么办?编译器如何知道name\u bins[1]。数据仍然包含“\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") } },
};
通过将数据的大小存储为一个单独的条目,您几乎可以随心所欲:
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\u bin
初始化是正确的。您可以在混合中加入宏,以避免重复:
#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")
};
通过将数据的大小存储为一个单独的条目,您几乎可以随心所欲:
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\u bin
初始化是正确的。您可以在混合中加入宏,以避免重复:
#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")
};
谢谢Sander——我确实明白你的意思,我在想也许有一种方法可以告诉GCC这个变量是不可触及的(不能在整个执行流程中改变)——然后,sizeof应该成为可能。有什么办法可以做到这一点吗?@Arkadi:简言之:没有。data
是一个char*
,然后sizeof(name\u bins[1]。data)
将与sizeof(char*)
相同。或者data
是一个字符数组char
,然后sizeof(name\u bins[1].data)
将返回该数组的总大小(但是sizeof(name\u bins[i].data)
对于每个i
都是相同的)。为什么需要这个来处理sizeof
?因为我不能使用strlen(),因为它可能包含空字节。有没有一种方法可以将结构定义为包含2个字符[]而不是2个字符*,从而允许sizeof()工作?(我没能做到这一点)@Arkadi:为什么不将数据的大小存储在struct中呢?或者更好的是,创建自己的新类型来抽象该细节(我将在答案中添加一个示例)。感谢Sander,这与mu的答案非常相似-感谢您的帮助!谢谢Sander——我确实明白你的意思,我在想也许有一种方法可以告诉GCC这个变量是不可触及的(不能在整个执行流程中改变)——然后,sizeof应该成为可能。有什么办法可以做到这一点吗?@Arkadi:简言之:没有。data
是一个char*
,然后sizeof(name\u bins[1]。data)
将与sizeof(char*)
相同。或者data
是一个字符数组char
,然后sizeof(name\u bins[1].data)
将返回该数组的总大小(但是sizeof(name\u bins[i].data)
对于每个i
都是相同的)。为什么需要这个来处理sizeof
?因为我不能使用strlen(),因为它可能包含空字节。有没有一种方法可以将结构定义为包含2个字符[]而不是2个字符*,从而允许sizeof()工作?(我没能做到这一点)@Arkadi:为什么不将数据的大小存储在struct中呢?或者更好的是,创建自己的新类型来抽象这个细节