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
  • But you do have to learn to start thinking and talking about a pointers value, not a pointers address.

    You will get into trouble if you do not see it as a variable. And variables have values. Sometimes they also have memory addresses.

    A base address is something completely different, so please do not continue thinking about the address of a pointer as a base address. The start address of an array could be seen as a base pointer but a pointer and an array are not identical.

    char buf[1000];
    char* p = buf;
    

    Now you think that the address of p is a base address. Why? The address of p has nothing to do with buf, and isn't the base of anything meaningful.

    The reason it is painful for you to "fulfill the microprocessor's picky demans" is that you have not spent any time on figuring out why. If you know why something is as it is, you will start to see a pattern. And when you see the pattern, it will not feel like any picky demands anymore. People have spent huge amounts of time thinking about logical (not picky) solutions to the language design, the processor instruction design, the processor peripherials etc.

    Everything you choose to treat as black magic will continue to be black magic. And black magic is something we humans are not comfortable with. It is up to you to decide if you want to take control, or if you cant to continue to be confused. As long as you decide to invent your own terminology, you will never be able to buy books and read. You will just be confused, since the books will - in your mind - be picky and invent the wrong terminology...

    You say you don't want to have to care about if a pointer's base address (sic!) is two or three bytes. You don't have to know the size of a pointer variable, as long as you stop playing with addresses in integers. For small chips it may still be good to know the size of a pointer variable, since you have limited memory in the chip. But that is a completely different issue. Right now, your problem is that you are writing code where you need to make a lot of assumptions. This specifically forces you to have the knowledge to be able to figure out if the assumptions are correct or not.

    You still have a warning?

    Maybe you should post the full set of data declarations, and your rewritten source line - including the type cast. Only then will people on this forum be able to tell if your cast is correct or not.

Reply
  • But you do have to learn to start thinking and talking about a pointers value, not a pointers address.

    You will get into trouble if you do not see it as a variable. And variables have values. Sometimes they also have memory addresses.

    A base address is something completely different, so please do not continue thinking about the address of a pointer as a base address. The start address of an array could be seen as a base pointer but a pointer and an array are not identical.

    char buf[1000];
    char* p = buf;
    

    Now you think that the address of p is a base address. Why? The address of p has nothing to do with buf, and isn't the base of anything meaningful.

    The reason it is painful for you to "fulfill the microprocessor's picky demans" is that you have not spent any time on figuring out why. If you know why something is as it is, you will start to see a pattern. And when you see the pattern, it will not feel like any picky demands anymore. People have spent huge amounts of time thinking about logical (not picky) solutions to the language design, the processor instruction design, the processor peripherials etc.

    Everything you choose to treat as black magic will continue to be black magic. And black magic is something we humans are not comfortable with. It is up to you to decide if you want to take control, or if you cant to continue to be confused. As long as you decide to invent your own terminology, you will never be able to buy books and read. You will just be confused, since the books will - in your mind - be picky and invent the wrong terminology...

    You say you don't want to have to care about if a pointer's base address (sic!) is two or three bytes. You don't have to know the size of a pointer variable, as long as you stop playing with addresses in integers. For small chips it may still be good to know the size of a pointer variable, since you have limited memory in the chip. But that is a completely different issue. Right now, your problem is that you are writing code where you need to make a lot of assumptions. This specifically forces you to have the knowledge to be able to figure out if the assumptions are correct or not.

    You still have a warning?

    Maybe you should post the full set of data declarations, and your rewritten source line - including the type cast. Only then will people on this forum be able to tell if your cast is correct or not.

