2013-06-09 4 views
3

C++에서 함수에 전달 된 "문자열"(해당 표현에 관계없이)이 해당 함수에 의해 유효한 문자열로 간주 될 수있는 방법이 있는지 궁금합니다.유효한 매개 변수를 함수 매개 변수로 보장

나는 C/C 아주 새로운 해요 ++하지만 지금까지 내가 볼 수 있듯이, 문제는 기본적으로 대한 답변 C에 싶게 당신은 당신이 확인해야 할 것을 알고 다른 방법이 없기 때문에 :

#include <stdio.h> 

void foo(const char *str) 
{ 
    if (str) 
     printf("%s\n", str); 
} 

int main() 
{ 
    char *name = "Jack"; 
    foo(name); 

    return 0; 
} 

하지만 C++에서는 참조와 같은 추가 정보를 제공하므로 확인할 필요가없는 방식으로 foo()를 작성할 수 있는지 궁금합니다. 나는 이것을 다음과 같이 시도했다 :

#include <iostream> 
#include <string> 

void foo(const std::string &str) 
{ 
    std::cout << str << std::endl; 
} 

int main(void) 
{ 
    std::string name = "Jack"; 
    foo(name); 

    std::string *str = NULL; 
    foo(*str); 

    return 0; 
} 

그러나 내가 볼 수 있듯이 나는 foo()를 속여 SegFault를 실행할 수있다. 그래서, 당신은 단지 항상을 확인해야 할 것입니다.

수정 # 1 :

좋아, 모든 답 미래의 답변에 대한 모든 감사의 첫 번째, 그들은 모두 많은 감사합니다!

그래서 내가 지금까지 배운 내용을 정리해 :

는 실제 함수 호출에 의해 오용을 제거 에 기능 (고화질)를 작성하는 C에는 구문 방법 ++ 없다.

맞습니까? 그렇다면 원래 질문에 대한 답을 볼 수 있습니다.

이제 foo()를 최대한 방어적인 것으로 써서 개가 foo()를 얼마나 많이 다루더라도 SegFault는 생성되지 않습니다.

#include <stdio.h> 

void foo(const char *str, const size_t len) 
{ 
    if (str && (str[len - 1] == '\0')) 
     printf("%s\n", str); 
} 

int main() 
{ 
    char *name = "Jack"; 
    foo(name, 5); 

    /* possible mistakes, but foo can handle them */ 
    foo(name, 4); 
    foo(name, -1); 
    foo(NULL, 5); 

    return 0; 
} 

그리고 C에서

는 ++ 나는이 노력하고있어 : CI에서

이제 (짧은 circut 평가를 가정)이처럼 작성합니다

#include <iostream> 
#include <string> 

void foo(const std::string &str) 
{ 
    if (&str) 
     std::cout << str << std::endl; 
} 

int main(void) 
{ 
    std::string name = "Jack"; 
    foo(name); 

    std::string *str = NULL; 
    foo(*str); 

    return 0; 
} 

을 ...하지만 난 그것이 어떤 approriate에 있는지, 또는이 경우에 예외로 할 수 있거나, 할 수 있거나,해야 할 일이 무엇인지 확실하지 않습니다.

당신은 어떻게 생각하십니까? 구문에 의한 오용을 방지 할 수 없다면주의 사항을 늘려야합니까?

+0

아니요, 확인하지 않아도됩니다. 당신이해야 할 일은 NULL 포인터를 참조 해제하지 않는 것입니다. 또한 C에 관해서는'null '로 끝나는 문자열의 시작이 아닌'char'에 대한 포인터를 전달하면'foo'가 깨질 수 있습니다. – juanchopanza

+0

원래 질문에 대한 답변이있는 경우 대답에 동의하십시오 (점수 아래의 왼쪽에있는 체크 표시를 클릭하십시오). 다른 질문이 있으면 다른 게시물을 작성하십시오. –

답변

9
std::string *str = NULL; 
foo(*str); 

이것은 호출자 측에서 정의되지 않은 동작입니다. 너의 문제는 아니야. 그래서 아니오, 당신 (foo의 작가)은 확인할 필요가 없습니다.

C를 사용하는 경우에도 포인터를 사용하여 반드시 확인하지 않아도됩니다. 문서 작성 만하면됩니다. "인수는 유효한 null 종료 문자열을 가리켜 야하며, 그렇지 않으면 호출은 정의되지 않은 동작입니다." - 사용자가 NULL을 전달하면 다시 문제가 발생합니다. 이것은 항상 수행됩니다. 그렇지 않은 경우 다음과 같은 모든 수준에서 포인터의 유효성을 확인하는 낭비한 호출 체인이 있습니다.

+0

+1,이 답변은 처음부터 나보다 낫습니다 :) –

2

아니요, 올바르지 않습니다.

두 번째 코드에서 정의되지 않은 동작은 포인터를 역 참조 할 때 전에에 도달하기 전에 발생합니다.

이것은 사용자의 기능에 문제가되지 않습니다. 함수 내에서 두 번째 서명을 사용하면 항상 유효한 문자열을 가진 것으로 가정 할 수 있으므로 첫 번째 문자열보다 우수합니다.

관련 문제