2013-05-16 2 views
2
#include<stdio.h> 
#include<stdlib.h> 

void function(void *i, void *j); 

struct mystruct { 
    int a; 
    int b; 
} ; 

int main() 
{ 

    int a = 50; 

    struct mystruct s ; 
    s.a = 100; 
    s.b = 200; 
    function(&a, &s); 


} 


void function(void *i, void *j) 
{ 
    printf("Integer is %d\n", *i); 
    printf("Struct member 1 is %d\n", j->a); 
    printf("Struct member 2 is %d\n", j->b); 


} 

Мой код выше. При компиляции я получаю следующие ошибки, и я понимаю, что мне нужно сделать, чтобы исправить их.void * использование для функции формальные аргументы

voidstartest.c: In function function: 
voidstartest.c:27: warning: dereferencing void * pointer 
voidstartest.c:27: error: invalid use of void expression 
voidstartest.c:28: warning: dereferencing void * pointer 
voidstartest.c:28: error: request for member a in something not a structure or union 
voidstartest.c:29: warning: dereferencing void * pointer 
voidstartest.c:29: error: request for member b in something not a structure or union 

Вот что мне нужно сделать, чтобы исправить ошибки:

printf("Integer is %d\n", *(int*)i); 

printf("Struct member 1 is %d\n", ((struct mystruct *)j)->a); 

printf("Struct member 2 is %d\n", ((struct mystruct *)j)->b); 

Вопросы:

  1. Если я должен исправить ошибки так, как я описал выше, не что означает, что я должен знать тип указателей, которые я отправляю в функцию заранее? Я считаю это очень строгим требованием. Не так ли?

  2. Некоторые библиотечные функции имеют формальный аргумент как void * также (например, qsort). Каким образом их реализация знает, каков правильный тип указателя, чтобы они могли разыменовать его для работы с фактическими данными (это указывает на)?

ответ

5
  1. Да. Это означает, что вы не можете написать функцию в агностическом типе, и поэтому вам нужно переосмыслить свой дизайн. При работе с void* обычно записывается функция шаблона и запрашивается у пользователя указатели на функции, которые знают о типе и выполняют основные операции.

  2. Их реализация не является. Они также запрашивают у вас указатели на параметры или параметры размера таким же образом, как я описал выше.

+0

Да, я вижу, что qsort.c отбрасывает базу на char *, а затем использует размер одного элемента массива, а число элементов выполняет арифметику указателя, чтобы обратиться к другим элементам массива для выбора элементов для сравнения для реализации алгоритма , http://forums.devshed.com/c-programming-42/teacher-wants-source-code-of-qsort-function-233585.html – abc

5

Некоторые функции библиотеки имеют формальный аргумент как пустота * также (как QSort). Каким образом их реализация знает, каков правильный тип указателя, чтобы они могли разыменовать его для работы с фактическими данными (это указывает на)?

Поскольку вы также обеспечиваете функцию сравнения, которая принимает два недействительных указателей и возвращает результат сравнения:

void qsort(void *base, size_t nmemb, size_t size, 
      int(*compar)(const void *, const void *)); 

В этой функции вы можете бросить пустоту указателей на указатели к фактическому типу элементы массива, а затем выполнить любую операцию, которую вы хотите

int compare_your_structs(const void *first, const void *second) 
{ 
    const struct mystruct *first_struct = (struct mystruct *)first; 
    const struct mystruct *second_struct = (struct mystruct *)second; 
    /* sort by the "a" field only */ 
    return first_struct->a - second_struct->a; 
} 
1

C статически типизирован. Программа C обычно не может вывести во время выполнения тип объекта, на который указывает указатель, является ли он указателем на пустоту или другим указателем. И он надеется, что вы не будете злоупотреблять указателями, указав их на объект другого типа из своего объявленного типа. Динамически типизированные языки обычно несут накладные расходы при предоставлении таких дополнительных функций.

qsort не нужно знать тип объекта, на который указывают его аргументы указателя на void. Он знает свои размеры и снабжен функцией сравнения, которая, как ожидается, будет написана для сравнения объектов рассматриваемого типа.

+0

Да, я вижу, что qsort.c отбрасывает базу на char *, а затем использует размер одного элемента массива и количество элементов выполняет арифметику указателя, чтобы обратиться к другим элементам массива для выбора элементов для сравнения для реализации алгоритма. http://forums.devshed.com/c-programming-42/teacher-wants-source-code-of-qsort-function-233585.html – abc

0

Функция библиотеки может обрабатывать void* разными способами. Например, qsort требует, чтобы пользователь предоставил указатель функции, который написан для определенных типов.Таким образом, пользователь должен знать только типы, но qsort работает без этой информации.

Другие функции, такие как memcpy, принимают void* для удобства. В действительности, поскольку memcpy является байт-мудрой копией, он задает параметры char*, чтобы он мог работать на уровне байта.

Можно также написать функцию, аналогичную printf, которая берет строку, которая идентифицирует типы ее параметров. В аналогичном ключе макрос va_arg (который используется для работы с varargs) ожидает параметр типа, например. va_arg(list, int). Хотя printf и va_arg не работают с void* (я думаю?), Они сталкиваются с той же проблемой, поскольку va_list нетипизирован. Таким образом, эти понятия могут использоваться также для функций, которые работают на void*.

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