Sự khác biệt giữa char s [] và char s là gì?


Bản nháp C99 N1256

Có hai cách sử dụng khác nhau của chuỗi ký tự:

Bạn đang xem: Char là gì *

  1. Khởi tạo ký tự[]:

    char c[] = “Abc”;

    Đây là “kỳ diệu hơn” và được mô tả tại 6.7.8 / 14 “Khởi tạo”:

    Một mảng kiểu ký tự có thể được khởi tạo bằng một chuỗi ký tự, tùy chọn được đặt trong dấu ngoặc nhọn. Các ký tự liên tiếp của chuỗi chữ theo nghĩa đen (bao gồm cả ký tự null kết thúc nếu còn chỗ hoặc nếu mảng có kích thước không xác định) khởi tạo các phần tử của mảng.

    Vì vậy, đây chỉ là một phím tắt cho:

    char c[] = {‘a’, ‘b’, ‘c’, ”};

    Giống như bất kỳ mảng thông thường nào khác, c có thể được sửa đổi.

  2. Ở mọi nơi khác: nó tạo ra:

    • không tên
    • mảng char Kiểu trong chuỗi C và C ++ là gì?
    • với bộ nhớ tĩnh
    • cung cấp cho UB nếu được sửa đổi

    Vì vậy, khi bạn viết:

    char * c = “abc”;

    Điều này tương tự như:

    / * __unname là ma thuật bởi vì sửa đổi nó mang lại UB. * / static char __unname[] = “Abc”; char * c = __unname;

    Xem thêm: Có nên nghỉ việc để làm freelancer thiết kế? – Xem xét một cách kĩ lưỡng

    Lưu ý diễn viên ngầm từ char[]thành char *, luôn luôn hợp pháp.

    Sau đó, nếu bạn sửa đổi c[0]bạn cũng sửa đổi __unname, đó là UB.

    Điều này được ghi lại trong 6.4.5 “Chuỗi”:

    5 Trong giai đoạn dịch 7, một byte hoặc mã có giá trị 0 được thêm vào mỗi chuỗi ký tự nhiều dòng kết quả từ một chuỗi ký tự hoặc chuỗi ký tự theo nghĩa đen. Sau đó, chuỗi ký tự multibyte được sử dụng để khởi tạo một mảng thời lượng và độ dài lưu trữ tĩnh vừa đủ để giữ chuỗi. Đối với các ký tự chuỗi, các phần tử mảng có kiểu char và được khởi tạo bằng các byte riêng lẻ của chuỗi ký tự nhiều dòng […]

    6 Không biết liệu các mảng này có khác biệt hay không miễn là các phần tử của chúng có các giá trị phù hợp. Nếu chương trình cố gắng sửa đổi một mảng như vậy, hành vi đó là không xác định.

6.7.8 / 32 “Khởi tạo” đưa ra một ví dụ trực tiếp:

VÍ DỤ 8: Tuyên bố

định nghĩa các đối tượng mảng char “đơn giản” s và t có các phần tử được khởi tạo bằng chuỗi ký tự.

Tuyên bố này giống với

Nội dung của các mảng có thể sửa đổi được. Mặt khác, tuyên bố

Xem thêm: Attack on Titan: Sức mạnh của tộc Ackerman và khả năng nào cho Levi có thể biến hình thành Titan

định nghĩa p với kiểu “con trỏ tới char” và khởi tạo nó để trỏ đến một đối tượng kiểu “mảng char” có độ dài 4 có các phần tử được khởi tạo bằng một chuỗi ký tự. Nếu cố gắng sử dụng p để sửa đổi nội dung của mảng, hành vi đó là không xác định.

ELF GCC 4,8 x86-64. Triển khai

Chương trình:

#bao gồm int main (void) {char * s = “abc”; printf (“% sn”, s); trả về 0; }

Biên dịch và dịch ngược:

gcc -ggdb -std = c99 -c main.c objdump -Sr main.o

Đầu ra chứa:

char * s = “abc”; 8: 48 c7 45 f8 00 00 00 movq $ 0x0, -0x8 (% rbp) f: 00 c: R_X86_64_32S .rodata

Kết luận: GCC lưu trữ char * nó trong phần .rodata, không phải trong .text.

Nếu chúng ta làm tương tự cho char[]:

char s[] = “Abc”;

Chúng tôi đạt được:

17: c7 45 f0 61 62 63 00 movl $ 0x636261, -0x10 (% rbp)

vì vậy nó được lưu trữ trong ngăn xếp (liên quan đến% rbp).

Tuy nhiên, lưu ý rằng tập lệnh ràng buộc mặc định đặt .rodata và .text trong cùng một phân đoạn, phân đoạn này thực thi nhưng không có quyền ghi. Điều này có thể được quan sát với:

readelf -l a.out

bao gồm:

Xem thêm: PC là viết tắt của gì? PC có thực sự là một máy tính để bàn?

Ánh xạ phần tới phân đoạn: Các phần của phân đoạn… 02 .text .rodata

Làm thế nào bạn tìm thấy bài báo?

Source: mangtannha.com
Category: wiki

0 0 votes
Đánh giá bài viết
Subscribe
Notify of
guest
0 Góp ý
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x