2

我有一个解析配置文件的 C 程序。配置文件允许格式中的一些通配符 option=%any

问题是当我使用 strcmp 比较值时,我得到一个非法指令错误。

示例程序来说明这一点:

char str1[10];
sprintf(str1,"%any");

if(strcmp(str1,"%any") == 0) 
        printf("match\n");

return 0;

输出:

$ ./a.out
Illegal instruction

printf 也会引发此错误。

用 printf("%s\n",str1);

输出是:

$ ./a.out
0x0.07fff00000001p-1022ny
Illegal instruction

我尝试转义,即在 sprintf 中使用“\%any”而不是“%any”;但这无济于事。

在 C++ 中,使用 std::string == 比较,使用 cout 打印似乎工作正常。

有人可以帮我找出如何用 C 来做到这一点。

4

2 回答 2

6

它来自sprintf.

#include <stdio.h>

sprintf(str1, "%%any");

正如Paul R.所说,您可以使用而strcpy不必担心这些格式。

于 2012-11-08T14:40:59.270 回答
1

在这种情况下,您可能应该编写以下内容之一:

char str1[10] = "%any";
char str1[] = "%any"; // str1 has size 5
const char *str1 = "%any"; // str1 points to a string literal

%a在格式化字符串中是十六进制浮点格式。除了您没有提供double参数(导致未定义的行为)这一事实之外,这可能会写入超过 10 个字节并因此超出您的缓冲区str1(导致未定义的行为)。

这就是为什么您会看到0x0.07fff00000001p-1022ny,它是一个十六进制浮点值0x0.07fff00000001p-1022,后跟ny. 您得到的非法指令错误可能是因为您破坏了存储在堆栈中的返回地址,因此当您的函数返回时,它会跳转到无效地址。

根据经验,如果您使用其中一个printf函数并且没有在格式字符串后指定至少一个可变参数,那么您很有可能做错了什么。fin的含义printf是该函数进行格式化,但是当您没有任何要格式化的内容时,您正在使用它。所以它只是一个字符串副本,有额外的机会出错。

如果您想使用printf函数系列中的一个来编写字符串,那么您可以避免意外指定您不希望这样的格式:

sprintf(str1, "%s", SOME_STRING);

或利用长度检查:

#define STR1_SIZE 10
char str1[STR1_SIZE];

if (snprintf(str1, STR1_SIZE, "%s", SOME_STRING) >= STR1_SIZE) {
    // error-handling here
}

如果您以某种方式知道它SOME_STRING适合您的缓冲区,那么您可以省略错误处理和/或strcpy改用。但是当你这样做并且弄错长度时,你看起来很愚蠢。

您还可以使用数组(因为它在这里)而不是指针(因为它在大多数字符串处理代码中)sizeof(str1)来代替STR1_SIZE提供的。str1

我尝试转义,即在 sprintf 中使用“\%any”而不是“%any”;但这无济于事。

不错的尝试,没有雪茄 ;-)

反斜杠用于转义字符串文字中的特殊字符。由于%在字符串文字中没有任何特殊含义,因此转义它没有任何效果。结果字符串是五个字符%, a, n, y, \0

稍后您将该字符串传递给sprintf. 现在具有%特殊含义,并且有不同的转义方式:%%.

于 2012-11-08T15:05:40.280 回答