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.
As you say, ptr_xdata is a pointer, and sPtr_obj->Adresse isn't - so the warning is perfectly correct!
As usual, an explicit cast should both stop the warning and make your intention clear...
"I just want to be sure that the warning does not affect the code to not work correctly"
There is always a risk in playing fast-and-loose with pointers like this!
I think you should be OK with the XDATA-Specific pointer...
Hello Andy! Thanks for your help.
You are wrong. "sPtr_obj->Adresse" is a struct pointer and gives me a number, an address that "ptr_xdata" is set to.
A pointers address?
The address of a pointer is another pointer.
What you where thinking about is the value of a pointer, not the address of a pointer.
You may decide that you would like to see the value of a pointer as an integer - after all, the memory can bee seen as a large data array with an integer index.
However, to the language, an integer and a pointer are two separate data types, just as char and int are two separate data types.
Almost all compilers will complain in almost all situations if you treat a pointers as an integer or an integer as a pointer.
By adding a typecast, you can inform the compiler that you are the master, and that you specifically want the integer to be known as a pointer value. You are allowed to do it, but it is up to you to make sure that integer value represents a valid pointer.
But once more: The value of a pointer may be an integer value, but it is not correct to assume a pointer value and an int (or unsigned int, long, ...) to be equivalent. Because they are not equivalent, the compiler will warn you.
It is only when programming in assembler, where you can play freely with addresses, since an assember doesn't have strict type checking.
Although the 8051 specifically has three distinct arrays (four, if you include the SFRs...)
Guys, please don't be so picky. A pointer's address for me is the address it points to. And this address is always uint, means two bytes. So if you're setting a pointer address, you should always use an uint value, while a char value would also do. That's all I meant. Not how many bytes a pointer actually consumes when compiled to machine code.
"Guys, please don't be so picky."
This is not picky - you have some very basic misunderstandings here! It's just as well that the compiler did warn you - otherwise you're heading for some really big traps!
"A pointer's address for me is the address it points to."
That is simply incorrect!
A pointer is a "variable" like any other; as such, it has a value, and it has an address - and they are in no way related!
"And this address (sic) is always uint, means two bytes."
That is not true in general, and not true for the 8051 specifically:
A pointer to DATA, IDATA or PDATA space is just a single byte; A pointer to CODE or XDATA is, indeed, 2 bytes; A Generic pointer - able to address any of the above - is three bytes
"So if you're setting a pointer address (sic), you should always use an uint"
Only in cases where the size of a uint (whatever that means) matches the size of the pointer.
"while a char value would also do"
Not necessarily: in general, you can only say that a char value might also do.
"Not how many bytes a pointer actually consumes when compiled to machine code."
But that is the value that actually matters - because that is the value that the code will actually be using!
Exactly. There is no guarantee of a one-to-one mapping of all aspects of a pointer when storing it's value in an integer.
A pointer may also have explicit rules about what values are allowed. For example a huge pointer on 16-bit x86 requires that the value is normalized, i.e. that the offset part is in the range 0 to 15, while the segment part can take the full range 0 to 65535.
The address of a pointer (a pointer's address) is a pointer to a pointer, and the concept is called dual indirection.
You need to use dual indirection when you program in C and want a C function to take a pointer as parameter and be able to modify the parameter on return.
It is also a common concept on hardware platforms that does not have a Memory Management Unit (MMU) and where you need to move allocated memory blocks around without having to know what parts of the code that have a reference to the memory blocks.
But no, it isn't picky to very clearly separate the value and the address of a pointer. There are a large number of programming situations where you must keep track of the number of indirections - and the compiler do keep track of the data type of pointers, i.e. a pointer to an int or a pointer to a pointer to an int are two very different data types, resulting in a warning if you mismatch your assign. The indirection of a pointer to a pointer to int is a pointer to int. The indirection of a pointer to int is the int, i.e. no longer an address.
You are all right, but I think this code is still not generally wrong. It wasn't written by me and it always worked. In order to distinguish the addresses a pointer is related to, I call the address the pointer points to the pointer address. The address where the pointer itself is located or managed, I call base address. But this address is commonly not used in consideration. When I'm writing C, then it's painful enough to fulfill the microprocessor's picky demands, so I don't want to care about if the pointer's base address consists of two or three bytes. Only if I wouldn't have enough RAM.
Back to my problem: Putting a cast in front of the particular line did not succeed. It still reports warning C289, which is not described in the C51 help file.
"I call the address the pointer points to the pointer address."
In your own little world, you can call it what you like. You just have to understand that it is completely contrary to what the rest of the world understands by that term. It also suggests that you have not fully grasped what's going on.
"The address where the pointer itself is located or managed, I call base address"
That is also contrary to the generally-accepted meaning of that term. A "base" address is generally accepted to mean the datum (or reference) from which an offset or relative address is calculated.
" But this address is commonly not used in consideration"
Oh yes it is!
As Per said, having a pointer to a pointer is quite common; in fact, the C51 compiler supports up to 19 levels of indirection! http://www.keil.com/support/man/docs/c51/c51_xd.htm
It is also common to need to know the address (ie, location) of a pointer when debugging...
"When I'm writing C, then it's painful enough to fulfill the microprocessor's picky demands"
Yes - you can get away with sloppy terminology when talking to other people, but not when talking to a compiler!
If you think 'C' is picky, you should try writing in Pascal or Ada...
Assembler may seem less "picky", but that just puts even more responsibility on the programmer to ensure that they have everything right!
"I don't want to care about if the pointer's base address (sic) consists of two or three bytes"
In general, you don't need to - it's only when you start trying to assign a non-pointer value (such as a uint) to a pointer that you need to be really sure of what you are doing...
"Only if I wouldn't have enough RAM."
No, that has nothing to do with it! If you mess up a pointer, it can point to absolutely anywhere in memory, and do untold damage.
That's why pointers in 'C' are both so powerful and so dangerous!
Which is why it is so important that you have a really firm understanding of what's going on.
Which is why compilers tend to give warnings when there's any doubt...
"Back to my problem: Putting a cast in front of the particular line did not succeed"
Show exactly what cast you used!
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.
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.
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.
"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.
Yes, you did: in your post of 5-Feb-2008 08:25, you wrote,
For any other variable, "the variable's address" means the address of the variable - but you said you're using "the pointer's address" to mean the value of the pointer.
I did not!
I can only repeat, that for me a pointer's address is NOT the same as the address of a pointer. Address is defined as a target, at least in my language. So a pointer points to a target (address) and this is the pointer's address (or target). The address of the pointer, where it is located in RAM, should be pronounced as the location of the pointer.
A pointer's value for me is the value it points to. Like the address (number) in the register DPTR is the address it points to. Anything else does not make sense, since no one cares for the pointer itself, except for its data type, even if it is a pointer to a pointer.
You all may call me unteachable, but this is my way of understanding this confusing topic. Confusing because when you hear the first time about pointers (some years ago in my case), people like to confuse with the fact that a pointer points to a certain address/value, but also has an address/value, as you call it. Whereas I don't see any sense in concerning the address of the pointer itself. It just confuses...
"I did not!"
You most certainly did. The quote came from your post. It's right up there in your post that Andy referenced, recorded for history and for all to read.
"A pointer's value for me is the value it points to."
A pointer's value is an address. A dereferenced pointer yields the value addressed by the pointer.
"a pointer's address is NOT the same as the address of a pointer."
OK, maybe that's just a problem with English not being your first language - but, in English, the phrase "a pointer's address" has exactly the same meaning as the phrase "the address of a pointer"
That's nothing to do with 'C' or programming - that's the way English works.
Just as "a dog's breakfast" has the same meaning as "the breakfast of a dog"
Or "a variable's address" has the same meaning as "the address of a variable"
Or "a variable's value" has the same meaning as "the value of a variable"
Or "a pointer's value" has the same meaning as "the value of a pointer"
In general, "a thing's property" has the same meaning as "the property of a thing"
"Address is defined as a target, at least in my language"
Again, not in English.
In English, an "address" identifies a location - whether it's a postal address, that identifies the location of a house, or a memory address, that identifies the location of a particular cell within the memory array.
"So a pointer points to a target (address)"
Correct
"and this is the pointer's address (or target)."
Wrong! That doesn't even make sense by your own reasoning!
If the pointer points to any address, then that address cannot be the pointer's own address - unless the pointer is pointing to itself!
"The address of the pointer, where it is located in RAM, should be pronounced as the location of the pointer."
Correct - and "the location of the pointer" is synonymous with "the address of the pointer" which is also synonymous with "the pointer's address" which is also synonymous with "the pointer's location"
"Whereas I don't see any sense in concerning the address of the pointer itself."
Just because you don't see a need for it doesn't mean that there is no need for it!
It is also no excuse for allowing your terminology to become misleading.
You have already been given several examples of where there is a need to be concerned with it
You all may call me unteachable, but this is my way of understanding this confusing topic.
You got that backwards. It's exactly your way of thinking that renders this topic so confusing for you. It's getting in the way of your understanding it.
Your private terminology is based on firmly held, yet incorrect beliefs. Mismatch of thought with reality is the consequence. That's pretty much the definition of "confusion".
The address of an ordinary variable is generally every bit as important as its value. The same holds for pointer variables: their address is as important as their value. Pretending otherwise will bite you in the lower back soon enough.
"You all may call me unteachable"
OK then: you are unteachable; that is, in English, at least.
Maybe it'd be better if you could find someone to explain this to you in your own language?
Just think of a pointer to a pointer!
char variable; char *pointer_to_variable; char **pointer_to_pointer_to_variable;
"It just confuses"
Only because you still don't understand it, and still insist on using confusing terminology!
Or "a pointer's value" has the same meaning as "the value of a pointer
Afaik, a pointer points to a value, but it doesn't have one.
You sure? A data packet in the internet is sent to an address, the IP. Network hardware has a MAC address, where data is addressed to. If you send a letter, you send it to an address. Perhaps I should have written destination instead of target. It's sometimes not easy to distinguish between multiple words in English (target, aim, goal, destination) that have only one meaning in German (Ziel).
But still, if a pointer points to a pointer, I don't need to care about both pointer locations. This is C, so I don't care about memory addresses. This is a matter of opinion, but I don't find it very elegant to put a pointer to a pointer...
I'm also not the super programmer like you folks seem to be. I rather do many things in my life than just learning a computer language down to its deepest meaning. What counts is that it has to work. And it does! Even without non-sense warnings of a picky compiler.
You don't seem to get it. I don't understand it, because it's confusing. I can understand anything that is logical for me. Electronics, current, atoms, physics, biology down to molecules, bits and bytes. I can explain you, down to the level of an electron, how a computer works, but this is not logical to me. My terminology helps me to understand it. It's enough to know what a pointer is and does, no need to understand it.
You plainly don't understand it, and your bad terminology may well be a contributing factor to that, if not just a symptom of it.
It's not complicated.
Keep it simple and just use the same terminology as the rest of the world.
"It's enough to know what a pointer is and does, no need to understand it."
If you know what it is and does, then you really should be capable of understanding it!
View all questions in Keil forum