Conversation started May 19, 2020 at 13:01.
May 19, 2020 13:01
@Aladdin if you're really interested there is a good explanation here.
 
2 hours later…
May 19, 2020 15:18
@JohnRennie Thanks!
 
13 hours later…
May 20, 2020 04:22
@JohnRennie Hi
the link has been very useful.I can make some progress because of it
how did u find it
Just luck. I Googled and it came up.
It's a well written article, isn't it?
May 20, 2020 05:16
@JohnRennie Can I ask a doubton this
@Aladdin hi
What's the question?
Hi
I tried working on type of C
My translation is : C is a function returning pointer to array of 4 pointers to array of 7 chars
#include <stdio.h>

char a[4][7] = {"Common", "Point", "Boost", "Better"};
 char (*b[4])[7] = {a+3, a+1, a, a+2};

char (*(*c())[4])[7](void)
{
    return &b;
}
But sadly this gives error
I'm busy with something at the moment I'm afraid. I have a rush job to finish this morning. I should be done in an hour or so.
no worries
 
4 hours later…
May 20, 2020 09:13
@JohnRennie Hello
are u free
@Aladdin hi :-)
Yes I'm free.
@JohnRennie If c return address of b then c()[1] would be first element in array b right?
Wouldn't it be (*c())[1] i.e. you need to derefernce c to get b?
I don't really know to be honest. Type declarations can get very confusing when they get this complicated.
yes
that helps
@JohnRennie I think I am close enough to solve it
Then you've done better than I did when I tried to solve it :-)
May 20, 2020 09:21
ig u didn't try the link which u gave
i think u can easily solve if u follow it
tho i understnd why this question is upsetting
@JohnRennie Btw can u send me outputs of aeroplane from linux
I will include it in my pdf
I had a quick look through that page and it looked a good description, but I wasn't that interested :-)
Let me fire up the Linux box now ...
renniej@H39FC72:~$ ./airport
Default time between the planes arriving is 10 minutes
Enter the new time in minutes or press return to accept the default


Default time for RANDOMNESS  is +/- 15 minutes
Enter the new time in minutes or press return to accept the default

Default number of  refuelling bays is 12 .
Enter the new value for no of refuelling bays or press return to accept the default

Default time for TURAROUND INTERVAL  is +/- 60 minutes
Enter the new time in minutes for Turnaround interval  or press return to accept the default
(I removed the flight listing as it didn't seem to add anything)
Do you want me to try with different parameters?
No this is Ok
but i would need screenshots
o both files and the output
I'm not sure what you mean by a screenshot of the files ...
like when we run the output the data is filled inside the file
just one_two photo would be enough of the data
You mean like:
renniej@H39FC72:~$ more<AirportQueueLengths.txt
Time    Arrivals        Turnaround      Departure
00:00   0       0       0
00:01   0       0       0
00:02   0       0       0
00:03   0       0       0
00:04   0       0       0
00:05   0       0       0
00:06   0       0       0
00:07   0       0       0
00:08   0       0       0
00:09   0       0       0
00:10   0       0       0
00:11   0       0       0
00:12   0       0       0
00:13   0       0       0
00:14   0       0       0
00:15   0       0       0
They are just the same as on Windows ...
May 20, 2020 09:32
Like this
Like that?
yep
ah wait
ur name is there
so ig it won't work then
You could use a bit of creative Photoshopping :-)
Or I could create a user in your name.
can u create with the name:"Abhinav"
But I don't see how this adds anything. Just say it was tried on Ubuntu 20.04LTS and gave the same results.
May 20, 2020 09:36
yea
i think that would be ok
@JohnRennie Do u know how this works:
#include<stdio.h>
int main()
{
    char b[2]="Al";

    printf("%s",&b[0]);
}
b is a char*. When you provide an index this derefences the pointer so b[0] is a char - it's the char 'A'.
So &(b[0]) is the address of the char 'A'.
ah ok
And since 'A' is the first character in the string the address of 'A' is the same as the address of the string i.e. b == &(b[0])
got it
Try this:
#include<stdio.h>
int main()
{
    char b[2]="Al";

    printf("%p %p\n",b, &b[0]);
}
May 20, 2020 09:48
Ah same addresss
May 20, 2020 10:11
the hard part is to understand the sprintf in that puzzle
i am done with everything except that
char* pointer_monster(char (** (*f)())[7])
Have you figured out the type of f?
no
still trying
It gives:
declare f as pointer to function returning pointer to pointer to array 7 of char
Though that's still pretty confusing :-)
I can write it as a type using the description
but I can't understand how to predict the descrption only
looks like this is gonna take a long time
the source code is so big
 
20 hours later…
May 21, 2020 06:20
@JohnRennie Hi
are u free
@Aladdin hi :-)
Yes I'm free
@JohnRennie
#include <stdio.h>

int main()
{

char a[4][7] = {"Common", "Point", "Boost", "Better"};
char (*b[4])[7] = {a+3, a+1, a, a+2};

printf("%s",&b[1]-3);
}
Can u tell why this prints ost
I get a compile error:
D:\rhs\c>cl rat2.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.25.28614 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

rat2.c
rat2.c(9): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'char (**)[7]'
okay.For some reason it prints in online comiler
@JohnRennie Can u tell what &b[1]-3 is gonna be
I think the online compiler is a lot less strict in its type checking.
May 21, 2020 06:29
i can't figure it out
Well b[1] is "Point", isn't it?
yes
pointer to "Point"
Yes. So &b[1] is the address of a pointer to "Point"
yea
but I don't understand what substracting 3 is gonna do
and it's something important
Try it ...
#include <stdio.h>

int main()
{

  char a[4][7] = {"Common", "Point", "Boost", "Better"};
  char (*b[4])[7] = {a+3, a+1, a, a+2};

  printf("b = %p\n",b);
  printf("&b[1] = %p\n",&b[1]);
  printf("&b[1]-3 = %p\n",&b[1]-3);
}
I get:
D:\rhs\c>rat2
b = 00CFFB9C
&b[1] = 00CFFBA0
&b[1]-3 = 00CFFB94
May 21, 2020 06:35
I didn't get
&b[1] has type pointer to pointer, and a pointer has 4 bytes (because it's a 32 bit address). So when you subtract 3 from &b[1] you are subtracting 3 pointers i.e. 12 bytes.
And 00CFFBA0 - 12 bytes = 00CFFB94
oh
so is it address f pointer to pointer of mon?
No. It points to an address that is 8 bytes before the array starts i.e. it points to some random junk.
&b[1] points to "Point" so &b[1]-1 points to "Common" and &b[1]+1 points to "Boost"
i didn't get how &b[1]-1 points to common
&b[1]-3 would point to two strings before "Common", but of course those two strings don't exist.
May 21, 2020 06:42
i think it is something to do with the 2d array
how to represent common point boost monster in 2d
Lets start with:
char a[4][7] = {"Common", "Point", "Boost", "Better"};
This is just a 2D array. C will arrange this as 4 x 7 = 28 sequetial bytes in memory i.e. if we looked at the bytes in the memory we would see:
Common0Point00Boost00Better0
0123456012345601234560123456
OK so far?
Ok
why 0 repeats
and other number
i didn't get this
The strings are all 7 characters long, so if the word is 6 characters long, like "Common", it gets padded to 7 bytes with one '\0' character.
If the word is 5 characters long it gets padded to 7 bytes with two '\0' characters.
I've used 0123456 to indicate the 7 characters in each string.
Ok
so it's 0123456
then again 0123456
is this a way of indicating two different strings
Suppose the first byte of all this data was at address 100, then the address of the four strings in a would be:
Common0Point00Boost00Better0
0123456012345601234560123456
^      ^      ^      ^
100    107    114    121
So the first string starts at 100, the second at 100+7, the third at 100+2*7 and the last at 100+3*7
(all numbers are in decimal)
May 21, 2020 06:51
yes
Now b is an array of four pointers. Yes?
Now, when you add an integer to a pointer in C it doesn't just add the number to the pointer.
It takes the number, multiplies it by sizeof() of the type that the pointer points to.
e.g.
If you have char* x and x = 100 then x+1 = 101 because sizeof(char) = 1.
If you have int* x and x = 100 then x+1 = 104 because sizeof(int) = 4.
OK so far?
In this case a[i][j] is a char so a[i] is a char*.
But the size of a is a[4][7] i.e. a[i] is a pointer to a string of length 7.
May 21, 2020 06:57
yes
So if a = 100 then a+1 = 107
Because the compile knows that the strings in a have length 7
Likewise a+2 = 114 abd a+3 = 121
Common0Point00Boost00Better0
0123456012345601234560123456
^      ^      ^      ^
100    107    114    121
a      a+1    a+2    a+3
OK so far?
Now lets look at b:
char (*b[4])[7] = {a+3, a+1, a, a+2};
You are declaring b as an array of 4 pointers.
May 21, 2020 06:59
yes
So substituting for a+3 etc in the declaration of b we get:
char (*b[4])[7] = {121, 107, 100, 114};
That's what the values of the four pointers in b would be.
OK so far?
ah i see
writing like this makes it so clearer
The array b is stored in memory as 16 bytes i.e. four pointers of four bytes each. Suppose the address of the first byte of memory that stores b is 200, then the 16 bytes of memory would contain:
200:  121
204:  107
208:  100
212:  114
how did u know it's 4 bytes
Pointers are an address of some memory. Yes?
May 21, 2020 07:06
yes
And in 32 bit programs addresses are always 32 bits i.e. 4 bytes.
aha ok
So in this example b = 200, *b is the contents of b i.e. 121, and **b would be the contents of the address 121 i.e. the first character of "Better".
OK so far?
i had a doubt
Yes ... ?
May 21, 2020 07:10
when we do char a[6]+"Hello" then a is a address of hello
so when b is array of 4 pointers then b is address of 1st pointer
ie 200 right?
ok then it's clear
So shall we look at what &b[1] is?
let me guess
b[1] isaddress of string "Point" ie107
so address o 107 is 204
that's what &b[1] is right?
Correct! :-) the numeric value of &b[1] is 204.
So what is &b[1]-3 ?
May 21, 2020 07:15
204-3*4=192
Yes, exactly. But the array b starts at address 200.
so it's a junk value
So address 192 is some other bit of memory that could store anything.
@Aladdin yes
ok finally some progress
One last question for you, what would be the numeric value of b[1]+1 ?
NB b[1]+1 not &b[1]+1
May 21, 2020 07:21
b[1] is 107
Yes ...
so b[1]+1 will be 111?
b[1] is a pointer. What type does it point to?
pointer
pointer to what type?
Hint:
char (*b[4])[7]
May 21, 2020 07:23
string of 7 chars
Yes! b[1] points to an object that has size 7 because it's a 7 character string.
So if b[1] = 107 then b[1]+1 = b[1] + 1 * 7 = 114
Ah b is array of pointer
so if pointer points to 107
then the next pointer points to 114
i see it
Only because the compiler knows that b is an array of pointers to char[7].
okay
This is why the declarations get complicated. b is basically just a pointer to pointer to chat i.e. a char**.
But ...
For the pointer addition to work you have to tell the compiler that b is a actually a pointer to a pointer to a seven character string.
Hence char (*b[4])[7]
May 21, 2020 07:29
yeah got it
never knew pointers were these shady
:-)
That's the whole point of the puzzle. It's intended to help you understand more about pointers.
But in real C programming it never gets as complicated as this.
The puzzle is a deliberately overcomplicated example.
yes
I agree
May 21, 2020 08:00
@JohnRennie I had a doubt
&b[1]-3 is 192 like we discussed
so if we do 192[3] it will give address of pointer pointing to pointer right?
(&b[1]-3)[3] would be a char*. Yes?
The way to look at this is that x[i] is basically the same as *(x+i)
where we are using pointer arithematic i.e. adding i to x actually adds i times the size of the data type in x.
So b[1] = *(b+1*sizeof(pointer))
And & does the opposite of * so &b[1] = b + 1*sizeof(pointer)
May 21, 2020 08:07
size is 7
b contains pointers
So &b[1]-3 = b + 1*sizeof(pointer) - 3*sizeof(pointer) = b - 2*sizeof(pointer)
That's why in my example when b = 200 then &b[1]-3 = 200 - 2*4 = 192
And (&b[1]-3)[3] is *((&b[1]-3) + 3*sizeof(pointer))
So it ends up as the contents of b + sizeof(pointer)
i.e. it's b[1].
ok
dereferencing b[1] will give pointer
Try it. Write the code and see what happens.
May 21, 2020 08:13
ok
i will have to try in online compiler
@JohnRennie Yeah
For quick programs you can use VS from the command prompt.
it gives Point
That's what I usually do.
i don't know how to use vs from cmd
Didn't we set this up?
You open a command prompt, cd your way to where the C files are kept then run msvcsetup.bat.
May 21, 2020 08:16
i forgot about this
let me run msvcsetup.bat
ah it ran
so i can code normally here
what to do after writing msvcsetup
Use Notepad or whatever you want to create the .c file then use the command:
cl example.c
to compile it.
Like that
stuck after this
Now just type pointer to run the program.
May 21, 2020 08:24
ah yea it compiled
*b[1] gives point
so that solves our first sprintf
What cl pointer.c does is to take the code in pointer.c and compile it to produce the executable file pointer.exe. Then to run the program type pointer - Windows assumes you mean pointer.exe so you don't have to type the .exe (though you can if you want).
Compiling this way is a lot quicker than using the Visual Studio IDE, though if you have more than one .c file it quickly gets complicated.
May 21, 2020 08:49
@JohnRennie Do u know about dererencing function pointer
the second sprintf is using it and I have no idea about it
I'm on the phone ...
oh sorry
May 21, 2020 09:11
@Aladdin hi :-)
Hello
You actually used function pointers. Remember when we used the qsort function?
For that you have to write the compar() function then pass it to qsort as a pointer.
May 21, 2020 09:14
I wonder if I can come with some code to show this. Give me a couple of minutes ...
Try this:
#include <stdio.h>

