2012-10-01 36 views
24

tôi đang học làm thế nào để tạo ra các mảng 1D động trong C. Đoạn code dưới đây cố gắng làm điều này:Mảng động trong C - Sự hiểu biết của tôi về malloc/realloc có đúng không?

  1. Tạo một mảng động có độ dài 10, giữ đôi, sử dụng malloc.
  2. Đặt từng mục nhập của mảng thành j/100 cho j = 0,1, ..., 9. Sau đó in .
  3. Thêm mục nhập bổ sung vào cuối mảng bằng cách sử dụng realloc.
  4. Đặt mục nhập mới là j/100 và in lại từng mục nhập một lần nữa.

thử nghiệm

double* data = (double*)malloc(10*sizeof(double)); 

for (j=0;j<10;j++) 
{ 
     data[j]= ((double)j)/100; 
     printf("%g, ",data[j]); 
} 

printf("\n"); 

data = (double*)realloc(data,11*sizeof(double)); 

for (j=0;j<11;j++) 
{ 
    if (j == 10){ data[j]= ((double)j)/100; } 
    printf("%g, ",data[j]); 
} 

free((void*) data); 

Câu hỏi

1) Tôi có mã hóa này phải không?

2) Hướng dẫn tôi tìm thấy sử dụng malloc mà không đặt (double*) ở phía trước. Ví dụ.

int *pointer; 

pointer = malloc(2*sizeof(int)); 

Điều này không biên dịch cho tôi trên Visual Studio 2010, Windows 7. Lỗi "giá trị của loại void không thể gán cho thực thể loại int".

Tại sao nó hoạt động cho những hướng dẫn đó chứ không phải cho tôi? Tôi có đúng để đoán rằng đó là bởi vì các trình biên dịch mà họ đang sử dụng tự động điền vào các (int*) cho họ trong ví dụ của tôi?

+0

"giá trị của loại void không thể được gán cho thực thể của loại int" không phải là lỗi mà trình biên dịch * C * sẽ tạo ra. Vấn đề là bạn đang sử dụng trình biên dịch * C++ *. Đảm bảo rằng tệp nguồn của bạn có tên là ' .c'. –

Trả lời

31

Bạn thân thiết.

Trong C (ít nhất kể từ phiên bản 1989 của tiêu chuẩn), các diễn viên trước khi mallocrealloc là không cần thiết, vì C có thể chuyển đổi các giá trị của loại void *-int * mà không có một dàn diễn viên. Đây là không phải là đúng cho C++, do đó dựa trên lỗi bạn đang nhận được, có vẻ như bạn đang biên dịch mã này là C++ chứ không phải C. Kiểm tra tài liệu cho VS2010 để xác định cách biên dịch mã là C.

sau đây là phong cách ưa thích của tôi để viết một cuộc gọi malloc:

double *data = malloc(10 * sizeof *data); 

Kể từ loại của biểu thức *datadouble, sizeof *data tương đương với sizeof (double). Điều này cũng có nghĩa là bạn không phải điều chỉnh các cuộc gọi malloc nếu loại thay đổi data.

Đối với cuộc gọi realloc, sẽ an toàn hơn khi chỉ định kết quả cho giá trị con trỏ tạm thời. realloc sẽ trả về NULL nếu nó không thể mở rộng bộ đệm, do đó, nó an toàn hơn để viết

double *tmp; 
... 
tmp = realloc(data, 11 * sizeof *data); 
if (!tmp) 
{ 
    // could not resize data; handle as appropriate 
} 
else 
{ 
    data = tmp; 
    // process extended buffer 
} 

Hãy nhận biết rằng Microsoft hỗ trợ cho C kết thúc với phiên bản năm 1989 của ngôn ngữ; đã có hai phiên bản của tiêu chuẩn ngôn ngữ kể từ đó, đã giới thiệu một số tính năng mới và các tính năng cũ không được chấp nhận. Vì vậy, trong khi một số trình biên dịch C hỗ trợ các tính năng C99 như khai báo hỗn hợp và mã, mảng biến độ dài, vv, VS2010 sẽ không.

+0

Cảm ơn, điều đó rất hữu ích. – Legendre

+0

Cập nhật: VS2015 hỗ trợ C99 + một phần C11 và tùy chọn cho các mục tiêu WinXP. Vì vậy, Microsoft tiếp tục hỗ trợ ISO C vào năm 2015. –

4

Trong C, bạn không nên truyền giá trị trả lại là malloc().

Ngoài ra, bạn nên mã hóa loại trong đối số malloc(). Đây là một cách tốt hơn:

double* data = malloc(10 * sizeof *data); 
+1

Bản dịch này. Nhưng Visual Studio 2010 cảnh báo rằng "giá trị của loại void không thể được sử dụng để khởi tạo một thực thể kiểu double". Có ok để chỉ bỏ qua cảnh báo? – Legendre

10

1) Tôi có mã hóa này phải không?

Chủ yếu là. Nhưng data = (double*)realloc(data,11*sizeof(double)); mất tham chiếu đến bộ nhớ được cấp nếu realloc không thành công, bạn nên sử dụng con trỏ tạm thời để giữ giá trị trả lại là realloc và kiểm tra xem đó là NULL (và bạn cũng phải kiểm tra giá trị trả lại là malloc).

2) Hướng dẫn tôi tìm thấy sử dụng malloc mà không đặt (double *) ở phía trước.

Trong C, malloc trả về một void* rằng ngầm có thể được chuyển đổi sang bất kỳ loại con trỏ khác, vì vậy không có dàn diễn viên là cần thiết (và rộng rãi nản vì đúc có thể che giấu lỗi). Visual Studio rõ ràng biên dịch mã như C++, nơi diễn viên được yêu cầu.

+0

+1 cảm ơn sự giúp đỡ. – Legendre

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