2012-09-22 31 views
11

Với một mảng của con trỏ đến xâu:Xác định chiều dài của một String Literal

char *textMessages[] = { 
    "Small text message", 
    "Slightly larger text message", 
    "A really large text message that " 
    "is spread over multiple lines" 
} 

Làm sao người ta xác định độ dài của một chuỗi đặc biệt theo nghĩa đen - nói rằng một phần ba? Tôi đã thử sử dụng lệnh sizeof như sau:

int size = sizeof(textMessages[2]); 

Nhưng kết quả có vẻ là số con trỏ trong mảng, chứ không phải là độ dài của chuỗi ký tự.

+3

'sizeof (textMessages [2])' sẽ tạo ra kích thước của kiểu 'char *'. Hoàn toàn trùng hợp là 'sizeof (char *)' xảy ra là 4 trên hệ thống của bạn, và không liên quan gì đến số phần tử trong mảng của bạn. –

+0

Bạn nên cân nhắc sử dụng định nghĩa 'static const char textMesssages [] [4]' cho mảng của bạn. –

+1

@MichaelFoukarakis Chỉ có * ba * con trỏ trong mảng (lưu ý chuỗi nối). – Jens

Trả lời

17

Nếu bạn muốn số tính tại thời gian biên dịch (như trái ngược với khi chạy với strlen) nó là hoàn toàn không quan trọng để sử dụng một biểu thức như

sizeof "A really large text message that " 
     "is spread over multiple lines"; 

Bạn có thể muốn sử dụng macro để tránh lặp lại chữ dài, mặc dù:

#define LONGLITERAL "A really large text message that " \ 
        "is spread over multiple lines" 

Lưu ý rằng giá trị được trả về bởi sizeof bao gồm kết thúc NUL, do đó, nhiều hơn strlen.

+0

Tôi muốn xác định chiều dài của mỗi chuỗi để tôi có thể lập chỉ mục độ dài và chuyển chúng đến một hàm. Có thể tính toán một loạt các độ dài như vậy tại thời gian biên dịch không? – Zack

+1

Cách tiếp cận của tôi là khai báo và khởi tạo một mảng 'struct {char * ptr; size_t len; } x [] '. Sau đó, bạn có thể gọi 'foo (x [i] .ptr, x [i] .len)'. Kể từ khi C không giữ độ dài chuỗi xung quanh, không có cách nào khác hơn là để theo dõi độ dài chuỗi trong mã của bạn. – Jens

0

strlen có thể?

size_t size = strlen(textMessages[2]); 
+3

Tại sao tính toán con số này trong thời gian chạy khi nó có thể được xác định tại thời gian biên dịch? – Jens

+0

@Jens: Không trừ khi bạn cũng biết chuỗi tại thời gian biên dịch. – Tudor

+0

@Tudor, vâng - bạn _do_ biết thời lượng tại thời gian biên dịch (câu hỏi nói "Chuỗi chữ") – ideasman42

0

Bạn nên sử dụng phương thức thư viện strlen() để nhận độ dài của chuỗi. sizeof sẽ cho bạn kích thước là textMessages[2], một con trỏ, phụ thuộc vào máy (4 byte hoặc 8 byte).

+0

Bạn có nghĩa là 4 hoặc 8 byte không? Trừ khi bạn có một máy 16-bit ... – Tudor

+0

phải, nhờ chỉnh sửa :) – Vikdor

0

strlen mang đến cho bạn chiều dài của chuỗi trong khi sizeof sẽ trở lại kích thước của Type liệu trong Bytes bạn đã nhập như tham số.

strlen

sizeof

-1

Tôi sẽ cho bạn biết điều gì đó, theo mảng Kiến thức của tôi, con trỏ là giống nhau ngoại trừ khi bạn sử dụng sizeof.

Khi bạn sử dụng sizeof trên một con trỏ nó sẽ trở lại luôn 4 BYTE bất kể những điều mà con trỏ trỏ đến, nhưng nếu nó được sử dụng trên mảng nó sẽ trở lại bao lâu mảng là lớn trong byte?.

