473,473 Members | 1,581 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

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_project3_assignment3.c: In function `main':
chris_readle_project3_assignment3.c:23: warning: passing arg 1 of
`displaySales' from incompatible pointer type

And here is the code in question:
void inputSales(float s[][PRODUCTS]);
void displaySales(const float s[][PRODUCTS]);

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

inputSales(sales);

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?

crr
Nov 14 '05 #1
15 9317
"Chris Readle" <c.******@cox.net> wrote in message
news:qMnBc.3235$DQ4.1776@fed1read05...
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_assignment3.c: In function `main':
chris_readle_project3_assignment3.c:23: warning: passing arg 1 of
`displaySales' from incompatible pointer type

And here is the code in question:
void inputSales(float s[][PRODUCTS]);
void displaySales(const float s[][PRODUCTS]);

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

inputSales(sales);

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?


That's the answer. The parameter is declared const
and the passed value is not a const.
Nov 14 '05 #2
xarax wrote:
"Chris Readle" <c.******@cox.net> wrote in message
news:qMnBc.3235$DQ4.1776@fed1read05...
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_assignment3.c: In function `main':
chris_readle_project3_assignment3.c:23: warning: passing arg 1 of
`displaySales' from incompatible pointer type

And here is the code in question:
void inputSales(float s[][PRODUCTS]);
void displaySales(const float s[][PRODUCTS]);

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

inputSales(sales);

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?

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

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
Nov 14 '05 #3
Chris Readle <c.******@cox.net> wrote:
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_assignment3.c: In function `main':
chris_readle_project3_assignment3.c:23: warning: passing arg 1 of
`displaySales' from incompatible pointer type

And here is the code in question:
void inputSales(float s[][PRODUCTS]);
void displaySales(const float s[][PRODUCTS]);

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

inputSales(sales);

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?


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).
Nov 14 '05 #4
Old Wolf <ol*****@inspire.net.nz> wrote:
Chris Readle <c.******@cox.net> wrote:
void inputSales(float s[][PRODUCTS]);
void displaySales(const float s[][PRODUCTS]);

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

inputSales(sales);

displaySales(sales); <---------This one gets the error
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).


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
Nov 14 '05 #5
In <2j*************@uni-berlin.de> "S.Tobias" <sN*******@amu.edu.pl> writes:
Old Wolf <ol*****@inspire.net.nz> wrote:
Chris Readle <c.******@cox.net> wrote:
> void inputSales(float s[][PRODUCTS]);
> void displaySales(const float s[][PRODUCTS]);
>
> float sales[SALESPEOPLE][PRODUCTS] = {{0}, {0}, {0}, {0}};
>
> inputSales(sales);
>
> displaySales(sales); <---------This one gets the error

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).


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?


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

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #6
Dan Pop wrote:
-snip-

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

Dan


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
Nov 14 '05 #7
Dan Pop <Da*****@cern.ch> wrote:
In <2j*************@uni-berlin.de> "S.Tobias" <sN*******@amu.edu.pl> writes:
Old Wolf <ol*****@inspire.net.nz> wrote:
Chris Readle <c.******@cox.net> wrote:
> void inputSales(float s[][PRODUCTS]);
> void displaySales(const float s[][PRODUCTS]);
>
> float sales[SALESPEOPLE][PRODUCTS] = {{0}, {0}, {0}, {0}};
>
> inputSales(sales);
>
> displaySales(sales); <---------This one gets the error [snip]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?

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


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
Nov 14 '05 #8
Chris Readle <c.******@cox.net> wrote:
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?


My advice would be to keep it as it is, and cast the argument, and
document why the cast was made:
void displaySales(const 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(const float (*)[PRODUCTS]) sales);
But some people don't like it.

--
Stan Tobias
Nov 14 '05 #9
S.Tobias wrote:

-snip a bunch of my crap-

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

-snip-

First, thanks for all your help.

Ok, let me see if I understand this, the call:
displaySales((const 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
Nov 14 '05 #10
Chris Readle <c.******@cox.net> wrote:
Ok, let me see if I understand this, the call:
displaySales((const 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?
Err, no...
I may be dense (ok, so no "may" about it ;) ), but what is the
[PRODUCTS] doing inside the cast?


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(float s[SALESPEOPLE][PRODUCTS]); /*SALESPEOPLE is ignored*/
or
void inputSales(float 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
Nov 14 '05 #11
S.Tobias wrote:

Again, thanks for the help.
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.
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-
(Sorry, could have made it shorter, but I don't want
to change all this at this point now.)


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
Nov 14 '05 #12
In <seGBc.3856$DQ4.470@fed1read05> Chris Readle <c.******@cox.net> writes:
Dan Pop wrote:
-snip-

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

Dan


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?


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: Da*****@ifh.de
Nov 14 '05 #13
Da*****@cern.ch (Dan Pop) wrote:

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".


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".
Nov 14 '05 #14
Old Wolf wrote:
Da*****@cern.ch (Dan Pop) wrote:

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".


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".


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 (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 14 '05 #15
In <40***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
Old Wolf wrote:
Da*****@cern.ch (Dan Pop) wrote:

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".
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".


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).


You don't need to study the documentation, in order to change the code.
Reading the code itself should be enough.
It would be nice to have a
mistake exposed at the earliest possible moment.
If you don't know what you're doing, you have no business touching that
code. There are far too many ways in which you can break it and no
compiler could possibly expose your mistakes.

I have no problems maintaining code I wrote 10 years ago, despite the
complete lack of const in it. And, by engaging my brain, I've been also
maintaining code (more or less badly) written by other people, without
relying on the compiler to find anything else than my own typos.
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.


Computers can't think for you. If you can't think, either, find a
different kind of job.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

58
by: jr | last post by:
Sorry for this very dumb question, but I've clearly got a long way to go! Can someone please help me pass an array into a function. Here's a starting point. void TheMainFunc() { // Body of...
1
by: george doubleu | last post by:
hi, i'm using "gcc version 3.3.3 (Debian)" to compile the program pasted below. I get the two warnings you can see in the remarks. The second warning is perfectly OK for me, but the first one I...
5
by: Oeleboele | last post by:
OK, I can't understand this exactly: I have this function: int howdy(void *) I first past this to the function &aCharArray I realized later that this should be aCharArray but... the former...
11
by: truckaxle | last post by:
I am trying to pass a slice from a larger 2-dimensional array to a function that will work on a smaller region of the array space. The code below is a distillation of what I am trying to...
7
by: Jeff K | last post by:
Can you pass an int array by reference to a function and modify selective elements? Here is my code: #include <stdio.h> #define COLUMNSIZE 30 #define ASIZE 5...
17
by: Charles Sullivan | last post by:
The library function 'qsort' is declared thus: void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); If in my code I write: int cmp_fcn(...); int...
11
by: cps | last post by:
Hi, I'm a C programmer taking my first steps into the world of C++. I'm currently developing a C++ 3D graphics application using GLUT (OpenGL Utility Toolkit written in C) for the GUI...
4
by: quigstah | last post by:
Hey All: Any insight you could give me would be tremendously appreciated. I have a data structure, one element of which takes the form: struct.struct.ptr Where ptr is a pointer to a...
3
by: iskeletor | last post by:
#include <stdio.h> #include <string.h> #include <math.h> #include <stdlib.h> #define STUDENT_NUMBER 68 #define ARRAY_LENGTH 10 struct node{ char Name,Surname; int data,no;
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.