/* Example function that just doubles its argument */
int bar(int i)
{
  return 2*i;
}

/* foo takes the function it is passed and applies it to the integer
and returns the result */
int foo(int i, int (*bar)(int))
{
  return bar(i);
}

int main()
{
  printf("foo(2) returned %d\n", foo(2, bar));
}
it says f00(2) returned 4
u used bar as a pointer
Yes. main calls foo(2, bar) i.e. it passes the integer 2 an the function bar to the function foo.
when i changed the function to this:
#include <stdio.h>

/* Example function that just doubles its argument */
int bar(int i)
{
  return 2*i;
}

/* foo takes the function it is passed and applies it to the integer
and returns the result */
int foo(int i, int (*bar)(int))
{
  return (***bar)(i);
}

int main()
{
  printf("foo(2) returned %d\n", foo(2, bar));
}
It still gave the same result
May 21, 2020 09:24
Hmm, so it does. OK, I'm officially surprised by that.
Ah, the post you linked says that * doesn't do anything for functions i.e. you can't have a pointer to a pointer to a function.
I wonder how you declare an array of functions ...
/* Example function that doubles its argument */
int bar0(int i)
{
  return 2*i;
}

/* Example function that triples its argument */
int bar1(int i)
{
  return 3*i;
}

/* foo takes the function it is passed and applies it to the integer
and returns the result */
int foo(int i, int (*fn)(int))
{
  return (fn)(i);
}

