为什么我们不应该在sprintf中包含最后一个数组元素?

时间:2013-04-05 01:29:55

标签: c++ c

我有一个如下所示的代码,最后一个语句只有在我使用l_plates [i]时才有效。在下面的例子中,它抛出一个错误“传递'sprintf'的参数1使整数指针没有强制转换” 如果我也需要另一个用于N的循环怎么办?如果我使用sprintf,我应该使用额外的元素吗? 请解释。提前谢谢。

char type, letters[4], digits[5];
char l_plates[M][N];

for (i=0; i<M; i++) {
    scanf(" %c", &type);
    scanf("%3s", letters); 
    scanf("%4s", digits); 
    sprintf(l_plates[i][N], "%s %s %c", letters, digits, type);
}

5 个答案:

答案 0 :(得分:3)

我在这里看到两个问题。首先,sprintf的第一个参数应该是char*,而不是char,这是你发送给它的。

其次,大小为N的数组从0索引到N - 1。通过尝试访问元素N,您将步入数组之外。最后一个元素是[N - 1]

答案 1 :(得分:0)

sprintf行中,表达式l_plates[i][N]引用单个字符,并且您尝试将整个字符串写入其中。

变量l_plates是一个长度为N的字符串的一维数组(或二维字符数组)。

如果您需要二维字符串数组,那么您需要使用以下内容定义l_plates

char* l_plates[M][N];

然后 malloc 相应的那些字符串。

答案 2 :(得分:0)

让我们看看l_plates

的声明

char l_plates [M] [N];

这表示l_platesNM个数组的数组。另一种思考方式是作为二维数组的字符。

那么l_plates[i][N]的类型是什么?这是一个char!换句话说,它是一个单一的符号。但是,sprintf()需要char*作为其第一个参数。这就是您使用上述代码收到编译器错误的原因。

另一方面,l_plates[i]char数组。 C和C ++都可以将此数组转换为char*,因此编译器不会抱怨。

答案 3 :(得分:0)

那是因为l_plates[i]是一个字符串,而l_plates[i][N]是一个单个字符,虽然是一个不合格的字符(因为N-1是最后一个字符)。

那就是说,snprintf()

可能会更好
snprintf(l_plates[i], N, "%s %s %c", letters, digits, type);

这可确保您不会溢出字符数组。

答案 4 :(得分:0)

您应该查看指针和数组在C中的工作方式。

l_plates[i][N]实际上是指char,所以它甚至不会编译; sprintf期望char*写入输出的位置。 l_plates[i]类型为char[N],可隐式转换为char*,指向内部数组的开头。将其作为sprintf的参数使其成为您可能想要的。

顺便说一下,l_plates[i][N]你以非法的偏移方式访问内部数组。大小为N的数组的偏移量应介于0到N-1之间。 C / C ++不一定会在运行时抱怨这一点,但它几乎总是一个bug。在这种情况下,l_plates[M-1][N]确实指向为l_plates分配的内存之外。