2012-03-30 34 views
37
#include "stdio.h" 
#include "string.h" 

main() 
{ 

    char string[] = "october"; // october is 7 letters 

    strcpy(string, "september"); // september is 9 letters 

    printf("the size of %s is %d and the length is %d\n\n", string, sizeof(string), strlen(string)); 

    return 0; 
} 

Output:sizeof vs strlen

kích thước của tháng chín là 8 và chiều dài là 9

Có điều gì sai với cú pháp của tôi hoặc những gì?

+10

Bạn đang viết quá ký tự kết thúc mảng 'chuỗi'. Đây là hành vi không xác định. 'chuỗi' chỉ có thể chứa 8 ký tự (7 cho" tháng mười "và 1 ký tự cho dấu kết thúc null). Khi bạn gọi 'strcpy', bạn đang viết 10 ký tự cho nó (9 cho" tháng chín "và 1 cho null terminator), có nghĩa là bạn đã đi qua cuối mảng và đang ghi đè lên bộ nhớ liền kề. – Marlon

+11

Lưu ý rằng 'sizeof' được tính tại thời gian * biên dịch * khi' strlen' là thời gian chạy. – Naveen

+5

@Naveen: Lưu ý rằng điều đó không nhất thiết đúng khi VLA có liên quan. – caf

Trả lời

1

Mảng đích của bạn là 8 byte (độ dài của "tháng mười" cộng với \ 0) và bạn muốn đặt trong 9 ký tự trong mảng đó.

man strcpy nói: Nếu chuỗi đích của strcpy() không đủ lớn thì mọi thứ có thể xảy ra.

Hãy cho tôi biết những gì bạn thực sự muốn làm, bởi vì đây mùi hôi chặng đường dài

+0

Đây là chương trình thử nghiệm để hiểu cách làm việc của sizeof() – beparas

33

sizeofstrlen() làm những việc khác nhau. Trong trường hợp này, lời tuyên bố của bạn

char string[] = "october"; 

cũng giống như

char string[8] = "october"; 

quá trình biên dịch có thể nói rằng kích thước của string là 8. Nó làm điều này vào thời điểm biên dịch.

Tuy nhiên, strlen() đếm số ký tự trong chuỗi tại thời gian chạy. Vì vậy, sau khi bạn gọi strcpy(), string hiện có chứa "tháng chín". strlen() đếm các ký tự và tìm 9 ký tự. Lưu ý rằng bạn đã không phân bổ đủ không gian cho string để giữ "tháng chín". Đây là hành vi không xác định.

3

Các Output là đúng vì

đầu tiên kích thước chuỗi tuyên bố đã được phân bổ bởi trình biên dịch đó là 7 + 1 (tháng 7 byte & 1 byte cho terminator null ở thời gian biên dịch)

tuyên bố thứ hai: bạn là sao chép tháng 9 (chuỗi 9 byte đến 8 byte);

ở đó đợi em có kích thước tháng là 8 byte (vẫn strlen() sẽ không hoạt động cho tháng chín nó không có kí tự null)

+1

Chuỗi ký tự '" september "' chứa ngầm ký tự null, vì vậy 'strlen()' sẽ hoạt động, nếu chương trình không bị hỏng (do viết qua cuối mảng 'chuỗi') –

-1

Bạn phải loại bỏ buffer overflow vấn đề trong ví dụ này. Một cách để thực hiện việc này - là sử dụng strncpy:

memset(string, 0, sizeof(string)); 
strncpy(string, "september", sizeof(string)-1); 
+1

Không, không, không. 'strncpy()', mặc dù tên của nó, là công cụ sai để làm bất cứ điều gì với ** chuỗi **. Trong ví dụ trên, 'chuỗi' kết quả sẽ không phải là một chuỗi * bởi vì không có phần tử nào trong số 8 phần tử của nó sẽ chứa một terminator 0. – pmg

+0

Tại sao công cụ sai? Tôi đã cố định vấn đề chấm dứt chuỗi. –

+0

Đó là công cụ sai cho các chuỗi chính xác bởi vì nó không giải thích cho các terminator 0 tồn tại trong mỗi và mọi chuỗi theo định nghĩa (thiết kế 'strncpy()' làm cho nó chỉ hữu ích cho ... errr ... * un-terminated dây*). Hãy chắc chắn rằng bạn có không gian và sử dụng 'strcpy()' (hoặc, nếu bạn có thể sử dụng BSD-isms, sử dụng 'strlcpy()'). – pmg