int main()
{
  int (*bar[2])(int) = {bar0, bar1};

  printf("foo(2, bar[0]) returned %d\n", foo(2, bar[0]));
  printf("foo(2, bar[1]) returned %d\n", foo(2, bar[1]));
}
This gives:
D:\rhs\c>rat3
foo(2, bar[0]) returned 4
foo(2, bar[1]) returned 6
I have never used function arrays.How do they work
Neither had I :-)
I find it hard to see where you would actually do this in real code.
Ah okay
May 21, 2020 09:33
I was just curious to see if it worked.
The question is can I pass the array to foo rather than a function ...
Amazingly, this works:
int foo(int i, int (*fn[2])(int))
{
  return (fn[0])(i)*fn[1](i);
}

int main()
{
  int (*bar[2])(int) = {bar0, bar1};

  printf("foo(2, bar) returned %d\n", foo(2, bar));
}
D:\rhs\c>rat3
foo(2, bar) returned 24
This also works:
int foo(int i, int (*fn[2])(int))
{
  return (*(fn+0))(i)*(*(fn+1))(i);
}
Ah though I have no idea ehy
Me neither! :-)
Actually it's not that complicated.
The functions bar0 and bar1 have type int bar0(int i).
So if you're passing these to a function you need the type of the argument to be:
int foo(int i, int (*fn)(int))
OK so far?
May 21, 2020 09:43
And you turn this into an array just by adding the []
So:
int foo(int i, int (*fn[2])(int))
The second argument is an array of int (*fn)(int) of size 2.
fn is a array of 2 pointers to function of int argument returning int
the link helps
tho u passed the array name
to the function
When you're unsure it's always worth trying some code to see what happens. VS is pretty good at warning you if you haven't got the types correct.
@JohnRennie I had a doubt
Yes ... ?
188[0] will give junk value
but can we modify 188[0]+ x to point to the any string
May 21, 2020 09:59
You mean in my example where I had b starting at address 200?
Yes. 188 is b-3 i.e. b - 3*sizeof(pointer).
So if you add 3 to it you'll get back to b
ah yes
thanks a lot!
So &188[0] + 3 would be the same as b
if i do:
*(188[0]+3)
then it will equivalent to a+3
May 21, 2020 10:04
No
no the string to a+3
188[0] is the same as *(188+0) i.e. it evaulates to the pointer stored at memory location 188, and that's a junk value.
So 188[0]+3 will be junkvalue + 3*sizeof(pointer)
yes
that will give b
No. &188[0] + 3 gives b.
Without the & i.e. 188[0] + 3 we get a junk value.
May 21, 2020 10:20
Ah i got it
it's actually (*188)[0]
*(188)[0]+x
can we get any string from evaluating this
if not then i don't know what to do
I've lost track of what you are asking. Where did the 188 come from?
len += sprintf(buf + len, "%s ", *((**f)()-1)[0]+/* ? */);
where f() returns: return c()[1] - 3;
and function c is:
char (*(*c())[4])[7]
{
    return &b;
}
so f() returns &b[1]-3 which is b-2*sizeof(pointer)
therefore (**f)()-1=f()-1=b-3*sizeof(pointer)
the first sprintf prints Point
so i think this sprintf prits "er"
making it pointer
If you get it working it prints "Pointer Monster" so it makes sense that having printed "Point" the next line would print "er".
May 21, 2020 10:53
And I got stuck..
 
Conversation ended May 21, 2020 at 10:53.