Операции с указателями на функции между исходными файлами 2c, вызывающие ошибки во время компиляции

0

Я работаю над небольшим проектом, чтобы действительно помочь мне понять, что c указателями/указательными функциями немного лучше. Приложение, над которым я работаю, состоит из 2 файлов источника (.c) и 1 файла заголовка (.h). Проблема, с которой я сталкиваюсь, заключается в следующей ошибке при попытке скомпилировать TurtleShell.c в файл ".o":

[ahopkins@localhost TurtleShell]$ gcc -c TurtleShell.c -o TurtleShell.o
TurtleShell.c: In function ‘main:
TurtleShell.c:12: error: ‘GetString undeclared (first use in this function)
TurtleShell.c:12: error: (Each undeclared identifier is reported only once
TurtleShell.c:12: error: for each function it appears in.)

Обычно, из моего понимания, это означало бы, что я забыл объявить функцию, которая помещена после main или что я забыл включить мой заголовочный файл как #include "GetString.h" и/или что заголовочный файл не находится в тот же каталог (или /usr/local/include,/usr/local) в качестве исходного файла, использующего его, однако три файла находятся в одном каталоге и объявлен заголовочный файл.

Следует отметить, что я пытаюсь получить доступ к GetString() с помощью указателя на функцию. Я использовал указатели функций в прошлом в том же исходном файле, но это мой первый реальный набег на использование нескольких исходных файлов для приложения, использующего указатели на функции, поэтому я сделал некоторые предположения в этом процессе. Исходный код выглядит следующим образом:

GetString.c:

#include <stdio.h>
#include <stdlib.h>

/*
This function handles getting a string from the user by allocating each
character in the string to a char array. This array is guaranteed to
grow as large as it needs as well as trim itself down to only the needed
amount of memory to store the char array once the null terminator is
processed.
*/

int GetString(void)
{
    //Set initial array length reasonably. size_t is used due to it ability
    //to allow an array to grow as large as it needs.
    size_t strLength = 32;
    char *stringPtr = malloc(strLength);
    if (stringPtr == NULL)
    {
        fprintf(stderr, "Unable to allocate memory to hold char array. Exiting!\n");
        return 1;
    }
    printf("Enter some input: ");
    int c = EOF;
    unsigned int i = 0;
    //Checks the value of c (user character input) to see if RETURN or CTRL+C/Z was entered
    while ((c = getchar()) != '\n' && c != EOF)
    {
        //Adds the character entered into the next index of the char array
        stringPtr[i++] = (char) c;
        //Check if we have reached the end of the allocated memory for the char array
        if (i == strLength)
        {
            //multiply the current amount of memory allocated by 2.
            strLength *= 2;
            if ((stringPtr = realloc(stringPtr, strLength)) == NULL)
            {
                fprintf(stderr, "Unable to expand memory to hold char array. Exiting!\n");
                return 2;
            }
        }
    }
    //End of input. This adds the null terminator to terminate the char array
    stringPtr[i] = '\0';
    //Check if we have any unused memory allocated for the array left. If so, we
    //shrink it down to be the size of the input including the null terminator
    if (sizeof(stringPtr) < strLength)
    {
        stringPtr = realloc(stringPtr, i);
    }
    printf("\n\nString value: %s\n\n\n", stringPtr);
    //Memory cleanup time
    free(stringPtr);
    stringPtr = NULL;
    return 0;
}

TurtleShell.c:

#include <stdio.h>
#include <stdlib.h>
#include "GetString.h"

int main(void)
{
    int running = 1;
    while(running)
    {
        //Create a function pointer for GetString() so we can manipulate the outputted string from GetString
        int (*GetStringPtr)(void);
        GetStringPtr = &GetString;
        char *string = malloc(GetStringPtr());
        free(string);
        string = NULL;
    }
}

GetString.h:

#ifdef GETSTRING_H_INCLUDED
#define GETSTRING_H_INCLUDED
extern int GetString(void);
#endif

Я знаю, что это связано с тем, как я пытаюсь создать указатель на функцию, как если бы я изменял TurtleShell.c в следующем формате, он работает по назначению:

#include <stdio.h>
#include <stdlib.h>
#include "GetString.h"

int main(void)
{
    int running = 1;
    while(running)
    {
        char *string = malloc(GetString());
        free(string);
        string = NULL;
    }
}

Я очень зелёный на C, поскольку я только писал в нем около 3 недель, так что, возможно, мне не хватает чего-то очевидного. У меня проблема с Googled, но я нашел, что это особенно сложно правильно сформулировать, чтобы найти соответствующие результаты. Любая помощь приветствуется.

PS - Мне хорошо известно, что есть много хороших функций типа GetString(), которые я мог бы использовать, однако, это для обучения, поэтому я работаю над созданием своих собственных функций по мере необходимости, чтобы увеличить образовательную ценность этих упражнения.

Теги:
pointers
function
header-files

2 ответа

1
Лучший ответ

#ifdef в Getstring.h должны быть #ifndef

  • 0
    Чистый результат: «Я забыл включить свой заголовочный файл»
  • 0
    Ты просто класс! Я не могу поверить, что это была опечатка. Я полагаю, я должен быть благодарен, что это не было чем-то хуже. Просто из любопытства, почему это работает без указателя функции?
Показать ещё 1 комментарий
1

Следующая строка не имеет смысла: char * string = malloc (GetString());

GetString() возвращает 0, 1 или 2. Это означает, что вы выделяете память длиной 0, 1 или 2 байта.

Если вы хотите получить строку, которую вы прочитали в GetString(), используйте аргумент, указатель на указатель на char. В этом случае вам не нужны указатели на функции.

int GetString(char** string)
{
  size_t strLength = 32;
  *string = malloc(strLength);
  ...
}

Не освобождайте строку в конце функции. Сделайте это в своей основной функции. Вы можете получить строку, передав char *, чтобы он функционировал следующим образом:

char *string;
int ret = GetString(&string); // Get the address of 'string'
  • 0
    Я ценю усилия, которые вы приложили к этому ответу, однако текущий код работает так, как задумано. Согласно вашему ответу, такое поведение было бы невозможно. Я что-то пропустил?
  • 0
    Переменная (указатель на символ) 'string' в вашей основной функции никогда не будет указывать на введенную строку. Вместо этого он будет указывать на неинициализированную память.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню