2009-08-18 38 views
28

Tôi đã cố gắng tìm hiểu cấu trúc thực sự là gì và nhấn một vấn đề, vì vậy tôi có 2 câu hỏi:Mảng Char trong cấu trúc - gán không tương thích?

1) Những gì được lưu trong 'sara'? Nó là một con trỏ đến phần tử đầu tiên của cấu trúc?

2) Câu hỏi thú vị hơn: Tại sao nó không biên dịch? GCC nói "test.c: 10: lỗi: loại không phù hợp trong chuyển nhượng" và tôi không thể tìm ra lý do tại sao ...

#include <stdio.h> 

struct name { 
    char first[20]; 
    char last[20]; 
}; 

int main() { 
    struct name sara; 
    sara.first = "Sara"; 
    sara.last = "Black"; 
    printf("struct direct: %x\n",sara); 

    printf("struct deref: %x\t%s\n", *sara, *sara); 


} 

(phần này đã được giải quyết bằng cách trả lời của bạn đã, tuyệt vời!) Cảm ơn bạn đã giúp đỡ!

+0

Dưới đây là trong thực tế, một dupe đầy đủ: http://stackoverflow.com/questions/1265117/structure-problem-in-c/ – sharptooth

+1

awww. Nhưng tôi đã tìm kiếm, thực sự: D – Patrick

Trả lời

51

này không có gì để làm với cấu trúc - mảng trong C là không thể chuyển nhượng:

char a[20]; 
a = "foo"; // error 

bạn cần phải sử dụng strcpy:

strcpy(a, "foo"); 

hoặc trong mã của bạn:

strcpy(sara.first, "Sara"); 
+4

+1 Đối với 'strcpy' trên' strncpy' ... :) – GManNickG

+0

Tôi đã sử dụng char * đầu tiên; sara.first = "Sara", vì tôi đã sử dụng các mảng kích thước cố định chỉ khi nó thực sự được yêu cầu; Thực hành tốt hay xấu (trong C, không phải C++)? – gramm

+1

@gramm Nếu bạn làm điều đó, bạn đang tự cam kết quản lý bộ nhớ động, điều này có thể không cần thiết hoặc mong muốn. –

4

sử dụng strncpy để đảm bảo bạn không bị tràn bộ đệm.

char name[]= "whatever_you_want"; 
strncpy(sara.first, name, sizeof(sara.first)-1); 
sara.first[sizeof(sara.first)-1] = 0; 
+1

Điều này giả định rằng âm thầm cắt ngắn dữ liệu không làm cho chương trình của bạn thất bại ở một nơi nào đó khác. Nó thường là tốt hơn để xử lý rõ ràng trường hợp chuỗi không phù hợp trong bộ đệm, hơn là gọi hành vi không xác định bằng strcpy hoặc đặt chương trình của bạn ở trạng thái không mong muốn với strncpy. Nhưng tôi khái quát - nếu phần còn lại của chương trình của bạn tính toán cắt ngắn im lặng (ví dụ: không bao giờ mong đợi rằng sara.first sẽ khớp với "whatever_you_want") thì trạng thái chương trình không phải là bất ngờ. –

+1

@onebyone hành vi này phải được ghi lại trong hợp đồng. – TimW

+0

Nếu đó là đủ, thì tại sao không chỉ tài liệu rằng chuỗi đầu vào không được dài hơn cấu trúc có thể đối phó với? Vấn đề là một trong những thiết kế API giúp khách hàng tránh được lỗi. IMO, âm thầm bỏ qua những gì có thể là một lỗi không làm điều này. Nhưng như tôi nói, tôi đang khái quát, và nó có thể không phải là một lỗi. Nếu hàm được gọi là "StoreFirst20CharsOf", thì chúng ta có thể giả định hợp lý rằng bất cứ ai liếc nhìn mã gọi sẽ hiểu nó làm gì. Vì vậy, có một vài sử dụng cho strncpy. –

2

