Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #98017 > unrolled thread

Understanding the program that has pointers to two_dimensional arrays

Started byAlla _ <modelling.data@gmail.com>
First post2016-12-05 07:45 -0800
Last post2016-12-05 12:50 -0500
Articles 20 on this page of 23 — 5 participants

Back to article view | Back to comp.lang.c


Contents

  Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-05 07:45 -0800
    Re: Understanding the program that has pointers to two_dimensional arrays Richard Heathfield <rjh@cpax.org.uk> - 2016-12-05 17:03 +0000
      Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-05 09:43 -0800
        Re: Understanding the program that has pointers to two_dimensional arrays Richard Heathfield <rjh@cpax.org.uk> - 2016-12-05 18:16 +0000
          Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-05 22:46 -0800
            Re: Understanding the program that has pointers to two_dimensional arrays Richard Heathfield <rjh@cpax.org.uk> - 2016-12-06 10:23 +0000
              Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-06 02:53 -0800
                Re: Understanding the program that has pointers to two_dimensional arrays Richard Heathfield <rjh@cpax.org.uk> - 2016-12-06 10:58 +0000
                  Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-06 03:42 -0800
                  Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-06 06:31 -0800
                    Re: Understanding the program that has pointers to two_dimensional arrays Richard Heathfield <rjh@cpax.org.uk> - 2016-12-06 14:49 +0000
                      Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-06 08:22 -0800
                        Re: Understanding the program that has pointers to two_dimensional arrays Richard Heathfield <rjh@cpax.org.uk> - 2016-12-06 16:48 +0000
                          Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-06 09:15 -0800
            Re: Understanding the program that has pointers to two_dimensional arrays Keith Thompson <kst-u@mib.org> - 2016-12-06 08:20 -0800
          Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-05 22:53 -0800
    Re: Understanding the program that has pointers to two_dimensional arrays Keith Thompson <kst-u@mib.org> - 2016-12-05 09:26 -0800
      Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-05 09:47 -0800
        Re: Understanding the program that has pointers to two_dimensional arrays Keith Thompson <kst-u@mib.org> - 2016-12-05 12:10 -0800
      Re: Understanding the program that has pointers to two_dimensional arrays Alla _ <modelling.data@gmail.com> - 2016-12-05 10:00 -0800
      Re: Understanding the program that has pointers to two_dimensional arrays Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-05 19:11 +0000
        Re: Understanding the program that has pointers to two_dimensional arrays Keith Thompson <kst-u@mib.org> - 2016-12-05 12:21 -0800
    Re: Understanding the program that has pointers to two_dimensional arrays "James R. Kuyper" <jameskuyper@verizon.net> - 2016-12-05 12:50 -0500

Page 1 of 2  [1] 2  Next page →


#98017 — Understanding the program that has pointers to two_dimensional arrays

FromAlla _ <modelling.data@gmail.com>
Date2016-12-05 07:45 -0800
SubjectUnderstanding the program that has pointers to two_dimensional arrays
Message-ID<481da833-61f6-4f1c-973b-1b129118c682@googlegroups.com>
Hello!

Please, take a look at my reading of the program (in comments to each statement) 
that uses pointers to two-dimensional  arrays. Is my understanding correct, i.e. do 
correctly interpret the given code? And, please, help me to understand one part closer 
to the end of the program. 


#include <stdio.h>
#include <stdlib.h>
      int main(void)
    {
       // define the number of rows and columns             
              int nrows = 5; 
              int ncols = 10; 
              int row;

      // initialise a pointer, which points to a pointer, which, in turn, points to type int,
      // i.e. stores the address of an integer value
              int **rowptr;
     
  /*** define rowptr pointer by assigning to it the value of the address of the array,
         allocated by the call to malloc for nrows (5 in this case) pointers to type int; 
         therefore the value of the rowptr after the call to malloc will be the address, 
         at which the first element in the array of pointers to integer type could be stored;
          of course, none of these pointers yet point anywhere 
  ***/
    
              rowptr = malloc(nrows * sizeof(int *));

        /** check of the memory has been allocated; if not, print the info message,
            and exit **/
         if (rowptr == NULL)
         {
                    puts("\nFailure to allocate room for row pointers.\n");
                   exit(0);
         }

        // Print the title
         printf("\n\n\nIndex Pointer(hex) Pointer(dec) Diff.(dec)");

         /** Allocate memory for an array of ncols integers for every row, and store the value of the 
             allocated address of the first element of each array at the pointer rowptr[row],
             such that rowptr[row] now points to corresponding address of the first element 
             in the array of ncols integers **/

         for (row = 0; row < nrows; row++)
          {
                      rowptr[row] = malloc(ncols * sizeof(int));

                   /** check of the memory has been allocated; if not, print the info message,
                     and exit **/
                     if (rowptr[row] == NULL)
                    {
                                 printf("\nFailure to allocate for row[%d]\n",row);
                                 exit(0);
                    }

          /** Here is the difficult part: print the number of the current row "row",
                print the hexadecimal address of the pointer that now has the value
                of the address of the first element of the array of integers; 
                and the third element should the same address of the pointer
                but its decimal value; 

                When I tried to compile this, I have received an error message,
         which I solved by casting (void *) to the first call to rowptr[row]
         (see my new printf below the original one), which is specified 
         by %p; but I can't solve the second error message (see below) 
         and I don't understand why the author has not mentioned anything
         about it:
         error: format specifies type 'int' but the argument has
         type 'int *' [-Werror,-Wformat]
         printf("\n%d %p %d", row, rowptr[row], rowptr[row]);
                         ~~                     ^~~~~~~~~~~
         
         **/

               /** original printf function:   
                   printf("\n%d %p %d", row, rowptr[row], rowptr[row]);  **/

               // partially corrected printf
                 printf("\n%d %p %d", row, (void *)rowptr[row], rowptr[row]);
                
               /** print the difference between the value of addresses of each row **/
                       
                  if (row > 0)
                             printf(" %d",(int)(rowptr[row] - rowptr[row-1]));
          }
              return 0;
    }

Thank you very much!

[toc] | [next] | [standalone]


#98024

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-12-05 17:03 +0000
Message-ID<o246iv$8m7$1@dont-email.me>
In reply to#98017
On 05/12/16 15:45, Alla _ wrote:
>
> Hello!
>
> Please, take a look at my reading of the program (in comments to each statement)
> that uses pointers to two-dimensional  arrays.

No, it doesn't. Not at any point. What it does use is a pointer to 
pointer to int, which you point at the beginning of storage suitable for 
storing several int * objects. And those int * are used for pointing at 
the beginning of storage that is suitable for storing several int objects.

> Is my understanding correct, i.e. do
> correctly interpret the given code? And, please, help me to understand one part closer
> to the end of the program.
>
>
> #include <stdio.h>
> #include <stdlib.h>
>       int main(void)
>     {
>        // define the number of rows and columns
>               int nrows = 5;
>               int ncols = 10;
>               int row;
>
>       // initialise a pointer, which points to a pointer, which, in turn, points to type int,
>       // i.e. stores the address of an integer value
>               int **rowptr;

Yes, rowptr is suitable for pointing to objects of type int *, which are 
in turn suitable to pointing to objects of type int.

>   /*** define rowptr pointer

No, it's already defined. What you're about to do is assign to it.

> by assigning to it the value of the address of the array,
>          allocated by the call to malloc for nrows (5 in this case) pointers to type int;

That's one way to say it, yes. You are asking for enough storage to 
store 5 objects of type int *.

>          therefore the value of the rowptr after the call to malloc will be the address,
>          at which the first element in the array of pointers to integer type could be stored;
>           of course, none of these pointers yet point anywhere
>   ***/

Correct.

>
>               rowptr = malloc(nrows * sizeof(int *));

Better: rowptr = malloc(nrows * sizeof *rowptr);

which will still be correct even if you later change the type of rowptr.

>
>         /** check of the memory has been allocated; if not, print the info message,
>             and exit **/
>          if (rowptr == NULL)
>          {
>                     puts("\nFailure to allocate room for row pointers.\n");
>                    exit(0);
>          }

Yes. Not /quite/ how I would do it, but you are correctly checking that 
the storage allocation request succeeded. If it didn't, you have to take 
evasive action. Terminating the program, as you are doing, is generally 
acceptable in student code.

>         // Print the title
>          printf("\n\n\nIndex Pointer(hex) Pointer(dec) Diff.(dec)");
>
>          /** Allocate memory for an array of ncols integers for every row, and store the value of the
>              allocated address of the first element of each array at the pointer rowptr[row],
>              such that rowptr[row] now points to corresponding address of the first element
>              in the array of ncols integers **/

Yes.

>
>          for (row = 0; row < nrows; row++)
>           {
>                       rowptr[row] = malloc(ncols * sizeof(int));

Better: rowptr[row] = malloc(ncols * sizeof *rowptr[row]);

>
>                    /** check of the memory has been allocated; if not, print the info message,
>                      and exit **/
>                      if (rowptr[row] == NULL)
>                     {
>                                  printf("\nFailure to allocate for row[%d]\n",row);
>                                  exit(0);
>                     }

Yes, that's fine.

>           /** Here is the difficult part: print the number of the current row "row",
>                 print the hexadecimal address of the pointer that now has the value
>                 of the address of the first element of the array of integers;
>                 and the third element should the same address of the pointer
>                 but its decimal value;
>
>                 When I tried to compile this, I have received an error message,
>          which I solved by casting (void *)

If the compiler is complaining that int * doesn't match void * in a call 
to printf, then the cast is (saints preserve us) actually correct! This 
is one of the very, very, very few times that a cast is not a completely 
hopeless idea.

> to the first call to rowptr[row]
>          (see my new printf below the original one), which is specified
>          by %p; but I can't solve the second error message (see below)
>          and I don't understand why the author has not mentioned anything
>          about it:
>          error: format specifies type 'int' but the argument has
>          type 'int *' [-Werror,-Wformat]
>          printf("\n%d %p %d", row, rowptr[row], rowptr[row]);
>                          ~~                     ^~~~~~~~~~~
>
>          **/
>
>                /** original printf function:
>                    printf("\n%d %p %d", row, rowptr[row], rowptr[row]);  **/

What is this horrible thing you are doing? \n is a line end character, 
not a line beginning character! Ouch eek ow ow bad! (It's not against 
the rules or anything. It just shows a complete disregard for the 
semantics of \n.)

>
>                // partially corrected printf
>                  printf("\n%d %p %d", row, (void *)rowptr[row], rowptr[row]);

You have been asked to do something too difficult. It's not impossible, 
of course, but it's difficult.

Printing the address with %p is correct. But /how/ it is printed is 
entirely up to the implementation. For example, on one early system it 
might print something like "DS:04E0", which is part-hexadecimal and 
part-abbreviation.

If you want to print it in hexadecimal (and then decimal), you're going 
to need to get to the object representation of the pointer value. And 
/that/ is a major distraction from learning about pointers to pointers.

>
>                /** print the difference between the value of addresses of each row **/
>
>                   if (row > 0)
>                              printf(" %d",(int)(rowptr[row] - rowptr[row-1]));

And that's just broken. rowptr[row] and rowptr[row - 1] point to 
different areas of memory. The subtraction invokes undefined behaviour. 
What book is this, and why haven't you burned it yet? What happened to 
your reading of K&R?

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#98030

FromAlla _ <modelling.data@gmail.com>
Date2016-12-05 09:43 -0800
Message-ID<a9a728fd-cc8e-4b08-aabd-6877015ef5f8@googlegroups.com>
In reply to#98024
On Monday, December 5, 2016 at 8:03:57 PM UTC+3, Richard Heathfield wrote:
> On 05/12/16 15:45, Alla _ wrote:
> >
> > Hello!
> >
> > Please, take a look at my reading of the program (in comments to each statement)
> > that uses pointers to two-dimensional  arrays.
> 
> No, it doesn't. Not at any point. What it does use is a pointer to 
> pointer to int, which you point at the beginning of storage suitable for 
> storing several int * objects. And those int * are used for pointing at 
> the beginning of storage that is suitable for storing several int objects.
> 
> > Is my understanding correct, i.e. do
> > correctly interpret the given code? And, please, help me to understand one part closer
> > to the end of the program.
> >
> >
> > #include <stdio.h>
> > #include <stdlib.h>
> >       int main(void)
> >     {
> >        // define the number of rows and columns
> >               int nrows = 5;
> >               int ncols = 10;
> >               int row;
> >
> >       // initialise a pointer, which points to a pointer, which, in turn, points to type int,
> >       // i.e. stores the address of an integer value
> >               int **rowptr;
> 
> Yes, rowptr is suitable for pointing to objects of type int *, which are 
> in turn suitable to pointing to objects of type int.
> 
> >   /*** define rowptr pointer
> 
> No, it's already defined. What you're about to do is assign to it.
> 
> > by assigning to it the value of the address of the array,
> >          allocated by the call to malloc for nrows (5 in this case) pointers to type int;
> 
> That's one way to say it, yes. You are asking for enough storage to 
> store 5 objects of type int *.
> 
> >          therefore the value of the rowptr after the call to malloc will be the address,
> >          at which the first element in the array of pointers to integer type could be stored;
> >           of course, none of these pointers yet point anywhere
> >   ***/
> 
> Correct.
> 
> >
> >               rowptr = malloc(nrows * sizeof(int *));
> 
> Better: rowptr = malloc(nrows * sizeof *rowptr);
> 
> which will still be correct even if you later change the type of rowptr.
> 
> >
> >         /** check of the memory has been allocated; if not, print the info message,
> >             and exit **/
> >          if (rowptr == NULL)
> >          {
> >                     puts("\nFailure to allocate room for row pointers.\n");
> >                    exit(0);
> >          }
> 
> Yes. Not /quite/ how I would do it, but you are correctly checking that 
> the storage allocation request succeeded. If it didn't, you have to take 
> evasive action. Terminating the program, as you are doing, is generally 
> acceptable in student code.
> 
> >         // Print the title
> >          printf("\n\n\nIndex Pointer(hex) Pointer(dec) Diff.(dec)");
> >
> >          /** Allocate memory for an array of ncols integers for every row, and store the value of the
> >              allocated address of the first element of each array at the pointer rowptr[row],
> >              such that rowptr[row] now points to corresponding address of the first element
> >              in the array of ncols integers **/
> 
> Yes.
> 
> >
> >          for (row = 0; row < nrows; row++)
> >           {
> >                       rowptr[row] = malloc(ncols * sizeof(int));
> 
> Better: rowptr[row] = malloc(ncols * sizeof *rowptr[row]);
> 
> >
> >                    /** check of the memory has been allocated; if not, print the info message,
> >                      and exit **/
> >                      if (rowptr[row] == NULL)
> >                     {
> >                                  printf("\nFailure to allocate for row[%d]\n",row);
> >                                  exit(0);
> >                     }
> 
> Yes, that's fine.
> 
> >           /** Here is the difficult part: print the number of the current row "row",
> >                 print the hexadecimal address of the pointer that now has the value
> >                 of the address of the first element of the array of integers;
> >                 and the third element should the same address of the pointer
> >                 but its decimal value;
> >
> >                 When I tried to compile this, I have received an error message,
> >          which I solved by casting (void *)
> 
> If the compiler is complaining that int * doesn't match void * in a call 
> to printf, then the cast is (saints preserve us) actually correct! This 
> is one of the very, very, very few times that a cast is not a completely 
> hopeless idea.
> 
> > to the first call to rowptr[row]
> >          (see my new printf below the original one), which is specified
> >          by %p; but I can't solve the second error message (see below)
> >          and I don't understand why the author has not mentioned anything
> >          about it:
> >          error: format specifies type 'int' but the argument has
> >          type 'int *' [-Werror,-Wformat]
> >          printf("\n%d %p %d", row, rowptr[row], rowptr[row]);
> >                          ~~                     ^~~~~~~~~~~
> >
> >          **/
> >
> >                /** original printf function:
> >                    printf("\n%d %p %d", row, rowptr[row], rowptr[row]);  **/
> 
> What is this horrible thing you are doing? \n is a line end character, 
> not a line beginning character! Ouch eek ow ow bad! (It's not against 
> the rules or anything. It just shows a complete disregard for the 
> semantics of \n.)
> 
> >
> >                // partially corrected printf
> >                  printf("\n%d %p %d", row, (void *)rowptr[row], rowptr[row]);
> 
> You have been asked to do something too difficult. It's not impossible, 
> of course, but it's difficult.
> 
> Printing the address with %p is correct. But /how/ it is printed is 
> entirely up to the implementation. For example, on one early system it 
> might print something like "DS:04E0", which is part-hexadecimal and 
> part-abbreviation.
> 
> If you want to print it in hexadecimal (and then decimal), you're going 
> to need to get to the object representation of the pointer value. And 
> /that/ is a major distraction from learning about pointers to pointers.
> 
> >
> >                /** print the difference between the value of addresses of each row **/
> >
> >                   if (row > 0)
> >                              printf(" %d",(int)(rowptr[row] - rowptr[row-1]));
> 
> And that's just broken. rowptr[row] and rowptr[row - 1] point to 
> different areas of memory. The subtraction invokes undefined behaviour. 
> What book is this, and why haven't you burned it yet? What happened to 
> your reading of K&R?

Thank you very very much! Nothing has happened to my reading K&R; 
I had a disastrous time in terms of learning C because I couldn't allocate
( :D ) time for it due to certain obligations; given my love to C, it was very
difficult not to continue with a proper learning process. Now, to refresh what 
I have already learned, I have found this thing, which, although not good, has
 helped me, and it is based on K&R. I did notice those non-elegant semantics, 
and have corrected them within my code, as well as deleting all global variables 
the author is using. Also it raises interesting issues, part of which are covered
in the this code. 
I also have to write a student's program within 2 weeks. So, I have to work
on this program, K&R and one more book on C, which is based on K&R, but
is more detailed and might be of a great help: 
 C: How to Program by Deitel and Deitel
I hope it will help me to understand the material better, and hopefully to do
all K&R exercises. 

[toc] | [prev] | [next] | [standalone]


#98034

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-12-05 18:16 +0000
Message-ID<o24ar4$pir$1@dont-email.me>
In reply to#98030
On 05/12/16 17:43, Alla _ wrote:

<snip>

> I also have to write a student's program within 2 weeks.

If you spent less time on these C courses, you might have time to learn 
C properly.

> So, I have to work
> on this program, K&R and one more book on C, which is based on K&R, but
> is more detailed and might be of a great help:
>  C: How to Program by Deitel and Deitel
> I hope it will help me to understand the material better, and hopefully to do
> all K&R exercises.

Deitel and Deitel is a reasonable book. Or at least I thought it was. 
Are you telling me the example code came from that book? If so, Deitel 
and Deitel have gone catastrophically downhill.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#98126

FromAlla _ <modelling.data@gmail.com>
Date2016-12-05 22:46 -0800
Message-ID<e4ceb105-96f5-428b-8fd6-28fc20b28eab@googlegroups.com>
In reply to#98034
On Monday, December 5, 2016 at 9:16:27 PM UTC+3, Richard Heathfield wrote:
> On 05/12/16 17:43, Alla _ wrote:
> 
> <snip>
> 
> > I also have to write a student's program within 2 weeks.
> 
> If you spent less time on these C courses, you might have time to learn 
> C properly.
> 
> > So, I have to work
> > on this program, K&R and one more book on C, which is based on K&R, but
> > is more detailed and might be of a great help:
> >  C: How to Program by Deitel and Deitel
> > I hope it will help me to understand the material better, and hopefully to do
> > all K&R exercises.
> 
> Deitel and Deitel is a reasonable book. Or at least I thought it was. 
> Are you telling me the example code came from that book? If so, Deitel 
> and Deitel have gone catastrophically downhill.
> 
No no no, this example is not from that book, I have not yet started it. This example is from
a tiny (53 pages) book on pointers, dating from 1997 or so. 

[toc] | [prev] | [next] | [standalone]


#98135

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-12-06 10:23 +0000
Message-ID<o263g7$v6m$1@dont-email.me>
In reply to#98126
On 06/12/16 06:46, Alla _ wrote:
> On Monday, December 5, 2016 at 9:16:27 PM UTC+3, Richard Heathfield wrote:
>> On 05/12/16 17:43, Alla _ wrote:
>>
>> <snip>
>>
>>> I also have to write a student's program within 2 weeks.
>>
>> If you spent less time on these C courses, you might have time to learn
>> C properly.
>>
>>> So, I have to work
>>> on this program, K&R and one more book on C, which is based on K&R, but
>>> is more detailed and might be of a great help:
>>>  C: How to Program by Deitel and Deitel
>>> I hope it will help me to understand the material better, and hopefully to do
>>> all K&R exercises.
>>
>> Deitel and Deitel is a reasonable book. Or at least I thought it was.
>> Are you telling me the example code came from that book? If so, Deitel
>> and Deitel have gone catastrophically downhill.
>>
> No no no, this example is not from that book, I have not yet started it. This example is from
> a tiny (53 pages) book on pointers, dating from 1997 or so.

That, at least, is a relief. Now that you know the book is seriously 
flawed, do you plan to continue using it?

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#98136

FromAlla _ <modelling.data@gmail.com>
Date2016-12-06 02:53 -0800
Message-ID<6b66b016-96d7-4c7e-856f-2942ca012384@googlegroups.com>
In reply to#98135
On Tuesday, December 6, 2016 at 1:23:28 PM UTC+3, Richard Heathfield wrote:
> On 06/12/16 06:46, Alla _ wrote:
> > On Monday, December 5, 2016 at 9:16:27 PM UTC+3, Richard Heathfield wrote:
> >> On 05/12/16 17:43, Alla _ wrote:
> >>
> >> <snip>
> >>
> >>> I also have to write a student's program within 2 weeks.
> >>
> >> If you spent less time on these C courses, you might have time to learn
> >> C properly.
> >>
> >>> So, I have to work
> >>> on this program, K&R and one more book on C, which is based on K&R, but
> >>> is more detailed and might be of a great help:
> >>>  C: How to Program by Deitel and Deitel
> >>> I hope it will help me to understand the material better, and hopefully to do
> >>> all K&R exercises.
> >>
> >> Deitel and Deitel is a reasonable book. Or at least I thought it was.
> >> Are you telling me the example code came from that book? If so, Deitel
> >> and Deitel have gone catastrophically downhill.
> >>
> > No no no, this example is not from that book, I have not yet started it. This example is from
> > a tiny (53 pages) book on pointers, dating from 1997 or so.
> 
> That, at least, is a relief. Now that you know the book is seriously 
> flawed, do you plan to continue using it?
> 
I am done with that book, as I have said yesterday - it served its purpose, and that's it;
I don't need it anymore ) I have K&R and Deitel books. 

[toc] | [prev] | [next] | [standalone]


#98137

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-12-06 10:58 +0000
Message-ID<o265hg$3i7$4@dont-email.me>
In reply to#98136
On 06/12/16 10:53, Alla _ wrote:
> On Tuesday, December 6, 2016 at 1:23:28 PM UTC+3, Richard Heathfield wrote:
>> On 06/12/16 06:46, Alla _ wrote:
>>> On Monday, December 5, 2016 at 9:16:27 PM UTC+3, Richard Heathfield wrote:
>>>> Deitel and Deitel is a reasonable book. Or at least I thought it was.
>>>> Are you telling me the example code came from that book? If so, Deitel
>>>> and Deitel have gone catastrophically downhill.
>>>>
>>> No no no, this example is not from that book, I have not yet started it. This example is from
>>> a tiny (53 pages) book on pointers, dating from 1997 or so.
>>
>> That, at least, is a relief. Now that you know the book is seriously
>> flawed, do you plan to continue using it?
>>
> I am done with that book, as I have said yesterday - it served its purpose, and that's it;
> I don't need it anymore )

You didn't need it before, either.

You need to get out of your head the idea that "this book is about C, 
therefore this book is good". Most books about C are written by people 
who don't know C terribly well.

> I have K&R and Deitel books.

For learning C, those two are sufficient. Please don't confuse yourself 
by getting any more, not until you've learned the language well enough 
not to be confused by wrong information.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#98142

FromAlla _ <modelling.data@gmail.com>
Date2016-12-06 03:42 -0800
Message-ID<2a862878-be53-43ba-848a-f59943da580d@googlegroups.com>
In reply to#98137
On Tuesday, December 6, 2016 at 1:58:15 PM UTC+3, Richard Heathfield wrote:
> On 06/12/16 10:53, Alla _ wrote:
> > On Tuesday, December 6, 2016 at 1:23:28 PM UTC+3, Richard Heathfield wrote:
> >> On 06/12/16 06:46, Alla _ wrote:
> >>> On Monday, December 5, 2016 at 9:16:27 PM UTC+3, Richard Heathfield wrote:
> >>>> Deitel and Deitel is a reasonable book. Or at least I thought it was.
> >>>> Are you telling me the example code came from that book? If so, Deitel
> >>>> and Deitel have gone catastrophically downhill.
> >>>>
> >>> No no no, this example is not from that book, I have not yet started it. This example is from
> >>> a tiny (53 pages) book on pointers, dating from 1997 or so.
> >>
> >> That, at least, is a relief. Now that you know the book is seriously
> >> flawed, do you plan to continue using it?
> >>
> > I am done with that book, as I have said yesterday - it served its purpose, and that's it;
> > I don't need it anymore )
> 
> You didn't need it before, either.
> 
> You need to get out of your head the idea that "this book is about C, 
> therefore this book is good". Most books about C are written by people 
> who don't know C terribly well.
> 
> > I have K&R and Deitel books.
> 
> For learning C, those two are sufficient. Please don't confuse yourself 
> by getting any more, not until you've learned the language well enough 
> not to be confused by wrong information.
> 
Thank you! Yes, I definitely won't look for any other books or materials.  

[toc] | [prev] | [next] | [standalone]


#98165

FromAlla _ <modelling.data@gmail.com>
Date2016-12-06 06:31 -0800
Message-ID<dabb5dff-d0d8-446a-b37c-60613fd9a8d3@googlegroups.com>
In reply to#98137
On Tuesday, December 6, 2016 at 1:58:15 PM UTC+3, Richard Heathfield wrote:
> On 06/12/16 10:53, Alla _ wrote:
> > On Tuesday, December 6, 2016 at 1:23:28 PM UTC+3, Richard Heathfield wrote:
> >> On 06/12/16 06:46, Alla _ wrote:
> >>> On Monday, December 5, 2016 at 9:16:27 PM UTC+3, Richard Heathfield wrote:
> >>>> Deitel and Deitel is a reasonable book. Or at least I thought it was.
> >>>> Are you telling me the example code came from that book? If so, Deitel
> >>>> and Deitel have gone catastrophically downhill.
> >>>>
> >>> No no no, this example is not from that book, I have not yet started it. This example is from
> >>> a tiny (53 pages) book on pointers, dating from 1997 or so.
> >>
> >> That, at least, is a relief. Now that you know the book is seriously
> >> flawed, do you plan to continue using it?
> >>
> > I am done with that book, as I have said yesterday - it served its purpose, and that's it;
> > I don't need it anymore )
> 
> You didn't need it before, either.
> 
> You need to get out of your head the idea that "this book is about C, 
> therefore this book is good". Most books about C are written by people 
> who don't know C terribly well.
> 
> > I have K&R and Deitel books.
> 
> For learning C, those two are sufficient. Please don't confuse yourself 
> by getting any more, not until you've learned the language well enough 
> not to be confused by wrong information.
> 
I have decided to add for the sake of complete honesty: although, yes, I 
won't look for any more books for now, I have quite a few of them already,
including the MIT one on algorithms, and much more ))) But! I will not 
even try to open them for now, that's for sure. At least I know my further
steps, and it's always good to look and plan beyond current possibilities )

[toc] | [prev] | [next] | [standalone]


#98166

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-12-06 14:49 +0000
Message-ID<o26j3q$mac$1@dont-email.me>
In reply to#98165
On 06/12/16 14:31, Alla _ wrote:
> On Tuesday, December 6, 2016 at 1:58:15 PM UTC+3, Richard Heathfield wrote:
>> On 06/12/16 10:53, Alla _ wrote:
>>> On Tuesday, December 6, 2016 at 1:23:28 PM UTC+3, Richard Heathfield wrote:
>>>> On 06/12/16 06:46, Alla _ wrote:
>>>>> On Monday, December 5, 2016 at 9:16:27 PM UTC+3, Richard Heathfield wrote:
>>>>>> Deitel and Deitel is a reasonable book. Or at least I thought it was.
>>>>>> Are you telling me the example code came from that book? If so, Deitel
>>>>>> and Deitel have gone catastrophically downhill.
>>>>>>
>>>>> No no no, this example is not from that book, I have not yet started it. This example is from
>>>>> a tiny (53 pages) book on pointers, dating from 1997 or so.
>>>>
>>>> That, at least, is a relief. Now that you know the book is seriously
>>>> flawed, do you plan to continue using it?
>>>>
>>> I am done with that book, as I have said yesterday - it served its purpose, and that's it;
>>> I don't need it anymore )
>>
>> You didn't need it before, either.
>>
>> You need to get out of your head the idea that "this book is about C,
>> therefore this book is good". Most books about C are written by people
>> who don't know C terribly well.
>>
>>> I have K&R and Deitel books.
>>
>> For learning C, those two are sufficient. Please don't confuse yourself
>> by getting any more, not until you've learned the language well enough
>> not to be confused by wrong information.
>>
> I have decided to add for the sake of complete honesty: although, yes, I
> won't look for any more books for now, I have quite a few of them already,
> including the MIT one on algorithms, and much more ))) But! I will not
> even try to open them for now, that's for sure. At least I know my further
> steps, and it's always good to look and plan beyond current possibilities )

