Passing arg from incompatible pointer type

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Chris Readle

    Passing arg from incompatible pointer type

    Hi all,

    Somewhat new to C and I'm getting the following error from my latest code.

    Here's the warning I'm getting:
    chris_readle_pr oject3_assignme nt3.c: In function `main':
    chris_readle_pr oject3_assignme nt3.c:23: warning: passing arg 1 of
    `displaySales' from incompatible pointer type

    And here is the code in question:
    void inputSales(floa t s[][PRODUCTS]);
    void displaySales(co nst float s[][PRODUCTS]);

    float sales[SALESPEOPLE][PRODUCTS] = {{0}, {0}, {0}, {0}};

    inputSales(sale s);

    displaySales(sa les); <---------This one gets the error

    So, why am I getting the error and what does it mean? And why do I get
    it on the second function call and not the first, which seems exactly
    the same, other than being to a different function and not declaring the
    parameter as a const?

    crr
  • xarax

    #2
    Re: Passing arg from incompatible pointer type

    "Chris Readle" <c.readle@cox.n et> wrote in message
    news:qMnBc.3235 $DQ4.1776@fed1r ead05...[color=blue]
    > Hi all,
    >
    > Somewhat new to C and I'm getting the following error from my latest code.
    >
    > Here's the warning I'm getting:
    > chris_readle_pr oject3_assignme nt3.c: In function `main':
    > chris_readle_pr oject3_assignme nt3.c:23: warning: passing arg 1 of
    > `displaySales' from incompatible pointer type
    >
    > And here is the code in question:
    > void inputSales(floa t s[][PRODUCTS]);
    > void displaySales(co nst float s[][PRODUCTS]);
    >
    > float sales[SALESPEOPLE][PRODUCTS] = {{0}, {0}, {0}, {0}};
    >
    > inputSales(sale s);
    >
    > displaySales(sa les); <---------This one gets the error
    >
    > So, why am I getting the error and what does it mean? And why do I get
    > it on the second function call and not the first, which seems exactly
    > the same, other than being to a different function and not declaring the
    > parameter as a const?[/color]

    That's the answer. The parameter is declared const
    and the passed value is not a const.


    Comment

    • Chris Readle

      #3
      Re: Passing arg from incompatible pointer type

      xarax wrote:
      [color=blue]
      > "Chris Readle" <c.readle@cox.n et> wrote in message
      > news:qMnBc.3235 $DQ4.1776@fed1r ead05...
      >[color=green]
      >>Hi all,
      >>
      >>Somewhat new to C and I'm getting the following error from my latest code.
      >>
      >>Here's the warning I'm getting:
      >>chris_readle_ project3_assign ment3.c: In function `main':
      >>chris_readle_ project3_assign ment3.c:23: warning: passing arg 1 of
      >>`displaySales ' from incompatible pointer type
      >>
      >>And here is the code in question:
      >>void inputSales(floa t s[][PRODUCTS]);
      >>void displaySales(co nst float s[][PRODUCTS]);
      >>
      >>float sales[SALESPEOPLE][PRODUCTS] = {{0}, {0}, {0}, {0}};
      >>
      >>inputSales(sa les);
      >>
      >>displaySales( sales); <---------This one gets the error
      >>
      >>So, why am I getting the error and what does it mean? And why do I get
      >>it on the second function call and not the first, which seems exactly
      >>the same, other than being to a different function and not declaring the
      >>parameter as a const?[/color]
      >
      >
      > That's the answer. The parameter is declared const
      > and the passed value is not a const.
      >
      >[/color]
      Aha, that's what I suspected.

      So this is not any kind of hidden thing that's going to come back and
      bite me later? I had noticed that everything seems to run just fine,
      but I wanted to make sure that this wasn't something that *could* mess
      me up later and also that it's not some big style faux pas of which I
      was unaware.

      crr

      Comment

      • Old Wolf

        #4
        Re: Passing arg from incompatible pointer type

        Chris Readle <c.readle@cox.n et> wrote:[color=blue]
        > Hi all,
        >
        > Somewhat new to C and I'm getting the following error from my latest code.
        >
        > Here's the warning I'm getting:
        > chris_readle_pr oject3_assignme nt3.c: In function `main':
        > chris_readle_pr oject3_assignme nt3.c:23: warning: passing arg 1 of
        > `displaySales' from incompatible pointer type
        >
        > And here is the code in question:
        > void inputSales(floa t s[][PRODUCTS]);
        > void displaySales(co nst float s[][PRODUCTS]);
        >
        > float sales[SALESPEOPLE][PRODUCTS] = {{0}, {0}, {0}, {0}};
        >
        > inputSales(sale s);
        >
        > displaySales(sa les); <---------This one gets the error
        >
        > So, why am I getting the error and what does it mean? And why do I get
        > it on the second function call and not the first, which seems exactly
        > the same, other than being to a different function and not declaring the
        > parameter as a const?[/color]

        You can't "do away with const" over 2 levels of indirection. If they
        were 1-D arrays it would have been OK. This is touched on in FAQ 11.10.
        There's a good reason for this rule (although it escapes me at the moment).

        Comment

        • S.Tobias

          #5
          Re: Passing arg from incompatible pointer type

          Old Wolf <oldwolf@inspir e.net.nz> wrote:[color=blue]
          > Chris Readle <c.readle@cox.n et> wrote:[color=green]
          > > void inputSales(floa t s[][PRODUCTS]);
          > > void displaySales(co nst float s[][PRODUCTS]);
          > >
          > > float sales[SALESPEOPLE][PRODUCTS] = {{0}, {0}, {0}, {0}};
          > >
          > > inputSales(sale s);
          > >
          > > displaySales(sa les); <---------This one gets the error[/color][/color]
          [color=blue]
          > You can't "do away with const" over 2 levels of indirection. If they
          > were 1-D arrays it would have been OK. This is touched on in FAQ 11.10.
          > There's a good reason for this rule (although it escapes me at the moment).[/color]

          I think that's an interesting problem.

          float *pf;
          const float **ppcf = &pf; //unsafe, we are lying to ppcf about pf
          const float fdata;
          *ppcf = &fdata; //legal, pf is pointed to fdata,
          //ppcf "thinks" it is safe
          *pf = 13; //disaster!

          In general, we were lying as to kind of an object pf points to.


          But in the original problem we deal with tables and there is
          only *one* level of indirection: `sales' decays to:
          float (*)[PRODUCTS]
          and is passed to `s', which decays to:
          const float (*)[PRODUCTS]
          (All items in the table are const, so we might say that the
          whole "table object" is const.)
          It is like passing `float*' to `const float*', with exception
          that in this case `float' is actually `float[PRODUCTS]' (or put
          a structure there with PRODUCTS members of type float).

          This even looks more like a C++ question.
          Can anyone comment on this?

          --
          Stan Tobias

          Comment

          • Dan Pop

            #6
            Re: Passing arg from incompatible pointer type

            In <2jnsmhF13v6rrU 1@uni-berlin.de> "S.Tobias" <sNOiSPAMt@amu. edu.pl> writes:
            [color=blue]
            >Old Wolf <oldwolf@inspir e.net.nz> wrote:[color=green]
            >> Chris Readle <c.readle@cox.n et> wrote:[color=darkred]
            >> > void inputSales(floa t s[][PRODUCTS]);
            >> > void displaySales(co nst float s[][PRODUCTS]);
            >> >
            >> > float sales[SALESPEOPLE][PRODUCTS] = {{0}, {0}, {0}, {0}};
            >> >
            >> > inputSales(sale s);
            >> >
            >> > displaySales(sa les); <---------This one gets the error[/color][/color]
            >[color=green]
            >> You can't "do away with const" over 2 levels of indirection. If they
            >> were 1-D arrays it would have been OK. This is touched on in FAQ 11.10.
            >> There's a good reason for this rule (although it escapes me at the moment).[/color]
            >
            >I think that's an interesting problem.
            >
            >float *pf;
            >const float **ppcf = &pf; //unsafe, we are lying to ppcf about pf
            >const float fdata;
            >*ppcf = &fdata; //legal, pf is pointed to fdata,
            > //ppcf "thinks" it is safe
            >*pf = 13; //disaster!
            >
            >In general, we were lying as to kind of an object pf points to.
            >
            >But in the original problem we deal with tables and there is
            >only *one* level of indirection: `sales' decays to:
            > float (*)[PRODUCTS]
            >and is passed to `s', which decays to:
            > const float (*)[PRODUCTS]
            >(All items in the table are const, so we might say that the
            >whole "table object" is const.)
            >It is like passing `float*' to `const float*', with exception
            >that in this case `float' is actually `float[PRODUCTS]' (or put
            >a structure there with PRODUCTS members of type float).
            >
            >This even looks more like a C++ question.
            >Can anyone comment on this?[/color]

            Staying away from "const" helps preserve your sanity (and your hair).

            Dan
            --
            Dan Pop
            DESY Zeuthen, RZ group
            Email: Dan.Pop@ifh.de

            Comment

            • Chris Readle

              #7
              Re: Passing arg from incompatible pointer type

              Dan Pop wrote:
              -snip-[color=blue]
              >
              > Staying away from "const" helps preserve your sanity (and your hair).
              >
              > Dan[/color]

              Is there another way to simulate least privilege here? This is a
              display function that should never modify the data in question, but
              *does* need to read it? Or should I just leave it modifiable and make
              in clear in comments (not that this code will ever be seen by anyone but
              me and my instructor, but I'm speaking more generally here) that to
              modify the table in displaySales will bring a slow and painful death?

              crr

              Comment

              • S.Tobias

                #8
                Re: Passing arg from incompatible pointer type

                Dan Pop <Dan.Pop@cern.c h> wrote:[color=blue]
                > In <2jnsmhF13v6rrU 1@uni-berlin.de> "S.Tobias" <sNOiSPAMt@amu. edu.pl> writes:[color=green]
                > >Old Wolf <oldwolf@inspir e.net.nz> wrote:[color=darkred]
                > >> Chris Readle <c.readle@cox.n et> wrote:
                > >> > void inputSales(floa t s[][PRODUCTS]);
                > >> > void displaySales(co nst float s[][PRODUCTS]);
                > >> >
                > >> > float sales[SALESPEOPLE][PRODUCTS] = {{0}, {0}, {0}, {0}};
                > >> >
                > >> > inputSales(sale s);
                > >> >
                > >> > displaySales(sa les); <---------This one gets the error[/color]
                > >[/color][/color]
                [snip][color=blue][color=green]
                > >But in the original problem we deal with tables and there is
                > >only *one* level of indirection: `sales' decays to:
                > > float (*)[PRODUCTS]
                > >and is passed to `s', which decays to:
                > > const float (*)[PRODUCTS]
                > >(All items in the table are const, so we might say that the
                > >whole "table object" is const.)
                > >It is like passing `float*' to `const float*', with exception
                > >that in this case `float' is actually `float[PRODUCTS]' (or put
                > >a structure there with PRODUCTS members of type float).
                > >
                > >This even looks more like a C++ question.
                > >Can anyone comment on this?[/color][/color]
                [color=blue]
                > Staying away from "const" helps preserve your sanity (and your hair).[/color]

                Thanks for advice, a few years too late, though. As for my hair - soon
                there might be no issue :)


                I have run OP's code through on-line como: error (warning) in C99
                and C90 mode in strict (relaxed) mode, and no diagnostics in C++ mode.
                Similarly with gcc/g++.

                In C99 Std 6.5.16.1 (Simple assignment): "[...] type pointed to by the
                left has all the qualifiers of the type pointed to by the right;",
                and argument passing relies on assignment for that matter (6.5.2.2).

                In C++ the right expression is converted to the type of left one,
                which includes Qualification conversion (4.4), which is slightly
                more complicated and more logical than in C IMO.

                To sum up: C (unnecessarily) requires all pointed to cv-quals the
                same and there's no way without a cast - even if we drop const in
                fn parameter, we might want to pass `const float[][]' and run into
                same problem - unless we "stay away from const" completely.
                (There you are, I've almost come to the same conclusion...)

                --
                Stan Tobias

                Comment

                • S.Tobias

                  #9
                  Re: Passing arg from incompatible pointer type

                  Chris Readle <c.readle@cox.n et> wrote:[color=blue]
                  > Is there another way to simulate least privilege here? This is a
                  > display function that should never modify the data in question, but
                  > *does* need to read it? Or should I just leave it modifiable and make
                  > in clear in comments (not that this code will ever be seen by anyone but
                  > me and my instructor, but I'm speaking more generally here) that to
                  > modify the table in displaySales will bring a slow and painful death?[/color]

                  My advice would be to keep it as it is, and cast the argument, and
                  document why the cast was made:
                  void displaySales(co nst float s[][PRODUCTS]);
                  void test()
                  {
                  displaySales( (const float (*)[PRODUCTS]) sales); /*cast in const*/
                  }


                  My personal way of _documenting_ this is a la C++ (though its meaning and
                  usage is *completely different*):
                  #define const_cast(type ) (type)
                  displaySales( const_cast(cons t float (*)[PRODUCTS]) sales);
                  But some people don't like it.

                  --
                  Stan Tobias

                  Comment

                  • Chris Readle

                    #10
                    Re: Passing arg from incompatible pointer type

                    S.Tobias wrote:

                    -snip a bunch of my crap-[color=blue]
                    >
                    > My advice would be to keep it as it is, and cast the argument, and
                    > document why the cast was made:
                    > void displaySales(co nst float s[][PRODUCTS]);
                    > void test()
                    > {
                    > displaySales( (const float (*)[PRODUCTS]) sales); /*cast in const*/
                    > }
                    >[/color]
                    -snip-

                    First, thanks for all your help.

                    Ok, let me see if I understand this, the call:
                    displaySales((c onst float (*)[PRODUCTS]) sales); is basically saying:

                    "Call the function displaySales with the array sales cast as a pointer
                    to a const of type float." Is that correct?

                    I may be dense (ok, so no "may" about it ;) ), but what is the
                    [PRODUCTS] doing inside the cast?

                    crr

                    Comment

                    • S.Tobias

                      #11
                      Re: Passing arg from incompatible pointer type

                      Chris Readle <c.readle@cox.n et> wrote:
                      [color=blue]
                      > Ok, let me see if I understand this, the call:
                      > displaySales((c onst float (*)[PRODUCTS]) sales); is basically saying:[/color]
                      [color=blue]
                      > "Call the function displaySales with the array sales cast as a pointer
                      > to a const of type float." Is that correct?[/color]

                      Err, no...
                      [color=blue]
                      > I may be dense (ok, so no "may" about it ;) ), but what is the
                      > [PRODUCTS] doing inside the cast?[/color]

                      It's a bit long story.

                      First, learn to read type definitions (this one is a little complex,
                      but not the most difficult one). There was this nice rule: follow
                      the parentheses, otherwise first read what is to the right, then
                      to the left.
                      const float (*)[PRODUCTS]
                      1. pointer
                      2. to length PRODUCTS table
                      3. of const float values
                      (in short: "pointer to table of floats")
                      I'd advise you to look into 6.7.6#3 of C99 Standard and see
                      a couple of fine examples.

                      Now, why "[]":
                      I'm sure you know that ptab2 and ptab3 (pointers to table of int) in:
                      int (*ptab2)[2];
                      int (*ptab3)[3];
                      are incompatible - the pointer arithmetic is different.
                      (If you don't see why, imagine:
                      typedef struct {int i0; int i1; } stab2_t;
                      typedef struct {int i0; int i1; int i2; } stab3_t;
                      stab2_t *pstab2;
                      stab3_t *pstab3;
                      Types stab2_t and stab3_t are different sizes; so are above "inner" tables.)
                      Compiler has to know the length of "inner" tables in order to know
                      the proper pointer arithmetic (hence the actual pointer type), but needn't
                      know the "outer" length. Thats why you can declare:
                      void inputSales(floa t s[SALESPEOPLE][PRODUCTS]); /*SALESPEOPLE is ignored*/
                      or
                      void inputSales(floa t s[][PRODUCTS]);
                      and you can pass arguments:
                      float sales[SALESPEOPLE][PRODUCTS];
                      or
                      float sales2[SALESPEOPLE+20][PRODUCTS];
                      but you can't pass:
                      float sales3[SALESPEOPLE][PRODUCTS+1];
                      ^ inner table length is different


                      Second, why this _form_ of cast:

                      `sales' is a table:
                      float sales[][PRODUCTS]; /*length doesn't matter*/
                      but parameter `s' is:
                      const float s[][PRODUCTS];

                      So when passing `sales' to `displaySales' we need to cast it to type like:
                      const float [][PRODUCTS]; /*table of: length PRODUCTS table of: const float*/
                      But in a cast operator type name shall be of "scalar type and the operand
                      shall have scalar type" (6.5.4#2). `sales' in the expression is
                      converted (decays) to "pointer to table of float" (6.3.2.1#3), so it is
                      the right (scalar) type here, and its type is:
                      float (*)[PRODUCTS]
                      What I did was just add `const' before `float' to convert it to
                      the desired type.

                      (Sorry, could have made it shorter, but I don't want
                      to change all this at this point now.)

                      --
                      Stan Tobias

                      Comment

                      • Chris Readle

                        #12
                        Re: Passing arg from incompatible pointer type

                        S.Tobias wrote:

                        Again, thanks for the help.
                        [color=blue]
                        > It's a bit long story.
                        >
                        > First, learn to read type definitions (this one is a little complex,
                        > but not the most difficult one). There was this nice rule: follow
                        > the parentheses, otherwise first read what is to the right, then
                        > to the left.
                        > const float (*)[PRODUCTS]
                        > 1. pointer
                        > 2. to length PRODUCTS table
                        > 3. of const float values
                        > (in short: "pointer to table of floats")
                        > I'd advise you to look into 6.7.6#3 of C99 Standard and see
                        > a couple of fine examples.[/color]

                        Aha, that's what I was missing. I thought it had something to do with
                        the length of the table, but I wasn't sure how that fit in. I just
                        finished DLing the Standard, and I'll look up the section you suggest.
                        -snip-
                        [color=blue]
                        > (Sorry, could have made it shorter, but I don't want
                        > to change all this at this point now.)
                        >[/color]

                        No, this was perfect (for me, at least) it really helped me understand
                        what was going on the cast.

                        Yet again, thanks for all the help, you're a life saver (or at least a
                        sanity saver ;) ).

                        crr

                        Comment

                        • Dan Pop

                          #13
                          Re: Passing arg from incompatible pointer type

                          In <seGBc.3856$DQ4 .470@fed1read05 > Chris Readle <c.readle@cox.n et> writes:
                          [color=blue]
                          >Dan Pop wrote:
                          >-snip-[color=green]
                          >>
                          >> Staying away from "const" helps preserve your sanity (and your hair).
                          >>
                          >> Dan[/color]
                          >
                          >Is there another way to simulate least privilege here? This is a
                          >display function that should never modify the data in question, but
                          >*does* need to read it? Or should I just leave it modifiable and make
                          >in clear in comments (not that this code will ever be seen by anyone but
                          >me and my instructor, but I'm speaking more generally here) that to
                          >modify the table in displaySales will bring a slow and painful death?[/color]

                          It is already implied by the name and semantics of the function.

                          Only when a display function *has* to modify its input data is a special
                          comment necessary, the default assumption is that such a function only
                          examines its input data.

                          The only "valid" argument for using const in such cases I have seen
                          until now is "I am an idiot and I cannot trust myself not to accidentally
                          alter the data, so I *need* the compiler diagnostics".

                          Dan
                          --
                          Dan Pop
                          DESY Zeuthen, RZ group
                          Email: Dan.Pop@ifh.de

                          Comment

                          • Old Wolf

                            #14
                            Re: Passing arg from incompatible pointer type

                            Dan.Pop@cern.ch (Dan Pop) wrote:[color=blue]
                            >
                            > The only "valid" argument for using const in such cases I have seen
                            > until now is "I am an idiot and I cannot trust myself not to accidentally
                            > alter the data, so I *need* the compiler diagnostics".[/color]

                            Or a slight variation: "Other developers maintaining this code or using
                            this library in their own code might be idiots, and I do not want
                            to waste my time fielding calls and emails from idiots who crash their
                            program and think it's my fault".

                            Comment

                            • CBFalconer

                              #15
                              Re: Passing arg from incompatible pointer type

                              Old Wolf wrote:[color=blue]
                              > Dan.Pop@cern.ch (Dan Pop) wrote:[color=green]
                              >>
                              >> The only "valid" argument for using const in such cases I have
                              >> seen until now is "I am an idiot and I cannot trust myself not
                              >> to accidentally alter the data, so I *need* the compiler
                              >> diagnostics".[/color]
                              >
                              > Or a slight variation: "Other developers maintaining this code
                              > or using this library in their own code might be idiots, and I do
                              > not want to waste my time fielding calls and emails from idiots
                              > who crash their program and think it's my fault".[/color]

                              Or, 3, 6, 12, whatever months from now I or someone else may be
                              modifying this code without taking the time to read and absorb the
                              mountainous documentation (if any). It would be nice to have a
                              mistake exposed at the earliest possible moment.

                              Believe it or not, computers (even some of those with Microsoft
                              software) are usually better at remembering and applying minutiae
                              than you are. I am not too proud to accept help.

                              --
                              Chuck F (cbfalconer@yah oo.com) (cbfalconer@wor ldnet.att.net)
                              Available for consulting/temporary embedded and systems.
                              <http://cbfalconer.home .att.net> USE worldnet address!


                              Comment

                              Working...