Trong ví dụ ở đây bạn *textMessage[] là mảng các con trỏ vì vậy khi bạn sử dụng sizeof(textMessage[2]) nó sẽ trở lại 4 BYTEtextMessage[2] là một con trỏ.

Tôi hy vọng nó sẽ hữu ích cho bạn.

+0

Tôi không hiểu những gì bạn muốn –

+0

Mục đích của tôi là cho bạn biết để cải thiện kiến ​​thức của bạn về ** sự khác biệt ** của mảng và con trỏ bằng cách đọc tất cả http://c-faq.com/aryptr/index.html Mảng không phải là con trỏ và chúng thường là 2 hoặc 8 thay vì 4 byte và kích thước của chúng thậm chí có thể phụ thuộc vào loại chúng trỏ đến. Vì vậy, hầu hết những gì bạn viết là không chính xác về mặt kỹ thuật. – Jens

+0

Được rồi, cảm ơn @jens –

0

Bạn có thể khai thác thực tế, rằng giá trị trong một mảng là liên tiếp:

const char *messages[] = { 
    "footer", 
    "barter", 
    "banger" 
}; 

size_t sizeOfMessage1 = (messages[1] - messages[0])/sizeof(char); // 7 (6 chars + '\0') 

Kích thước được xác định bằng cách sử dụng các ranh giới của các yếu tố.Khoảng cách giữa đầu và phần đầu của phần tử thứ hai là kích thước của phần tử đầu tiên.

Điều này bao gồm việc chấm dứt \0. Các giải pháp, tất nhiên, chỉ hoạt động đúng với các chuỗi liên tục. Nếu các chuỗi sẽ là con trỏ, bạn sẽ nhận được kích thước của một con trỏ thay vì độ dài của chuỗi.

Điều này không đảm bảo hoạt động. Nếu các trường được căn chỉnh, điều này có thể mang lại kích thước sai và có thể có các cảnh báo khác do trình biên dịch giới thiệu, như sáp nhập các chuỗi giống hệt nhau. Ngoài ra, bạn sẽ cần ít nhất hai phần tử trong mảng của mình.

+3

Điều này không đảm bảo hoạt động. Trong khi các con trỏ trong mảng phải liên tiếp, thì các chuỗi ký tự không cần. Hãy suy nghĩ của sự liên kết và như vậy. Hoặc sử dụng cùng một con trỏ cho các chuỗi ký tự giống hệt nhau. – Jens

+0

Bạn nói đúng, căn chỉnh sẽ phá vỡ điều này (nhưng có thể điều khiển được). Các kích cỡ khác nhau cho 'char' cũng sẽ phá vỡ điều này. Tôi sẽ đánh dấu câu trả lời của tôi là không đáng tin cậy. – nemo

+1

Sáp nhập các chuỗi giống hệt nhau, một tối ưu hóa phổ biến, cũng phá vỡ nó. – Jens

11

Đề xuất của tôi sẽ là sử dụng strlen và bật tối ưu hóa trình biên dịch.

Ví dụ, với gcc 4.7 trên x86:

#include <string.h> 
static const char *textMessages[3] = { 
    "Small text message", 
    "Slightly larger text message", 
    "A really large text message that " 
    "is spread over multiple lines" 
}; 

size_t longmessagelen(void) 
{ 
    return strlen(textMessages[2]); 
} 

Sau khi chạy make CFLAGS="-ggdb -O3" example.o:

$ gdb example.o 
(gdb) disassemble longmessagelen 
    0x00000000 <+0>: mov $0x3e,%eax 
    0x00000005 <+5>: ret 

Tức là trình biên dịch đã thay thế cuộc gọi thành strlen với giá trị không đổi 0x3e = 62.

Đừng lãng phí thời gian thực hiện tối ưu hóa trình biên dịch có thể làm cho bạn!

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