简体   繁体   English

C语言,数组,指针

[英]C programming language, array, pointer

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

this code gives me a stack overflow error why? 此代码给我一个堆栈溢出错误,为什么? But if instead of printf(arr,j) we use printf(arr) then it prints Abc. 但是,如果我们使用printf(arr)而不是printf(arr,j) printf(arr)那么它将打印Abc。 please tell me how printf works , means 1st argument is const char* type so how arr is treated by compiler. 请告诉我printf工作原理,这意味着第一个参数是const char*类型,因此编译器如何处理arr。 sorry! 抱歉! above code is right it doesn't give any error,I write this by mistake. 上面的代码是正确的,它没有任何错误,我写错了。 but below code give stack overflow error. 但是下面的代码给出了堆栈溢出错误。

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

since variable i take any garbage value so that will be the size of the array so why this code give this error when i use DEV C++ and if I use TURBO C++ 3.0 then error:constant expression required displayed. 由于变量我采用任何垃圾值,因此将是数组的大小,因此为什么当我使用DEV C ++时,如果我使用TURBO C ++ 3.0,此代码为何会给出此错误,然后显示error:constant expression required。 if size of array can't be variable then when we take size of array through user input.no error is displayed. 如果数组的大小不能可变,那么当我们通过用户输入获取数组的大小时,不会显示错误。 but why in this case. 但是为什么在这种情况下。

please tell me how printf works 请告诉我printf的工作原理

First of all, pass only non-user supplied or validated strings to the first argument of printf() ! 首先, 仅将非用户提供或验证的字符串传递给printf()的第一个参数!

printf() accepts a variable number of arguments after the required const char* argument (because printf() is what's called a variadic function ). printf()在必需的const char*参数之后接受可变数量的参数(因为printf()可变参数函数 )。 The first const char* argument is where you pass a format string so that printf() knows how to display the rest of your arguments. 第一个const char*参数是您传递格式字符串的位置,以便printf()知道如何显示其余参数。

If the arr character array contains user-inputted values, then it may cause a segfault if the string happens to contain those formatting placeholders, so the format string should always be a hard-coded constant (or validated) string. 如果arr字符数组包含用户输入的值,则如果字符串恰好包含那些格式占位符,则可能会导致段错误,因此格式字符串应始终为硬编码的常量(或经过验证的)字符串。 Your code sample is simple enough to see that it's really a constant, but it's still good practice to get used to printf("%s", arr) to display strings instead of passing them directly to the first argument (unless you absolutely have to of course). 您的代码示例很简单,可以看到它确实是一个常数,但是习惯于使用printf("%s", arr)来显示字符串而不是将它们直接传递给第一个参数(除非您绝对必须这样做)仍然是一种好习惯。当然)。

That being said, you use the formatting placeholders (those that start with % ) to format the output. 就是说,您可以使用格式占位符(以%开头的占位符)来格式化输出。 If you want to display: 如果要显示:

Abc 97 abc 97

Then your call to printf() should be: 然后,您对printf()调用应为:

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

The %s tells printf() that the second argument should be interpreted as a pointer to a null-terminated string. %s告诉printf()第二个参数应解释为指向以空字符结尾的字符串的指针。 The %d tells printf() that the third argument should be interpreted as a signed decimal. %d告诉printf()第三个参数应解释为带符号的十进制。

this code gives me a stack overflow error why? 此代码给我一个堆栈溢出错误,为什么?

See AndreyT's answer. 请参阅AndreyT的答案。

I see that now the OP changed the description of the behavior to something totally different, so my explanation no longer applies to his code. 我看到,现在OP将对行为的描述更改为完全不同的内容,因此我的解释不再适用于他的代码。 Nevertheless, the points I made about variadic functions still stand. 尽管如此,我关于可变参数功能的观点仍然存在。

This code results in stack invalidation (or something similar) because you failed to declare function printf . 这段代码导致堆栈无效(或类似的错误),因为您未能声明函数printf printf is a so called variadic function, it takes variable number of arguments. printf是一个所谓的可变参数函数,它接受可变数量的参数。 In C language it has [almost] always been mandatory to declare variadic functions before calling them. 在C语言中,几乎总是必须在调用可变参数函数之前先声明它们。 The practical reason for this requirement is that variadic functions might (and often will) require some special approach for argument passing. 产生此要求的实际原因是可变参数函数可能(并且经常会)需要一些特殊的方法来传递参数。 It is often called a calling convention . 它通常称为调用约定 If you forget to declare a variadic function before calling it, a pre-C99 compiler will assume that it is an ordinary non-variadic function and call it as an ordinary function. 如果忘记在调用可变参数函数之前声明它,则C99之前的编译器将假定它是普通的非可变函数,并将其作为普通函数调用。 Ie it will use a wrong calling convention, which in turn will lead to stack invalidation. 即它将使用错误的调用约定,从而导致堆栈无效。 This all depends on the implementation: some might even appear to "work" fine, some will crash. 这完全取决于实现方式:有些甚至看起来可以“正常工作”,有些甚至会崩溃。 But in any case you absolutely have to declare variadic functions before calling them. 但是无论如何,您绝对必须在调用可变参数函数之前先声明它们。