Books about algorithms are fine. I was only talking about books on C. 
Sometimes, of course, C is used in books on algorithms. The trick is to 
learn the algorithms from the algorithm experts, and C from the C 
experts. K&R are of course C experts, and it isn't too much of a stretch 
to say that Deitel and Deitel are, too. Also acceptable are Harbison & 
Steele, and (so I am told) K N King ("C Programming: A Modern 
Approach"). Oh, and let's not forget Steve Summit (C FAQs).

Don't make the mistake of thinking that experts on other subjects are 
necessarily experts on C. Charles Petzold, for example, has a 
tremendously in-depth knowledge of the Windows programming API, but his 
C is absolutely gerharsterly.[1] The trick is to be able to extract the 
good teaching and leave the bad C behind.


[1] Out of curiosity, I looked up this word in a Web search just now. To 
my surprise, I only got seven hits. To my even greater surprise, *all 
seven* of them were Web copies of articles I had posted to Usenet.

Oh well. I guess this makes it eight.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#98174

FromAlla _ <modelling.data@gmail.com>
Date2016-12-06 08:22 -0800
Message-ID<0ef69e52-232b-4b69-b38d-11d51530069f@googlegroups.com>
In reply to#98166
On Tuesday, December 6, 2016 at 5:49:58 PM UTC+3, Richard Heathfield wrote:
> On 06/12/16 14:31, Alla _ wrote:
> > On Tuesday, December 6, 2016 at 1:58:15 PM UTC+3, Richard Heathfield wrote:
> >> On 06/12/16 10:53, Alla _ wrote:
> >>> On Tuesday, December 6, 2016 at 1:23:28 PM UTC+3, Richard Heathfield wrote:
> >>>> On 06/12/16 06:46, Alla _ wrote:
> >>>>> On Monday, December 5, 2016 at 9:16:27 PM UTC+3, Richard Heathfield wrote:
> >>>>>> Deitel and Deitel is a reasonable book. Or at least I thought it was.
> >>>>>> Are you telling me the example code came from that book? If so, Deitel
> >>>>>> and Deitel have gone catastrophically downhill.
> >>>>>>
> >>>>> No no no, this example is not from that book, I have not yet started it. This example is from
> >>>>> a tiny (53 pages) book on pointers, dating from 1997 or so.
> >>>>
> >>>> That, at least, is a relief. Now that you know the book is seriously
> >>>> flawed, do you plan to continue using it?
> >>>>
> >>> I am done with that book, as I have said yesterday - it served its purpose, and that's it;
> >>> I don't need it anymore )
> >>
> >> You didn't need it before, either.
> >>
> >> You need to get out of your head the idea that "this book is about C,
> >> therefore this book is good". Most books about C are written by people
> >> who don't know C terribly well.
> >>
> >>> I have K&R and Deitel books.
> >>
> >> For learning C, those two are sufficient. Please don't confuse yourself
> >> by getting any more, not until you've learned the language well enough
> >> not to be confused by wrong information.
> >>
> > I have decided to add for the sake of complete honesty: although, yes, I
> > won't look for any more books for now, I have quite a few of them already,
> > including the MIT one on algorithms, and much more ))) But! I will not
> > even try to open them for now, that's for sure. At least I know my further
> > steps, and it's always good to look and plan beyond current possibilities )
> 
> Books about algorithms are fine. I was only talking about books on C. 
> Sometimes, of course, C is used in books on algorithms. The trick is to 
> learn the algorithms from the algorithm experts, and C from the C 
> experts. K&R are of course C experts, and it isn't too much of a stretch 
> to say that Deitel and Deitel are, too. Also acceptable are Harbison & 
> Steele, and (so I am told) K N King ("C Programming: A Modern 
> Approach"). Oh, and let's not forget Steve Summit (C FAQs).
> 
> Don't make the mistake of thinking that experts on other subjects are 
> necessarily experts on C. Charles Petzold, for example, has a 
> tremendously in-depth knowledge of the Windows programming API, but his 
> C is absolutely gerharsterly.[1] The trick is to be able to extract the 
> good teaching and leave the bad C behind.
> 
> 
Of course, I understand all that. It doesn't apply only to C and/or programming )

> [1] Out of curiosity, I looked up this word in a Web search just now. To 
> my surprise, I only got seven hits. To my even greater surprise, *all 
> seven* of them were Web copies of articles I had posted to Usenet.
> 
> Oh well. I guess this makes it eight.
> 
Does it mean that this word is your invention? If so, what does it mean? 
I have checked dictionaries, and have also checked German-English one
(because it does have some sort of a germanic sound),
just in case I could find meanings of some parts of this word to deduce 
the overall meaning. Failed ) 

[toc] | [prev] | [next] | [standalone]


#98177

FromRichard Heathfield <rjh@cpax.org.uk>
Date2016-12-06 16:48 +0000
Message-ID<o26q2c$hbe$1@dont-email.me>
In reply to#98174
On 06/12/16 16:22, Alla _ wrote:
> On Tuesday, December 6, 2016 at 5:49:58 PM UTC+3, Richard Heathfield wrote:

<snip>

>> Don't make the mistake of thinking that experts on other subjects are
>> necessarily experts on C. Charles Petzold, for example, has a
>> tremendously in-depth knowledge of the Windows programming API, but his
>> C is absolutely gerharsterly.[1] The trick is to be able to extract the
>> good teaching and leave the bad C behind.
>>
>>
> Of course, I understand all that. It doesn't apply only to C and/or programming )
>
>> [1] Out of curiosity, I looked up this word in a Web search just now. To
>> my surprise, I only got seven hits. To my even greater surprise, *all
>> seven* of them were Web copies of articles I had posted to Usenet.
>>
>> Oh well. I guess this makes it eight.
>>
> Does it mean that this word is your invention?

No. That's the strange thing. As far as I can tell, it was Terry 
Pratchett who first used that spelling, in "Moving Pictures" (context: 
"gerharsterly things from the Dungeon Dimensions", or something along 
those lines). But this doesn't seem to have been quoted anywhere on the 
Web, and neither does anyone else appear to have adopted it.

