Почему (const char *) аргумент в прототипе fopen в заголовке C stdio.h - PullRequest
0 голосов
/ 12 октября 2019

Я не совсем понимаю это. Я всего лишь студент, и я замечаю что-то в stdio.h

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

, почему мы передаем "const char *" ??? Но __filename, например "hello.txt", является строковым типом, а не типом char. Или то, что мы передаем здесь, является адресом этого имени файла, но этот адрес является типом символа ????

- я также запутался, это * принадлежит __restrict или __filename, это __restrict то же самоев качестве ключевого слова restrict мы используем, когда объявляем нормальную функцию C в C99.

- Почему в другом прототипе функции, например

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

, передать "long int __off" не указатель?

Ответы [ 2 ]

0 голосов
/ 12 октября 2019

Передача строки

почему мы передаем "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 указывает смещение в файле на диске илидругое хранилище. Это не адрес чего-либо в основной памяти, поэтому это не указатель. Это число байтов от начала файла, поэтому это число.

0 голосов
/ 12 октября 2019

почему мы передаем "const char *" ???, если я знаю это значение, передаем указатель на константу переменной типа char. Но __filename, например "hello.txt", является строковым типом, а не типом char. Или то, что мы передаем здесь, является адресом этого имени файла, но это адрес типа char ????

В «C» строковая константа (например, «hello.txt»)такой же, как завершенный нулем массив символов. Адрес строки - это позиция первого символа. В целях безопасности / надежности большинство современных компиляторов помещают эти строки в раздел программы, предназначенный только для чтения, и задают тип константы const char **, уменьшая изменение при непредвиденном поведении программы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...