【问题标题】:Mixing char and string in C array init在 C 数组 init 中混合字符和字符串
【发布时间】:2017-08-31 02:36:31
【问题描述】:

我知道以下 2 个初始化器是等价的:

char T1[]="abc";
char T2[]={'a', 'b', 'c', 0};

我有一个这样的数组初始化器:

char T[]={0x10, 0xF, 0xF0, 'H', 'e', 'l', 'l', 'o', 0xC1, 0xD0};

撇开有符号/无符号字符的潜在问题不谈,有没有办法混合两种初始化器样式,做类似的事情(这不起作用):

char T[]={0x10, 0xF, 0xF0, "Hello", 0xC1, 0xD0};

【问题讨论】:

  • 不,我不认为你可以按照你想要的方式做。

标签: c arrays initializer


【解决方案1】:

你不能这样混合它们。你可以做的是用字符串插入十六进制代码,例如:

char T[] = "\x10\x0f\xf0" "Hello" "\xc1\xd0";

请记住,这会将\0 放在该数组的末尾,因此如果您使用sizeof 来获取字节数,您可能需要进行调整:

size_t bytesInT = sizeof(T) - 1;

同样,Hello 的末尾不会为空,但您可以通过以下方式解决此问题:

char T[] = "\x10\x0f\xf0" "Hello\0" "\xc1\xd0";

您可能想知道为什么将字符串分成三个部分。这是有效的,因为编译过程的早期阶段涉及连接相邻的字符串,这意味着 "paxdiablo""pax" "diablo" 在功能上是等效的。

一个原因是可读性,但重要一个原因是确保十六进制规范不会“吞下”以下字符。 Hello 无关紧要,因为 H 不是有效的十六进制字符,但您可以在这里看到问题:

#include <stdio.h>
int main(void) {
    printf ("%d %d\n", sizeof("\x20Hi"), sizeof("\x20Bi"));
    return 0;
}

这将输出4 3,尽管两个字符串的唯一区别(似乎)是一个字符的变化。长度不同,因为Bi 中的B 实际上是作为十六进制数字使用的,被视为\x20B(尽管gcc 一方面会警告您结果值超出范围)。

【讨论】:

  • 你必须小心\x。例如char T[] = "\x10\x0f\xf0Byee!\xc1\xd0"; 不会按预期工作。使用字符串文字连接可以解决它:char T[] = "\x10\x0f\xf0" "Byee!" "\xc1\xd0";
  • @Ian,好点,已将您的信息纳入答案。
【解决方案2】:

您不能混合使用这两种样式,但您可以在以空字符结尾的字符串中包含十六进制字符 HEX escape sequences

// Instead of this
char T1[] = {0x10, 0xF, 0xF0, 'H', 'e', 'l', 'l', 'o', 0xC1, 0xD0};
// Do this:
char T2[] = "\x10\x0F\xF0" "Hello" "\xC1\xD0";
// or even this:
char T3[] = "\x10" "\x0F" "\xF0" "Hello" "\xC1" "\xD0";

上述和您拥有的初始化程序之间的唯一区别是T2T3 将在末尾有一个带有空终止符的额外字节。

上述语法利用了 C 的自动连接多个由空格分隔的字符串文字的特性。

【讨论】:

  • 也许在十六进制转义 "\x10\x0F\xF0ByeBye\xC1\xD0"; 之后开始文本时分隔字符串文字是一个问题。 "\x10\x0F\xF0" "ByeBye\xC1\xD0"; 可以
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多