> If so, what does it mean?

It's a corruption of "ghastly", which you will find in any reasonable 
dictionary.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#98180

FromAlla _ <modelling.data@gmail.com>
Date2016-12-06 09:15 -0800
Message-ID<a8d2a606-3e80-4b10-93a0-82088904e536@googlegroups.com>
In reply to#98177
On Tuesday, December 6, 2016 at 7:48:35 PM UTC+3, Richard Heathfield wrote:
> On 06/12/16 16:22, Alla _ wrote:
> > On Tuesday, December 6, 2016 at 5:49:58 PM UTC+3, Richard Heathfield wrote:
> 
> <snip>
> 
> >> Don't make the mistake of thinking that experts on other subjects are
> >> necessarily experts on C. Charles Petzold, for example, has a
> >> tremendously in-depth knowledge of the Windows programming API, but his
> >> C is absolutely gerharsterly.[1] The trick is to be able to extract the
> >> good teaching and leave the bad C behind.
> >>
> >>
> > Of course, I understand all that. It doesn't apply only to C and/or programming )
> >
> >> [1] Out of curiosity, I looked up this word in a Web search just now. To
> >> my surprise, I only got seven hits. To my even greater surprise, *all
> >> seven* of them were Web copies of articles I had posted to Usenet.
> >>
> >> Oh well. I guess this makes it eight.
> >>
> > Does it mean that this word is your invention?
> 
> No. That's the strange thing. As far as I can tell, it was Terry 
> Pratchett who first used that spelling, in "Moving Pictures" (context: 
> "gerharsterly things from the Dungeon Dimensions", or something along 
> those lines). But this doesn't seem to have been quoted anywhere on the 
> Web, and neither does anyone else appear to have adopted it.
> 
> > If so, what does it mean?
> 
> It's a corruption of "ghastly", which you will find in any reasonable 
> dictionary.
>
Good that at least this one I managed to understand in a snap )

[toc] | [prev] | [next] | [standalone]


#98173

FromKeith Thompson <kst-u@mib.org>
Date2016-12-06 08:20 -0800
Message-ID<ln37i13u7v.fsf@kst-u.example.com>
In reply to#98126
Alla _ <modelling.data@gmail.com> writes:
[...]
>> Deitel and Deitel is a reasonable book. Or at least I thought it was. 
>> Are you telling me the example code came from that book? If so, Deitel 
>> and Deitel have gone catastrophically downhill.
>> 
> No no no, this example is not from that book, I have not yet started
> it. This example is from a tiny (53 pages) book on pointers, dating
> from 1997 or so.

Is there some reason you're unwilling to identify the book?  I'd like to
know what it is so I can take a look and possibly warn people away from
it.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#98128

FromAlla _ <modelling.data@gmail.com>
Date2016-12-05 22:53 -0800
Message-ID<3127b0eb-c0c1-4e70-b5a3-b891b41318e8@googlegroups.com>
In reply to#98034
On Monday, December 5, 2016 at 9:16:27 PM UTC+3, Richard Heathfield wrote:
> On 05/12/16 17:43, Alla _ wrote:
> 
> <snip>
> 
> > I also have to write a student's program within 2 weeks.
> 
> If you spent less time on these C courses, you might have time to learn 
> C properly.

Yes, I agree, that is why I have to write the program in two weeks and get over with it, 
so to be able to learn C. Now I do have a sense of few basic languages, but none 
compare to C (though given the huge few months hiatus in programming, I am not sure 
I remember those properly :) ). I do think that C is the best language, although php and 
java are more suitable for higher level programming, and for all web programming; still  
I believe that none can compare to C - it's interesting, elegant, not so easy, which makes 
it even more attractive. 
I have no idea why people shun learning it, and learn only higher level languages.  
> 
> > So, I have to work
> > on this program, K&R and one more book on C, which is based on K&R, but
> > is more detailed and might be of a great help:
> >  C: How to Program by Deitel and Deitel
> > I hope it will help me to understand the material better, and hopefully to do
> > all K&R exercises.
> 
> Deitel and Deitel is a reasonable book. Or at least I thought it was. 
> Are you telling me the example code came from that book? If so, Deitel 
> and Deitel have gone catastrophically downhill.
> 
> -- 
> Richard Heathfield
> Email: rjh at cpax dot org dot uk
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#98025

