2012-03-23 2 views
1

У меня есть программа на C, как показано ниже. Я пытаюсь написать обертку поверх malloc с подписью int myAlloc(). Эта оболочка должна возвращать 1 при успешном распределении памяти или возвращать 0, если распределение памяти не выполняется.несовместимый указатель типа предупреждение

#include <stdio.h> 
#include <stdlib.h> 

int myAlloc(void **ptr, int size) 
{ 
    *ptr = malloc(size); 

    if (!ptr) 
     return 0; 
    else 
     return 1; 
} 

void main() 
{ 
    int *p = NULL; 
    myAlloc(&p, sizeof(int)); 
    printf("%d\n", *p); 
} 

Когда я скомпилирую это, я получаю предупреждение, говорящее «несовместимый тип указателя». Как я могу позволить, чтобы эта функция вызывалась с любым возможным типом указателя без получения предупреждения?

Можно ли удалить операцию литья из фактического вызова функции?

Обновление

Я нашел ответ. Вот исправленный код:

#include <stdio.h> 
#include <stdlib.h> 

int myAlloc(void *ptr,int size) 
{ 
    *(void **)ptr = malloc(size); 

    if (!ptr) 
     return 0; 
    else 
     return 1; 

} 

int main() 
{ 
    int *p = NULL; 
    myAlloc(&p, sizeof(int)); 
    *p = 5; 
    printf("%d\n", *p); 

    return 1; 
} 
+0

Это, как представляется, не быть стандартным с, или C++, в качестве основного не возвращается тщетным. –

+0

@ RichardJ.RossIII Вы ошибаетесь. Прочитайте [this] (http://stackoverflow.com/questions/5296163/why-is-the-type-of-the-main-function-in-c-and-c-left-to-the-user-to -define/5296593 # 5296593). – Lundin

+1

@ Lundin Я прочитал это, и мой вопрос все еще стоит. Я не считаю, что это находится в автономной среде или в среде размещения. –

ответ

0
#include <stdio.h> 
#include <stdlib.h> 

int myAlloc(void *ptr,int size) 
{ 
    *(void **)ptr=malloc(size); 
    if(!ptr) return 0; 
    else return 1; 

} 

int main() 
{ 
    int *p=NULL; 
    myAlloc(&p,sizeof(int)); 
    *p=5; 
    printf("%d\n",*p); 
    return 1; 
} 
-1

p является тип int*, в то время как ваша функция принимает void**.

myAlloc((void **)&p,sizeof(int)); 
-1

В соответствии с подписью myAlloc, вы должны назвать его myAlloc((void**)&p,sizeof(int)) так как р int* (PTR в целом), а не void* (PTR к мочеиспусканию).

-2

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

if(!(*ptr)) return 0; 
0

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

src.c: In function ‘main’: 
src.c:15:17: warning: passing argument 1 of ‘myAlloc’ from incompatible pointer type [enabled by default] 
src.c:4:5: note: expected ‘void **’ but argument is of type ‘int **’ 

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

myAlloc((void **)&p,sizeof(int)); 

И теперь он компилируется без предупреждений.

Возможно, вы захотите ознакомиться с разделом pointers от The C Book, особенно в разделе 5.3.5, в котором явно рассматриваются некоторые проблемы, поднятые здесь.

+0

Это не даст предупреждения, но может привести к сбою. подумайте о платформе, которая имеет 'sizeof (int *) asaelr

+0

Это одна из причин, по которой я указал на раздел 5.3.5 книги C. Если вы посмотрите, вы увидите, что это обсуждает это. – larsks

3

ваша функция, myMalloc принимает указатель на указатель к мочеиспусканию, или void** вы передаете его адрес указателя на междунар или int**

Вам нужно привести указатель вы передаете недействительным, например

myAlloc((void**)&p,sizeof(int)); 
+0

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

+0

Это приводит к неопределенному поведению из-за нарушения строгой псевдонимы в '* ptr = malloc (size)' (C99 6.5 §7) – Christoph

+1

Я так не думаю ... шаблоны сделали бы это ловушкой, но IIRC C ничего не значит шаблоны. Другие мудрые, перегрузки для всех типов, но тогда это просто будет запутано – thecoshman

0

Это может показаться интересным академический, но не ваш внутренний код в обертке делает тот же типа булевой проверки?

void *ptr; 
if((ptr = malloc(1000))) 
{ 
    /* Do stuff with ptr */ 
} 
else 
{ 
    /* throw a tantrum */ 
} 

Вам действительно нужен код возврата int с дополнительной сложностью параметра?

0

В C есть тип void* для общего указателя, но нет указателя на указатель указателя.Хуже того, размер разных типов указателей может быть неравным. Следовательно, если ваша функция не знает, какой тип указателя она должна назначить, она не может просто «поместить данные в адрес», поскольку размер правильного указателя может отличаться от размера указателя, который он назначает.

Например, ваш код может быть поврежден (и является UB), если sizeof(int*)<sizeof(void*).

Из-за этого, я думаю, что невозможно написать обертку, как вы хотите.

0

Невозможно написать такую ​​функцию в стандартах C, поскольку int * и void * несовместимы.

A (в основном) эквивалент макроопределения может выглядеть следующим образом:

#define myAlloc(PTR, SIZE) (!!(PTR = malloc(SIZE)))