Какой эффект имеет приведение переменной как (void *)? - PullRequest
1 голос
/ 29 марта 2011

В программе на Си я вижу следующее утверждение:

memcpypgm2ram((void*)&AppConfig.MyMACAddr, (ROM void*)SerializedMACAddress, sizeof(AppConfig.MyMACAddr));

Что делает случай (void *)? Это написано для компилятора Microchip C30.

AppConfig определяется следующим образом:

APP_CONFIG AppConfig;  // APP_CONFIG is obviously a structure...

SerializedMACAddress определяется следующим образом:

static ROM BYTE SerializedMACAddress[6] = {MY_DEFAULT_MAC_BYTE1, MY_DEFAULT_MAC_BYTE2, MY_DEFAULT_MAC_BYTE3, MY_DEFAULT_MAC_BYTE4, MY_DEFAULT_MAC_BYTE5, MY_DEFAULT_MAC_BYTE6};

РЕДАКТИРОВАТЬ: Я должен был сказать это раньше, но memcpypgm2ram определяется как: #define memcpypgm2ram (a, b, c) memcpy (a, b, c)

так в основном, void *memcpy(void *dest, const void *src, size_t n);

Ответы [ 6 ]

5 голосов
/ 29 марта 2011

void* - это универсальный тип указателя данных, который при использовании в качестве типа аргумента означает, что функция работает с «пустыми» блоками памяти. Он не может быть разыменован.

Любой другой тип указателя данных может быть неявно преобразован в void*, поэтому явное приведение может быть либо неправильным (ненужным), либо обходным решением для сломанного компилятора, либо сокращением, приведенным к unsigned char * (в этом случае это обходной путь для сломанного интерфейса).

1 голос
/ 29 марта 2011

Приведение void * преобразует указатель некоторого типа в универсальный указатель.

0 голосов
/ 29 марта 2011

в этом случае приведение к (void *) может использоваться, чтобы избавиться от предупреждения компилятора.

0 голосов
/ 29 марта 2011

Невозможно сказать, какой смысл использовать (void *) приведение в этом конкретном случае, не видя больше контекста (как объявляется memcpypgm2ram?).

В языке C (как и в C ++) типы указателей неявно преобразуются в тип void *, что означает, что в преобразованиях указателей обычно нет причин использовать явное приведение к типу void *. Похоже, в вашем примере все преобразования являются преобразованиями указателей, поэтому, принимая во внимание то, что я сказал, явное приведение к void * не требуется.

Другая возможность, однако, заключается в том, что исходные типы указателей являются const-квалифицированными, поэтому приведение к void * использовалось для удаления const-квалификации. Однако я не вижу каких-либо постоянных квалификаций в том, что вы предоставили, что означает, опять же, что, скорее всего, приведение к void * не нужно. Я полагаю, что тот, кто положил его туда, сделал это «на всякий случай» без какой-либо реальной причины.

Короче говоря, приведение (void *) преобразует указатели в тип void *. Но так как это преобразование в любом случае произойдет неявно, приведение совершенно не нужно (при условии, что memcpypgm2ram объявлено с void * параметрами).

0 голосов
/ 29 марта 2011

memcpypgm2ram предположительно принимает пустой указатель в качестве аргумента. Тип C достаточно типичен, чтобы распознавать, что тип & AppConfig.MyMACAddr равен (MACAddr *) и будет выдавать ошибку во время компиляции, если вы не приведете его как void *.

Дело в том, что memcpypgm2ram - это функция, которая работает с любыми байтами, хранящимися в памяти, поэтому она не будет принимать строго типизированные указатели в качестве аргументов.

0 голосов
/ 29 марта 2011

Функция memcpypgm2ram не требует определенного типа.Он должен быть определен с помощью следующего прототипа: memcpypgm2ram (void * p1, void * p2, int n);«void *» - приведение к типу общего указателя.

Функция просто берет два указателя любого типа и копирует n байтов (в вашем случае n = sizeof (AppConfig.MyMACAddr)) с одного адреса наДругой.

...