2009-07-08 7 views
2

Как я могу преобразовать следующие struct в unsigned char*?Преобразование структуры в unsigned char *

typedef struct { 
    unsigned char uc1; 
    unsigned char uc2; 
    unsigned char uc3; 
    unsigned char uc5; 
    unsigned char uc6; 
} uchar_t; 

uchar_t *uc_ptr = new uchar; 
unsigned char * uc_ptr2 = static_cast<unsigned char*>(*uc_ptr); 
// invalid static cast at the previous line 

ответ

7

Здесь вы не можете использовать static_cast, так как нет никакой связи между типами. Вам нужно будет использовать reinterpret_cast.

В принципе, в большинстве случаев следует использовать static_cast, тогда как reinterpret_cast, вероятно, поставит вам вопрос, почему вы так делаете.

Вот время, когда вы будете использовать static_cast:

class Base { 
}; 

class Derived : Base { 
}; 

Base* foo = new Derived; 
Derived* dfoo = static_cast<Derived*>(foo); 

В то время как здесь, где вы, вероятно, необходимо reinterpret_cast:

void SetWindowText(WPARAM wParam, LPARAM lParam) 
{ 
    LPCTSTR strText = reinterpret_cast<LPCTSTR>(lParam); 
} 
+0

Спасибо Джону за редактирование. Я не поймал этого, набирая торопливость. – Jared

+0

В примере, который вы указали при использовании броска, должен быть dynamic_cast <>, поскольку существует отношение наследования. static_cast <> может использоваться с несвязанными (с точки зрения отношения наследования) для преобразования, например, целого числа в тип перечисления, double в int ... –

+0

@ Jared - вы можете использовать static_cast здесь - см. мой ответ. @dribeas - здесь не работает static_cast - динамический_cast на самом деле не будет работать здесь, поскольку в базе нет виртуальных функций, но если бы существовал виртуальный деструктор - можно было бы использовать одну из приведений - static_cast будет больше конечно, хотя dynamic_cast имеет определенные преимущества во время выполнения (не требуется в этом сценарии). –

2

Пробовать reinterpret_cast<unsigned char*>. static_cast предназначен для преобразования между совместимыми типами, такими как базовый класс, в производный класс. reinterpret_cast предназначен для отливок между несвязанными типами.

+0

Ничего себе, вы избили меня до него. 35 секунд впереди меня :) – Jared

1

Почему бы вам использовать такой странный-структуру вместо:

неподписанный символ uc [5];

, которые вы можете индивидуально адресовать как uc [0], uc [1], uc [2], uc [3], uc [4] и указателем на агрегацию (предположительно, что вы хотите с unsigned char *) просто «uc».

Кажется намного проще, чем структуры с несколькими неподписанных элементами гольцов, которые пронумерованы в именах членов (и кстати, что случилось с UC4 -. Другой ошибкой решения массива бы избежать)

+0

Я только что заметил отсутствующий uc4. Пример, который я опубликовал, является иллюстративным, структура, которую я имею, имеет некоторое значение. Спасибо, в любом случае. – freitass

4

Благодаря структуру что вы не можете сделать это надежно и переносимо, не используя массив, чтобы начать или написать некоторый код, который заполнял новый массив по одному из членов структуры по имени. Reinterpret_cast может работать на одном компиляторе/платформе/версии и переходить на другой.

Вам лучше распределить массив в куче или стеке, а затем заполнить его один за другим.

+0

Я собирался опубликовать то же самое сам. Всегда пишите функции упаковки/распаковки для такого рода вещей. –

+0

Возможно, вам удастся справиться с некоторыми прагмами для управления упаковкой, но это будет специфичным для компилятора. –

1

Как насчет просто:

unsigned char * uc_ptr2 = &uc_ptr->uc1; 
1

самого безопасного, переносимого способа для преобразования POD (т.е.C совместимые структуры) типы беззнакового указателей гольцов не используя reinterpret_cast, но с помощью static_cast (C++ 0x исправляет это и дает reinterpret_cast однозначно имеют ту же портативную семантику, следующая строка коды):

unsigned char *uc_ptr2 = static_cast<unsigned char*>(static_cast<void*>(uc_ptr)); 

Но для всех практических целей, хотя стандарт C++ 03 считается несколько неоднозначным в этой проблеме (не столько при преобразовании указателей типов классов, но при преобразовании указателей неклассических типов в «unsigned char *») , большинство реализаций будут поступать правильно, если вы используете reinterpret_cast следующим образом:

unsigned char *uc_ptr2 = reinterpret_cast<void*>(uc_ptr); 

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

1

В этом случае, литье с reinterpret_cast, чтобы unsigned char* гарантированно работать и будет указывать на первый элемент данных unsigned char, потому что ваш тип является так называемая СТРУЧОК структура (примерно, С структура).

Цитата Стандарта (от 9.2/17, если вы хотите выглядеть)

Указатель на объект POD-структуры, соответственно превращенного с помощью reinterpret_cast, указывает на его первоначального члена (или, если этот член является бит-поле, затем в блок, в котором он находится) и наоборот. [Примечание. Таким образом, в случае объекта POD-структуры, но не в начале, может возникнуть неназванное заполнение, если необходимо, для достижения соответствующего выравнивания. ]

Так следующие работы

unsigned char * uc_ptr2 = reinterpret_cast<unsigned char*>(uc_ptr); 
0

Вы хотите, чтобы преобразовать адрес структуры на адрес без знака полукокса (как некоторые из ответов предположить) или фактическую структуру к указателю (как указывает ваш вопрос)? Если первое, то здесь есть несколько возможностей:

unsigned char * uc_ptr2 = static_cast<unsigned char *>(static_cast<void *>(uc_ptr)); 
unsigned char * uc_ptr2 = reinterpret_cast<unsigned char *>(uc_ptr); 
unsigned char * uc_ptr2 = (unsigned char *)uc_ptr; 

В последнем случае вы можете использовать один из:

unsigned char * uc_ptr2 = *static_cast<unsigned char **>(static_cast<void *>(uc_ptr)); 
unsigned char * uc_ptr2 = *reinterpret_cast<unsigned char **>(uc_ptr); 
unsigned char * uc_ptr2 = *(unsigned char **)uc_ptr; 
0

Одним из вариантов является сделать наоборот. Сначала создайте буфер «unsigned char *», а затем используйте новое место размещения, чтобы выделить объект поверх этого буфера.

#include <iostream> 

struct uchar_t { 
    unsigned char uc1; 
    unsigned char uc2; 
    unsigned char uc3; 
    unsigned char uc4; 
    unsigned char uc5; 
    unsigned char uc6; 
}; 

int main() 
{ 
    unsigned char * buffer 
    = new unsigned char[ sizeof (uchar_t)/sizeof (unsigned char) ]; 
    uchar_t * uc = new (buffer) uchar_t(); 

    uc->uc3 = 'a'; 
    std::cout << buffer[2] << std::endl; 

    delete buffer; 
}