【问题标题】:Please, why is this code printing with an extra "n" when I run it?请问,为什么当我运行这段代码时,它会打印一个额外的“n”?
【发布时间】:2020-02-03 00:24:24
【问题描述】:

我正在尝试使用此代码获取 pid。但是当我运行编译的代码时。我收到一条错误消息“警告:格式指定类型'unsigned long',但参数的类型为'pid_t'(又名'int')[-Wformat]”。

当我将格式说明符更改为“%lu”时,它会打印而没有多余的字符。

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
pid_t pid = getpid();

printf("pid: %lun", pid);
}

我预计 pid 为“60316”。我得到“60316n”的 pid。

【问题讨论】:

  • 您希望%lun 中的n 做什么?应该是\n
  • n 不是格式说明符%lu 的一部分;它是常规字符串的一部分。它按原样打印出来。
  • 除了 UnholySheep 的注释,%lu 专门用来打印一个unsigned long,后面的n 被简单地当作字符串字面量处理,就像前缀pid : 一样。
  • 好的。我现在明白了。谢谢大家让这个更清楚。

标签: c


【解决方案1】:

n 打印出来的原因与p 打印的原因相同。 n 不是说明符的一部分。

      vvv  --- specifier for unsigned long 
"pid: %lun"
 ^^^^^   ^ --- non-specifier characters

旁白:

pid_t 数据类型是signed integer 类型,能够表示进程 ID

What is the correct printf specifier for printing pid_t?

【讨论】:

  • 我检查了链接。这很有帮助。
【解决方案2】:

您传递给printf 的格式字符串是普通字符和格式说明符的混合体。普通字符本身打印,格式说明符导致转换和打印额外参数之一。但是每个额外参数的类型必须与格式说明符所期望的类型或多或少完全匹配。

我们可以从警告消息中看出pidint。所以正确的格式说明符是%d

如果 pid 的类型为 unsigned long int,则说明符 %lu 将是正确的。

格式说明符是它们自己的小型编程语言。 unsigned int 类型的基本格式说明符是 %u,您可以将其修改为打印 unsigned long int,而不是使用 l(字母 ell)修饰符:%lu

但是当您编写 %lun 时,n 实际上并不是任何格式说明符的一部分,因此它本身就打印出来了。

(另外,你很幸运:尽管pid 的类型和格式说明符%lu 不匹配,但你还是得到了一个合理的值。)

通常,让参数和格式说明符对齐很容易:int 用于 %dunsigned int 用于 %u%xlong int 用于 %ldfloatdouble 用于%f 等。但是对于类型为pid_tpid,正确的说明符是什么?今天,在您的计算机上,pid_t 看起来像 int,所以 %d 是正确的,但如果在其他计算机上,它有不同的类型怎么办?你如何编写一段代码,可以在任何计算机上正常工作?一种方法是选择一个可能正确的类型,并使用该类型的说明符,然后使用显式 cast 将您的值转换为您选择的类型。像这样:

printf("pid: %d\n", (int)pid);

或者像这样:

printf("pid: %lu\n", (unsigned long int)pid);

如果不需要强制转换(如果您选择的格式说明符对于您计算机上的 pid 类型已经正确),则强制转换不会受到影响。

最后,恭喜你使用了一个实际上给你警告信息的编译器:

警告:格式指定类型“无符号长”,但参数的类型为“pid_t”(又名“int”)

太多的初级程序员被困在使用不打印此类警告的旧编译器中,这显然使得追踪由不匹配的格式说明符引起的问题变得更加困难! (您的编译器特别有用,因为它为您提供了pid 的明显类型,即pid_t,以及实际的底层类型int。)

【讨论】:

  • 所以我只是简单地打印出“n”。我现在知道了。谢谢
  • 那么我对 pid 使用 unsigned long 有错吗?我认为没关系,因为范围更大。
  • 是的,这是错误的。如果pid 真的是一个int,严格来说,用u 将它打印为无符号是错误的(尽管你几乎总是会侥幸逃脱)。使用l 打印更糟糕,因为pid(无论如何,在您的机器上)肯定不会太长。在 intlong int 都是 32 位的 32 位机器上,您也经常会侥幸逃脱。 (但它在我的机器上不起作用,int 是 32 位,但 long 是 64。)
猜你喜欢
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
  • 1970-01-01
  • 2018-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多