Передача строки
почему мы передаем "const char *" ???, если я знаю, что это означает, передайте указатель на постоянную переменную типа char. Но __filename, например «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
. Мы можем передать простой указатель на char
, char *
, и он будет автоматически преобразован в const char *
. Это означает, что функция будет обрабатывать символы как const
. Другими словами, функция будет читать только символы;он не изменит их.
(Технически, указатель типа const char *
может быть юридически преобразован в char *
и использован для изменения объектов, на которые он указывает, до тех пор, пока эти объекты не были первоначально определеныс const
. Но это то, что используется для особых обстоятельств. Нормальные определения функций, которые используют const
в своих параметрах, этого не делают.)
__restrict
в параметре
- Я также запутался, это * принадлежит * __restrict или __filename, это __restrict - то же самое, что ключевое слово restrict, которое мы используем при объявлении нормальной функции C в C99.
__restrict
используетсявнутри некоторых заголовков C ничего не значат (при компиляции для старых версий C) или restrict
(при компиляции для современных версий C). Например, в заголовках, которые Apple распространяет вместе со своими инструментами разработчика, <stdio.h>
включает заголовок, который определяет __restrict
следующим образом:
#if __STDC_VERSION__ < 199901
#define __restrict
#else
#define __restrict restrict
#endif
Компилятор определяет (или опускает определение) __STDC_VERSION__
в соответствии сверсия C, для которой она компилируется (которую можно выбрать с помощью переключателей командной строки, например -std=c17
). Тогда приведенные выше операторы определяют __restrict
, так что restrict
не используется при компиляции для очень старых версий C, но используется при компиляции для современных версий.
Смещение для fseek
Почему в другом прототипе функции, например ... fseek
... передать "long int __off", а не указатель?
Параметр off
указывает смещение в файле на диске илидругое хранилище. Это не адрес чего-либо в основной памяти, поэтому это не указатель. Это число байтов от начала файла, поэтому это число.