This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Compiling differences between C51 v7.03 and v8.06

Hello!

I have uVision that compiles fine with the C51 v7.03 compiler and the related package, but not complete with the 8.06. I used two different Keil installations. All files are in the same folder.

In the 8.06 I get linker errors like "object does not fit in to pdata page" and "0080H". This looks like the compiler was thinking the PDATA was only 128 bytes, but it is set to 256 bytes in the startup.a51. Any clue what's different in the newer Keil package?

Also there is a warning in 8.06 (which does not show in 7.03) "converting non-pointer to pointer" on this

ptr_xdata = sPtr_obj->Adresse;


while the vars are set like this:

uchar uc_set_obj( uchar pdata *ptr_Set)
{
   uchar i;
   uchar xdata *ptr_xdata;
   struct stOBJADR code *sPtr_obj;

   sPtr_obj=&Obj[*ptr_Set];
   .
   .
   .
   ptr_xdata = sPtr_obj->Adresse;
}


The struct stOBJADR has a member "uint Adresse;"

I can see no wrong use of the pointers. I just want to be sure that the warning does not affect the code to not work correctly.

Parents
  • Right now, you are arguing against yourself. You are saying that you are fine with your terminology. You are saying that the important thing is that your programs works. But you are saying that pointers are confusing. If you do spend time learning the correct terminology, you will be less confused. And if you are less confused, your programs will work (even) better.

    I repeat for the xth time that I absolutely KNOW what a pointer is and I also KNOW the terminology, but this KNOWLEGDE does not help me understanding it. So I just bend the terminology and then I know two terminologies, of which only my one helps me out when using pointers and describing them. Instead of telling me a thousands time, you could also just leave me have my terminology and just try to understand it for the very moment you are thinking about the pointer warning problem I actually had and then turn back to your terminology.
    Now you could say "why don't you turn to our terminology for a moment?". Well, I could and I did. But it didn't help.
    My problem is, in your terminology: if I read a value out of a struct via a struct pointer and this value is an uint value and I put this value to another pointer, also of type uint, I simply expect this procedure to be correct. The warning message C289 says "converting non-pointer to pointer". In my understanding and I guess in everyone else too, this means that I was trying to convert something that's not a pointer (a normal variable, for exmple) to a pointer. Since ptr_xdata is declared as a pointer, it will still be a pointer after its value has changed. Because the struct was formerly initialised with an address of a variable and this address turns to an uint value when stored in the location of the struct. So when reading this value I actually do the same as setting the pointer value directly to the address of the variable.

Reply
  • Right now, you are arguing against yourself. You are saying that you are fine with your terminology. You are saying that the important thing is that your programs works. But you are saying that pointers are confusing. If you do spend time learning the correct terminology, you will be less confused. And if you are less confused, your programs will work (even) better.

    I repeat for the xth time that I absolutely KNOW what a pointer is and I also KNOW the terminology, but this KNOWLEGDE does not help me understanding it. So I just bend the terminology and then I know two terminologies, of which only my one helps me out when using pointers and describing them. Instead of telling me a thousands time, you could also just leave me have my terminology and just try to understand it for the very moment you are thinking about the pointer warning problem I actually had and then turn back to your terminology.
    Now you could say "why don't you turn to our terminology for a moment?". Well, I could and I did. But it didn't help.
    My problem is, in your terminology: if I read a value out of a struct via a struct pointer and this value is an uint value and I put this value to another pointer, also of type uint, I simply expect this procedure to be correct. The warning message C289 says "converting non-pointer to pointer". In my understanding and I guess in everyone else too, this means that I was trying to convert something that's not a pointer (a normal variable, for exmple) to a pointer. Since ptr_xdata is declared as a pointer, it will still be a pointer after its value has changed. Because the struct was formerly initialised with an address of a variable and this address turns to an uint value when stored in the location of the struct. So when reading this value I actually do the same as setting the pointer value directly to the address of the variable.