FromKeith Thompson <kst-u@mib.org>
Date2016-12-05 09:26 -0800
Message-ID<lnvauy478f.fsf@kst-u.example.com>
In reply to#98017
Alla _ <modelling.data@gmail.com> writes:
> Please, take a look at my reading of the program (in comments to each
> statement) that uses pointers to two-dimensional arrays. Is my
> understanding correct, i.e. do correctly interpret the given code?
> And, please, help me to understand one part closer to the end of the
> program.

I presume this is code you got from someone else, not something you
wrote.

The indentation is inconsistent and IMHO excessive.  The comments are
far more verbose than you'd want in real-world code, but the program is
obviously intended for teaching, not production.

There is no pointer to a two-dimensional array anywhere in the code.
Such a pointer might be defined like this:
    int (*p)[10][20]

The program creates a data structure that acts like a two-dimensional
array, but isn't one (and the way the program does it is likely to be
more useful and flexible than an actual 2D array).  It creates an array
of int* pointers, each of which points to an array of ints, with
everything allocated using malloc(), with an int** pointing to the
initial element of the array of pointers.  It's similar to the layout
used by argv.

> #include <stdio.h>
> #include <stdlib.h>
>       int main(void)
>     {
>        // define the number of rows and columns             
>               int nrows = 5; 
>               int ncols = 10; 
>               int row;
>
>       // initialise a pointer, which points to a pointer, which, in turn, points to type int,
>       // i.e. stores the address of an integer value
>               int **rowptr;

The comment is incorrect.  This declares and defines a pointer object,
but it doesn't *initialize* anything.  Also, "the address of an integer
value" doesn't make sense; values don't have addresses.  A pointer
points to an object, not to a value.

>   /*** define rowptr pointer by assigning to it the value of the address of the array,
>          allocated by the call to malloc for nrows (5 in this case) pointers to type int; 
>          therefore the value of the rowptr after the call to malloc will be the address, 
>          at which the first element in the array of pointers to integer type could be stored;
>           of course, none of these pointers yet point anywhere 
>   ***/

rowptr holds the address of *the initial element of* the array, not the
address of the array itself.  The two refer to the same location in
memory, but with different types.  It's common to refer to a pointer to
(equivalently, the address of) the initial element of an array as a
pointer to the array itself, but it's incorrect.

>               rowptr = malloc(nrows * sizeof(int *));

This is ok, but it would be better written using the usual idiom:

    rowptr = malloc(nrows * sizeof *rowptr);

You can add parentheses around *rowptr if you think that makes it
clearer (personally, I don't).

>         /** check of the memory has been allocated; if not, print the info message,
>             and exit **/
>          if (rowptr == NULL)
>          {
>                     puts("\nFailure to allocate room for row pointers.\n");
>                    exit(0);
>          }

Error messages should be printed to stderr, and program failure should
be indicated by returning a non-zero status, preferably EXIT_FAILURE.

    if (rowptr == NULL) {
        fputs("Failure to allocate room for row pointers.\n", stderr);
        exit(EXIT_FAILURE);
    }

Exiting on a malloc failure is a bit drastic, but it's ok for a small
demo program like this.

>         // Print the title
>          printf("\n\n\nIndex Pointer(hex) Pointer(dec) Diff.(dec)");

The author of this program certainly likes newlines, but omits them at
the ends of lines.  I see this kind of thing in program written for
Windows.  Perhaps there's some reason to print three blank lines before
the title.  Normally every line of output should end in a newline.

>          /** Allocate memory for an array of ncols integers for every row, and store the value of the 
>              allocated address of the first element of each array at the pointer rowptr[row],
>              such that rowptr[row] now points to corresponding address of the first element 
>              in the array of ncols integers **/

That description seems to be accurate, apart from a bit of confusion
about a pointer "pointing to an address" vs. "*containing* an address"
and "pointing to an object".

>          for (row = 0; row < nrows; row++)
>           {
>                       rowptr[row] = malloc(ncols * sizeof(int));

Again, I'd write this as:

    rowptr[row] = malloc(ncols * sizeof *rowptr[row]);

>                    /** check of the memory has been allocated; if not, print the info message,
>                      and exit **/
>                      if (rowptr[row] == NULL)
>                     {
>                                  printf("\nFailure to allocate for row[%d]\n",row);
>                                  exit(0);
>                     }

And again, the error message should be printed to stderr, and exit(0)
should be exit(EXIT_FAILURE).

>           /** Here is the difficult part: print the number of the current row "row",
>                 print the hexadecimal address of the pointer that now has the value
>                 of the address of the first element of the array of integers; 
>                 and the third element should the same address of the pointer
>                 but its decimal value; 
>
>                 When I tried to compile this, I have received an error message,
>          which I solved by casting (void *) to the first call to rowptr[row]
>          (see my new printf below the original one), which is specified 
>          by %p; but I can't solve the second error message (see below) 
>          and I don't understand why the author has not mentioned anything
>          about it:
>          error: format specifies type 'int' but the argument has
>          type 'int *' [-Werror,-Wformat]
>          printf("\n%d %p %d", row, rowptr[row], rowptr[row]);
>                          ~~                     ^~~~~~~~~~~
>          
>          **/
>
>                /** original printf function:   
>                    printf("\n%d %p %d", row, rowptr[row], rowptr[row]);  **/

This is attempting to print pointer values as integers.  The original
author seems to be unaware that this has undefined behavior, and
particularly on a system where int and pointers have different sizes it
can fail badly.

row is of type int, so of course %d is the correct format.

The code uses %p to print the value of rowptr[row], which is of type
int*.  That's almost correct, but %p requires an argument of type void*,
not int*.  The two types have the same representation on *most* systems,
so that's likely to "work", but there are no guarantees.  You need to
cast the value to void* (as you've done below).  Note that the author
assumes that %p prints pointer values in hexadecimal; that's common, but
not specified by the standard.

Using "%d" to print the value of rowptr[row] again is likely to "work"
on *some* systems, but can fail badly.  (On my system, where int is 32
bits and pointers are 64 bits, it appears to discard the high-order bits
of the pointer value.)  It can be corrected; see below.

>                // partially corrected printf
>                  printf("\n%d %p %d", row, (void *)rowptr[row], rowptr[row]);

You've correctly fixed the first attempt to print the value of
rowptr[row].  The final %d is intended to print the pointer value in
decimal -- something that might not even make sense.

I'd convert the pointer value to uintptr_t and print it:

    printf("%d %p %llu\n",
           row,
           (void*)rowptr[row],
           (unsigned long long)(uintptr_t)rowptr[row]);

Note that this requires adding "#include <stdint.h>" at the top.

I convert the pointer value to uintptr_t because that conversion is well
defined *if* the implementation defines uintptr_t.  I then convert it to
unsigned long long so I can print it with "%llu".  I could *probably*
get away with converting directly to unsigned long long, but I'm being
paranoid.  (If I were being *really* paranoid, I'd cast rowptr[row] to
void* before casting it to uintptr_t.  I might also use uintmax_t rather
than unsigned long long, just in case uintptr_t is an extended integer
type wider than unsigned long long -- which is very unlikely.)

I could have used the PRIuPTR macro defined in <inttypes.h> to print the
uintptr_t value directly, but I can never remember how all those macros
are spelled, so I just convert to a known type instead.

There's no guarantee that the result of the conversion is meaningful,
but on most systems it will be.  (Personally I'd just stick with "%p"
and count on the system to show me something meaningful.)

>                /** print the difference between the value of addresses of each row **/
>                        
>                   if (row > 0)
>                              printf(" %d",(int)(rowptr[row] - rowptr[row-1]));

Now this is a bit messed up.  The author gets points for using pointer
arithmetic and converting the result to int, but the result is not
particularly meaningful.  The pointers being subtracted are of type
int*, so the difference is in units of sizeof(int) not in bytes.  The
decimal values are likely to be byte addresses, so the displayed
differences aren't going to correspond to them.  That might be
interesting, but there are no comments indicating that the author is
aware of this important distinction.

Furthermore, the two pointers point to distinct objects, allocated by
separate calls to malloc(), so subtracting them has undefined behavior.
Since malloc() allocates strictly allocated memory, the difference is
likely to be a whole number of units of sizeof (int*) bytes, and the
output might give some insight into how the system's malloc() behaves,
but there's no indication that the author really knows what's going on.
Perhaps there's more context at the place where you got this program?

On my system, the pointers differ by 48 bytes, which is probably
an indication of how much overhead when malloc allocates 8 bytes
(sizeof (int*)).

>           }
>               return 0;
>     }

Here's my version of the program, without the comments:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(void) {
    const int nrows = 5;
    const int ncols = 10;
    int **rowptr = malloc(nrows * sizeof *rowptr);
    if (rowptr == NULL) {
        fputs("Failure to allocate room for row pointers.\n", stderr);
        exit(EXIT_FAILURE);
    }

    printf("Index Pointer(hex) Pointer(dec) Diff.(dec)\n");

    for (int row = 0; row < nrows; row++) {
        rowptr[row] = malloc(ncols * sizeof *rowptr[row]);
        if (rowptr[row] == NULL) {
            fprintf(stderr, "Failure to allocate for row %d\n", row);
            exit(EXIT_FAILURE);
        }
        printf("%d %p %llu",
               row, (void *) rowptr[row], (unsigned long
               long)(uintptr_t)rowptr[row]);
        if (row > 0) {
            printf(" %d", (int)((char*)rowptr[row] -
               (char*)rowptr[row-1]));
        }
        putchar('\n');
    }
    return 0;
}

The output on my system is:

Index Pointer(hex) Pointer(dec) Diff.(dec)
0 0x55c044d51450 94284276896848
1 0x55c044d51480 94284276896896 48
2 0x55c044d514b0 94284276896944 48
3 0x55c044d514e0 94284276896992 48
4 0x55c044d51510 94284276897040 48

The output when I compile in 32-bit mode (gcc -m32) is:

Index Pointer(hex) Pointer(dec) Diff.(dec)
0 0x57726428 1467114536
1 0x57726458 1467114584 48
2 0x57726488 1467114632 48
3 0x577264b8 1467114680 48
4 0x577264e8 1467114728 48

(Aligning the columns would be an interesting exercise.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#98031

FromAlla _ <modelling.data@gmail.com>
Date2016-12-05 09:47 -0800
Message-ID<128218c6-6fa1-49e3-8224-93d5810d060c@googlegroups.com>
In reply to#98025
On Monday, December 5, 2016 at 8:26:46 PM UTC+3, Keith Thompson wrote:
> Alla _ <modelling.data@gmail.com> writes:
> > Please, take a look at my reading of the program (in comments to each
> > statement) that uses pointers to two-dimensional arrays. Is my
> > understanding correct, i.e. do correctly interpret the given code?
> > And, please, help me to understand one part closer to the end of the
> > program.
> 
> I presume this is code you got from someone else, not something you
> wrote.
> 
> The indentation is inconsistent and IMHO excessive.  The comments are
> far more verbose than you'd want in real-world code, but the program is
> obviously intended for teaching, not production.
> 
I am sniping the rest of your message - I have just started reading it,
but have decided to comment on these two paragraphs first:
yes, of course, I have not written this code; this is the code I have 
picked up from a book on pointers. But all these bizarre looking and 
excessive comments are mine, and they are not intended to be 
usual comments to a program but a mere description of the way 
I read the code :)
<snip>

[toc] | [prev] | [next] | [standalone]


#98057

FromKeith Thompson <kst-u@mib.org>
Date2016-12-05 12:10 -0800
Message-ID<lnk2be3znn.fsf@kst-u.example.com>
In reply to#98031
Alla _ <modelling.data@gmail.com> writes:
> On Monday, December 5, 2016 at 8:26:46 PM UTC+3, Keith Thompson wrote:
>> Alla _ <modelling.data@gmail.com> writes:
>> > Please, take a look at my reading of the program (in comments to each
>> > statement) that uses pointers to two-dimensional arrays. Is my
>> > understanding correct, i.e. do correctly interpret the given code?
>> > And, please, help me to understand one part closer to the end of the
>> > program.
>> 
>> I presume this is code you got from someone else, not something you
>> wrote.
>> 
>> The indentation is inconsistent and IMHO excessive.  The comments are
>> far more verbose than you'd want in real-world code, but the program is
>> obviously intended for teaching, not production.
>> 
> I am sniping the rest of your message - I have just started reading it,
> but have decided to comment on these two paragraphs first:
> yes, of course, I have not written this code; this is the code I have 
> picked up from a book on pointers. But all these bizarre looking and 
> excessive comments are mine, and they are not intended to be 
> usual comments to a program but a mere description of the way 
> I read the code :)
> <snip>

