-5

Consider the following code:

1: #include <stdio.h>
2: int poin(int p[4]){
3:    printf("%u\n", p[0]);
4:    printf("%u\n", p[1]);
5:    printf("%u\n", p[2]);
6:    printf("%u\n", p[3]);
7:
8: }
9: int main(){
10:     int *p[4],a=1,b=2,c=3,d=4;
11:
12:    p[1]=&b;
13:    p[2]=&c;
14:    p[3]=&d;
15:    p[0]=&a;
16:    poin(*p);
17:    return 0;
18:}

it shows this output:

1
2686716
2686712
2686708

Process returned 0 (0x0)   execution time : 0.078 s
Press any key to continue.

let's modify the program in line 14 & 15, look at the modified code:

1: #include <stdio.h>
2: int poin(int p[4]){
3: printf("%u\n", p[0]);
4: printf("%u\n", p[1]);
5: printf("%u\n", p[2]);
6: printf("%u\n", p[3]);
7:
8:}
9: int main(){
10: int *p[4],a=1,b=2,c=3,d=4;
11:
12:     p[1]=&b;
13:     p[2]=&c;
14:     p[3]=&a;
15:     p[0]=&d;
16:     poin(*p);
17:     return 0;
18:     }

it shows the following output:

4
3
2
1

Process returned 0 (0x0)   execution time : 0.062 s
Press any key to continue.

please explain me why and how these outputs occured i am very confused and not able to understand the programs

Hash
  • 556
  • 5
  • 17

1 Answers1

1

The both programs have undefined behaviour because it is unspecified how (in which order) the compiler places variables with the automatic storage duration in memory.

But the obtained result for example in the second program can be explained the following way.

It seems that the compiler places the variables a, b, c, d in the order

d, c, b, a

without memory gaps.

So as the function parameter p that has the type int * points to the variable d all the variables after d are outputted.

Take into account that these statements

12:     p[1]=&b;
13:     p[2]=&c;
14:     p[3]=&a;

are even redundant because the function does not access p[1], p[2] and p[3].

It was enough to write

15:     p[0]=&d;

The function does not deal with the array. It deals with the pointer that points to the variables d.

To make this more clear just run the second program the following way

 poin(&d);

Without the initialization of the array elements.

A correct program can look like

1: #include <stdio.h>
2: int poin(int **p ){
3: printf("%u\n", *p[0]);
4: printf("%u\n", *p[1]);
5: printf("%u\n", *p[2]);
6: printf("%u\n", *p[3]);
7:
8:}
9: int main( void ){
10: int *p[4],a=1,b=2,c=3,d=4;
11:
12:     p[1]=&b;
13:     p[2]=&c;
14:     p[3]=&a;
15:     p[0]=&d;
16:     poin(p);
17:     return 0;
18:     }
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • why compiler places d,c,b,a – Hash Jan 25 '18 at 12:56
  • @Hash I have made the conclusing based on the program output. However as I have pointed out it is unsoecified how the compiler can place variables with automatic storage duration. So it is implementation defined. – Vlad from Moscow Jan 25 '18 at 12:57
  • Also undefined behavior to print an `int` with `%u` due to mismatch between conversion specifier and argument type. – ad absurdum Jan 25 '18 at 14:36
  • @DavidBowling There is no undefined behaviour provided that the signed integer value can fit in an unsigned integer. – Vlad from Moscow Jan 25 '18 at 15:24
  • @VladfromMoscow -- a `signed int` value is not converted to `unsigned int` automatically, and [the Standard explicitly says that it is undefined behavior to use conversion specifiers which do not match the type of the associated argument.](http://port70.net/~nsz/c/c11/n1570.html#7.21.6.1p9) `%u` is explicitly for `unsigned int`, and `int` is a different type. – ad absurdum Jan 25 '18 at 16:05
  • @DavidBowling The standard also says that signed int can be used when an unsigned int is accepted provided that the signed int is in the range of unsigned int. – Vlad from Moscow Feb 15 '18 at 12:03
  • @VladfromMoscow -- that is not what the Standard says. It says that ["wherever an 'int' or 'unsigned int' may be used"](http://port70.net/~nsz/c/c11/n1570.html#6.3.1.1p2) an integer type _other than `int` or `unsigned int`_ and with conversion rank less than or equal to the rank of `int` may be used, and that in such a case the value will be converted to an `int` or an `unsigned int`. – ad absurdum Feb 15 '18 at 14:59
  • @DavidBowling As I said a funcvtion that accepts signed int can accept unsigned int provided thyat its value is in the range of signed int. – Vlad from Moscow Feb 16 '18 at 13:21
  • @DavidBowling I have no the Standard at hand now but this question already arised and there is no undefined behavior. – Vlad from Moscow Feb 16 '18 at 13:35
  • @VladfromMoscow -- the rules of integer promotion do not apply here. This is undefined behavior, according to the Standard description of `fprintf()`. Sure, unlikely to be a problem in practice, and maybe a defect in the language of the Standard, but still UB. [See this SO question](https://stackoverflow.com/questions/4664100/does-printfx-1-invoke-undefined-behavior) – ad absurdum Feb 16 '18 at 13:49
  • @DavidBowling There is no the integer promotion. Positive values of signed and unsigned int have the same internal representation provided that they are in the range of signed int. And the Standard says that a function that has a parameter of the type int can accept an object of the type unsigned int provided that the value can be represented in signed int. – Vlad from Moscow Feb 16 '18 at 13:53
  • @DavidBowling As I said this case has nothing common with the integer promotion. – Vlad from Moscow Feb 16 '18 at 14:03
  • @DavidBowling See 6.5.2.2 Function calls, #6) — one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is representable in both types; – Vlad from Moscow Feb 16 '18 at 14:05
  • @VladfromMoscow -- you are missing the point. _You_ mentioned "`signed int` can be used when an `unsigned int` is accepted ", which sounds like it comes from the language of integer promotions in the Standard. I pointed out that integer promotion does not happen here. Glad you agree with this. The whole point of the question I linked to is that `fprintf()` seems to be a fringe case. The consensus there is that it is UB to use a conversion specifier expecting `unsigned` with a `signed` argument, as per the Standard definition of `fprintf()`. Representability does not come into play. – ad absurdum Feb 16 '18 at 14:18