#c #xcode #data-structures #struct
#c #xcode #структуры данных #структура
Вопрос:
После изменения кода я получил новую ошибку в database_definitions.файл заголовка h. Ошибка находится рядом с ‘extern const Lookup_Table TableLookup[TABLE_COUNT];’ и упоминается ошибка в коде с комментариями рядом с ней. Я также получил предупреждение в файле ‘database.c’ рядом с возвратом amp; (TableLookup[index]); в функции ‘Lookup_Table * GetTableMetadata (char * tableName)’. Ошибка вставляется в код рядом с ней. Пожалуйста, просмотрите и помогите мне в решении этой проблемы.
**database.c**:
const Lookup_Table TableLookup[TABLE_COUNT]=
{
{
.tableName = "Folder_Table",
// .tableInitializer = (void*)amp;InitFolder_Table,
.tableMemory = sizeof(Folder_Table),
.columns = 5,
.columnNames = {"folderID","field1","field2","field3","field4"}, // Fill out field name metadata
.columnSize = {SIZE_OF(Folder_Table,folderID), SIZE_OF(Folder_Table,field1), SIZE_OF(Folder_Table,field2),
SIZE_OF(Folder_Table,field3), SIZE_OF(Folder_Table,field4)},
.columnType = {TYPE_INT, TYPE_FLOAT, TYPE_INT, TYPE_FLOAT, TYPE_TEXT},
.subTable = {{.tableName = "Item_Table", .pointerOffset = offsetof(Folder_Table,item)},
{.tableName = "nextRow", .pointerOffset = offsetof(Folder_Table, nextRow)},
{.tableName = "lastRow", .pointerOffset = offsetof(Folder_Table, lastRow)},
{.tableName = "", .pointerOffset = 0 }},
},
{
.tableName = "Item_Table",
// .tableInitializer = (void*)amp;InitItem_Table,
.tableMemory = sizeof(Item_Table),
.columns = 4,
.columnNames = {"ItemID","FolderID","field1","field2"},
.columnSize = {SIZE_OF(Item_Table,itemID), SIZE_OF(Item_Table,folderID), SIZE_OF(Item_Table,field1),
SIZE_OF(Item_Table,field2)},
.columnType = {TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_FLOAT},
.subTable = {{.tableName = "nextRow", .pointerOffset = offsetof(Item_Table, nextRow)},
{.tableName = "lastRow", .pointerOffset = offsetof(Item_Table, lastRow)},
{.tableName = "", .pointerOffset = 0}},
}
};
//====================================================================================
// Struct Table Initializer and metadata functions
//====================================================================================
//------------------------------------------------------------------------------------
// Find the memory size of a table specified by name
//------------------------------------------------------------------------------------
int GetTableSize(char *tableName)
{
int index;
//// Find function matching function name string
for (index=0 ; index < TABLE_COUNT; index )
{
if (strcmp(TableLookup[index].tableName, tableName))
{
return(TableLookup[index].tableMemory);
}
}
return 1; // Return error, should this be an exception?
}
//------------------------------------------------------------------------------------
// Return the index of of the table from the table-lookuptable
//------------------------------------------------------------------------------------
Lookup_Table* GetTableMetadata(char *tableName)
{
//// Find function matching function name string
for (int index=0; index < TABLE_COUNT; index )
{
if (strcmp(TableLookup[index].tableName, tableName))
{
`return amp;(TableLookup[index]);//error: 'Returning 'const Lookup_Table*(aka 'const structLookup_Table') from a function with result type 'Lookup_Table'(aka 'struct Lookup_Table") discards qualifiers`'
}
}
return 0; // Return error
}
**database.h**:
#ifndef database_h
#define database_h
#include "database_definitions.h"
#define ONE_ROW 1
//====================================================================================
// Function Definitions
//====================================================================================
int SQLOpen(void);
//isc_db_handle SQLGetDatabase(void);
Lookup_Table* GetTableMetadata(char *tableName);
Sub_Table* GetSubTableMetadata(char *tableName, char *subTableName);
#endif
**database_definitions.h**:
#ifndef database_database_h
#define database_database_h
extern const Lookup_Table TableLookup [TABLE_COUNT];
//error:unknown type name 'Lookup_Table'
//====================================================================================
// SQL Table Metadata Structures
//====================================================================================
typedef struct Folder_Table // Table type name gets "_Table" added to the SQLite name
{
//// Fields // Comments are added to seperate the fields, Relationships, and metadata
int folderID; // Fields are added as elements of the type and length listed in SQLite
float field1;
int field2;
float field3;
char field4[40]; // string length '40' is queried from SQLite settings for field
//// Relationships
struct Item_Table *item; // Pointer to the sub-table
struct Folder_Table *nextRow; // Linked List Pointer to the next-row
struct Folder_Table *lastRow; // Linked List Pointer to the last-row
} Folder_Table;
typedef struct Item_Table
{
//// Fields
int itemID;
int folderID;
char field1[32];
float field2;
//// Relationships
Folder_Table *folder;
struct Item_Table *nextRow;
struct Item_Table *lastRow;
} Item_Table;
typedef struct Sub_Table
{
char tableName [TABLE_NAME_LENGTH]; // Sub-table name
int pointerOffset; // Sub-table pointer memory offset in the struct
}Sub_Table;
typedef struct Lookup_Table
{
char tableName [TABLE_NAME_LENGTH]; // Stores table name
void (*tableInitializer)(void *); // Pointer to the initializer function
int tableMemory; // Size of the table memory instance
int columns; // Number of columns in the table
char columnNames[MAX_COLUMNS][COLUMN_NAME_LENGTH]; // Array of column names
int columnSize [MAX_COLUMNS]; // Array of column variable memory sizes
int columnType [MAX_COLUMNS]; // Array of column variable types
Sub_Table subTable [MAX_SUB_TABLES]; // Stores sub-table pointers
}Lookup_Table;
#endif
**main.c**:
#include <stdio.h>
#include "database.h"
int main(int argc, const char * argv[])
{
// SQLOpen();
return 0;
}
Комментарии:
1. Похоже на TableLookup в database_definitions. h определяется (через включение) как в database.c, так и в main.c. Скомпилированный объектный файл для database.c и main.c содержит его копию, поэтому компоновщик видит повторяющиеся определения и жалуется. Можете ли вы определить таблицу в database.c?
2.
const Lookup_Table TableLookup[TABLE_COUNT]={...}
не принадлежит вашему заголовочному файлу. Он должен бытьextern const Lookup_Table TableLookup[TABLE_COUNT];
в заголовке и определен в одном исходном файле илиstatic
в заголовке, который, хотя и дублируется на единицу перевода, все равно будет работать для ваших нужд.3. @BrianWalker У меня есть другие функции в дальнейшем, которые будут связаны с TableLookup, и мне нужно определить в database_definitions. файл заголовка h. Есть ли другой способ избавиться от этой проблемы?
4. @WhozCraig Спасибо за ответ. Я не понял, что вы говорили. Где я должен изменить имя на extern const Lookup_Table TableLookup?
5. Удалите весь блок кода TableLookup в database_definitions. h и поместите его в базу данных.c. В database_definitions.h добавьте «extern const Lookup_Table TableLookup[TABLE_COUNT];». Это позволит другим файлам видеть TableLookup, но определять фактические данные для TableLookup только один раз.
Ответ №1:
Вы определяете TableLookup
в своем заголовочном файле, который вы включаете из нескольких исходных (и, следовательно, объектных) файлов. Это приводит к тому, что он определяется во всех объектных файлах, которые включают этот заголовок, и это приводит к тому, что компоновщик выдает эти ошибки.
Что вам нужно сделать, это объявить TableLookup
as extern
, а затем определить его в database.c
(или в каком-либо другом файле, где он подходит). Итак, в database_definitions.h
:
extern const Lookup_Table TableLookup[ TABLE_COUNT ];
И в database.c
:
#include "database_definitions.h"
/* ... */
const Lookup_Table TableLookup[TABLE_COUNT]=
{
{
.tableName = "Folder_Table",
// .tableInitializer = (void*)amp;InitFolder_Table,
.tableMemory = sizeof(Folder_Table),
.columns = 5,
.columnNames = {"folderID","field1","field2","field3","field4"}, // Fill out field name metadata
.columnSize = {SIZE_OF(Folder_Table,folderID), SIZE_OF(Folder_Table,field1), SIZE_OF(Folder_Table,field2),
SIZE_OF(Folder_Table,field3), SIZE_OF(Folder_Table,field4)},
.columnType = {TYPE_INT, TYPE_FLOAT, TYPE_INT, TYPE_FLOAT, TYPE_TEXT},
.subTable = {{.tableName = "Item_Table", .pointerOffset = offsetof(Folder_Table,item)},
{.tableName = "nextRow", .pointerOffset = offsetof(Folder_Table, nextRow)},
{.tableName = "lastRow", .pointerOffset = offsetof(Folder_Table, lastRow)},
{.tableName = "", .pointerOffset = 0 }},
},
{
.tableName = "Item_Table",
// .tableInitializer = (void*)amp;InitItem_Table,
.tableMemory = sizeof(Item_Table),
.columns = 4,
.columnNames = {"ItemID","FolderID","field1","field2"},
.columnSize = {SIZE_OF(Item_Table,itemID), SIZE_OF(Item_Table,folderID), SIZE_OF(Item_Table,field1),
SIZE_OF(Item_Table,field2)},
.columnType = {TYPE_INT, TYPE_INT, TYPE_TEXT, TYPE_FLOAT},
.subTable = {{.tableName = "nextRow", .pointerOffset = offsetof(Item_Table, nextRow)},
{.tableName = "lastRow", .pointerOffset = offsetof(Item_Table, lastRow)},
{.tableName = "", .pointerOffset = 0}},
}
};
Это позволяет всем исходным файлам, в которые вы включаете database_definitions.h
, знать, что переменная существует, но они не содержат явных определений. Вместо этого компоновщику поручено «связать» эти ссылки на внешние символы с местами, где определены символы.
Комментарии:
1. Спасибо за ответ. Я обновил свой код. Я получил новую ошибку и упомянул в приведенном выше коде. Пожалуйста, просмотрите его. ошибка: неизвестное имя типа ‘Lookup_Table’ и одно предупреждение в файле database.c.
2. В
database_definitions.h
, переместитеextern const...
в конец файла, чтобы он понимал типLookup_table
. Что касается другой ошибки вdatabase.c
, это потому, что вы определили таблицу поиска какconst
, но вы возвращаете неconst
указатель из функции. Измените возвращаемый типGetTableMetadata
toconst Lookup_Table*
.3. Вы просите меня заменить ‘Lookup_Table* GetTableMetadata (char tableName’ на ‘const Lookup_Table GetTableMetadata (char * tableName)’?? когда я это сделал, я получил ошибку: конфликтующие типы для ‘GetTableMetadata’
4. Чтобы изменить сигнатуру функции, вам необходимо изменить ее как в файлах .h, так и .c . Прежде чем вы в следующий раз спросите о StackOverflow, я советую вам глубже понять основы, например, пройдя руководство для начинающих по C.
Ответ №2:
TableLookup является массивом и не должен определяться в .h .
Вот что произошло:
два файла, включающие database_definitions.h — database.c и main.c, имеют определение массива в соответствующих объектных файлах — database.o и main.c.o Когда компоновщик пытается объединить два файла, он терпит неудачу, потому что TableLookup определяется дважды.
TableLookup должен быть определен в одном из файлов .c — предпочтительно database.c, затем любой файл .c, который хочет его использовать, должен добавить:
extern const Lookup_Table TableLookup[TABLE_COUNT];
или, что еще лучше, добавьте extern в database.h, и любой .c, который включает его, будет иметь extern и сможет его использовать
Комментарии:
1. Спасибо за ответ. Я обновил свой код. Я получил новую ошибку и упомянул в приведенном выше коде. Пожалуйста, просмотрите его. ошибка: неизвестное имя типа ‘Lookup_Table’ и одно предупреждение в файле database.c.