0
#include<stdio.h>
#include<conio.h>

int main(){

    char i;
    int c;

    scanf("%i",&c);
    scanf("%c",&i);// catch the new line or character introduced before x number
    printf("%i",i);// value of that character

    getch();
    return(0);
}

The program will behave in the same way with the next variable declarations instead of the above variable declaration:

this:

int c;
int *x;
int i;

or this:

int *x;
int c;
int i;

And only this way: c variable and a x pointer before the i variable. I know that those last declarations haven't sense, the int i instead of char i, and an added pointer that isn't even needed. But this have been occurred accidentally and im wondering if it's only an a coincidence.

nEAnnam
  • 1,246
  • 2
  • 16
  • 22
  • Can someone explain what behavior? Your question is rather unclear. – Dark Falcon Dec 15 '11 at 20:48
  • What is `%i` supposed to mean? – Sadique Dec 15 '11 at 20:52
  • @Acme It matches an "optionally-signed integer whose format is the same as expected for the subject sequence of strtol()". So you can pass it `0x2A`. – cnicutar Dec 15 '11 at 20:53
  • @Acme: `%i` is a valid alternative to `%d` for a signed integer (even though I prefer `%d`). – AusCBloke Dec 15 '11 at 20:53
  • If I understand the question correctly, you are curious as to the layout of the local variables in memory? I believe that's unspecified. (If a variable is never used it may be removed, and if a variable's address is never used it might only live in a register.) Consider posting two *full test cases* showing the behavior(s) in question. –  Dec 15 '11 at 20:57
  • Thanks @cnicutar and AusCBloke... that was new to me... any links i could read about it? – Sadique Dec 15 '11 at 20:58
  • 1
    @Acme [SUSv4](http://pubs.opengroup.org/onlinepubs/9699919799/functions/scanf.html) – cnicutar Dec 15 '11 at 20:59
  • @Acme: The man pages contain the definition of the format specifiers (`%i` also does slightly more than `%d` in terms of also being able to read a number as base 8 or 16) such as: http://linux.die.net/man/3/sscanf or http://pubs.opengroup.org/onlinepubs/9699919799/functions/scanf.html – AusCBloke Dec 15 '11 at 21:02

2 Answers2

1

The function expects a sequence of references as additional arguments, each one pointing to an object of the type specified by their corresponding %-tag within the format string, in the same order. Read about scanf

These can additionally help you:

I don't understand why I can't get three inputs in c

scanf() leaves the new line char in buffer?

Regarding the last portion of your question, the number of bits of int is always more than char, so it won't cause a problem.

Community
  • 1
  • 1
Sadique
  • 22,572
  • 7
  • 65
  • 91
  • If i declare **i** as an integer will not print the value of the character introduced before the call to scanf, instead, it prints one big value – nEAnnam Dec 15 '11 at 21:05
  • That is because `scanf` stops reading at newline since it ignores whitespace characters.. I do not think anything is being read. Use `getchar()` to fix this. – Sadique Dec 15 '11 at 21:19
1

The order in which you declare your variables should make no difference at all, assuming there's nothing wrong with the rest of your code. The order of declaration needn't have anything at all to do with the way they're laid out in memory. And even if it did, you refer to variables by name; as long as your code is correct, a reference to i is a reference to i, and the compiler will generate whatever code is needed to access the variable correctly.

Now if you do this:

int i;
scanf("%c", &i);

then you're doing something wrong. scanf with a "%i" format requires a char* argument, which points to the char object into which the value will be stored. You're giving it an int* rather than a char*. As a result, your program's behavior is undefined; the language standard says nothing about how it will behave.

So why does it appear to work correctly? What's probably happening is that scanf treats the address of the int object i as if it were a pointer to a char. It will probably point to the first byte of the representation of i; for example, i might be 32 bits, and the pointer will point to the first 8 of those bits. (They could be the high-order or low-order bits, depending on the system.)

Now when you print the value of i:

printf("%d\n", i);

the contents of i are, for example, 1 byte consisting of whatever character you just read into it, and 3 bytes of garbage. Those 3 garbage bytes may well all be zeros, but they could be anything. If the garbage bytes happen to be 0, and the first byte happens to be the high-order byte (i.e., you're on a big-endian machine), then you're likely to get the "correct" output.

But don't do that. Since the behavior is undefined, it can work "correctly" for years, and then fail spectacularly at the worst possible moment.

The lesson here is that C tends to assume that you know what you're doing. There are a lot of constructs that have undefined behavior, which means that they're invalid, but neither the compiler nor the runtime system is required to tell you that there's a problem. In C, more than in most other languages, it's up to you as a programmer to get things right. The compiler (and other tools) will tell you about some errors, but not all of them.

And in the presence of undefined behavior, the order in which you declare your variables can make a difference. For example, if you write code that reads or writes past the end of a variable, it can matter what happens to be stored there. But don't be tempted to shuffle your declarations around until the program works. Get rid of the undefined behavior so the order doesn't matter.

The solution: Don't make mistakes in the first place. (Of course that's much easier said than done.)

And naming conventions can be helpful. If you had called your char variable c, and your int variable i, rather than vice versa, it would have been easier to keep track of which is which.

But c is a reasonable name for an int variable used to hold input character values -- not for scanf, but for getchar(), as in:

int c;
while ((c = getchar()) != EOF) {
    /* ... */
}
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631