2011-11-29 47 views
7

tôi đã thực hiện một typedef cho mảng float, như thế này:typedef một mảng phao không bị giới hạn trong C

typedef float fooType[]; 

Vì vậy mà tôi có thể tuyên bố và khởi mảng float tĩnh như thế này:

fooType myArray = {1.0, 2.0, 3.0} 

đó làm việc khỏe. Tôi có thể nói myArray[2] không có vấn đề gì và thường sử dụng số fooType như tôi muốn. Trong bối cảnh của chương trình của tôi nó rất rõ ràng rằng fooType là một loại mảng (nó thực sự là một bảng tra cứu khổng lồ) đó là lý do tại sao tôi không chỉ đơn giản là làm typedef float fooType.

Làm cách nào để khai báo và sử dụng biến để trỏ đến bar và truy cập các yếu tố của bar? Tôi không thể khai báo một biến đơn giản như thế này:

fooType bar = myArray; 

Vì lỗi đó với invalid initializer; Tôi không mong đợi nó làm việc vì trình biên dịch không biết có bao nhiêu bộ nhớ để cấp phát. Tôi đã thử một vài điều với con trỏ:

fooType *bar = myArray; 

này đưa ra một cảnh báo: initialization from incompatible pointer type và các lỗi khi tôi truy cập vào các yếu tố với bar[1] .. này tuyên bố tốt, như tôi mong đợi nó đến từ các loại phù hợp với bây giờ:

fooType *bar = &myArray; 

Nhưng như trên các lỗi trình biên dịch với số invalid use of array with unspecified bounds khi tôi nói bar[1].

này hoạt động:

float *bar = myArray; 
float val = bar[3]; 

Nhưng tôi không muốn vì tôi đã làm mất khả năng đọc typedef tôi.

Tôi đã được chôn trong một thời gian dài trong một thế giới OO âu yếm (Java), vì vậy tôi hy vọng sẽ hiểu được điều này thành ngữ trong C trong tình huống này. Tôi khá chuẩn bị để thay đổi việc sử dụng typedef cho phù hợp với quy ước nếu không có giải pháp trực tiếp. Tôi có một cảm giác mặc dù, và nó không phức tạp.

Cảm ơn

+0

Điểm mấu chốt là bạn ** không ** muốn tạo typedef cho mảng ... Bạn có thể, nhưng sau đó bạn phải đối mặt với tất cả những "khó khăn" đó. Ví dụ điều này 'fooType myArray = {1.0, 2.0, 3.0}; fooType bar = myArray; 'có nghĩa là' float myArray [] = {1.0, 2.0, 3.0}; float bar [] = myArray; 'Có thể đọc được không? :) Một "câu đố" khác là khi bạn xác định nguyên mẫu hàm nhận 'fooType' làm đối số _output_. (Tương tự như 'memset', v.v.) – debleek63

+0

Điều đó giờ đã rõ ràng @ debleek63. Cảm ơn. –

Trả lời

5

Vấn đề bạn gặp phải ở đây là sự kiện mảng không phải là con trỏ trong C, mà là phân rã thành con trỏ đến phần tử đầu tiên khi được sử dụng ở phía bên tay phải của toán tử gán.Vì vậy, nếu bạn khai báo một mảng như

fooType myArray = {1.0, 2.0, 3.0} 

loại myArrayfloat[3], và & myArray là (*float)[3], hoặc "con trỏ đến một mảng của 3 nổi". Do đó, bạn không thể chỉ đơn giản là nói

fooType *bar = myArray; 

Loại fooType* không phải là con trỏ đến phao ... do đó đó là loại con trỏ không tương thích. Làm

fooType* bar = &myArray; 

làm việc, nhưng vấn đề bạn đang gặp phải là bar[1] không phải là một phần tử trong mảng myArray, vì bar chính nó là một con trỏ. Bạn sẽ phải dereference bar như (*bar)[1] để truy cập một phần tử trong myArray. Ví dụ:

typedef float fooType[]; 
fooType myArray = {1.0, 2.0, 3.0} 
fooType* bar = &myArray; 
(*bar)[1] = 5.0; 

Cuối cùng, hãy nhớ rằng với C, bạn không thể gán một mảng vào mảng khác ... vì vậy bạn can'd làm điều gì đó như:

fooType bar = myArray; 

