2009-04-13 36 views
13

Tôi đã hỏi một câu hỏi tương tự trên cấu trúc here nhưng tôi đang cố gắng tìm ra cách C xử lý những thứ như gán biến và tại sao nó không được phép gán chúng cho eachother nếu chúng có chức năng giống nhau.Khai báo và gán mảng C?

phép nói rằng tôi có hai mảng:

int x[10]; 
int y[10]; 

Tại sao không x = y sẽ biên dịch? Nếu cả hai đều là "chữ ký" giống như vậy, thì bạn không thể gán chúng qua lại được không?

Tôi có thể khai báo chúng theo cách có thể cho phép tôi thực hiện điều đó trong C không? Nó có ý nghĩa với tôi rằng bạn sẽ có thể, nhưng có lẽ có một cách mà điều này có thể được thực hiện? Typedefs cho các cấu trúc dường như là giải pháp, nó sẽ giống nhau cho việc khai báo mảng và gán?

Tôi đánh giá cao sự giúp đỡ của các bạn, tôi mới làm quen với Stackoverflow nhưng đó thực sự là một nguồn lực tốt cho tôi!

Trả lời

23

Nói một cách đơn giản, mảng không thể gán được. Chúng là "giá trị không thể sửa đổi". Điều này tất nhiên đặt ra câu hỏi: tại sao? Vui lòng tham khảo cho câu hỏi này để biết thêm thông tin:

Why does C++ support memberwise assignment of arrays within structs, but not generally?

Mảng không gợi ý.x tại đây không tham chiếu đến một mảng, mặc dù trong nhiều trường hợp, "phân rã" (được chuyển đổi ngầm) thành con trỏ đến phần tử đầu tiên của nó. Tương tự, y cũng là tên của một mảng, không phải là một con trỏ.

Bạn có thể làm phân mảng trong cấu trúc:

struct data { 
    int arr[10]; 
}; 

struct data x = {/* blah */}; 
struct data y; 
y = x; 

Nhưng bạn không thể làm điều đó trực tiếp với mảng. Sử dụng memcpy.

+0

Mã đó vẫn không làm những gì anh ta * muốn * nó làm gì, phải không? Có lẽ tôi sai, nhưng tôi có ấn tượng rằng anh ấy đã hy vọng sao chép nội dung của mảng y vào x. –

+0

Đúng. May mắn thay, nhiều câu trả lời khác đã chỉ ra memcpy() là lựa chọn đúng đắn. Tôi sẽ thêm nó vào ... –

+6

"Tên của một mảng thực sự là địa chỉ của phần tử đầu tiên của mảng đó. \ Mã ví dụ bạn cung cấp ở đây đang cố gán cho một thứ không phải là giá trị l". : vì lợi ích của hậu thế, tôi nghĩ tôi muốn lưu ý rằng cả hai câu này từ câu trả lời được bầu chọn nhiều nhất đều sai. Đầu tiên, tên của một mảng chắc chắn nhất * không phải là * một con trỏ (ví dụ: nghĩ sizeof()), nó chỉ đơn giản phân rã thành một con trỏ trong nhiều trường hợp. Thứ hai, tên mảng * là * một giá trị, không phải là một giá trị có thể sửa đổi được. –

1

Để gán mảng, bạn sẽ phải chỉ định các giá trị bên trong mảng.

tức là. x = y tương đương với

for(int i = 0; i < 10 < ++i) 
{ 
x[i] = y[i]; 
} 
+0

x = y là lỗi trình biên dịch. – Naveen

+0

đó là lý do tại sao tôi cho tương đương! –

+0

nó cho ấn tượng rằng x = y là một câu lệnh hợp lệ – Naveen

0

Khi nói "int x [10]" đang nói ", đặt trước một số cho 10 số nguyên và chuyển con trỏ đến vị trí". Vì vậy, để bản sao có ý nghĩa, bạn cần phải hoạt động trên bộ nhớ được chỉ bởi, thay vì 'tên của vị trí bộ nhớ'.

Vì vậy, để sao chép tại đây, bạn sẽ sử dụng vòng lặp for hoặc memcpy().

