繁体   English   中英

C语言,数组,指针

[英]C programming language, array, pointer

int main()
{
    int j=97;
    char arr[4]="Abc";
    printf(arr,j);
    getch();
    return 0;
}

此代码给我一个堆栈溢出错误,为什么? 但是,如果我们使用printf(arr)而不是printf(arr,j) printf(arr)那么它将打印Abc。 请告诉我printf工作原理,这意味着第一个参数是const char*类型,因此编译器如何处理arr。 抱歉! 上面的代码是正确的,它没有任何错误,我写错了。 但是下面的代码给出了堆栈溢出错误。

#include <stdio.h>
int main()
    {
       int i, a[i];
       getch();
       return 0;
    }

由于变量我采用任何垃圾值,因此将是数组的大小,因此为什么当我使用DEV C ++时,如果我使用TURBO C ++ 3.0,此代码为何会给出此错误,然后显示error:constant expression required。 如果数组的大小不能可变,那么当我们通过用户输入获取数组的大小时,不会显示错误。 但是为什么在这种情况下。

请告诉我printf的工作原理

首先, 仅将非用户提供或验证的字符串传递给printf()的第一个参数!

printf()在必需的const char*参数之后接受可变数量的参数(因为printf()可变参数函数 )。 第一个const char*参数是您传递格式字符串的位置,以便printf()知道如何显示其余参数。

如果arr字符数组包含用户输入的值,则如果字符串恰好包含那些格式占位符,则可能会导致段错误,因此格式字符串应始终为硬编码的常量(或经过验证的)字符串。 您的代码示例很简单,可以看到它确实是一个常数,但是习惯于使用printf("%s", arr)来显示字符串而不是将它们直接传递给第一个参数(除非您绝对必须这样做)仍然是一种好习惯。当然)。

就是说,您可以使用格式占位符(以%开头的占位符)来格式化输出。 如果要显示:

abc 97

然后,您对printf()调用应为:

printf("%s %d", arr, j);

%s告诉printf()第二个参数应解释为指向以空字符结尾的字符串的指针。 %d告诉printf()第三个参数应解释为带符号的十进制。

此代码给我一个堆栈溢出错误,为什么?

请参阅AndreyT的答案。

我看到,现在OP将对行为的描述更改为完全不同的内容,因此我的解释不再适用于他的代码。 尽管如此,我关于可变参数功能的观点仍然存在。

这段代码导致堆栈无效(或类似的错误),因为您未能声明函数printf printf是一个所谓的可变参数函数,它接受可变数量的参数。 在C语言中,几乎总是必须在调用可变参数函数之前先声明它们。 产生此要求的实际原因是可变参数函数可能(并且经常会)需要一些特殊的方法来传递参数。 它通常称为调用约定 如果忘记在调用可变参数函数之前声明它,则C99之前的编译器将假定它是普通的非可变函数,并将其作为普通函数调用。 即它将使用错误的调用约定,从而导致堆栈无效。 这完全取决于实现方式:有些甚至看起来可以“正常工作”,有些甚至会崩溃。 但是无论如何,您绝对必须在调用可变参数函数之前先声明它们。

在这种情况下,应在调用printf之前包括<stdio.h> 头文件<stdio.h>是一个标准头,其中包含printf的声明。 你忘了做 因此错误(最有可能)。 由于它取决于实现,因此无法百分百确定。

否则,您的代码有效。 该代码很奇怪,因为您将j传递给printf而不为其提供格式说明符,但这不是一个错误printf只是忽略了多余的可变参数。 无论如何,您的代码都应打印Abc 在代码的开头添加#include <stdio.h> ,假定它已完成您想要的工作,它应该可以正常工作。

同样,此代码

#include <stdio.h>

int main()
{
    int j=97;
    char arr[4]="Abc";
    printf(arr,j);
    return 0;
}

是一个奇怪的但完全有效的C程序,具有完美定义的输出(尽管在输出末尾添加\\n是个好主意)。

在您的int i, a[i];行中int i, a[i]; 在更正的破损代码样本中, ai元素的可变长度数组,但i未初始化。 因此,您的程序具有未定义的行为。

我怀疑printf()问题是一个红色的鲱鱼,因为以空终止的“ Abc”将忽略其他参数。

你调试过程序了吗? 如果不能,您是否可以确定故障不在getch()中
我无法复制您的问题,但是为了简单起见,我注释掉了getch()

顺便说一句,为什么不使用fgetc()getchar()呢? 您打算在更大的程序中使用curses吗?

=====编辑后添加=====

好吧,不是红鲱鱼,只是OP的一个错误。

C ++确实允许分配一个由变量指定的大小的数组。 正如您所推论的那样,您实际上已经使用随机(垃圾)大小完成了此操作,并且使堆栈溢出。 使用C ++进行编译时,通常不再编译C,并且规则也会更改(取决于特定的编译器)。

就是说,我不明白您的问题-您需要更加清楚“ 当我们通过用户输入获取数组大小时 ……”

您会看到C语言的字符串被视为char*并且printf函数可以直接打印字符串。 要使用此功能打印字符串,应使用以下代码:

printf("%s", arr);

%s告诉函数第一个变量将为char*

如果要同时打印arr和j,则应首先定义格式:

printf("%s%d", arr, j);

%d告诉函数第二个变量将是int

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM