2014-09-30 3 views
5

이것은 실용적인 것이 아니라 지금이 시점에서 개념적으로 더 많은 질문이지만 실제로는 저를 괴롭 히고 있습니다.sizeof를 사용하여 argv에서 문자열의 크기 찾기

"test.c"라는 C 프로그램이 있으며 사용자가 인수로 입력하는 단어가 배열에있는 공백 수를 찾고 싶다고 가정 해 보겠습니다. 예를 들어, "./test.c test_run"은 8자를, 그리고 널 문자를 종료하기 때문에 9를 출력해야합니다. argv에 sizeof를 사용하려고 할 때 약간의 문제가 있습니다.

int main(int argc, char *argv[]) { 
    char buf10[10]; 
    printf("The size of buf10 is: %i.\n", sizeof(buf10)); 
    return 0; 
} 

이 결과를 출력 "buf10의 크기는 다음 10". char 배열을 선택했기 때문에 이것은 의미가 있습니다. C에서 char의 크기는 1 바이트입니다. int를 선택하면이 숫자는 4가됩니다.

이제 제 질문으로 왜 argv에서이 작업을 수행 할 수 없습니까? 이 9되어야하지만, 마이너스는 \ "0"제

제작하므로

argv[1] has the value: Hello_SO 
strlen of argv[1] is: 8 
sizeof of argv[1] is: 4 

문자열 길이 말이 :

int main(int argc, char *argv[]) { 
    printf("argv[1] has the value: %s\n", argv[1]); 
    printf("strlen of argv[1] is: %i\n", strlen(argv[1])); 
    printf("sizeof of argv[1] is: %i\n", sizeof(argv[1])); 
    return 0; 
} 

"./test Hello_SO"와 RAN은 출력을 제공한다 그러나 sizeof가 4 (포인터의 크기)를 반환하는 이유를 이해하지 못합니다. 나는 * argv []가 ** argv로 간주 될 수 있음을 이해한다. 그러나 나는 이것을 이미 설명했다. 첫 번째 예제에서는 "buf"를 인쇄하지만 여기서 "argv [1]"을 인쇄합니다. strlen을 사용하여 쉽게 답을 얻을 수 있다는 것을 알지만, 이전에 말했듯이 지금은 개념적입니다.

+0

아마도 당신 자신의 질문에 답한 것 같습니다. – alex

+0

'argv [1]'은 타입'char *'을 가지고 있으므로'sizeof argv [1]'은'sizeof (char *)'를 의미합니다. 그것이 sizeof의 기능입니다. –

+0

하지만 buf10은 10을 인쇄하고 argv [1]은 9를 인쇄하지 않습니다. buf10도 포인터가 아닙니까? –

답변

3

많은 상황에서 포인터와 배열이 똑같지는 않지만 동일합니다. sizeof은 주요 차이점입니다.

int arr[10]; 
assert(sizeof arr == (sizeof(int) * 10)); 
int *ip; 
assert(sizeof ip == sizeof(int*)); 

arr의 유형은 상술 int[10]이다. 배열 유형과 포인터의 차이를 확인하는 또 다른 방법은 할당하려는 것입니다.

int i; 
ip = &i; // sure, fine 
arr = &i; // fails, can't assign to an int[10] 

배열을 할당 할 수 없습니다.

가장 혼란스러운 점은 배열을 함수 매개 변수로 사용하는 경우 실제로는 이고 포인터에 동일한 것이 있다는 것입니다.

int f(int arr[10]) { 
    int x; 
    arr = &x; // fine, because arr is actually an int* 
    assert(sizeof arr == sizeof(int*)); 
} 

은 불규칙 배열 때문에 그것의, 당신은 sizeof argv[1]을 사용하고 문자열 (플러스 \0의 1)의 크기를 얻을 수없는 이유의 질문을 해결하기 위해. 이 경우 첫 번째 차원은 알 수없는 크기와 두 번째 차원입니다. sizeof은이 경우 컴파일 타임 작동처럼 작동하며 런타임까지 문자열의 길이를 알 수 없습니다.

#include <stdio.h> 

int main(int argc, char *argv[]) { 
    printf("%zu\n", sizeof argv[1]); 
} 

이 생성 조립은 다음과 같습니다 : 당신이 볼 수

.LC0: 
    .string "%zu\n" 
    .text 
    .globl main 
    .type main, @function 
main: 
.LFB3: 
    .cfi_startproc 
    subq $8, %rsp 
    .cfi_def_cfa_offset 16 
    movl $8, %esi  # this 8 is the result of sizeof 
    movl $.LC0, %edi  # the format string 
    movl $0, %eax 
    call printf   # calling printf 
    movl $0, %eax 
    addq $8, %rsp 
    .cfi_def_cfa_offset 8 
    ret 
    .cfi_endproc 

, sizeof argv[1]의 결과가 컴파일시에 이루어집니다, 아무것도 위를 계산하지

다음 프로그램을 고려 문자열의 길이 나는 포인터가 8 바이트가되도록 64 비트를 사용하고있다.

+1

혼란은 함수 매개 변수로서 배열을 가질 수 없다는 사실 때문에 실제로 발생합니다. 함수 매개 변수를 배열로 선언하면 컴파일러는이를 자동으로 포인터로 바꾸어 "오해"를 숨기고 이러한 오류를 유도합니다. –

+0

@ChrisDodd 네,하지만 규칙이 다른 다차원 배열을 잊지 마세요. –

+0

다차원 배열은 C 배열로만 존재합니다. 다른 배열과 마찬가지로 인수로 사용하면 포인터로 변합니다. 그런 다음 배열 배열과 포인터 배열 사이에 혼동이 있습니다.이 배열은 동일한 구문으로 액세스 할 수 있다는 사실에도 불구하고 완전히 다릅니다. –

1

buf10 변수는 컴파일시 10 자의 (연속적인) 배열로 알려져 있습니다. 다른 포인터는 동적으로 할당되며 문자에 대한 포인터입니다. 이것이 문자 배열과 sizeof (char *)의 크기를 비교하는 이유입니다.

+0

char buf10 [10] = "Hello"와 char buf10 [] = "Hello"사이에 차이점이 있습니까? –

+1

은 "Hello"를 저장하는 데 필요한 공간의 크기에 따라 배열의 길이를 계산합니다. 그래서 크기는 6이 될 것입니다. 그래도 여전히 배열입니다. 당신이'const char * s = "Hello"'를했다면'sizeof s'는'sizeof (char *)'가 될 것입니다. –