2

Một số thông báo ở đây nói rằng tên của một mảng mang lại địa chỉ của phần tử đầu tiên của nó. Nó không phải luôn luôn đúng:

#include <stdio.h> 

int 
main(void) 
{ 
    int array[10]; 

    /* 
    * Print the size of the whole array then the size of a pointer to the 
    * first element. 
    */ 
    printf("%u %u\n", (unsigned int)sizeof array, (unsigned int)sizeof &array[0]); 

    /* 
    * You can take the address of array, which gives you a pointer to the whole 
    * array. The difference between ``pointer to array'' and ``pointer to the 
    * first element of the array'' matters when you're doing pointer arithmetic. 
    */ 
    printf("%p %p\n", (void*)(&array + 1), (void*)(array + 1)); 

    return 0; 
} 

Output:

40 4 
0xbfbf2ca4 0xbfbf2c80 
0

Tôi đã sử dụng các trình biên dịch C nơi đó sẽ biên dịch tốt ... và khi chạy mã sẽ làm cho x điểm đến mảng y xác định.

Bạn thấy, trong C tên của một mảng là một con trỏ trỏ đến phần bắt đầu của mảng. Trong thực tế, mảng và con trỏ về cơ bản có thể hoán đổi cho nhau.Bạn có thể lấy bất kỳ con trỏ nào và lập chỉ mục nó như một mảng.

Quay lại khi C được phát triển vào đầu những năm 70, nó có nghĩa là cho các chương trình tương đối nhỏ hầu như không ở trên ngôn ngữ lắp ráp trong trừu tượng. Trong môi trường đó, thật thuận tiện để có thể dễ dàng chuyển qua lại giữa việc lập chỉ mục mảng và toán con trỏ. Sao chép toàn bộ mảng dữ liệu, mặt khác, là một điều rất tốn kém, và hầu như không được khuyến khích hoặc trừu tượng khỏi người dùng.

Có, trong những lần hiện đại này, nó sẽ có ý nghĩa hơn để có tên của mảng là viết tắt của "toàn bộ mảng", chứ không phải là "một nhà thơ để phía trước của mảng". Tuy nhiên, C không được thiết kế trong những thời hiện đại này. Nếu bạn muốn có một ngôn ngữ, hãy thử Ada. x: = y có chính xác những gì bạn mong đợi; nó sao chép nội dung của một mảng sang nội dung khác.

+0

Ping ngẫu nhiên thân thiện. :) Như bạn chắc chắn (bây giờ) biết, tên của một mảng không phải là một con trỏ. – GManNickG

1

Trong một nỗ lực để bổ sung cho câu trả lời Trống, tôi nghĩ ra chương trình sau đây:

localhost:~ david$ cat test.c 
#include <stdlib.h> 
#include <stdio.h> 
int main (int argc, char * argv []) 
{ 
    struct data { 
    int c [2]; 
    } x, y; 
    x.c[0] = x.c[1] = 0; 
    y.c[0] = y.c[1] = 1; 
    printf("x.c %p %i %i\n", x.c, x.c[0], x.c[1]); 
    printf("y.c %p %i %i\n", y.c, y.c[0], y.c[1]); 
    x = y; 
    printf("x.c %p %i %i\n", x.c, x.c[0], x.c[1]); 
    printf("y.c %p %i %i\n", y.c, y.c[0], y.c[1]); 

    return 0; 
} 

Khi thực hiện, sau đây là kết quả:

x.c 0x7fff5fbff870 0 0 
y.c 0x7fff5fbff860 1 1 
x.c 0x7fff5fbff870 1 1 
y.c 0x7fff5fbff860 1 1 

Vấn đề là để minh họa cách các bản sao của cấu trúc 'giá trị xảy ra.

3
int x [sz]; 
int *y = x; 

Biên dịch này và y sẽ giống như x.

+2

'y' sẽ là một con trỏ tương đương với' & x [0] ', do chuyển đổi mảng thành con trỏ, nhưng nó sẽ không" giống nhau "như' x' là một mảng, không phải là một con trỏ. – GManNickG

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