In this case you should include <stdio.h> before calling printf . 在这种情况下,应在调用printf之前包括<stdio.h> Header file <stdio.h> is a standard header that contains the declaration of printf . 头文件<stdio.h>是一个标准头,其中包含printf的声明。 You forgot to do it; 你忘了做 hence the error (most likely). 因此错误(最有可能)。 There's no way to be 100% sure, since it depends on the implementation. 由于它取决于实现,因此无法百分百确定。

Otherwise, your code is valid. 否则,您的代码有效。 The code is weird, since you are passing j to printf without supplying a format specifier for it, but it is not an error - printf simply ignores extra variadic arguments. 该代码很奇怪,因为您将j传递给printf而不为其提供格式说明符,但这不是一个错误printf只是忽略了多余的可变参数。 Your code should print Abc in any case. 无论如何,您的代码都应打印Abc Add #include <stdio.h> at the beginning of your code, and it should work fine, assuming it does what you wanted it to do. 在代码的开头添加#include <stdio.h> ,假定它已完成您想要的工作,它应该可以正常工作。

Again, this code 同样,此代码

#include <stdio.h>

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

is a strange, but perfectly valid C program with a perfectly defined output (adding \\n at the end of the output would be a good idea though). 是一个奇怪的但完全有效的C程序,具有完美定义的输出(尽管在输出末尾添加\\n是个好主意)。

In your line int i, a[i]; 在您的int i, a[i];行中int i, a[i]; in the corrected sample of broken code, a is a variable-length array of i elements, but i is uninitialized. 在更正的破损代码样本中, ai元素的可变长度数组,但i未初始化。 Thus your program has undefined behavior. 因此,您的程序具有未定义的行为。

I suspect the printf() issue is a red herring, since with a null-terminated "Abc" will ignore other arguments. 我怀疑printf()问题是一个红色的鲱鱼,因为以空终止的“ Abc”将忽略其他参数。

Have you debugged your program? 你调试过程序了吗? If not can you be sure the fault isn't in getch() ? 如果不能,您是否可以确定故障不在getch()中
I cannot duplicate your issue but then I commented out the getch() for simplicity. 我无法复制您的问题,但是为了简单起见,我注释掉了getch()

BTW, why did you not use fgetc() or getchar() ? 顺便说一句,为什么不使用fgetc()getchar()呢? Are you intending to use curses in a larger program? 您打算在更大的程序中使用curses吗?

===== Added after your edit ===== =====编辑后添加=====

Okay, not a red herring, just a mistake by the OP. 好吧,不是红鲱鱼,只是OP的一个错误。

C++ does allow allocating an array with the size specified by a variable; C ++确实允许分配一个由变量指定的大小的数组。 you've essentially done this with random (garbage) size and overflowed the stack, as you deduced. 正如您所推论的那样,您实际上已经使用随机(垃圾)大小完成了此操作,并且使堆栈溢出。 When you compile with C++ you are typically no longer compiling C and the rules change (depending on the particular compiler). 使用C ++进行编译时,通常不再编译C,并且规则也会更改(取决于特定的编译器)。

That said, I don't understand your question - you need to be a lot more clear with " when we take size of array through user input " ... 就是说,我不明白您的问题-您需要更加清楚“ 当我们通过用户输入获取数组大小时 ……”

You see strings in C language are treated as char* and printf function can print a string directly. 您会看到C语言的字符串被视为char*并且printf函数可以直接打印字符串。 For printing strings using this function you should use such code: 要使用此功能打印字符串,应使用以下代码:

printf("%s", arr);

%s tells the function that the first variable will be char* . %s告诉函数第一个变量将为char*

If you want to print both arr and j you should define the format first: 如果要同时打印arr和j,则应首先定义格式:

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

%d tells the function that the second variable will be int %d告诉函数第二个变量将是int

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

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