Children
  • "... another pointer, also of type uint"

    No!

    A pointer is not of type uint!

    In this particular case, it might just happen to be the same size as a uint, but that is a pure coincidence - it does not make it the same type.

    Just as the fact that some small dogs are the same size as cats does not make them cats!

    A pointer may be of type pointer to uint - but it is not of type uint!

    Pointers - and only pointers - have pointer type

    Therefore, any thing that is not a pointer does not have pointer type - in other words, they have non-pointer type

    Hence the warning is correct - you are assigning from a non-pointer (uint) to a pointer.

  • I repeat for the xth time that I absolutely KNOW what a pointer is and I also KNOW the terminology,

    Repeating it doesn't help when your explanations indicate the opposite.

    if I read a value out of a struct via a struct pointer and this value is an uint value and I put this value to another pointer, also of type uint, I simply expect this procedure to be correct.

    A pointer is not uint or whatever. A pointer is a pointer
    Also, you haven't even shown your definition of uint yet. It could be anything.

    A pointer is not an integer value to the compiler. It cannot and must not be, since it needs to be treated completely differently than an integer value in operations. Going back to my earlier example (did you read it, and think about it?):

    unsigned int some_int = 0;
    unsigned int *some_ptr = 0;
    
    some_int++;
    some_ptr++;
    

    What is the value of the two variables after the increment ? The correct answer should also explain why pointers and unsigned integers are two completely different data types. That they take up the same amount of memory is pure coincidence.

    In my understanding and I guess in everyone else too, this means that I was trying to convert something that's not a pointer (a normal variable, for exmple) to a pointer.

    What is a "normal variable" ? An integer is "normal", and not a pointer, and you are trying to convert it implicitly to a pointer. The compiler is totally correct when it issues a warning. If you want the warning to disappear, you need to do an explicit type cast (which you said you did, but you did not post the code you used, so we cannot tell if it is correct).

    You need to grab a C textbook and read up on 1) pointers and b) operators that work on pointers, especially the "member reference from pointer" operator "->".

    some_struct_ptr->some_int_member
    

    evaluates to the value of some_int_member, not to its address. If you want the address, you need to use

    &some_struct_ptr->some_int_member
    

  • And for the x:th time: you can not absolutely know about pointers and how it is used if you think that the address of a pointer is less important (or more or less irrelevant) than the address of the variable it points to.

    Basically, you are ignoring arithmetic on pointers, which is something that is very commonly done.

    When you do choose to see a pointer's address, a pointer's value and the value it points to as three separate things, your life will be a lot easier.

    char buf[100];
    char *p = buf+1;
    char **pp = &p;
    *buf = 'H';
    *p++ = 'e';
    p[0] = 'l';
    p[1] = 'l';
    buf[4] = 'o';
    *(buf+5) = '\0';
    *pp = strchr(buf,'\0');
    printf("Number of characters in string is %ld\n",(long)(p-buf));
    

    So when reading this value I actually do the same as setting the pointer value directly to the address of the variable
    And for that, you should tell your friendly compiler that the number you have really is an address - the address of an object of the same type that your left-hand-object (the pointer) is expected to point at.

    You are assuming that a pointer is a number and because of this, the compiler should always accept the assign of any number to any pointer without getting upset.

    Note that pound and dollar are two currencies. The amount of money are always numeric. But you can't simply assign a dollar value to a pound purchase. If you try to do that, the shop will issue a format conversion warning. The conversion from one currency to a different currency requres a type cast. For currencies, this is normally done by checking the current sell price for dollar and the current buy price for pound. In the case of converting from one currency to another, there is a change to the numeric value. The same thing happens when performing an assign from an integer to a floating point number, or the reverse.

    In some special cases, there is no actual conversion performed. But the cast should be there anyway. Not because a change is needed to the numeric value, but because a change is needed to the data type, i.e. to tell the compiler that the object on the left and the object on the right are both of the same data type (or at least of compatible data types) - even if a quick look says something else.

    Adding a type cast when assigning a number to a pointer tells the compiler that the numeric source value is a proper value for storage in the pointer. In this case, that the number really is a pointer value and suitable for the pointer you want to assign to.

    This is no different from the following:

    int a = 5;
    unsigned b = 5;
    if (a == b) ...
    

    A lot of compilers will notice that a is a signed integer, and b is an unsigned integer, and will issue a warning about a comparison between signed and unsigned data. The warning is there because there is a reasonable chance that the signed/unsigned mismatch is caused by an invalid assumption somewhere.

    When you add a typecast, the compiler will check if it is technically possible to treat the right-hand value as compatible with the left-hand value. If you don't write an explicit typecast, the compiler will check it's available automagic data type rewrite rules (as specified by the standard) to see if it somehow (with or without data loss) can convert the right-hand value into something suitable for the left-hand value. However, unless the compiler is really, really happy about any conversion rules it knows about it will complain by issuing a warning. Some compilers have a larger set of warnings than others. But when they do warn, you should care, because that means you are living on the edge.

    In your case, a proper cast will tell your compiler that you have turned off the power and removed the fuse before doing electrical work in your house. The cast will mute the warning since you are giving the compiler a written contract where you, the developer, dearly promises that the value in your uint really, really do represent a good pointer to a variable of the correct data type.

  • int      a = 5;
    unsigned b = 5;
    
    a = b;
    

    Could generate a warning, because some legal unsigned values won't fit in a signed int

    Similarly,

    int      a = 5;
    unsigned b = 5;
    
    b = a;
    

    Could generate a warning, because some legal signed values won't fit into an unsigned int.

    In both cases, you can tell the compiler that it's not an accidental oversight by giving an explicit cast.

    Exactly the same applies when assigning a non-pointer to a pointer, as has already been explained.

  • "In my understanding and I guess in everyone else too, this means that I was trying to convert something that's not a pointer (a normal variable, for exmple) to a pointer."

    Yes correct:
    The pointer is ptr_xdata;
    The non-pointer is sPtr_obj->Adresse.

    "Since ptr_xdata is declared as a pointer, it will still be a pointer after its value has changed."

    Correct - but the warning is not about that:
    Read it again, the warning is about converting a non-pointer to pointer - that is, the thing being converted is the non-pointer

            ptr_xdata  =  (sPtr_obj->Adresse);
                    ^     ^
                    |     |
                    |     |
    This is a pointer     This is not a pointer (it's a uint)
    


    So the above assignment is from a non-pointer (on the right-hand side) to a pointer (on the left-hand side)

    And so the warning is correct:

    "converting [from] non-pointer to pointer"

  • You don't seem to get it. I don't understand it, because it's confusing.

    In this case, it is actually the reverse. It is confusing because you don't understand it.

    A number of million students have thought that pointers are confusing. However, there are quite a lot of programmers in this world that do know about pointers now. And they can testify that as soon as they really did understand pointers, they no longer see them as confusing.

    It's just a question of getting the correct internal picture of the pointer concept. Before you have a working mental picture, they will be confusing. With the picture in place, you will think: gosh, that was easy.

    The reason so many programs fails because of pointer errors, is not because pointers are hard to grasp but because they are powerful and a more powerful tool is inherently more dangerous. People makes mistakes. When they make mistakes with pointers, bad things happens. So a developer should always be extra careful when working with pointers.

    Right now, we are trying to get you to change your internal view of pointers. A number of us believe that the terminology really is crucial to this task. If you see a pointer as a variable, with the normal properties of a variable (location, value, size, ...) then we believe you have a better chance to be able to switch your mental image of pointers, and be able to figure out their full potential. And their full potential really do require you to think about the address of the pointer, i.e. where it is stored. You really do have to understand why several steps of indirection is needed, or why programs must be able to modify the value of the pointer, and not just the value it points to.

  • I repeat for the xth time that I absolutely KNOW

    And everybody else has to keep repeating, that you don't know anywhere as much as you think.

    You're contradicting yourself all the time. One moment you claim you understand pointers perfectly, the next you admit you're confused by them.

    You've stated painfully obvious nonsense like this, several times by now

    this value is an uint value and I put this value to another pointer, also of type uint,

    It shouldn't need saying yet another time, but apparently it does: No, that pointer is not of type uint. It's of type pointer-to-uint. A uint is not a pointer any more than a car is a driver's license. Staying in that image, you got a warning because you tried to put the car in your inside pocket.

    Everybody, including you, is allowed to be wrong once in a while. But that doesn't mean we'll seeingly tolerate your insisting on staying a confused fool forever.

  • "the struct [element?] was formerly initialised with an address of a variable"

    I presume you're talking about sPtr_obj->Adresse - yes?

    If this is supposed to hold the address of a variable, why was it not properly defined as a pointer in the first place?!

  • I presume you're talking about sPtr_obj->Adresse - yes?
    If this is supposed to hold the address of a variable, why was it not properly defined as a pointer in the first place?!

    Because it does not really work to access a pointer address value inside a struct that is pointed to by a pointer. It should be something like

    ptr_xdata = *(sPtr_obj->Adresse)
    

    if Adresse wouldn't be an uint, but a pointer instead. We had severe problems in the past calming down the compiler when using such a way. The chance is 50:50 that it will work. Means, the compiler was unsure how to handle it.

  • Means, the compiler was unsure how to handle it.

    That is a statement to print and put on the wall. The next time I get a compiler error, I will complain about insecure compilers. That is almost as funny as saying that the car stood still when the tree suddenly decided to run into it.

    You can have any (!) level of pointer indirection (with or without any structs in the indirection chain) without any problems separating operations on the pointer value (the pointer) or on the referenced object. It all follows from the operator precedence rules.

  • "Because it does not really work to access a pointer address value (sic) inside a struct that is pointed to by a pointer"

    Doesn't it?

    If the struct element is correctly defined as a pointer, then there is no difference whether it is read via a direct access as

    ptr_xdata = some_struct.some_pointer
    

    or via a pointer as

    ptr_xdata = struct_ptr->some_pointer
    

    "We had severe problems in the past calming down the compiler when using such a way"

    I very much suspect that all comes back to you not really understanding what's going on.

    "chance is 50:50 that it will work"

    The compiler will do exactly what you tell it to do - but, as mentioned earlier, if you cannot express what you want correctly, then the compiler cannot guess for you...

    "the compiler was unsure how to handle it."

    Again, the compiler does what you tell it - but, if you tell it rubbish, you will get rubbish as a result.

    Hence the well-known programming term, GIGO = Garbage In; Garbage Out.

  • Because it does not really work to access a pointer address value inside a struct that is pointed to by a pointer.

    It should work just fine as long as proper attention is paid to things like operator precedence. This functionality is well-defined and definitely not compiler-specific. If it does not work, then there is either a mistake in the C code or a bug in the compiler. The former is usually much more likely than the latter.

    It should be something like

    No. It shouldn't be something like X - this leads to bugs. The syntax for doing that is very clear and if you would not insist on ignoring how to work with pointers in C, you would probably know how to do it.

    Have you read up on pointer-specific operators, especially the "Member access from pointer" operator, "->" ?

    ptr_xdata = *(sPtr_obj->Adresse)
    

    What is this supposed to do ?

    1. Copy the value of the structure member Adresse to ptr_xdata ?
    2. Copy the address of the structure member Adresse to ptr_xdata ?
    3. Copy the contents of the memory address pointed to by the structure member Aresse to ptr_xdata ?

    We had severe problems in the past calming down the compiler when using such a way.

    The compiler should have absolutely no trouble parsing a trivial operation like that, provided it is fed with the correct code.

    The chance is 50:50 that it will work.

    Compilers don't roll dice. Provided that you didn't switch compilers somewhere in the middle, there should be no statistics involved. The code is either correct, or it is not.

  • The compiler will do exactly what you tell it to do - but, as mentioned earlier, if you cannot express what you want correctly, then the compiler cannot guess for you...
    "the compiler was unsure how to handle it."

    Often, a compiler will try to figure out what you ment and instead of an error issue a warning, which, in a way means "the compiler was unsure how to handle it.". Then, it is up to you to accept "unsure" or find the reason for the warning and remove it. Should you decide to accept 'unsure' please tell me and I will avoid buying any of your products.

    Again, the compiler does what you tell it - but, if you tell it rubbish, you will get rubbish as a result.

    Hence the well-known programming term, GIGO = Garbage In; Garbage Out.

    I thought that in the OK it was "RIRO rubbish in, rubbish out" :)

    Erik

  • "Means, the compiler was unsure how to handle it."

    Assuming that you're running the C51 compiler on Windows on a PC using , the compiler will be consistent with its decisions.

    As far as I am aware, the random computer is not in common usage.

    You obviously use English as a method of communication - Haven't you noticed that it (like all languages) is based on mutual understanding.

    If someone, unilaterally, opts to change the meaning of a word, then that person is obviously going to generate misunderstanding.

    Why to you want that someone to be you?

  • Yes, I suppose it should be - but we are beset by far too many americanisms...

    :-(