này đi trở lại toàn bộ vấn đề mảng và sự phân rã của chúng thành con trỏ tới phần tử đầu tiên, và thực tế là kiểu của mảng đó không giống như kiểu của phần tử đầu tiên trong mảng.

Bạn có thể cuối cùng chỉ muốn nhập mảng, sau đó nhập các loại phần tử mảng kể từ khi sử dụng float để bất kỳ ai sử dụng mã của bạn sẽ biết loại phần tử nào thuộc về phần tử kia.

+0

Cảm ơn Jason. Đó là một chút rõ ràng hơn bây giờ. Tôi không thể sử dụng typedef sau đó, có vẻ như, vì kiểu của nó là ... 'float []'? Tôi có nên sử dụng 'float * bar = myArray' thay thế không? Không phải là dễ đọc nhưng nó hoạt động. –

+0

Tôi biết kích thước của mảng tại thời gian biên dịch nên tùy chọn thứ hai của bạn sẽ hoạt động, nhưng cả hai đề xuất của bạn đã giúp ích rất nhiều. Cảm ơn bạn. –

+0

BTW, tôi đã thay đổi câu trả lời của mình một chút ... có vẻ như đã xảy ra lỗi cú pháp chặn bạn từ một trong các giải pháp của bạn. – Jason

1

Bạn có hỗn hợp C với Java.

Cố gắng thay đổi typedef của bạn để

typedef float *fooType; 

Sau đó, tuy nhiên bạn sẽ không thể khởi tạo một biến kiểu fooType như

fooType myArray = {1.0, 2.0, 3.0}; 

fooType là một con trỏ bây giờ.

+0

Ẩn một loại con trỏ phía sau một 'typedef' thường được coi là thực hành xấu ... –

+0

@OliCharlesworth oops. cảm ơn. Tôi chỉ muốn mã của OP hoạt động. – Beginner

+0

Cảm ơn Roman, Oli. Nó làm việc như tôi đã viết nó mặc dù: Tôi có thể khởi tạo mảng của tôi và sử dụng chúng trực tiếp. Tôi cần để có thể khởi tạo trong tuyên bố như trong câu hỏi. Điều duy nhất tôi không thể làm là sau đó khai báo các biến khác trỏ đến chúng. –

0

Sử dụng Visual Studio 2013 Tôi thấy rằng bạn có thể sử dụng các cấu trúc như trong ví dụ này. Điều này cũng dường như làm việc với Visual Studio 2015.

Chú ý rằng việc sử dụng malloc() để tạo ra một loạt các fooType đòi hỏi một con trỏ dereferenced loại pfooType chứ không phải là loại fooType hoặc *pfooType để biên dịch. Tôi đã thay đổi typedef từ float thành doublesizeof(*p2) đã thay đổi từ 4 đến 8 byte như mong đợi.

#include <malloc.h> 

typedef float fooType[], *pfooType; 

int xxmain2(void) 
{ 
    fooType myArray = { 1.0, 2.0, 3.0 }; // define the array with its elements 
    pfooType p = myArray; // get a pointer to the array. 
    int i; 
    int nElements = sizeof(myArray)/sizeof(*p); // determine number of elements in the array. 

    pfooType p2 = malloc(sizeof(*p2) * 5); // malloc() an array of 5 elements. 

    for (i = 0; i < 5; i++) p2[i] = (float)i * 10.0; // initialize my malloced array. 
    myArray[0] = *p;  // dereference pointer 
    myArray[1] = p[1];  // use array subscripting with pointer 

    for (i = 0, p = myArray; i < nElements; i++) *p++ = 0; // increment the pointer to traverse the array. 

    free(p2); 
    return 0; 
} 

Tôi cũng thấy rằng tôi không thể tạo ra một kích thước nhất định một mảng với một cái gì đó giống như fooType myRay2[10]; (lỗi lập "lỗi C2087: 'myRay2': thiếu subscript") hoặc một cái gì đó tương tự. Và fooType myRay2; đưa ra lỗi biên dịch là "lỗi C2133: 'myRay2': kích thước không xác định".

Vì vậy, cách duy nhất có vẻ là sử dụng khởi tạo để định kích thước mảng hoặc sử dụng malloc() để tạo một mảng có kích thước cụ thể sau đó yêu cầu free().

Các vấn đề liên quan