What book?

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#98033

FromAlla _ <modelling.data@gmail.com>
Date2016-12-05 10:00 -0800
Message-ID<abc7808c-b5e5-49b4-b6e6-5c67f82eca21@googlegroups.com>
In reply to#98025
On Monday, December 5, 2016 at 8:26:46 PM UTC+3, Keith Thompson wrote:
> Alla _ <modelling.data@gmail.com> writes:
> > Please, take a look at my reading of the program (in comments to each
> > statement) that uses pointers to two-dimensional arrays. Is my
> > understanding correct, i.e. do correctly interpret the given code?
> > And, please, help me to understand one part closer to the end of the
> > program.
> 
> I presume this is code you got from someone else, not something you
> wrote.
> 
> The indentation is inconsistent and IMHO excessive.  The comments are
> far more verbose than you'd want in real-world code, but the program is
> obviously intended for teaching, not production.
> 
> There is no pointer to a two-dimensional array anywhere in the code.
> Such a pointer might be defined like this:
>     int (*p)[10][20]
> 
> The program creates a data structure that acts like a two-dimensional
> array, but isn't one (and the way the program does it is likely to be
> more useful and flexible than an actual 2D array).  It creates an array
> of int* pointers, each of which points to an array of ints, with
> everything allocated using malloc(), with an int** pointing to the
> initial element of the array of pointers.  It's similar to the layout
> used by argv.
> 
> > #include <stdio.h>
> > #include <stdlib.h>
> >       int main(void)
> >     {
> >        // define the number of rows and columns             
> >               int nrows = 5; 
> >               int ncols = 10; 
> >               int row;
> >
> >       // initialise a pointer, which points to a pointer, which, in turn, points to type int,
> >       // i.e. stores the address of an integer value
> >               int **rowptr;
> 
> The comment is incorrect.  This declares and defines a pointer object,
> but it doesn't *initialize* anything.  Also, "the address of an integer
> value" doesn't make sense; values don't have addresses.  A pointer
> points to an object, not to a value.
> 
> >   /*** define rowptr pointer by assigning to it the value of the address of the array,
> >          allocated by the call to malloc for nrows (5 in this case) pointers to type int; 
> >          therefore the value of the rowptr after the call to malloc will be the address, 
> >          at which the first element in the array of pointers to integer type could be stored;
> >           of course, none of these pointers yet point anywhere 
> >   ***/
> 
> rowptr holds the address of *the initial element of* the array, not the
> address of the array itself.  The two refer to the same location in
> memory, but with different types.  It's common to refer to a pointer to
> (equivalently, the address of) the initial element of an array as a
> pointer to the array itself, but it's incorrect.
> 
> >               rowptr = malloc(nrows * sizeof(int *));
> 
> This is ok, but it would be better written using the usual idiom:
> 
>     rowptr = malloc(nrows * sizeof *rowptr);
> 
> You can add parentheses around *rowptr if you think that makes it
> clearer (personally, I don't).
> 
> >         /** check of the memory has been allocated; if not, print the info message,
> >             and exit **/
> >          if (rowptr == NULL)
> >          {
> >                     puts("\nFailure to allocate room for row pointers.\n");
> >                    exit(0);
> >          }
> 
> Error messages should be printed to stderr, and program failure should
> be indicated by returning a non-zero status, preferably EXIT_FAILURE.
> 
>     if (rowptr == NULL) {
>         fputs("Failure to allocate room for row pointers.\n", stderr);
>         exit(EXIT_FAILURE);
>     }
> 
> Exiting on a malloc failure is a bit drastic, but it's ok for a small
> demo program like this.
> 
> >         // Print the title
> >          printf("\n\n\nIndex Pointer(hex) Pointer(dec) Diff.(dec)");
> 
> The author of this program certainly likes newlines, but omits them at
> the ends of lines.  I see this kind of thing in program written for
> Windows.  Perhaps there's some reason to print three blank lines before
> the title.  Normally every line of output should end in a newline.
> 
> >          /** Allocate memory for an array of ncols integers for every row, and store the value of the 
> >              allocated address of the first element of each array at the pointer rowptr[row],
> >              such that rowptr[row] now points to corresponding address of the first element 
> >              in the array of ncols integers **/
> 
> That description seems to be accurate, apart from a bit of confusion
> about a pointer "pointing to an address" vs. "*containing* an address"
> and "pointing to an object".
> 
> >          for (row = 0; row < nrows; row++)
> >           {
> >                       rowptr[row] = malloc(ncols * sizeof(int));
> 
> Again, I'd write this as:
> 
>     rowptr[row] = malloc(ncols * sizeof *rowptr[row]);
> 
> >                    /** check of the memory has been allocated; if not, print the info message,
> >                      and exit **/
> >                      if (rowptr[row] == NULL)
> >                     {
> >                                  printf("\nFailure to allocate for row[%d]\n",row);
> >                                  exit(0);
> >                     }
> 
> And again, the error message should be printed to stderr, and exit(0)
> should be exit(EXIT_FAILURE).
> 
> >           /** Here is the difficult part: print the number of the current row "row",
> >                 print the hexadecimal address of the pointer that now has the value
> >                 of the address of the first element of the array of integers; 
> >                 and the third element should the same address of the pointer
> >                 but its decimal value; 
> >
> >                 When I tried to compile this, I have received an error message,
> >          which I solved by casting (void *) to the first call to rowptr[row]
> >          (see my new printf below the original one), which is specified 
> >          by %p; but I can't solve the second error message (see below) 
> >          and I don't understand why the author has not mentioned anything
> >          about it:
> >          error: format specifies type 'int' but the argument has
> >          type 'int *' [-Werror,-Wformat]
> >          printf("\n%d %p %d", row, rowptr[row], rowptr[row]);
> >                          ~~                     ^~~~~~~~~~~
> >          
> >          **/
> >
> >                /** original printf function:   
> >                    printf("\n%d %p %d", row, rowptr[row], rowptr[row]);  **/
> 
> This is attempting to print pointer values as integers.  The original
> author seems to be unaware that this has undefined behavior, and
> particularly on a system where int and pointers have different sizes it
> can fail badly.
> 
> row is of type int, so of course %d is the correct format.
> 
> The code uses %p to print the value of rowptr[row], which is of type
> int*.  That's almost correct, but %p requires an argument of type void*,
> not int*.  The two types have the same representation on *most* systems,
> so that's likely to "work", but there are no guarantees.  You need to
> cast the value to void* (as you've done below).  Note that the author
> assumes that %p prints pointer values in hexadecimal; that's common, but
> not specified by the standard.
> 
> Using "%d" to print the value of rowptr[row] again is likely to "work"
> on *some* systems, but can fail badly.  (On my system, where int is 32
> bits and pointers are 64 bits, it appears to discard the high-order bits
> of the pointer value.)  It can be corrected; see below.
> 
> >                // partially corrected printf
> >                  printf("\n%d %p %d", row, (void *)rowptr[row], rowptr[row]);
> 
> You've correctly fixed the first attempt to print the value of
> rowptr[row].  The final %d is intended to print the pointer value in
> decimal -- something that might not even make sense.
> 
> I'd convert the pointer value to uintptr_t and print it:
> 
>     printf("%d %p %llu\n",
>            row,
>            (void*)rowptr[row],
>            (unsigned long long)(uintptr_t)rowptr[row]);
> 
> Note that this requires adding "#include <stdint.h>" at the top.
> 
> I convert the pointer value to uintptr_t because that conversion is well
> defined *if* the implementation defines uintptr_t.  I then convert it to
> unsigned long long so I can print it with "%llu".  I could *probably*
> get away with converting directly to unsigned long long, but I'm being
> paranoid.  (If I were being *really* paranoid, I'd cast rowptr[row] to
> void* before casting it to uintptr_t.  I might also use uintmax_t rather
> than unsigned long long, just in case uintptr_t is an extended integer
> type wider than unsigned long long -- which is very unlikely.)
> 
> I could have used the PRIuPTR macro defined in <inttypes.h> to print the
> uintptr_t value directly, but I can never remember how all those macros
> are spelled, so I just convert to a known type instead.
> 
> There's no guarantee that the result of the conversion is meaningful,
> but on most systems it will be.  (Personally I'd just stick with "%p"
> and count on the system to show me something meaningful.)
> 
> >                /** print the difference between the value of addresses of each row **/
> >                        
> >                   if (row > 0)
> >                              printf(" %d",(int)(rowptr[row] - rowptr[row-1]));
> 
> Now this is a bit messed up.  The author gets points for using pointer
> arithmetic and converting the result to int, but the result is not
> particularly meaningful.  The pointers being subtracted are of type
> int*, so the difference is in units of sizeof(int) not in bytes.  The
> decimal values are likely to be byte addresses, so the displayed
> differences aren't going to correspond to them.  That might be
> interesting, but there are no comments indicating that the author is
> aware of this important distinction.
> 
> Furthermore, the two pointers point to distinct objects, allocated by
> separate calls to malloc(), so subtracting them has undefined behavior.
> Since malloc() allocates strictly allocated memory, the difference is
> likely to be a whole number of units of sizeof (int*) bytes, and the
> output might give some insight into how the system's malloc() behaves,
> but there's no indication that the author really knows what's going on.
> Perhaps there's more context at the place where you got this program?
> 
> On my system, the pointers differ by 48 bytes, which is probably
> an indication of how much overhead when malloc allocates 8 bytes
> (sizeof (int*)).
> 
> >           }
> >               return 0;
> >     }
> 
> Here's my version of the program, without the comments:
> 
> #include <stdio.h>
> #include <stdlib.h>
> #include <stdint.h>
> int main(void) {
>     const int nrows = 5;
>     const int ncols = 10;
>     int **rowptr = malloc(nrows * sizeof *rowptr);
>     if (rowptr == NULL) {
>         fputs("Failure to allocate room for row pointers.\n", stderr);
>         exit(EXIT_FAILURE);
>     }
> 
>     printf("Index Pointer(hex) Pointer(dec) Diff.(dec)\n");
> 
>     for (int row = 0; row < nrows; row++) {
>         rowptr[row] = malloc(ncols * sizeof *rowptr[row]);
>         if (rowptr[row] == NULL) {
>             fprintf(stderr, "Failure to allocate for row %d\n", row);
>             exit(EXIT_FAILURE);
>         }
>         printf("%d %p %llu",
>                row, (void *) rowptr[row], (unsigned long
>                long)(uintptr_t)rowptr[row]);
>         if (row > 0) {
>             printf(" %d", (int)((char*)rowptr[row] -
>                (char*)rowptr[row-1]));
>         }
>         putchar('\n');
>     }
>     return 0;
> }
> 
> The output on my system is:
> 
> Index Pointer(hex) Pointer(dec) Diff.(dec)
> 0 0x55c044d51450 94284276896848
> 1 0x55c044d51480 94284276896896 48
> 2 0x55c044d514b0 94284276896944 48
> 3 0x55c044d514e0 94284276896992 48
> 4 0x55c044d51510 94284276897040 48
> 
> The output when I compile in 32-bit mode (gcc -m32) is:
> 
> Index Pointer(hex) Pointer(dec) Diff.(dec)
> 0 0x57726428 1467114536
> 1 0x57726458 1467114584 48
> 2 0x57726488 1467114632 48
> 3 0x577264b8 1467114680 48
> 4 0x577264e8 1467114728 48
> 
> (Aligning the columns would be an interesting exercise.)
> 
> -- 
> Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
> Working, but not speaking, for JetHead Development, Inc.
> "We must do something.  This is something.  Therefore, we must do this."
>     -- Antony Jay and Jonathan Lynn, "Yes Minister"

Thank you very much! I have learned a lot again thanks to your explanations
and explanations Richard has written above. Thank you!

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web