2013-09-26 53 views
14

Tôi có 2 câu hỏi ... (tôi đang học C và điều này có thể là câu hỏi ngớ ngẩn. Xin lỗi)Có hợp lệ để in địa chỉ của chuỗi trong C

  • Theo How to declare strings in C và trong hầu hết các sách, họ luôn nói tuyên bố một chuỗi mặc dù bạn đang phân bổ bộ nhớ bằng cách nói

    char p2[] = "String"; 
    

câu hỏi của tôi là, Liệu có cách nào để khai báo một chuỗi?

được đặt trong khu vực đọc chỉ và sau đó sao chép vào mảng. Có hợp lệ trong C để in địa chỉ của chuỗi như thế này không?

printf("%p\n", &"Hello There"); // I tried, it prints some address 

và bằng cách làm này

printf("%p\n", &"Hello There"); 
printf("%p\n", &"Hello There"); 

nó được in cùng một địa chỉ. cảm giác là gì, nó nên in địa chỉ khác nhau. Là trình biên dịch làm một số tối ưu hóa ở đây?

Trả lời

14

tiêu chuẩn C, §6.4.5 Chuỗi chữ, nói:

Không xác định xem các mảng này có khác biệt với điều kiện các phần tử của chúng có giá trị thích hợp hay không.

Vì vậy, hai chuỗi ký tự có cùng nội dung có thể biểu thị cùng một mảng và in địa chỉ của chúng cho cùng một giá trị con trỏ hai lần. Nó tùy thuộc vào trình biên dịch và trình liên kết để quyết định điều này; khi tôi biên dịch chương trình sau đây là hai mô-đun riêng biệt ...

// main.c 
#include <stdio.h> 

extern void print_foo_addr(void); 

int main() 
{ 
    printf("%p\n", &"foo"); 
    print_foo_addr(); 
    return 0; 
} 

// printfoo.c 
#include <stdio.h> 

void print_foo_addr() 
{ 
    printf("%p\n", &"foo"); 
} 

... sau đó tôi nhận được hai giá trị con trỏ khác nhau (GCC 4.7.3 trên Linux), nhưng khi tôi đặt định nghĩa cho print_foo_addr trong main.c, tôi nhận được cùng một giá trị hai lần. Vì vậy, có, đó là một tối ưu hóa được cho phép một cách rõ ràng bởi các tiêu chuẩn, nhưng GCC ít nhất chỉ thực hiện tối ưu hóa này trên cơ sở cho mỗi mô-đun.

+0

Có cách nào khai báo biến chuỗi không? – StackIT

+0

Tôi không nghĩ rằng có thể khai báo một biến chuỗi. Biến chuỗi luôn được xác định. Tôi có đúng không? – StackIT

+1

@Patil: bạn có ý nghĩa gì bởi "biến chuỗi"? Bạn có thể có một mảng char, hoặc một con trỏ đến một char. Những người có thể được tuyên bố. Nếu mảng chứa một ký tự null và tất cả các giá trị trước đó là giá trị trong một số bộ ký tự cụ thể (hoặc nếu cùng giữ cho giá trị được chỉ bởi char *), thì bạn có thể gọi biến là "chuỗi". –

3

Điều này được đặc biệt cho phép theo tiêu chuẩn C.

6.4.5p5-6:

Trong giai đoạn dịch 7, một byte hoặc mã có giá trị không được gắn cho mỗi chuỗi ký tự multibyte mà kết quả từ một chuỗi chữ hoặc literals. Chuỗi ký tự multibyte sau đó được sử dụng để khởi tạo một mảng thời gian lưu trữ tĩnh và độ dài vừa đủ để chứa chuỗi. ...

Không xác định xem các mảng này có khác biệt với điều kiện các phần tử của chúng có các giá trị thích hợp hay không.

+3

câu hỏi này là về C – moooeeeep

+0

Bạn có thể giải thích liên quan đến C không? – StackIT

+0

Rất tiếc, vâng. Đã sửa. – aschepler

0

"Hello There" là chuỗi chữ và nó sẽ có sẵn trong bảng chuỗi (Lý do đằng sau nhận cùng địa chỉ cho "Hello There" trong printf).

Khi bạn làm

nhớ
char p2[] = "String"; 

sẽ được phân bổ và "String" sẽ được sao chép vào bộ nhớ mới được tạo ra. Nhưng

char * p3 = "String"; sẽ trỏ đến phần chỉ đọc. tức là bảng chuỗi.

Trong trường hợp này, nếu bạn in p3&"String" sẽ là cùng.

Nếu bạn in p2&"String", địa chỉ khác sẽ được in. Bởi vì p2 là địa chỉ ngăn xếp.

0

Chuỗi ký tự được đặt trong phần đặc biệt, chỉ nên đọc. Ngoài ra, nếu bạn đang sử dụng cùng một chuỗi chữ ở nhiều nơi, thì trình biên dịch thường có thể tạo chỉ một thể hiện của chuỗi đó. Đây là lý do tại sao bạn thấy cùng một địa chỉ trong ví dụ này:

printf("%p\n", &"Hello There"); 
printf("%p\n", &"Hello There"); 

Tuy nhiên, bạn không thể dựa vào điều này, vì tối ưu hóa trình biên dịch có thể hoặc không thể xảy ra.

+0

BSS thường được sử dụng cho dữ liệu tĩnh được khởi tạo bằng không. Dữ liệu liên tục thường đi trong phần văn bản với mã. – Dipstick

+0

@Dipstick, vâng bạn nói đúng, tôi đã xóa nó. – Devolus

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