Children
  • LOL.

    You won Andy. But there are a lot of similarities in our answers ;)

  • So if you're setting a pointer address, you should always use an uint value

    Not true. intptr_t is the integer type wide enough to hold a pointer; ptrdiff_t is the type wide enough to hold a difference of two pointers. Neither one is necessarily the same as an unsigned int.

    Compilers are allowed to warn about whatever they feel like. Given the complexity of the 8051 addresses spaces, as mentioned above, along with the variable width of pointers in the C51 implementation, I think it's a good thing for C51 to be sensitive in this regard. You're always free to disable or ignore the warning if you think it's silly, but in this case I'd recommended taking it to heart and putting in the proper casts where needed to convert the data type explicitly, rather than relying on default, implicit, conversions -- even if those did work in version 7.

  • char buf[1000];
    char* p = buf;
    Now you think that the address of p is a base address. Why? The address of p has nothing to do with buf, and isn't the base of anything meaningful.

    This is what I consider as pointer address.

    But we better stop here. I'm programming since a few years now and never had such problems. I think I don't need to read a bible about pointers, just to write some code. That's not the meaning of a computer language. To be more complicated than its inventor.

    My conclusion is: if I set a pointer address in XDATA with a number I read from a struct and as long as this number is 2 bytes long and thus valid, then the pointer has to be set. Period.
    By assigning a pointer's address I'm not doing a pointer conversion, because the pointer only changes the byte it points to. Nothing more, nothing less.

  • This is what I consider as pointer address.

    We know that by now. And it's still wrong, because this use of the term is guaranteed to confuse everyone exposed to it --- apparently including it's original user, i.e. you.

    long as this number is 2 bytes long and thus valid,

    That "thus" exposes that you still haven't understood what the issue actually is. No, a 2-byte number is not self-evidently "valid" to hold a pointer. You need 3 bytes to hold an arbitrary pointer in C51.

    To put it bluntly: you're deluding yourself. You don't understand pointers anywhere as well as you think you do. Your insistence on ill-fitting terminology may well be part of the problem, preventing true understanding.

    then the pointer has to be set.

    What exactly made you think it wasn't? You say you've been programming for years, but you still don't recognize the difference between an error and a warning?

  • "I think I don't need to read a bible about pointers"

    The way you write about them suggests otherwise.

    "as long as this number is 2 bytes long and thus valid"

    That is a non-sequitur; ie, the conclusion does not follow from the reason stated.

    A 2-byte number might happen to be valid as an XDATA pointer, or it might not - the fact of its size being 2 bytes has absolutely no relation whatsoever to its validity (or otherwise) as a pointer!

    "then the pointer has to be set"

    There never was any doubt that the pointer would be set - the question is whether it gets set to anything meaningful...

    "By assigning a pointer's address I'm not doing a pointer conversion"

    By assinging from an int to a pointer you are doing an implicit conversion!

    "the pointer only changes the byte it points to"

    Eh??!
    A pointer of itself changes nothing; only when you dereference the pointer does the pointed-to location get accessed.

    You still haven't shown the cast that you used and that still gave the warning. If you want to get back to that, then do it...

  • "That's not the meaning of a computer language. To be more complicated than its inventor."

    It isn't complicated; it is really quite simple.
    You are the one that is complicating it by messing-up the terminology!

    Every program "object" - variables and functions - has an address, and that address is the location at which the object itself is stored.
    Simple.
    No exceptions.

    This is the terminology used by the inventors of the language - Messrs Kernighan & Ritchie.

    You are the one who is complicating this by using "address of" when applied to a pointer to mean something different from "address of" when applied to any other object!

    Because you have thus modified the meaning of "address of" when applied to a pointer, you then also have to invent another term to use when you do want to refer to the location of the pointer itself!

    All this is further complicated by the fact that the non-standard terms you have chosen already have well-established and quite different meanings in the more general context!

  • Note that all variables are not guaranteed to have a memory address - they could be register-based too. On one hand, that regsiter could be seen as an address, but on the other hand, the compiler could move the variable around if it feels like it. For some processors with few GP registers and slow memory access (at least old 16-bit x86 processors) there was some advantages to switching registers.

  • Seems like we talking past each other.

    In other words: I know what a pointer is, but for me the only thing of interest is what it does. That's what I was talking about. An example:

    char *ptr;
    char a;
    ptr = 7;
    

    is the same principle as

    ptr = &a;
    

    where the address of 'a' is not determined.
    I'm setting the pointer to point to an address, whether this is a number (an absolute address) or a variable. This is all what is done in the code above.
    Where is the conversion? I can't see it.
    Because warning C289 says "converting non-pointer to pointer" in v8.06. Actually I'm setting a pointer to an address of a variable.

    1. A struct is declared.
    2. The struct has a member 'Adresse', uint type.
    3. This member is set to the address of a variable, let's say &test.
    4. A struct pointer is set to this struct.
    5. A char pointer is declared.
    6. The struct pointer is set to point to the member 'Adresse'.
    7. The value of 'Adresse' is read out and used to set the char pointer to point to 'test'.

    Totally OK for me. Where's the problem?

  • Where is the conversion? I can't see it.

    You cannot see it, but the compiler can. Even though C is a fairly weakly-typed language, an integer and a pointer are not the same for the compiler, and need to be treated differently in a number of situations.

    Consider the following code snippet:

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

    Can you tell what the value of some_int will be after the snippet ? (that's trivial, right ?)

    Can you tell what the value of some_ptr will be at the end of the code snippet ? (If yes, please state what it will be and why. If no, please state what information you are missing.)

    And that is just one example.

    Since C is fairly weakly-typed, the compiler might allow a number of so-called implicit type casts. More high-level languages are usually more strongly-typed, and would require an explicit cast in many situations.

    Now back to your warning - can you post the line with the explicity type cast you use that still results in a warning ?

  • The & in 'C' is the "address-of" operator; the result of the expression

    &a
    

    gives the "address-of" a - so its type is self-evidently "pointer to a"

    So, when you write

    p = &a
    

    the compiler can clearly see that you are assigning a pointer-type expression (&a) to a pointer-type variable (p)

    However, when you write

    p = 7
    

    it is not self-evident that 7 is intended to be a valid address; more particularly, when you write

    p = a
    

    there must be some doubt that you might have meant

    p = &a
    

    hence the compiler gives the warning.

    To avoid the warning, you can make you intention clear by using an explicit cast:

    p = (char*)a
    

    If you're still getting the warning, you must have done it wrong.
    If you want an explanation of what you've done wrong, you will have to show what you have done!

  • The problem is that it is not self-evidently correct.

    The compiler has noticed the possibility that what you wrote was not what you intended - and so it gives you a Warning.

    The Warning is particularly justified as this is such a common mistake - like writing "=" instead of "==" in an 'if' clause...

    One more time: you can stop the warning by using an appropriate explicit type-cast.

  • You are the one who is complicating this by using "address of" when applied to a pointer to mean something different from "address of" when applied to any other object!>
    I never wrote this. English is not my native language, but I guess I'm not totally wrong when understanding that a pointer address is not the same as the address of a pointer.
    The address of a pointer is the pointer itself.
    So how do you call the address the pointer points to in your terminology? I just call it pointer address. Still because I don't need to care where (at which address) the pointer itself is located.

  • To avoid the warning, you can make you intention clear by using an explicit cast:
    p = (char*)a

    Now that makes sense to me.

  • "The address of a pointer is the pointer itself."

    No: The address of the pointer is the location of the pointer itself.

    "So how do you call the address the pointer points to in your terminology?"

    That is the value of the pointer.

    "I just call it pointer address"

    Don't call it that - it's just confusing!

    "Still because I don't need to care where (at which address) the pointer itself is located"

    You would care if you needed a pointer to the pointer...

  • The address of the pointer (or variable) is the same as the pointer's (or variable's) address, i.e. the location where the pointer (or variable) is stored.

    The value of the pointer is an address - the address that the pointer points to.

    "The address of a pointer is the pointer itself." should be rewritten as:
    "The address of a pointer is the location of the pointer itself".

    The address the pointer points to? That's the value of the pointer. Just as the value of variable my_int below is 5.

    int my_int = 5;
    

    Variables stores values. It doesn't matter what data type the variable has (pointer, pointer, struct, ...), it still stores one or more values.

    As soon as you write more complex programs, you regularly do have to care about the address of the pointer, i.e. where the pointer is stored. Or, more specifically, your application will need the address of your pointer, so that it will be able to indirectly (through a pointer) modify the address stored in the pointer (the pointer's value).

    Look at strtol(const char* str,char **endptr,int base) which takes a pointer to a pointer as second parameter.

    char input_string[] = "12345broken chars";
    char *end;
    long val;
    val = strtol(input_string,&end,10);
    if (*end != '\0')
        printf("Invalid number string\n");
    else
        printf("The value was %ld\n",val);
    


    Now the pointer end (not what it points to) will be modified to point at the first non-valid character in the input string.

    This is a simple case where you use the address of a pointer to change the pointer instead of changing what it points to. There are many more - many of them way more complex - that are commonly used in standard C/C++ programs. Some RTOS may have half their API centering around pointers to pointers... Array manipulation functions are a different area where multiple levels of indirection is often needed.