sara là struct chính nó, không phải là một con trỏ (ví dụ: vị trí đại diện cho biến trên stack nơi dữ liệu struct thực tế được lưu trữ). Do đó, *sara là vô nghĩa và không biên dịch.

+0

ah, ok ... Cảm ơn – Patrick

0

Cấu trúc Sara là khối bộ nhớ chứa các biến bên trong. gần không có sự khác biệt giữa một tờ khai cổ điển:

char first[20]; 
int age; 

và một cấu trúc:

struct Person{ 
char first[20]; 
int age; 
}; 

Trong cả hai trường hợp, bạn chỉ bố trí một số bộ nhớ để lưu trữ các biến, và trong cả hai trường hợp sẽ có 20 Đã đặt +4 byte. Trong trường hợp của bạn, Sara chỉ là một khối bộ nhớ của 2x20 byte.

Sự khác biệt duy nhất là với cấu trúc, bộ nhớ được cấp dưới dạng một khối, vì vậy nếu bạn lấy địa chỉ bắt đầu của Sara và nhảy 20 byte, bạn sẽ tìm thấy biến "cuối cùng". Điều này đôi khi có thể hữu ích.

kiểm tra http://publications.gbdirect.co.uk/c_book/chapter6/structures.html để biết thêm :).

+0

Sara là khối bộ nhớ của * ít nhất * 2 * 20 byte.Nó có thể nhiều hơn, nếu có đệm. – caf

+0

Và 'offsetof (struct name, last)' không nhất thiết là 20, hoặc (mặc dù nó gần như chắc chắn là). – caf

+0

Không biết điều đó. Có khả năng đệm khi chỉ định kích thước biến không? Ví dụ: tốc độ char chưa được ký: 7; cờ char chưa ký: 3; v.v ... Tôi đang sử dụng tính năng này tại nơi làm việc và không bao giờ gặp vấn đề với đệm và sắp xếp dữ liệu. – gramm

3

Bạn cũng có thể khởi nó như thế này:

struct name sara = { "Sara", "Black" }; 

Kể từ (như là một trường hợp đặc biệt) bạn được phép khởi mảng char từ hằng chuỗi.

Bây giờ, về cấu trúc thực sự là gì - đó là một loại hợp chất bao gồm các giá trị khác. Những gì sara thực sự trông giống như trong bộ nhớ là một khối 20 giá trị char liên tiếp (có thể được gọi bằng cách sử dụng sara.first, tiếp theo là 0 hoặc nhiều byte đệm, tiếp theo là khối khác 20 giá trị char liên tiếp (có thể được gọi bằng cách sử dụng sara.last) .Tất cả các trường hợp khác của loại struct name đều được trình bày theo cùng một cách.

Trong trường hợp này, nó là rất không chắc rằng có bất kỳ đệm, do đó, một struct name chỉ là một khối 40 ký tự, mà bạn có tên trong 20 đầu tiên và cuối cùng 20.

Bạn có thể tìm hiểu khối bộ nhớ lớn như thế nào struct name sử dụng sizeof(struct name) và bạn có thể tìm ra vị trí nằm trong khối bộ nhớ đó mỗi thành viên của cấu trúc được đặt tại số offsetof(struct name, first)offsetof(struct name, last).

8

Hoặc bạn chỉ có thể sử dụng giao năng động, ví dụ .:

struct name { 
    char *first; 
    char *last; 
}; 

struct name sara; 
sara.first = "Sara"; 
sara.last = "Black"; 
printf("first: %s, last: %s\n", sara.first, sara.last); 
0

Bạn có thể sử dụng strcpy để cư nó. Bạn cũng có thể khởi tạo nó từ một cấu trúc khác.

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

struct name { 
    char first[20]; 
    char last[20]; 
}; 

int main() { 
    struct name sara; 
    struct name other; 

    strcpy(sara.first,"Sara"); 
    strcpy(sara.last, "Black"); 

    other = sara; 

    printf("struct: %s\t%s\n", sara.first, sara.last); 
    printf("other struct: %s\t%s\n", other.first, other.last); 

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