C在缓冲区中创建额外的字节
我今天一直在搞乱C,当我在这段代码中注释掉第三个缓冲区时,我不理解输出的差异:
#include #include #include void main() { unsigned char letters[10]; memset(letters, 0x00, 10); memset(letters, 0x41, 10); printf(letters); printf(" Total buffer len: %d bytes\n",strlen(letters)); char nletters[10]; memset(nletters, 0x00, 10); memset(nletters, 0x42, 10); printf(nletters); printf(" Total buffer len: %d bytes\n",strlen(nletters)); int nums[10]; memset(nums, 0x00, 10); memset(nums, 0x43, 10); printf(nums); printf(" Total buffer len: %d bytes\n",strlen(nums)); return 0; }
不同之处在于在nums缓冲区周围删除了注释:
AAAAAAAAAA 7ǝ U Total buffer len: 16 bytes BBBBBBBBBBAAAAAAAAAA 7ǝ U Total buffer len: 26 bytes
并留下缓冲区:
AAAAAAAAAA Total buffer len: 10 bytes BBBBBBBBBBAAAAAAAAAA Total buffer len: 20 bytes CCCCCCCCCC U Total buffer len: 14 bytes
我没有得到的是:
-
如何注释掉第三个缓冲区会影响其他缓冲区的大小?
-
缓冲区末尾的额外字节是多少,如何丢失/管理它们(如果我选择连接缓冲区)?
-
当我选择是否评论第三个缓冲区时,为什么打印缓冲区大小和初始化大小的差异不一致?
-
缓冲区2应该是10个字节,为什么它是20个? 我不希望它是20,我只要求10.我不认为这是不合理的。
C中的char
字符串实际上称为以空字符结尾的字节字符串。 这个以null结尾的位很重要,并且所有字符串函数都会查找它以了解字符串何时结束。
如果将未终止的字符串传递给字符串函数,它将超出范围,这将导致未定义的行为 。
终结符等于零,整数0
或字符'\0'
。
当然,这个null-terminator字符需要字符串中的空格。 这意味着一个10个字符的字符串必须有11个空格才能适应终结符。
简单的第一个看起来像
char letters[11] = { 0 }; // Space for ten character plus terminator // The above definition also initializes all elements in the array to zero, // which is the terminator character memset(letters, 'A', 10); // Set the ten first characters to the letter 'A' printf("%s", letters); // Never print a data string directly using printf's first parameter. printf(" Total buffer len: %d bytes\n", strlen(letters));
请注意对printf
的更改。 这是因为如果您从用户那里获得字符串输入,将其作为格式字符串直接传递给printf
是一个非常糟糕的安全漏洞。 如果字符串包含格式化代码但没有参数,则会导致未定义的行为 。
另请注意,我将幻数 0x41
更改为与其对应的ASCII字符。 魔术数字是一种坏习惯,使代码更难以阅读,理解和维护。
试试这个:
memset(letters, 0x00, 10); memset(letters, 0x41, 9); /* <--- see the array size minus one there */
这将使printf(3)
正常工作,但只打印一个9 A
的列表。 正如其他回复中所解释的那样,这与C程序员的噩梦有关,它使null终止手工构建的字符串。 因此,更常见的是使用
函数。
在另一个地方,不建议使用printf()
的第一个没有字符串文字的参数,就像你的字符串有一个%
字符的情况一样,它会被解释为格式描述符,你会遇到更多未定义的行为, 。