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.
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
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.
Yes, you did: in your post of 5-Feb-2008 08:25, you wrote,
"A pointer's address for me is the address it points to."
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!
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!
Afaik, a pointer points to a value, but it doesn't have one.
Don't you mean: As Far As You Think You Know?
Pointer-to-pointer inellegant? Did you look at my strtol() example? Have you ever used strtol()?
Please suggest a more elegamnt method of knowing the position of the first invalid character in the input string.
In the general case, a function that needs to send back multiple values need to do one of the following: - Return a struct - Take a pointer to a struct as parameter, and fill in the struct. - Take multiple pointers as parameters, and update the individual parameters. - Return one value and report the other values through one or more pointers sent as parameters.
If you insist that a pointer's value is the value of the variable it points to, what value would you say a NULL pointer has? And what type si that value? If the pointer was of type pointer-to-int, is it's value then 0 or (int)NULL or what?
This is not advanced programming. The distinction between a pointer's address and it's value is what you are expected to learn during the first year if studying at a university.
It is a pre-requisite to later working with red-black trees, hash-tables, abstract data types, multi-dimensional dynamically allocated arrays etc. A real-world application may be performing just as much manipulation of a pointer as it is dereferencing the pointer, i.e. accessing the value (possibly also a pointer) that the pointer points to.
Have you tried to use qsort() to sort an array of pointers to structures? The comparison function really have to care about the level of indirection needed.
On my unix machine, the \usr\include directory contains about 1000 ** (after stripping away ** used in comments). That gives an indication that quite a lot of developers have thought that a pointer-to-a-pointer is an important concept. All these data structures and function calls does not work unless the user do care about the pointer, instead of just thinking about what it points to.
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.
One one man stands against the world, the world is often right. The alternative is that he is a genious, and have seen the light.
Since the world has not seen the light, and have chosen to implement a huge amount of API with multiple indirection, you have to learn to accept the concept, or you will have to invent your whole world around you.
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.
"... 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?):
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.
"One one man stands against the world, the world is often right."
To the insane, the rest of the world is crazy and they are the ones who are sane.
"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?!
The only reason why the language allows conversion from integers to pointers is for systems programming (embedded or when you write hardware drivers), i.e. when you need to access a hardware device at a specific location or when you need to locate variables dynamically at absolute locations.
Taking the address of a variable and convert to an integer and later converting the integer back to a pointer is something a program should hardly ever need. Most required address manipulation can be performed on the pointer. If you implement a memory manager, you might like to play with / and % (or more probably with >> and &) to figure out memory page and offset within memory page.
View all questions in Keil forum