printf Implemented by Apple



https://opensource.apple.com/source/xnu/xnu-201/osfmk/kern/printf.c.auto.html

你好!在分析苹果的printf代码时,我有一个问题!

case 's':
{
register char *p;
register char *p2;
if (prec == -1)
prec = 0x7fffffff;  /* MAXINT */
p = va_arg(*argp, char *);
if (p == (char *)0)
p = "";
if (length > 0 && !ladjust) {
n = 0;
p2 = p;
for (; *p != '' && n < prec; p++)
n++;
p = p2;
while (n < length) {
(*putc)(' ');
n++;
}
}
n = 0;
while (*p != '') {
if (++n > prec || (length > 0 && n > length))
break;
(*putc)(*p++);
}
if (n < length && ladjust) {
while (n < length) {
(*putc)(' ');
n++;
}
}
break;
}

如下,Apple删除了"% 2s"一词并打印出来。

例如,"你好"被打印为"他"!

但是,如果实际的 printf 输出不超过字符串的长度,则它将返回整个字符串。

例如,"hello">

被打印为"hello"!

我缺少苹果代码的哪一部分?


这是% 3s的代码。在我的代码中:

void printf_str(va_list listp, t_list *_flags)
{
char *src;
char *src_cpy;
long n;
if (_flags->prec == -1)
_flags->prec = 0x7fffffff;
src = va_arg(listp, char *);
if(src == (char *)0)
src = "";
if (_flags->length > 0 && !_flags->ladjust)
{
n = 0;
src_cpy = src;
while (*src != '' && n < _flags->prec)
{
n++;
src++;
}
printf("%ld, %d, %dn", n, _flags->prec, _flags->length);
src = src_cpy;
while (n < _flags->length)
{
putchar_fd(1, ' ');
n++;
}
}
n = 0;
printf("%ld, %d, %dn", n, _flags->prec, _flags->length);
while (*src != '')
{
printf("%ld, %d, %dn", n, _flags->prec, _flags->length);
if (++n > _flags->prec || (_flags->length > 0 && n > _flags->length))
break;
putchar_fd(1, *(src++));
}
printf("%ld, %d, %dn", n, _flags->prec, _flags->length);
if (n < _flags->length && _flags->ladjust)
{
while (n < _flags->length)
{
putchar_fd(1, ' ');
n++;
}
}
}

长度: 3 预选: -1 调整: 0 *FMT: S

结果:5, 2147483647, 3 0, 2147483647, 3 0, 2147483647, 3 h1, 2147483647, 3 e2, 2147483647, 3 l3, 2147483647, 34, 2147483647, 3






实际输出部分将是这部分。

while (*p != '') {
if (++n > prec || (length > 0 && n > length))
break;
(*putc)(*p++);
}

再次总结我的问题,这是Apple的代码,但是printf在Mac上的行为完全打印出你好。那么,当我重新实施时,我应该遵循哪些准则?

这不是你认为的printf - 它是一个内部内核printf,而不是由C程序调用的libc printf。据我所知,您对代码的解释是正确的,如果给定的长度小于字符串的长度,它确实会截断字符串。您在程序中看不到该行为,因为您没有使用此 printf。

回答您的问题:

再次总结我的问题,这是Apple的代码,但是printf的代码 Mac上的行为完全打印出Hello。所以当我重新实施时, 我应该遵循哪些准则?

您应该按照 C ISO 标准的定义实现它。这意味着整数指定了最小字段宽度,因此在hello示例中,%2s应打印整个单词hello

引用自: https://en.cppreference.com/w/c/io/fprintf

(可选(整数值或 *,指定最小字段宽度。这 结果用空格字符填充(默认情况下(,如果需要,在 左对齐时为右对齐,如果左对齐,则为右对齐。在 使用 * 的情况,宽度由附加 int 类型的参数。如果参数的值为负数,则 指定了 - 标志和正字段宽度的结果。(注: 这是最小宽度:该值永远不会被截断。

阅读文档,了解有关 printf 函数的更多详细信息。

这是Macprintf的旧版本(2000(。

%2s的情况下,length2,单词是"你好"。

一些解释。这里

if (length > 0 && !ladjust) {
n = 0;
p2 = p;
// Does n = strlen(p)
for (; *p != '' && n < prec; p++)
n++;
p = p2;  // p is reset to beginning of string
// That does nothing, since 4 >= 2
while (n < length) {
(*putc)(' ');
n++;
}

然后,感兴趣的部分

n = 0;  // Reset n !
// Prints the chars, maximum of length characters
// This will break as soon as n > length
while (*p != '') {
if (++n > prec || (length > 0 && n > length))
break;
(*putc)(*p++);
}

所以它确实只打印 2 个字符,he.

最新更新