[c] C에서 % n 형식 지정자의 사용은 무엇입니까?

%nC 에서 형식 지정자 의 사용은 무엇입니까 ? 누구든지 예를 들어 설명 할 수 있습니까?



답변

아무것도 인쇄되지 않았습니다. 인수는 지금까지 기록 된 문자 수가 저장되는 signed int에 대한 포인터 여야합니다.

#include <stdio.h>

int main()
{
  int val;

  printf("blah %n blah\n", &val);

  printf("val = %d\n", val);

  return 0;

}

이전 코드는 다음을 인쇄합니다.

blah  blah
val = 5


답변

이 답변의 대부분 %n (아무것도 인쇄하지 않고 지금까지 인쇄 된 문자 수를 int변수 에 쓰는 것입니다) 무엇을하는지 설명 하지만 지금까지 아무도 그것이 무엇을 사용 하는지에 대한 예를 제공하지 않았습니다 . 다음은 하나입니다.

int n;
printf("%s: %nFoo\n", "hello", &n);
printf("%*sBar\n", n, "");

인쇄됩니다 :

hello: Foo
       Bar

Foo와 Bar가 정렬되어 있습니다. ( %n이 특정 예제 를 사용하지 않고 그렇게하는 것은 사소한 일이며 일반적으로 항상 첫 번째 printf호출을 끊을 수 있습니다 .

int n = printf("%s: ", "hello");
printf("Foo\n");
printf("%*sBar\n", n, "");

약간 추가 된 편리함이 난해한 것과 같은 것을 사용할 가치가 있는지 %n(그리고 오류를 유발할 수 있음) 여부는 논쟁의 여지가 있습니다.)


답변

실제로 %n지정자 의 실제 사용을 많이 보지 못했지만 형식 문자열 공격 과 함께 구식 printf 취약성에서 꽤 오래 전에 사용되었다는 것을 기억합니다 .

이렇게 된 것

void authorizeUser( char * username, char * password){

    ...code here setting authorized to false...
    printf(username);

    if ( authorized ) {
         giveControl(username);
    }
}

악의적 인 사용자가 형식 문자열로 printf에 전달되는 사용자 이름 매개 변수를 이용하고 %d, %c또는 w / e 조합을 사용 하여 호출 스택을 통과 한 다음 실제 값으로 승인 된 변수를 수정할 수 있습니다.

예, 그것은 난해한 용도이지만 보안 허점을 피하기 위해 데몬을 작성할 때 항상 유용합니까? :디


답변

여기 에서 지금까지 인쇄 된 문자 수를 저장하는 것을 볼 수 있습니다.

n 인수는 fprintf()함수 중 하나에 대한이 호출에 의해 지금까지 출력에 기록 된 바이트 수를 기록하는 정수에 대한 포인터 입니다. 인수는 변환되지 않습니다.

사용 예는 다음과 같습니다.

int n_chars = 0;
printf("Hello, World%n", &n_chars);

n_chars그러면 값이 12.


답변

지금까지 모든 대답은 그에 대한 %n것이지만, 처음에 누군가가 그것을 원하는 이유는 아닙니다. 저장된 값이 결과 문자열에 대한 배열 인덱스이기 때문에 나중에 결과 문자열을 분리하거나 수정해야 할 때 sprintf/ snprintf를 사용하면 다소 유용 합니다. 이 응용 프로그램은를 사용하면 훨씬 더 유용합니다. sscanf특히 scanf패밀리의 함수는 처리 된 문자 수를 반환하지 않고 필드 수를 반환하기 때문입니다.

또 다른 정말 hackish 사용은 다른 작업의 일부로 숫자를 인쇄하는 동안 동시에 무료로 pseudo-log10을 얻는 것입니다.


답변

와 연관된 인수 %n는로 처리되며 int*.NET Framework에서 해당 지점에 인쇄 된 총 문자 수로 채워집니다 printf.


답변

다른 날 나는 %n내 문제를 멋지게 해결할 수 있는 상황에 처했다. 이전 답변 과 달리이 경우 좋은 대안을 고안 할 수 없습니다.

지정된 텍스트를 표시하는 GUI 컨트롤이 있습니다. 이 컨트롤은 해당 텍스트의 일부를 굵게 (또는 기울임 꼴 또는 밑줄 등) 표시 할 수 있으며 시작 및 끝 문자 색인을 지정하여 어느 부분을 지정할 수 있습니다.

제 경우에는를 사용하여 컨트롤에 대한 텍스트를 생성하고 snprintf있으며 대체 항목 중 하나를 굵게 표시하고 싶습니다. 이 대체에 대한 시작 및 끝 인덱스를 찾는 것은 다음과 같은 이유로 중요하지 않습니다.

  • 문자열에는 여러 개의 대체가 포함되며 대체 중 하나는 임의의 사용자 지정 텍스트입니다. 이것은 내가 관심을 갖는 대체물에 대한 텍스트 검색을 수행하는 것이 잠재적으로 모호하다는 것을 의미합니다.

  • 형식 문자열은 지역화 될 수 있으며 $위치 형식 지정자에 POSIX 확장을 사용할 수 있습니다 . 따라서 원래 형식 문자열에서 형식 지정자 자체를 검색하는 것은 간단하지 않습니다.

  • 지역화 측면은 또한 형식 문자열을 snprintf.

따라서 특정 대체에 대한 인덱스를 찾는 가장 간단한 방법은 다음과 같습니다.

char buf[256];
int start;
int end;

snprintf(buf, sizeof buf,
         "blah blah %s %f yada yada %n%s%n yakety yak",
         someUserSpecifiedString,
         someFloat,
         &start, boldString, &end);
control->set_text(buf);
control->set_bold(start, end);