programing

println!

nasanasas 2020. 12. 30. 08:15
반응형

println! 오류 : 리터럴 / 형식 인수가 문자열 리터럴이어야합니다.


이 매우 간단한 Rust 프로그램 :

fn main() {
    let c = "hello";
    println!(c);
}

다음 컴파일 타임 오류가 발생합니다.

error: expected a literal
 --> src/main.rs:3:14
  |
3 |     println!(c);
  |              ^

이전 버전의 Rust에서 오류는 다음과 같습니다.

error: format argument must be a string literal.
     println!(c);
              ^

프로그램을 다음으로 대체 :

fn main() {
    println!("Hello");    
}

잘 작동합니다.

이 오류의 의미는 나에게 명확하지 않으며 Google 검색에서도 실제로 밝혀지지 않았습니다. 왜 통과 않는 c받는 println!컴파일 타임 오류 원인 매크로? 이것은 매우 특이한 행동처럼 보입니다.


TL; DR 이유를 신경 쓰지 않고 문제를 해결 하려면 형제 답변을 참조하십시오 .


그 이유

fn main() {
    let c = "hello";
    println!(c);
}

작동 할 수없는 이유는 println!매크로가 컴파일 타임에 문자열 을보고 인수와 인수 지정자가 양과 유형에서 일치하는지 확인하기 때문입니다 (매우 좋은 것입니다!). 이 시점에서 매크로 평가 중에 그것이 c리터럴이나 함수에서 나왔는지 또는 무엇을 가지고 있는지 알 수 없습니다.

다음은 매크로가 확장되는 대상의 예입니다.

let c = "hello";
match (&c,) {
    (__arg0,) => {
        #[inline]
        #[allow(dead_code)]
        static __STATIC_FMTSTR: &'static [&'static str] = &[""];
        ::std::io::stdio::println_args(&::std::fmt::Arguments::new(
            __STATIC_FMTSTR,
            &[::std::fmt::argument(::std::fmt::Show::fmt, __arg0)]
        ))
    }
};

나는 컴파일러가 이것을 알아내는 것이 실제로 불가능하다고 생각하지 않지만 아마도 많은 작업이 필요할 것입니다 (잠재적으로 약간의 이득을 위해). 매크로는 AST의 일부에서 작동하며 유형 정보 만 있다고 가정합니다. 이 경우에 작동하려면 AST가 식별자의 소스와 "안전"하다고 판단하기에 충분한 정보를 포함해야합니다. 또한 유형 추론과 제대로 상호 작용하지 않을 수 있습니다. 아직 선택되기 전에 유형을 알고 싶을 것입니다!

오류 메시지는 "문자열 리터럴"을 요구합니다. 있다 SO에 대한 질문은 무엇을 그 수단의 링크 위키 백과 항목 :

리터럴은 소스 코드에서 고정 값을 나타내는 표기법입니다.

"foo"문자열 리터럴이고 8숫자 리터럴입니다. let s = "foo"문자열 리터럴의 값을 식별자 (변수)에 할당하는 문입니다. println!(s)매크로에 식별자를 제공하는 문입니다.


이것은 작동합니다.

fn main() {
    let c = "hello";
    println!("{}", c);
}

문자열 "{}"은에 {}전달 된 다음 인수로 대체 될 템플릿 println!입니다.


형식 문자열이 적당한 횟수만큼만 재사용되고 일부 변수 데이터 만 변경되는 경우 매크로보다 작은 함수가 더 나은 옵션 일 수 있습니다.

fn pr(x: &str) {
    println!("Some stuff that will always repeat, something variable: {}", x);
}

pr("I am the variable data");

출력

항상 반복되는 일부 변수, 변수 : I am the variable data


정말로 println의 첫 번째 인수를 정의하고 싶다면! 한 곳에서 방법을 찾았습니다. 매크로를 사용할 수 있습니다.

macro_rules! hello {() => ("hello")};
println!(hello!());

Doesn't look too useful here, but I wanted to use the same formatting in a few places, and in this case the method was very helpful:

macro_rules! cell_format {() => ("{:<10}")};  // Pads with spaces on right
                                              // to fill up 10 characters
println!(cell_format!(), "Foo");
println!(cell_format!(), 456);

The macro saved me from having to duplicate the formatting option in my code.

You could also, obviously, make the macro more fancy and take arguments if necessary to print different things with different arguments.

ReferenceURL : https://stackoverflow.com/questions/27734708/println-error-expected-a-literal-format-argument-must-be-a-string-literal

반응형