【问题标题】:Why (const char * ) argument in fopen prototype in C header stdio.h为什么 C 头文件 stdio.h 中 fopen 原型中的 (const char * ) 参数
【发布时间】:2019-10-12 02:44:53
【问题描述】:

我真的不明白。我只是一名学生,我注意到 stdio.h 中有一些内容

extern FILE *fopen (const char *__restrict __filename,
                 const char *__restrict __modes)

为什么我们传递“const char *”???,如果我知道这意味着传递指向 char 类型常量变量的指针。但是像 "hello.txt" 这样的 __filename 是字符串类型,而不是字符类型。或者我们这里传的是这个文件名的地址,但是那个地址是char类型吗????

-- 我也很困惑,这个 * 是属于 __restrict 还是 __filename,这个 __restrict 是不是和我们在 C99 中声明普通 C 函数时使用的关键字 restrict 一样。

--为什么在其他函数原型中像

extern int fseek (FILE *__stream, long int __off, int __whence);

传递“long int __off”而不是指针?

【问题讨论】:

    标签: c header


    【解决方案1】:

    传递字符串

    为什么我们传递“const char *”???,如果我知道这意味着传递指向 char 类型常量变量的指针。但是 __filename like "hello.txt" 是字符串类型,而不是字符类型。

    C 没有“字符串类型”。在 C 中,字符串是 char 的数组,其结尾由空字符(值为零的字符)标记。尽管在像fopen("myfile", "r") 这样的调用中,我们使用"myfile" 作为参数,但数组"myfile" 会自动转换为指向其第一个元素的指针。它的第一个元素是char,所以这个指针是char *

    这来自 C 标准中的一条规则,在 C 2018 6.3.2.1 3 中,它表示任何类型为“type”的表达式都将转换为指向其第一个元素的指针,除非:

    • 表达式是sizeof 或一元& 的操作数,或者
    • 是用于初始化数组的字符串文字(如char x[] = "abc";)。

    const 在一个参数中

    参数具有const char * 类型的事实并不意味着我们必须传递指向const 的指针。我们可以将一个普通指针传递给charchar *,它会自动转换为const char *。这表明该函数会将字符视为const。换句话说,该函数只会读取字符;它不会修改它们。

    (从技术上讲,const char * 类型的指针可以合法地转换为char * 并用于修改指向的对象,只要这些对象最初不是用const 定义的。但这是一些东西用于特殊情况。在参数中使用const 的普通函数定义不会这样做。)

    __restrict 在一个参数中

    -- 我也很困惑,这个*是属于__restrict还是__filename,这个__restrict和我们在C99中声明普通C函数时使用的关键字restrict一样吗?

    __restrict 用于某些 C 头文件中,表示无意义(在为旧版本的 C 编译时)或 restrict(在为现代版本的 C 编译时)。例如,在 Apple 随其开发人员工具分发的标头中,<stdio.h> 包含一个标头,该标头以这种方式定义 __restrict

    #if __STDC_VERSION__ < 199901
    #define __restrict
    #else
    #define __restrict      restrict
    #endif
    

    编译器根据它正在编译的 C 版本定义(或省略定义)__STDC_VERSION__(可以使用命令行开关选择,例如-std=c17)。然后上面的语句定义了__restrict,这样restrict在编译非常旧的C版本时不使用,但在编译现代版本时使用。

    fseek 的偏移量

    为什么在...fseek...等其他函数原型中传递“long int __off”而不是指针?

    off 参数指定磁盘或其他存储上的文件中的偏移量。它不是主存中某物的地址,所以它不是指针。它是从文件开头开始的字节数,所以它是一个数字。

    【讨论】:

      【解决方案2】:

      为什么我们传递“const char *”???,如果我知道这意味着传递指针 为 char 类型的常量变量。但是 __filename like "hello.txt" 是 字符串类型,而不是 char 类型。或者我们在这里传递的是地址 这个文件名,但是那个地址是char类型吗????

      在“C”中,字符串常量(例如“hello.txt”)与以空字符结尾的字符数组相同。字符串的地址是第一个字符的位置。出于安全性/可靠性考虑,大多数现代编译器会将这些字符串放入程序的只读部分,并设置常量“const char **”的类型,从而减少对意外程序行为的更改。

      【讨论】:

      • 字符串字面量的类型不包括const,不管C实现是否将其放入只读存储中。
      • -Wwrite-string 将使 gcc 为 char *x = "abcd" 产生警告; - 与 g++ 相同。安全总比后悔好。
      猜你喜欢
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-20
      • 2011-08-14
      • 1970-01-01
      • 1970-01-01
      • 2014-07-03
      相关资源
      最近更新 更多