strange warning

Discussion in 'C Programming' started by Bill Cunningham, May 10, 2014.

  1. This code looks correct to me. But the compiler issued this warning.
    What's it trying to tell me?

    #include <stdio.h>

    int main()
    {
    int *p;
    int a[5] = { 0 };
    p = &a;
    printf("%d\n", *(p + 1));
    printf("%d\n", *(p + 3));
    }

    p.c: In function 'main':
    p.c:7:7: warning: assignment from incompatible pointer type [enabled by
    default]
     
    Bill Cunningham, May 10, 2014
    #1
    1. Advertisements

  2. You want:

    p=a;

    instead.

    -- glen
     
    glen herrmannsfeldt, May 10, 2014
    #2
    1. Advertisements

  3. Compiler being fussy.
    If "a" is an array, "&a" and "a" mean almost the same thing. It's a quirk
    of C, the "array pointer equivalence" rule which almost holds but not quite.
    Take off the & and the the warning should go away and the code will
    do the same thing. Silly, but that's how it works.

    The compiler thinks that int a[5]; p = &a; means p should be a pointer to
    5 integers, so p++ would increment the pointer by five integers instead
    of one. Not something you probably want. It thinks int a[5], p = a;
    means p should be a plain int *, so p++ increments the pointer by one
    and moves it along to the next integer. That's what you normally do
    want.
     
    Malcolm McLean, May 10, 2014
    #3
  4. Bill Cunningham

    Ian Collins Guest

    s/fussy/correct/
     
    Ian Collins, May 10, 2014
    #4
  5. Bill Cunningham

    Osmium Guest

    The compiler has set up a location and agreed to let you call that location
    'a'. They are telling you that a does not contain an int. Consider: If it
    did contain an int, where would they put a[1]? How would they find a[1]?
    In fact, a contains effectively a *pointer* to an int, not an int. That's
    what they are telling you. p is of type pointer to int and a is not an int.
    They want you to fix it.
     
    Osmium, May 10, 2014
    #5
  6. p can only hold values of type pointer to int. The expression &a has
    type pointer to array of 5 int. This type is incompatible with p
    (there is no implicit conversion from int(*)[5] to int*).

    If you change the expression to
    p = a;
    the situation changes. a is an expression with array type. Under
    most conditions, such an expression is automatically converted by the
    compiler the address of the first element with type pointer to element
    type. In this case, the first element is a[0] which is an int so the
    expression is converted to type pointer to int. This renders the
    changed statement exactly equivalent to
    p = &a[0];

    The reason the changed statement works while your original doesn't is
    because one the exceptions to the conversion rule stated above is when
    the array expression is the operand of the & operator. If you are
    interested in the details of the conversion rule see n1256, section
    6.3.2.1-3, or the equivalent in any of the newer versions of the
    standard.
     
    Barry Schwarz, May 10, 2014
    #6
  7. Actually, a contains 5 int.
    a does not contain any pointers at all. It contains enough space to
    hold exactly 5 int and each of those int is initialized to 0.
    What the error message says is p is of type pointer to int but &a is
    of an incompatible type.
     
    Barry Schwarz, May 10, 2014
    #7
  8. The compiler is doing what any conforming compiler is required to do:
    issuing a diagnostic message for a constraint violation.

    In my opinion it isn't being fussy enough; a violation like this
    *should* cause the code to be rejected. But gcc often prints mere
    warnings for errors like this. (Yes, a warning is sufficient as far as
    the language is concerned, and yes, gcc can be made to treat it as a
    fatal error with "-pedantic-errors".)
    Pointers to incompatible types are incompatible. Assigning a
    pointer-to-array value to a pointer-to-int object is no more valid than
    assigning a pointer-to-int value to a pointer-to-double object. And in
    either case, if you *really* need to perform such an assignment for some
    reason you can use a cast.

    Do you want all pointer types to be compatible, or should the language
    be sloppy only for a pointer to an array vs. a pointer to an element of
    the array?
    In both cases, what the compiler "thinks" is simply what the language
    specifies.
     
    Keith Thompson, May 10, 2014
    #8
  9. Right so far.
    Was that a typo? p is a pointer to an int. a is an array.
     
    Keith Thompson, May 10, 2014
    #9
  10. The language should tighten up the distinction between a buffer and
    an array. A buffer is a region of memory which may or may not contain
    data, and typically has a few unused bytes at the end. An array is
    a set of data that can be indexed in O constant time by an integer
    subscript.
    C arrays should obviously only allow subscripts from 0 to N-1 and
    with no facilities for gaps or sparse arrays. There are serious questions
    about how to best handle multi-dimensional arrays. Until those are
    answered, it's hard to say what sorts of pointer conversions should
    be considered "sloppy".
     
    Malcolm McLean, May 10, 2014
    #10
  11. Bill Cunningham

    Ian Collins Guest

    There isn't anything to tighten up, C doesn't have a buffer type. An
    array is a type and a pointer to an array is a pointer to an object of
    that type.
    Is it now.
    Are there?
    No it isn't. A pointer to one type is distinct from a pointer to
    another type.
     
    Ian Collins, May 10, 2014
    #11
  12. void *ptr;
    size_t sz = 123;
    ptr = malloc(sz);

    will get you a buffer of 123 bytes. It's not an array, and in fact ptr[0] = x;
    is illegal.
    However

    unsigned char buff[123];

    is almost certainly a drop-in replacement for the above code, it's
    probably also a buffer. But we can't be sure, maybe it's really an array
    of 123 bytes which will be initialised in the next few lines.
    Yes. Images are inherently 2D, but it doesn't usually make sense to hardcode
    their dimensions at runtime. On the other hand filters for image processing
    usually do have dimensions known at runtime, and it makes sense to code
    4x4 or above filters in subroutines generically, but 3x3 filters really
    you don't want to pass filter dimensions to a generic subroutine. So we've
    got three types of 2D array, for a simple image processing program.

    Then what does the syntax

    bezierpatch[j] = x;

    actually mean? Is bezierpatch a matrix, or a ragged array accessed through
    a double pointer? I don't say this is a fatal flaw, but it's an undesireable
    feature of the syntax.
    No, because we can't use an int (*ptr)[5] to manipulate the data elements,
    we need to derive an int * from it at some point. I was going to say
    you can't access the elements, but of course you can, but it's contorted
    and no-one sensible would write C that way.
     
    Malcolm McLean, May 10, 2014
    #12
  13. Bill Cunningham

    Ian Collins Guest

    Maybe its is, but as I said, the language does not make any such
    distinction.
    If the function is generic, that you have to pass the dimensions one way
    or another.


    How would your clear it up?
    How is that relevant? There may be an issues with C's inability to copy
    arrays, but an array is still a distinct type. For example, this will
    cause a diagnostic:

    typedef int (FiveInts)[5];

    void f5( FiveInts* p );

    int main(void)
    {
    int a[]={10,20,30,40,50};

    f5(&a);

    int b[]={10,20,30,40,50,60};

    f5(&b);
    }
     
    Ian Collins, May 10, 2014
    #13
  14. Bill Cunningham

    BartC Guest



    You've probably hit on one of the few unique features of C that other
    languages might want to copy.

    Sometimes it's good to hide the dereferences likes this (you can change the
    implementation of bezierpatch between and arrays and pointers to arrays, and
    that code will still work.)

    But if you did want to show the dereferences explicitly, I don't think the
    language stops you doing that. However the prefix nature of '*' and its
    precedence makes for ugly syntax:

    (*(*bezierpatch))[j]) = x;

    (Or something like those lines.)

    (A postfix version of * would give you the more readable:

    bezierpath**[j] = x;

    although that looks too much like multiply if you stay with '*')
     
    BartC, May 10, 2014
    #14
  15. Bill Cunningham

    jacob navia Guest

    Le 10/05/2014 13:16, Richard a écrit :
    Yes... I agree with that, the answers are in the pure style of the
    "regs": but I missed some citations of the verses of the bible, oh
    pardon me, the holy standard.
     
    jacob navia, May 10, 2014
    #15
  16. Bill Cunningham

    Osmium Guest

    No, I meant what I said. I am not particularly interested in what the
    standard says and, in fact, I'm appalled that so many people (10 or 20)
    think a language standard can be so interesting. I look at the end result
    of all these shenanigans.

    In my view, C does not *have* arrays. They go through some sophistry to
    make it look like they have arrays, and they use the word "array", but what
    they actually have is sophistry. An array has, for example, a *size*. The
    thing C has is without bounds. That's not an array. Should you not be able
    to set one array to the value of another with the same characteristics?
    That is b = a? No, you can't do that in C.

    If a was an array Bill should be able to tell an independently compiled
    function that a was an array. There is no such way. Such a function can be
    satisfied by a parameter that is an ordinary, *indistinguishable* pointer.
    What happened to the array? The gurus say it transmogrified or some such.
    I say it never existed in the first place. it was all imaginary.

    When C sees
    int a[10];
    it goes into a little dance. It sets aside room for 10 ints in one place
    and in another place it creates a variable named 'a'. They set a to point
    at the first int in the space set aside. Bill's problem originates with the
    variable named 'a'. Thus my answer to him.

    Troll score:
    [0/10]
    Bills confusion is simply the result you get when you misuse words that
    already had a well established meaning.
     
    Osmium, May 10, 2014
    #16
  17. int ar[4];

    has a size. Is it not, then, an array? A pointer to a row of an array
    is incremented to point to the next row:

    int m[4][4];
    int (*rp)[4] = &m[0];
    ...
    rp++; // move to the next row

    If C has no arrays, why does a pointer to an array move in units of what
    appears to be the array size?

    In my view, it's better to think of C as having second class arrays with
    some rather peculiar rules.

    <snip>
     
    Ben Bacarisse, May 10, 2014
    #17
  18. You are, of course, entitled to that view.

    However, others of us see the same set of facts and conclude more simply
    that C just doesn't have arrays (in the sense of that term that we are used
    to). It is probably safe to say that C has "C arrays".

    With the usual understanding that if you have to qualify a thing, then it
    is understood that the thing you're describing is not really an instance of
    the larger class of things. It's just sort of *like* an instance of the
    larger class.
     
    Kenny McCormack, May 10, 2014
    #18
  19. Bill Cunningham

    Stefan Ram Guest

    What programming language, then, has formed this what your
    brain is »used to«?

    »15.03.08
    array
    An aggregate that is an instance of an array type and
    each element or appropriate group of elements in which
    may be referenced randomly and independently of the others.«

    ISO/IEC 2382-15, Information technology -- Vocabulary --
    Part 15 Programming Languages
     
    Stefan Ram, May 10, 2014
    #19
  20. So much of what has been said in this thread so far is over my head. I
    hope someone is learning something. But I see what you're saying as in p=a;
    But can you maybe exaplin to me in simpler terms that what the regualr
    poster C programmers are saying? What is meant by incompatible type? I think
    the pointer variable type is int or pointer to int. What does the compiler
    think a[] is ? Maybe another pointer? Sorry I'm not not getting what they're
    saying here.

    Bill
     
    Bill Cunningham, May 10, 2014
    #20
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.