getpid()
之类的调用返回类型为pid_t
的值而不是unsigned int
的逻辑是什么?还是int
?这有什么用?
我猜这与便携性有关?保证pid_t
在不同平台上的大小相同,可能有不同大小的int
等?
答案 0 :(得分:39)
我认为恰恰相反:使程序可以跨平台移植,无论例如PID是16位还是32位(甚至更长)。
答案 1 :(得分:31)
原因是允许讨厌的历史实现仍然符合要求。假设您的历史实施(相当常见):
short getpid(void);
当然,现代系统要求pid至少为32位,但如果标准规定:
int getpid(void);
然后使用short
的所有历史实现都将变得不符合要求。这被认为是不可接受的,因此创建了pid_t
,并且允许实现以pid_t
来定义它所喜欢的方式。
请注意,只要您使用足够大的类型来存储任何pid(pid_t
例如可以正常工作),您就没有义务在自己的代码中使用intmax_t
。 pid_t
需要存在的唯一原因是标准用于定义getpid
,waitpid
等。
答案 2 :(得分:9)
在不同的平台和操作系统上,32位计算机上的不同类型(例如pid_t)可能是32位(unsigned int),64位计算机上可能是64位(无符号长整数)。或者,由于某些其他原因,操作系统可能选择具有不同的大小。此外,它在读取代码时明确表示此变量表示“对象”,而不仅仅是任意数字。
答案 3 :(得分: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位),因此不支持16位二进制补码整数类型(例如36位系统)。通常映射到现代计算机上的short
,尽管它可能是旧版本的int
。int_least32_t
(int_leastX_t
):必须是可以存储至少32位的最小尺寸,例如36位或72位系统上的36位。通常映射到现代计算机上的int
,尽管它可能是旧版本的long
。int_fastX_t
:必须是可以存储至少X位的最快类型。一般来说,如果(X <= word_size)
(或char
有时为int_fast8_t
),则为系统的字大小,如果int_leastX_t
则为(X > word_size)
,则为intmax_t
long long
:必须是系统支持的最大整数宽度。通常,它在现代系统上至少为64位,尽管某些系统可能支持大于intmax_t
的扩展类型(如果是这样,typedef
必须是这些类型中最大的类型)。 / LI>
从机制上讲,它允许编译器的安装程序intX_t
在幕后标识符(无论是标准类型还是笨拙的内部类型)的适当类型,无论是通过创建适当的头文件,将其编码到编译器的可执行文件或其他一些方法。例如,在32位系统上,Microsoft Visual Studio将实现// 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;
和类似类型,如下所示(注意:我添加的评论):
pid_t
然而,在64位系统上,它们可能不一定以相同的方式实现,并且我可以保证它们不会在古老的16位系统上以相同的方式实现,假设您可以找到一个版本与一个MSVS兼容。
总的来说,无论实现的具体细节如何,它都允许代码正常工作,并且在任何标准兼容系统上满足相同的要求(例如pid_t
可以保证足够大以容纳任何有效的PID在所讨论的系统上,无论你编写什么系统)。它还可以防止您不必了解细节,并且必须查找您可能不熟悉的内部名称。简而言之,无论int
(或任何其他类似的typedef)是作为short
,long
还是long long
实现的,它都会确保您的代码能够正常工作,一个__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.
}
,所以你不必这样做。
此外,它还可以作为一种文档形式,让您一目了然地了解给定变量的含义。请考虑以下事项:
size_t a;
pid_t b;
...
if (a > b) {
// Why are we comparing sizes to PIDs? We probably messed up somewhere.
}
现在,让我们再试一次:
{{1}}
如果这样使用,它可以帮助您在任何中断之前找到可能存在问题的代码段,并且可以使故障排除比原本更容易。
答案 4 :(得分:2)
程序中的每个进程都有一个特定的进程ID。通过调用pid,我们知道当前进程的已分配ID。当我们使用fork()
时,知道pid非常重要,因为它可以接收地返回0
和!=0
个子和父副本的值这两个视频有清晰的解释:video#1 Video#2
一个例子:假设我们有以下c程序:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main (int argc, char *argv[])
{
printf("I am %d\n", (int) getpid());
pid_t pid = fork();
printf("fork returned: %d\n", (int) pid);
if(pid<0){
perror("fork failed");
}
if (pid==0){
printf("This is a child with pid %d\n",(int) getpid());
}else if(pid >0){
printf("This is a parent with pid %d\n",(int)getpid());
}
return 0;
}
如果您运行它,您将获得0
代表孩子而非zero/greater than zero
代表父母。
答案 5 :(得分:0)
有一点需要指出的是,在大多数答案中,我都看到了类似的东西 &#34;使用pid_t使代码在不同的系统上工作&#34; ,这不一定是真的。
我认为准确的措辞应该是:它使代码“编译”#39;在不同的系统上。
例如,在使用32位pid_t的系统上编译代码将产生一个二进制文件,如果在另一个使用64位pid_t的系统上运行,可能会中断。