Реализация C-стека — проблема с malloc

#c #struct #compiler-errors #declaration #definition

#c #структура #ошибки компилятора #объявление #определение

Вопрос:

Я пытаюсь реализовать проверку баланса скобок с помощью stack, и, похоже, я не могу избавиться от этого

Ошибка

 tempCodeRunnerFile.c: In function ‘main’:
tempCodeRunnerFile.c:26:20: error: dereferencing pointer to incomplete type ‘struct StackRecord’
   26 |  S = malloc(sizeof(*S));
      |

 
 

Вот код:

баланс.c

 #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stack.h"

void main() 
{
    struct StackRecord *S;
    char str[500], c;
    int l, i;

    S = malloc(sizeof(*S));
    while (1) {
        .............
        .............
    
    return;
}
 

стек.c

         #include "stack.h"
        #include "fatal.h"
        #include <stdlib.h>

        #define EmptyTOS ( -1 )
        #define MinStackSize ( 5 )

        struct StackRecord
        {
            int Capacity;
            int TopOfStack;
            ElementType *Array;
        };

.............
.............
 

stack.h

 typedef int ElementType;
/* START: fig3_45.txt */
        #ifndef _Stack_h
        #define _Stack_h

        struct StackRecord;
        typedef struct StackRecord *Stack;

        int IsEmpty( Stack S );
        int IsFull( Stack S );
        Stack CreateStack( int MaxElements );
        void DisposeStack( Stack S );
        void MakeEmpty( Stack S );
        void Push( ElementType X, Stack S );
        ElementType Top( Stack S );
        void Pop( Stack S );
        ElementType TopAndPop( Stack S );

        #endif  /* _Stack_h */

/* END */
 

Я помещаю только важные части, которые вызывают проблему. Это не имеет никакого смысла, так как все кажется правильным:/

Комментарии:

1. Если вы хотите создать непрозрачную структуру данных, то вам необходимо реализовать собственную фабричную функцию для создания экземпляров структуры данных.

2. Вы должны прочитать Modern C , документацию вашего компилятора C (например, GCC …) и вашего отладчика (например, GDB ). Если вы используете GCC, скомпилируйте со всеми предупреждениями и отладочной информацией, например gcc -Wall -Wextra -g . Возможно, вам захочется иметь какой-то гибкий элемент массива

3. Возможно, вам захочется прочитать какой-нибудь стандарт C, например, n2176 . Вы наверняка хотите черпать вдохновение из существующего программного обеспечения с открытым исходным кодом, например GNU bash или remake или GTK . Вас может заинтересовать Frama-C

Ответ №1:

В блоке перевода с основным

 #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stack.h"

void main() 
{
    struct StackRecord *S;
    char str[500], c;
    int l, i;

    S = malloc(sizeof(*S));
    while (1) {
        .............
        .............
    
    return;
}
 

определение структуры struct StackRecord неизвестно. Таким образом, компилятор не может вычислить размер объекта этого типа в операторе sizeof

 S = malloc(sizeof(*S));
 

Вам необходимо переместить определение структуры из "stack.c" заголовка "stack.h" .

Обратите внимание на то, что в соответствии со стандартом C функция main должна быть объявлена как

 int main( void )
 

вместо

 void main()
 

Ответ №2:

Чтобы выделить a struct StackRecord , нужно знать размер a struct StackRecord . И чтобы узнать размер a struct StackRecord с помощью sizeof оператора, нужно определение a struct StackRecord .

Проблема в том, что определение struct StackRecord нигде не найдено в текущей единице перевода. ( stack.c не участвует в компиляции balance.c .)

Чтобы решить эту проблему, переместите определение struct StackRecord from stack.c в stack.h , или stack.c предоставьте функцию для выделения struct StackRecord .

Комментарии:

1. Но разве не следует компилировать так: gcc balance.c stack.c исправить проблему?

2. Это сокращение gcc -c balance.c; gcc -c stack.c; gcc balance.o stack.o от того, что он компилирует balance.c, затем компилирует stack.c, а затем связывает два файла .o. Размер необходим во время компиляции, а не связывания.

3. @DaviHlav Вам нужно узнать о концепции единиц перевода . Компилятор не видит все исходные файлы, все, что он когда-либо видит, — это одна единица перевода (в основном один исходный файл со всеми включенными файлами заголовков). Компилятор ничего не знает о других единицах перевода или о том, что они содержат. Даже такая команда, как gcc balance.c stack.c будет создавать два исходных файла отдельно один за другим.

4. @DaviHlav Код не является допустимым C, то, как вы его компилируете, этого не меняет.