为什么char不是单个字符
Why is char not a single character?
在Microsoft的DEV_BROADCAST_DEVICEINTERFACE_A文档中,dbcc_name
的类型定义如下:
char dbcc_name[1];
但如这个StackOverflow问题所示,它原来是一个具有多个字符的string
。
char
不是一个16位值的单个字符吗?这是怎么回事?
(我最初认为char
是16位。可能是因为这是它在c#中的大小。实际上,这可能是因为我在看DEV_BROADCAST_DEVICEINTERFACE_W,它实际上是2字节。)
char
不是16位值吗?
在什么平台上?在大多数平台上(包括所有运行Windows、AFAIK的平台),char
是8位。
这是如何工作的?
类型文档对此进行了解释:
dbcc_size
此结构的大小,以字节为单位。这是成员的大小加上dbcc_name字符串的实际长度(通过将dbcc_name声明为一个字符数组来解释空字符)
换句话说,_DEV_BROADCAST_DEVICEINTERFACE_A
的定义利用了数组在C++中衰减为指针的事实,因此在大多数上下文中,具有数组类型的dbcc_name
可以用作以零结尾的字符串。实际字符串与_DEV_BROADCAST_DEVICEINTERFACE_A
对象连续存储在从dbcc_name
偏移量开始的地址处。
值得注意的是,数组(1)的大小与其内容的长度无关;它只是C++中最小的合法静态数组大小(遗留代码偶尔会使用char[0]
类型的结构成员。然而,这是编译器扩展,不是合法的C++)。
这就是所谓的"结构破解"。这是一个技巧,允许您将大小可变的数据存储在struct
实例中。
您将最后一个成员设置为大小为1的数组,如下所示:
struct foo { int i; char c[1] };
假设一个4字节的int
,这种类型是5字节宽的(尽管它可能需要8个字节才能满足任何对齐要求),struct foo
的实例看起来是这样的:
+---+
i: | |
+---+
| |
+---+
| |
+---+
| |
+---+
c: | |
+---+
但是,如果使用malloc
或calloc
为其动态分配内存,则可以分配比struct
类型所需更多的内存,并且额外的内存将被视为数组的一部分(因为struct
元素保证按声明的顺序排列,数组类型不强制大小)。
struct foo *p = malloc( sizeof *p + strlen( "hello" ));
p->i = 1;
strcpy( p->c, "hello" );
因此,我们为struct
类型分配了足够的内存(5字节)加上足够的内存来存储"hello"
,这给了我们(假设小端)
+---+ ----+
i: | 1 | |
+---+ |
| 0 | |
+---+ |
| 0 | +---- size of struct foo
+---+ |
| 0 | |
+---+ |
c: |'h'| |
+---+ ----+
|'e'| |
+---+ |
|'l'| |
+---+ |
|'l'| +---- Extra memory for "hello"
+---+ |
|'o'| |
+---+ |
| 0 | |
+---+ ----+
为什么我们将c
设为大小为1的数组而不是指针?如果我们把c
作为一个指针,就像一样
struct foo { int i; char *c };
那么这个技巧不起作用,因为所有c
可以存储的都是地址,而不是数据。
C允许"灵活的数组成员",其中声明中不需要大小:
struct foo { int i; char c[] };
但是,C++(还)不支持这一点,所以您必须指定一个非零大小。
这是一个非常古老的技巧。
typedef struct
{
size_t size;
char str[1];
} mystring_t;
mystring_t *allocate(size_t size)
{
return malloc(sizeof(mystring_t) + size -1);
}
然后您可以很容易地重新分配它,因为灵活的部分总是在结构的末尾。
在较新的C版本中
typedef struct
{
size_t size;
char str[];
} mystring_t;
或使用gcc
typedef struct
{
size_t size;
char str[0];
} mystring_t;
- 如何读取单个字符并在输入两个字符序列时输出? 使用 while 循环和C++
- 为什么char不是单个字符
- C++ 字符串单个字符
- 将单个字符转换为 std::string 前缀 \x01
- 尝试一次将单个字符读取到大小不确定的数组中
- C++ 如何将字符串拆分为单个字符
- 如何在C++中将单个字符哈希为相对较小的素数?
- 如何将像'A'这样的单个字符替换为类似"10"?
- 我通过迭代加法将二进制数转换为十进制并检查单个字符(请参阅代码)的方法有什么问题?
- std::bad_alloc 将文本文件中的单个字符存储到矢量C++中时
- 如何从用户那里获取单个字符,直到他输入"."或输入
- 字符串中单个字符作为数组的数据类型是什么
- 字符串中的重音,如何在单个字符中存储重音字符
- 从字符串中提取单个字符并将其转换为 int
- 如何将单个字符转换为为基本密码哈希器设置整数,C++
- 下推解析器是否扫描令牌或单个字符
- 如何定义一个从任何编码空间解析单个字符的精神 x3 解析器?
- C :占用更多内存,将单个字符作为char或字符串存储
- 如何从字符串中读取单个字符
- WM_GETTEXT只返回单个字符