2013-08-04 64 views
5

Tôi đã đoạn mã sau vào header Clỗi malloc trong struct (C)

typedef struct { 
    kiss_fft_scalar r; 
    kiss_fft_scalar i; 
} kiss_fft_cpx; 

Và tôi thực hiện đoạn mã sau trong chương trình thử nghiệm

kiss_fft_cpx *fin = malloc(4*sizeof(kiss_fft_cpx)); 

Và nó đã cho tôi được thông báo lỗi : "Không thể sử dụng giá trị loại void để khởi tạo thực thể thuộc loại 'kiss_fft_ctx'".

Tôi đang sử dụng dự án bảng điều khiển Win32 C/C++ win32.

Bất cứ ai có thể cho tôi biết cách sử dụng chính xác malloc ở đây? Cảm ơn!

+0

bản sao có thể có của [chuyển đổi không hợp lệ từ 'void \ *' thành 'node \ *' \ [-fpermissive \]] (http://stackoverflow.com/questions/16793587/invalid-conversion-from-void-to -node-fpermissive) –

+1

Tôi không nghĩ rằng thông báo lỗi là 'void không thể được sử dụng để khởi tạo kiss_fft_ctx'. Tôi nghĩ đó là 'void *' và 'kss_fft_ctx *'. Những dấu sao đó tạo nên sự khác biệt ** BIG ** trong ý nghĩa và sự hiểu biết của bạn về ngôn ngữ. – abelenky

Trả lời

12

Bạn cần phải cast kiểu trả về như thế này:

kiss_fft_cpx *fin = (kiss_fft_cpx*) malloc(4*sizeof(kiss_fft_cpx)); 

nhưng ngụ ý là bạn đang biên soạn mã của bạn như C++ chứ không phải C, bởi vì đó là một ++ lỗi C chứ không phải là một lỗi C. Bạn có thể muốn kiểm tra phần mở rộng tập tin của bạn và/hoặc cài đặt trình biên dịch của bạn.

Nếu bạn thực sự sử dụng C++, bạn nên ở một sử dụng tối thiểu new hơn malloc:

kiss_fft_cpx *fin = new kiss_fft_cpx[4]; 

và lý tưởng suy nghĩ lại xem bạn cần phải tạo các đối tượng động như thế này - bạn có thể sử dụng một std::vector hoặc tương tự thay thế?

+2

+1 cho ghi chú về C++. –

+0

Thật tuyệt, vấn đề là tôi phải sử dụng mã C được lập trình bởi những người khác trong dự án C++ của tôi. Vì vậy, tôi tự hỏi nếu nó cũng có thể sử dụng chương trình khác chứ không phải là malloc để hoàn thành việc cấp phát bộ nhớ (Nếu không, C + + có vẻ là khá câm ở đây khi chúng tôi sử dụng C trong C + +) – Cancan

+4

@Cancan Đó là, nhưng bạn tốt hơn không. Chỉ cần biên dịch thành C thay vào đó. ** Đừng bao giờ cố gắng biên dịch mã C thành C++. ** Chúng là các ngôn ngữ khác nhau. –

3

Trong C, bạn có thể bỏ con trỏ void trả về malloc. C làm điều này cho bạn nhưng bạn cũng có thể rõ ràng.

malloc trả lại con trỏ void * hoặc void, giá trị trả về này sau đó có thể được một lập trình viên đưa vào các loại con trỏ khác. Hoặc lập trình viên có thể dựa vào C để thực hiện chuyển đổi kiểu. Chuyển đổi loại C bằng cách sử dụng phôi sẽ không thay đổi.

Tuy nhiên, mã C dựa trên trình biên dịch C có thể gây trở ngại và khó đọc. Một lập trình viên phát triển có thể giúp các lập trình viên bảo trì, những người cuối cùng sẽ phải đọc mã.

Thêm diễn viên rõ ràng vào giá trị trả về malloc giúp những người sẽ có để đọc mã và xác định ý định của tác giả. Đây là lợi ích thực sự của việc đúc con trỏ rỗng một cách rõ ràng bởi malloc. Thực hành lập trình này không KHÔNG chỉ định sai trình biên dịch hoặc sử dụng một số tính năng biên dịch phức tạp có thể thay đổi.

Ba ví dụ sau làm nổi bật thực hành lập trình này. Trong ví dụ đầu tiên, malloc (được xác định trong <stdlib.h>) được truyền một cách rõ ràng và một số công việc nhỏ nhặt được thực hiện .

#include <stdlib.h> 
    #define nr_chars 4 
    main() 
    { 
    char *data; 

    data = (char *) malloc(nr_chars*sizeof(char)); 

    *data++ = 'a'; 
    *data++ = 'b'; 
    *data++ = 'c'; 
    *data++ = '\0'; // it is allowed to go one past an array 

    data -= nr_chars; // back to the front of data 

    printf("%s\n", data); 
    // prints abc at the console 

    } 

Trong ví dụ thứ hai này, khác biệt duy nhất là <stdlib.h> được nhận xét. Mã số vẫn chạy và tạo ra kết quả tương tự. Bây giờ, "lý do" tại sao công trình này lại khá trực tiếp. Khi C KHÔNG tìm nguyên mẫu cho hàm, nó giả định rằng hàm trả về một số int, nhưng malloc trả về một con trỏ rỗng.Trong trường hợp này diễn viên rõ ràng đã nói với trình biên dịch C, cũng như đơn vị carbon của nguồn, giá trị trả về bởi malloc phải được chuyển đổi thành một con trỏ ký tự.

//#include <stdlib.h> 
    #define nr_chars 4 
    main() 
    { 
    char *data; 

    data = (char *) malloc(nr_chars*sizeof(char)); 

    *data++ = 'a'; 
    *data++ = 'b'; 
    *data++ = 'c'; 
    *data++ = '\0'; // it is allowed to go one past an array 

    data -= nr_chars; // back to the front of data 

    printf("%s\n", data); 
    // prints abc at the console 

    } 

Ví dụ cuối cùng (vd) KHÔNG phát hành và không bao gồm <stdlib.h>. Cả trình soạn thảo Eclipse và trình biên dịch đều phàn nàn về mã này (như chúng cần). Thông điệp biên dịch là

..\main.c(18) : warning C4047: '=' : 'char *' differs in levels of indirection from 'int' 

Và mã nguồn là:

//#include <stdlib.h> 
    #define nr_chars 4 
    main() 
    { 
    char *data; 

    data = malloc(nr_chars*sizeof(char)); 

    *data++ = 'a'; 
    *data++ = 'b'; 
    *data++ = 'c'; 
    *data++ = '\0'; // it is allowed to go one past an array 

    data -= nr_chars; // back to the front of data 

    printf("%s\n", data); 
    // compiler displays a "warning" and prints abc at the console 

    } 

Thay đổi ví dụ 3 để bao gồm kết quả trong không có cảnh báo và chương trình chạy như dự định. Tuy nhiên, cả hai ví dụ 2 và 3 thiếu diễn xuất rõ ràng và trong suốt thời gian mã được viết theo kiểu này, mã này sẽ đắt hơn và có nhiều khả năng bị thay đổi không chính xác bởi con người (do đó chi phí bổ sung). C-trình biên dịch.