C/Unix:如何从st_模式提取位?

C/Unix:如何从st_模式提取位?,c,linux,file,unix,directory,C,Linux,File,Unix,Directory,我是Unix编程和C语言的初学者,我有两个关于struct stat及其字段st_mode的问题: 访问下面的st_mode字段时,返回什么类型的数字(八进制、十进制等) 我以为数字是八进制的,但是当我运行这个代码时,我得到了值33188。基础是什么 我发现st_模式编码了一个16位二进制数,表示文件类型和文件权限。如何从上述输出中获取16位数字(特别是当它似乎不是八进制时)。16位数字的哪些部分编码哪些信息 谢谢你的帮助。我想你在这里混搭了一些概念 在内存中,整数值总是二进制的,我们称之为本

我是Unix编程和C语言的初学者,我有两个关于
struct stat
及其字段
st_mode
的问题:

  • 访问下面的
    st_mode
    字段时,返回什么类型的数字(八进制、十进制等)

  • 我以为数字是八进制的,但是当我运行这个代码时,我得到了值
    33188
    。基础是什么

  • 我发现
    st_模式
    编码了一个16位二进制数,表示文件类型和文件权限。如何从上述输出中获取16位数字(特别是当它似乎不是八进制时)。16位数字的哪些部分编码哪些信息

  • 谢谢你的帮助。

    我想你在这里混搭了一些概念

    在内存中,整数值总是二进制的,我们称之为本机格式
    st_模式
    属于
    mode_t
    类型,并且该类型是未指定的整数类型,可能是
    int

    基数的概念,即十进制、八进制或十六进制,只有当您将内存中的数字以本机格式转换为文本表示(或从文本转换回本机)时才有用

    例如:

    int x = 42;
    
    将数字42指定给整数变量。由于源代码是文本,
    42
    作为文本输入,我们知道它是一个十进制值(没有前缀)。但请注意,我们没有为变量指定基数:它没有基数。 其他代码:

    int x = 0x2A;
    
    两者完全相同。它不使用十进制常量
    42
    ,而是使用十六进制常量
    0x2A
    ,但这是相同的,
    x
    在这两种情况下得到相同的值。同样地:

    int x = 052;
    
    也是等效的,但有一个八进制常数

    现在来看看你的代码。当您这样做时:

    printf("%d", file.st_mode);
    33188
    
    您告诉程序将该变量的值作为十进制数输出。请记住,
    printf
    将数字从本机格式转换为文本,因此文本的基础很重要。如果您希望将值视为八进制,只需编写:

    printf("%o", file.st_mode);
    100644
    
    或十六进制:

    printf("%x", file.st_mode);
    81A4
    
    关于八进制的好处是,它每八进制数字正好表示3位(十六进制为每位4位),因此只要稍加练习,你就可以不用计算就能看到这些位

    例如,您的
    st_模式
    是十进制的
    33188
    ,或者是八进制的
    0100644
    。十进制没有告诉我什么,但八进制确实有意义,因为我记得最后9位(3个八进制数字)是权限:3位为所有者,3位为组,3位为其他。因此:

    * Owner: 6 that is rw-
    * Group: 4 that is r--
    * Other: 4 that is r--
    
    顺便说一句,最后一个1是这个常数:

    #define S_IFREG 0100000
    

    这只是意味着它是一个常规文件。

    我认为您在这里混合了一些概念

    在内存中,整数值总是二进制的,我们称之为本机格式
    st_模式
    属于
    mode_t
    类型,并且该类型是未指定的整数类型,可能是
    int

    基数的概念,即十进制、八进制或十六进制,只有当您将内存中的数字以本机格式转换为文本表示(或从文本转换回本机)时才有用

    例如:

    int x = 42;
    
    将数字42指定给整数变量。由于源代码是文本,
    42
    作为文本输入,我们知道它是一个十进制值(没有前缀)。但请注意,我们没有为变量指定基数:它没有基数。 其他代码:

    int x = 0x2A;
    
    两者完全相同。它不使用十进制常量
    42
    ,而是使用十六进制常量
    0x2A
    ,但这是相同的,
    x
    在这两种情况下得到相同的值。同样地:

    int x = 052;
    
    也是等效的,但有一个八进制常数

    现在来看看你的代码。当您这样做时:

    printf("%d", file.st_mode);
    33188
    
    您告诉程序将该变量的值作为十进制数输出。请记住,
    printf
    将数字从本机格式转换为文本,因此文本的基础很重要。如果您希望将值视为八进制,只需编写:

    printf("%o", file.st_mode);
    100644
    
    或十六进制:

    printf("%x", file.st_mode);
    81A4
    
    关于八进制的好处是,它每八进制数字正好表示3位(十六进制为每位4位),因此只要稍加练习,你就可以不用计算就能看到这些位

    例如,您的
    st_模式
    是十进制的
    33188
    ,或者是八进制的
    0100644
    。十进制没有告诉我什么,但八进制确实有意义,因为我记得最后9位(3个八进制数字)是权限:3位为所有者,3位为组,3位为其他。因此:

    * Owner: 6 that is rw-
    * Group: 4 that is r--
    * Other: 4 that is r--
    
    顺便说一句,最后一个1是这个常数:

    #define S_IFREG 0100000
    
    这只是意味着它是一个常规文件

  • 该数字被设置为一个值。在
    printf()
    中,您可以使用
    %d”
    以十进制形式打印它(正如您所做的那样),或者使用
    %o”
    (或
    %lo”
    )以八进制形式打印它

  • 检查每个信息是如何表示的。然后,可以使用位掩码提取所需的信息。手册页中有一个示例演示了这一点

  • 该数字被设置为一个值。在
    printf()
    中,您可以使用
    %d”
    以十进制形式打印它(正如您所做的那样),或者使用
    %o”
    (或
    %lo”
    )以八进制形式打印它

  • 检查每个信息是如何表示的。然后,可以使用位掩码提取所需的信息。手册页中有一个示例演示了这一点


  • 你把它打印成十进制,所以你得到了十进制。如果你把它打印成八进制,你就会得到八进制;十六进制也一样

    当打印为八进制时,
    st_mode
    字段最容易理解

    printf("mode = %07o\n", file.st_mode);
    
    最后三位数字是大家熟悉的
    chmod
    等的权限(例如644)。右侧第四位数字通常为0,但对于set-UID、set-GID或sticky-bit文件或目录,则不是零。其余数字标识文件的类型

    您可以使用
    中的宏来解析