2017-01-31 5 views
1

Давайте представим, у меня есть 3 различных типов наборов данных в 3-х различных структурах:Пустота указателя на структуру указателя внутри структуры без разыменования его

typedef struct 
{ 
    int a; 
    //... 
}DATATYPE1; 

typedef struct 
{ 
    int a; 
    //... 
}DATATYPE2; 

typedef struct 
{ 
    int a; 
    //... 
}DATATYPE3; 

Затем представьте, я хочу один из тех типов данных, которые будут отнесены к услугам Основная структура, как это:

typedef struct 
{ 
    int b; 
    void* data; 
    //... 
}OBJECT; 

Say заявляю OBJECT* abc = malloc(sizeof(OBJECT)); и DATATYPE1* dt1 = malloc(sizeof(DATATYPE1)); есть ли способ, которым я мог бы бросить в коде что-то вроде этого:

abc->data = dt1; 

, а затем вызвать:

(abc->data)->a; 

без разыменования abc->data указателя обратно e.g. DATATYPE1* dp = abc->data, а затем использовать dp->a;

+2

1) Не используйте имена всех прописных букв для чего-либо еще, кроме макросов или enum-констант. 2) Никогда не используйте 'void *' без истинной необходимости. Введите безопасный код! 3) Как компилятор должен знать, к какому типу ваш 'void * 'указывает без приведения? 4) Какова ваша ** актуальная проблема, которую вы пытаетесь решить? – Olaf

+0

Вот в чем дело, я не знаю. Но есть ли способ, который он мог бы работать так близко? – Primemaster

+0

Может? Может быть (если бы вы могли прояснить пункт 4). Фактический вопрос: ** если вы **?На что легче ответить: ** НЕТ! ** – Olaf

ответ

3

Я предполагаю, что проблема заключается в том, что вы хотите получить доступ к a поля ваши три DATATYPE S, не зная, какой DATATYPE на самом деле присутствует. Ответ: да, вы можете, потому что спецификация C явно говорит, что независимо от того, что присутствует DATATYPE, указатель указывает на первый элемент структуры и, следовательно, можно безопасно отнести к этому типу.

См: Are there any guarantees about C struct order? и в особенности:

15 В пределах объекта структуры, члены небитового поля и блоки , в котором битовые поля располагаются имеют адреса, которые увеличивают в порядке , в котором они объявлены. Указатель на объект структуры, подходящим образом преобразованный , указывает на его исходный элемент (или если этот элемент является битовым полем , а затем к единице, в которой он находится) и наоборот. В объекте структуры может быть неназванное заполнение, но не на начало .

Таким образом, следующий код позволяет вам получить доступ к:

OBJECT* abc = malloc(sizeof(OBJECT)); 
abc->data = malloc(sizeof(DATATYPE1)); 
int* pointerToA = (int*) abc->data; 

ли это хорошая практика программирования другой вопрос, что я не буду отвечать.

0

Вы должны объявить все, что вы будете делать ссылки в коде C. Это единственный способ, которым компилятор знает размер и местоположение объекта в этом конкретном адресе.

Я думаю, что вы можете использовать анонимные союзные блоки и сделать что-то вроде этого:

typedef struct 
{ 
    int b; 
    union { 
     void* data; 
     DATATYPE1 *dt1; 
     DATATYPE2 *dt2: 
     DATATYPE3 *dt3; 
    };  
} OBJECT; 

затем использовать:

OBJECT* abc = (OBJECT*)malloc(sizeof(OBJECT)); 
DATATYPE1* dt1 = (DATATYPE1*)malloc(sizeof(DATATYPE1)); 
abc->data = (void *)dt1; 
int val = abc->dt1->a; 
+0

Нет необходимости в каких-либо из этих приемов, но все здесь кажется правильным. Трудно определить, действительно ли это отвечает на этот вопрос, поскольку ОП кажется немного неопределенным именно тем, что он хочет знать. Тем не менее, профсоюз действительно может быть хорошим способом для ОП подойти к его проблеме. –

+0

Я согласен с вами. Я попытался показать ему, что я думаю, что может создать код, который очень похож на его желание. Спасибо, что комментировали броски, они действительно не нужны. – lewohart

Смежные вопросы