Рубрики

Важность прототипа функции в C

Прототип функции сообщает компилятору о количестве параметров, принимаемых функцией, типах данных параметров и типе возвращаемой функции. Используя эту информацию, компилятор проверяет параметры функции и их тип данных с помощью определения функции и вызова функции. Если мы игнорируем прототип функции, программа может скомпилировать с предупреждением и может работать должным образом. Но иногда это дает странный результат, и очень трудно найти такие ошибки программирования. Давайте посмотрим на примерах

#include <errno.h>
#include <stdio.h>

  

int main(int argc, char *argv[])

{

    FILE *fp;

  

    fp = fopen(argv[1], "r");

    if (fp == NULL) {

        fprintf(stderr, "%s\n", strerror(errno));

        return errno;

    }

  

    printf("file exist\n");

  

    fclose(fp);

  

    return 0;

}

Выше программа проверяет наличие файла, предоставленного из командной строки, если данный файл существует, то программа печатает «файл существует», в противном случае выводит соответствующее сообщение об ошибке. Давайте предоставим имя файла, которого нет в файловой системе, и проверим вывод программы на архитектуре x86_64.

[narendra@/media/partition/GFG]$ ./file_existence hello.c
Segmentation fault (core dumped)

Почему эта программа потерпела крах, вместо этого она должна показать соответствующее сообщение об ошибке. Эта программа будет хорошо работать на архитектуре x86, но будет зависать на архитектуре x86_64. Давайте посмотрим, что случилось с кодом. Внимательно изучите программу, сознательно я не включил прототип функции strerror (). Эта функция возвращает «указатель на символ», который выведет сообщение об ошибке, которое зависит от того, какая ошибка передана этой функции. Обратите внимание, что архитектура x86 — это модель ILP-32, то есть целочисленные, указатели и long имеют 32-битную ширину, поэтому программа будет корректно работать на этой архитектуре. Но x86_64 — это модель LP-64, то есть long и указатели шириной 64 бита. В языке Си, когда мы не предоставляем прототип функции, компилятор предполагает, что функция возвращает целое число . В нашем примере мы не включили заголовочный файл «string.h» (в этом файле объявлен прототип strerror), поэтому компилятор предположил, что функция возвращает целое число. Но его типом возврата является указатель на символ. В x86_64 указатели имеют ширину 64 бита, а целые числа — 32 бита, поэтому при возврате из функции возвращаемый адрес усекается (т. Е. Адрес 32-битной ширины, то есть размер целого числа в x86_64), что недопустимо, и когда мы пытаемся разыменовать этот адрес, в результате возникает ошибка сегментации.

Теперь включите заголовочный файл «string.h» и проверьте вывод, программа будет работать правильно.

[narendra@/media/partition/GFG]$ ./file_existence hello.c
No such file or directory

Рассмотрим еще один пример.

#include <stdio.h>

  

int main(void)

{

    int *p = malloc(sizeof(int));

  

    if (p == NULL) {

        perror("malloc()");

        return -1;

    }

  

    *p = 10;

    free(p);

  

    return 0;

}

Выше код будет работать нормально на модели IA-32, но не будет работать на модели IA-64. Причина сбоя этого кода в том, что мы не включили прототип функции malloc (), а возвращаемое значение усекается в модели IA-64.

Эта статья составлена Нарендрой Кангралкар . Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Важность прототипа функции в C

0.00 (0%) 0 votes