pid_t(和类似的类型) - 为什么,为什么?

ntl*_*0ve 48 c pid type-equivalence

调用背后的逻辑是什么,比如getpid()返回类型的值pid_t而不是unsigned int?还是int?这有什么用?

我猜这与便携性有关?保证pid_t在不同平台上的尺寸相同,可能有不同尺寸int的等等?

zvr*_*rba 41

我认为恰恰相反:使程序可以跨平台移植,无论例如PID是16位还是32位(甚至更长).

  • 超出xiint8_t xint16_t xint32_t xint64_t的子类型整数不能解决任何问题:有自动整数转换.因此,每个合理年龄(例如10年)和大小(例如1MLOC)的现实世界程序包含1000个关于整数大小的不可检测的无声假设. (5认同)

R..*_*R.. 34

原因是允许令人讨厌的历史实现仍然符合要求.假设您的历史实施(相当常见):

short getpid(void);
Run Code Online (Sandbox Code Playgroud)

当然,现代系统要求pid至少为32位,但如果标准强制要求:

int getpid(void);
Run Code Online (Sandbox Code Playgroud)

那么所有使用过的历史实现short都会变得不符合要求.这被认为是不可接受的,因此pid_t创建并允许实现定义pid_t它更喜欢的方式.

请注意,pid_t只要您使用足够大的类型来存储任何pid(intmax_t例如可以正常工作),您就没有义务在自己的代码中使用.唯一的原因,pid_t 需要存在是一个标准的定义getpid,waitpid等在它的条款.

  • "无用"类型的一个更好的例子是`socklen_t`,它是出于同样的原因而添加的(对某些函数是否应该采用`int`或`size_t`参数的分歧). (4认同)
  • 使用`int`可能不是一个好主意,因为它不支持假设的将来使用64位pid的实现。我只是将pid_t用于大多数用途,但是请记住,如果您的数据结构可以存储大类型的“泛型整数”(即intmax_t),则以这种方式存储pid是可以接受的。 (2认同)

Maz*_*Maz 9

在不同的平台和操作系统上,32位计算机上的不同类型(例如pid_t)可能是32位(unsigned int),64位计算机上可能是64位(unsigned long).或者,由于某些其他原因,操作系统可能选择具有不同的大小.此外,它在读取代码时明确表示此变量表示"对象",而不仅仅是任意数字.

  • `fork()`失败时返回`-1`,所以`pid_t`必须是有符号整数类型. (2认同)

Jus*_*ica 7

它的目的是使pid_t平台无关或任何其他类型的排序,使其无论实际如何实现都能正常工作.此实践用于任何需要与平台无关的类型,例如:

  • pid_t:必须足够大,以便在您编码的系统上存储PID.映射到int就我所知,虽然我不是最熟悉的GNU C库.
  • size_t:一个unsigned能够存储sizeof运算符结果的变量.通常大小与您编码的系统的字大小相等.
  • int16_t(intX_t):无论平台如何,都必须精确为16位,并且不会在不使用2 n位字节(通常是8位或16位)的平台上定义,或者更不频繁地提供方法从更大的类型中访问正好16位(例如,PDP-10的"字节",它可以是36位字中的任意数量的连续位,因此可能正好是16位),因此不要t支持16位二进制补码整数类型(例如36位系统).通常映射到short现代计算机上,虽然它可能是int旧的.
  • int_least32_t(int_leastX_t):必须是可以存储至少32位的最小尺寸,例如36位或72位系统上的36位.通常映射到int现代计算机上,虽然它可能是long旧的.
  • int_fastX_t:必须是可以存储至少X位的最快类型.通常,它是系统的字大小,如果(X <= word_size)(或有时charint_fast8_t),或者像int_leastX_tif 一样(X > word_size))
  • intmax_t:必须是系统支持的最大整数宽度.通常,它在现代系统上至少为64位,尽管某些系统可能支持大于long long(并且如果intmax_t需要,则需要是这些类型中最大的类型的扩展类型).
  • 和更多...

从机制typedef上讲,无论是通过创建适当的头文件,将其编码到编译器的可执行文件还是其他方法,它都允许编译器的安装程序在适当的类型下使用标识符(无论是标准类型还是标记为内部类型)的适当类型.例如,在32位系统上,Microsoft Visual Studio将实现以下intX_t类似的类型(注意:我添加的注释):

// Signed ints of exactly X bits.
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;

// Unsigned ints of exactly X bits.
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;

// Signed ints of at least X bits.
typedef signed char int_least8_t;
typedef short int_least16_t;
typedef int int_least32_t;

// Unsigned ints of at least X bits.
typedef unsigned char uint_least8_t;
typedef unsigned short uint_least16_t;
typedef unsigned int uint_least32_t;

// Speed-optimised signed ints of at least X bits.
// Note that int_fast16_t and int_fast32_t are both 32 bits, as a 32-bit processor will generally operate on a full word faster than a half-word.
typedef char int_fast8_t;
typedef int int_fast16_t;
typedef int int_fast32_t;

// Speed-optimised unsigned ints of at least X bits.
typedef unsigned char uint_fast8_t;
typedef unsigned int uint_fast16_t;
typedef unsigned int uint_fast32_t;

typedef _Longlong int64_t;
typedef _ULonglong uint64_t;

typedef _Longlong int_least64_t;
typedef _ULonglong uint_least64_t;

typedef _Longlong int_fast64_t;
typedef _ULonglong uint_fast64_t;
Run Code Online (Sandbox Code Playgroud)

但是,在64位系统上,它们可能不一定以相同的方式实现,并且我可以保证它们不会在古老的16位系统上以相同的方式实现,假设您可以找到兼容的MSVS版本一个人.

总的来说,它允许代码无论实现的具体情况如何都能正常工作,并且能够满足任何标准兼容系统的相同要求(例如,pid_t可以保证足够大,以便在相关系统上保留任何有效的PID,无论如何你正在编写什么系统).它还可以防止您不必了解细节,并且必须查找您可能不熟悉的内部名称.简而言之,无论是否pid_t(或任何其他类似的typedef)实现为a int,a short,a long,a long long甚至是a ,它都可以确保您的代码工作原理相同__Did_you_really_just_dare_me_to_eat_my_left_shoe__,因此您不必这样做.


此外,它还可以作为一种文档形式,让您一目了然地了解给定变量的含义.考虑以下:

int a, b;

....

if (a > b) {
    // Nothing wrong here, right?  They're both ints.
}
Run Code Online (Sandbox Code Playgroud)

现在,让我们再试一次:

size_t a;
pid_t b;

...

if (a > b) {
    // Why are we comparing sizes to PIDs?  We probably messed up somewhere.
}
Run Code Online (Sandbox Code Playgroud)

如果这样使用,它可以帮助您在任何中断之前找到可能存在问题的代码段,并且可以使故障排除比原本更容易.