2015-04-23 18 views
25

Hàm chuẩn strstr được sử dụng để tìm vị trí của chuỗi con trong chuỗi. Cả hai đối số của hàm là loại const char *, nhưng kiểu trả về là char *.Cách quay trở lại strstr không phải là hằng số

Tôi muốn biết cách chức năng chuẩn được triển khai vi phạm chính xác const.

+5

Bạn đang bao gồm cstring, chứ không phải string.h? Nếu không, bạn đang sử dụng phiên bản C - thần biết họ làm gì. Các phiên bản C++ 'std :: strstr' chỉ trả về' char * 'nếu tham số đầu tiên cũng không phải là 'const'' char * '. Xem [tại đây] (http://en.cppreference.com/w/cpp/string/byte/strstr). (Xin lỗi - chỉ cần chú ý đến thẻ C ... bạn đang sử dụng ngôn ngữ nào?) –

+3

@TonyD Phiên bản C là 'char * strstr (const char *, const char *); ' –

+3

Lưu ý rằng trong C++, có [hai overloads của strstr] (http://www.cplusplus.com/reference/cstring/strstr/) với tham số const char * và một với char bình thường *, và các giá trị trả về theo. –

Trả lời

13

C cho phép trỏ đến bộ nhớ với const hay không const con trỏ, không phân biệt nếu đối tượng đã được xác định với các vòng loại const hay không.

6,5 Expressions

  1. Một đối tượng có trách nhiệm đã có giá trị được lưu trữ của nó truy cập chỉ bằng một biểu thức vế trái có một trong các loại sau đây:

- phiên bản đủ điều kiện của loại tương thích với loại đối tượng hiệu quả,

Nguyên mẫu của strstr trong C là:

char *strstr(const char *s1, const char *s2); 

Con trỏ trả về, nếu hợp lệ, trỏ tới chuỗi s1. Điều này có thể đạt được với dàn diễn viên:

const char safe = 's' ; 
char* careful = (char*)&safe ; 

Sự cố đang sửa đổi bộ nhớ đó.

6.7.3 Loại vòng loại

  1. Nếu một nỗ lực được thực hiện để sửa đổi một đối tượng được xác định với một kiểu const trình độ thông qua sử dụng của một giá trị trái với không const loại đủ tiêu chuẩn, hành vi không xác định.

Kể từ khi bạn đã tạo chuỗi, bạn nên biết liệu bạn có thể sửa đổi nó hay không, do đó bạn có thể chấp nhận giá trị trả về với một con trỏ đến const, để tránh bất kỳ vấn đề:

const char* find = strstr(...) ; 
28

Tất cả các const char * cho bạn biết là strstr sẽ không sửa đổi chuỗi mà bạn chuyển vào đó.

Cho dù bạn sửa đổi chuỗi trả lại hay không là tùy thuộc vào bạn vì nó là chuỗi của bạn!

Trong C++, điều này đã bị thay đổi do quá tải phương thức và có hai phiên bản, phiên bản nhập const có đầu ra const.

Trong C, nó không có mức độ an toàn cao được tích hợp sẵn cho bạn và giả sử bạn biết mình có nên sửa đổi chuỗi trả về hay không.

+3

Những gì C không có thực sự là quá tải chức năng. Nếu hàm được giới thiệu lần đầu tiên trong C++, hàm này có thể có hai hương vị, const và non-const. Nhưng chức năng này lần đầu tiên được giới thiệu trong C. Hơn nữa, nó đã được giới thiệu trong thời gian K & R, khi không có từ khóa 'const'. – ach

13

Theo ISO C++ 21,8 (7) strstr trả về một const char* hoặc một char* tùy thuộc vào nếu nó được một const char* hoặc một char*.

const char* strstr(const char* s1, const char* s2); 

char* strstr(char* s1, const char* s2); 
+3

Đó là sự thật cho C++, nhưng trong tiêu chuẩn C99 'strstr' trả về' char * '. – Paul

+2

Tôi thấy thẻ C++ đầu tiên vì vậy tôi đã sử dụng tiêu chuẩn C++. Bạn đúng về tiêu chuẩn C. – NathanOliver

1

Giá trị trả về không phải là biến mà bạn đã chuyển cho hàm làm tham số. Hàm này trả về một con trỏ tới lần xuất hiện đầu tiên trong haystack của bất kỳ chuỗi ký tự nào được chỉ định trong kim, hoặc một con trỏ rỗng nếu chuỗi không có trong haystack.

+1

Nó vẫn liên quan đến nó (là một phần của cùng một khai báo mảng hoặc cấp phát bộ nhớ), và do đó chắc chắn có cùng "const-ness" giống như haystack, nếu hàm được sử dụng đúng. – Random832

5

Nó được thực hiện bằng cách chỉ định chữ ký và để việc triển khai lên đến trình tạo trình biên dịch.

Lưu ý rằng trả lại một char* trỏ đến một chuỗi const char[] chỉ nguy hiểm, nhưng chưa vi phạm bất kỳ quy tắc nào. Tuy nhiên, mọi nỗ lực ghi vào bộ nhớ đó vẫn là Hành vi không xác định.

2

C++ provides two versions một đối số const và đối số không có const.

const char* strstr(const char* str, const char* target);  
char* strstr(  char* str, const char* target); 

Vì trong C chúng ta không thể quá tải, chúng tôi là trái với hai sự lựa chọn khó chịu:

  • Hoặc chúng ta lấy lý lẽ như không const nhưng nếu nguồn của chúng tôi là thực sự const thì chúng ta cần phải thực hiện một diễn viên khó chịu để không const.
  • Tùy chọn thứ hai là tùy chọn mà chúng tôi có là chúng tôi lấy các đối số dưới dạng const nhưng chúng tôi trả về giá trị không phải là const. Chúng ta có thể trả về một const char * nhưng sau đó chúng ta không bao giờ có thể sửa đổi kết quả.
4

Chức năng strstr có từ ngày trở về trước khi có con trỏ const. Trong trường hợp nó sẽ là hợp pháp cho mã để ghi vào bộ nhớ được xác định bởi con trỏ đầu tiên được chuyển đến strstr, nó sẽ là hợp pháp cho mã để ghi vào bộ nhớ được xác định bởi con trỏ trả về, và trong trường hợp giá trị trả về sẽ chỉ được sử dụng trong những cách hợp pháp với con trỏ đến bộ nhớ chỉ đọc (ví dụ: chuỗi ký tự), một cách hợp pháp có thể truyền con trỏ như vậy đến strstr. Nếu một chức năng tương tự như strstr đã được xác định ngày hôm nay, nó có thể được thực hiện bằng hai phương pháp - một trong số đó có thể chấp nhận bất kỳ con trỏ nào và trả về con trỏ mà người nhận không thể viết được. chấp nhận các con trỏ có thể ghi được nhưng sẽ trả về một con trỏ mà người nhận có thể sử dụng khi nó thấy phù hợp. Bởi vì một số mã sử dụng strstr sẽ cần phải chuyển con trỏ chỉ đọc, và vì một số mã được sử dụng strstr cần thiết để có thể ghi vào con trỏ mà nó sẽ mang lại khi có con trỏ có thể ghi, cần phải có một bộ trình độ con trỏ hoạt động theo cả hai cách. Hậu quả là một tập hợp các trình độ con trỏ không thực sự "an toàn" [vì nó có thể trả về một con trỏ có thể ghi vào vùng chỉ đọc của bộ nhớ] và nó sẽ cho phép biên dịch mã trong một số trường hợp nó thực sự "không nên", nhưng sẽ cho phép mã được viết trước ngày const con trỏ để tiếp tục hoạt động như dự định.

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