Memory Problem in PIC18F46K22

takao21203

Joined Apr 28, 2012
3,702
It's funny that you mention that!

One of the things I learned last week is that unlike BASIC, C, for some strange reason, doesn't use line numbers. I suppose this so that you can write more concise code (and probably save the memory that would normally store the line numbers, I guess). But, without line numbers, I can't figure out where the GOTOs go to.

Maybe the memory is leaking from the space where the line numbers are missing?

I'm going to put line numbers back in my C code to see if that fixes the problem. I'll let you know.
That will be tedious but rest assured, in the assembly code there will always be line numbers, or lets say, kind of line numbers.

C is just hiding the GOTOs as they dont look nice if there are too many. Its an automated means to write assembler. Once you used the disassembler for a while for your C code, you'll know which C construct will produce what in assembler.
 

joeyd999

Joined Jun 6, 2011
5,283
That will be tedious but rest assured...
But successful! I went ahead and added all the line numbers back, changed the "printf"s to "PRINT", typed RUN, and everything worked! Here's proof:

Rich (BB code):
READY
RUN
HELLO, WORLD!
WHAT IS YOUR NAME? JOEYD999
HELLO, JOEYD999. NICE TO MEET YOU.
READY
>_
Thanks for all the help. My boss is going to be really happy! Oh, and C is great. I love it!
 

nsaspook

Joined Aug 27, 2009
13,262
It's funny that you mention that!

One of the things I learned last week is that unlike BASIC, C, for some strange reason, doesn't use line numbers. I suppose this so that you can write more concise code (and probably save the memory that would normally store the line numbers, I guess). But, without line numbers, I can't figure out where the GOTOs go to.
The structured equivalent of a GOTO in C is the 'switch' statement (with break). If you have a programming problem that needs a GOTO like functionally restructure it to use a switch that can also replace long if/then/else statements.

This is a GOTO -> label example: Don't use code like this.
http://www.tutorialspoint.com/cprogramming/c_goto_statement.htm
 
Last edited:

joeyd999

Joined Jun 6, 2011
5,283
The structured equivalent of a GOTO in C is the 'switch' statement (with break). If you have a programming problem that needs a GOTO like functionally restructure it to use a switch that can also replace long if/then/else statements.
I guess that makes sense. But I don't have any switches. Just keys. And one of the keys is marked "BREAK". Is that what you mean?

But when I press it, the result is:

Rich (BB code):
BREAK IN 50
>_
or something like that.

I am starting to think that the book I learned from is not that good, although it does mention what you said about BREAK. Maybe you can recommend something better. Here is what I have:

 

Attachments

NorthGuy

Joined Jun 28, 2014
611
Yes it is a conversion of y (the value it contains) into a pointer to y (the address the pointer points to will be the value of y, and the displacement will be multiplied by the size of the type of y).

similar to
Rich (BB code):
(unsigned char*(y))
.
The compiler wont neccessarily add 1 literally.

You'll get a compiler warning too.
C is so cryptic, so even experienced C programmers cannot decipher it correctly.

Rich (BB code):
int y;

x = (y*(y))+1;
This squares y and adds 1 to it.

Rich (BB code):
typedef int y;

x = (y*(y))+1;
This would be a typecast, but it is illegal because you try to cast something to a function. Shouldn't compile.
 

NorthGuy

Joined Jun 28, 2014
611
The structured equivalent of a GOTO in C is the 'switch' statement (with break).
I thought it was "while"

Rich (BB code):
past_label:
  if (someting)  goto forward_label;
  do_one();
  if (something_else) goto past_label;
  do_two();
  goto past_label;
forward_label:
Rich (BB code):
while (1) {
  if (someting)  break;
  do_one();
  if (something_else) continue;
  do_two();
}
 

takao21203

Joined Apr 28, 2012
3,702
C is so cryptic, so even experienced C programmers cannot decipher it correctly.

Rich (BB code):
int y;

x = (y*(y))+1;
This squares y and adds 1 to it.

Rich (BB code):
typedef int y;

x = (y*(y))+1;
This would be a typecast, but it is illegal because you try to cast something to a function. Shouldn't compile.
i dont think you properly understand what you are talking about.

of .course y* () is a typecast. It should be avoided, so you better write type_of_y* ().

if you write y*y+1, guess what is the result? Multiplication is evaluted first.

Im my simulator session, SHOWDispWhat is 3, and x is 4.
if a multiplication would be the result of the construct, it would yield 9.

On the other hand, if x is defined as numeric, then the construct will indeed result in a multiplication.
 

Attachments

takao21203

Joined Apr 28, 2012
3,702
these warnings about GOTO are a hoax resulting from an excentric Article published by a single computer scientist, probably with the purpose to spread dissident attitudes.

Compareable to one freak photoshopping a regular red strawberry into a blue one and as a result numerous articles can be found on the web, all using the same photoshopped image.

You can even find them on ebay, and this photoshopped image will be present.

Most hoaxes dont catch on but some do, and once this happens, they are impossible to eradicate.

You can produce a big mess with any kind of statements, be it for, while, switch, if, pointers, or mathematic functions.

It rather correlates to your programming abilities.

The author of the anti goto pamphlet did know that, and his intention was to spread dissendent attitudes.

And you see many webpages, where the ssame phrases are repeated over and over, and guess most of the authors never used goto and dont have a clue, just repeat what was told to them.

http://en.wikipedia.org/wiki/Goto
https://www.cs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF
http://en.wikipedia.org/wiki/Edsger_Dijkstra
 

NorthGuy

Joined Jun 28, 2014
611
so you better write type_of_y* ()
Won't compile neither. You cannot cast to a function. You cannot do this:

Rich (BB code):
typedef int type_of_y;
type_of_y *y_function();

y_function = (type_of_y*())+1;
The closest you can get is this:

Rich (BB code):
typedef int type_of_y;
type_of_y*(*y_function)();

y_function = (type_of_y*(*)())+1;
On the other hand, if x is defined as numeric, then the construct will indeed result in a multiplication.
This is not correct. The evaluation of the expression in C does not depend on where the result is going to be assigned to.
 

nsaspook

Joined Aug 27, 2009
13,262
these warnings about GOTO are a hoax resulting from an excentric Article published by a single computer scientist, probably with the purpose to spread dissident attitudes.
GOTO is not evil but like a loaded shotgun it's the right weapon to use on a charging bear but will blow a hole in your wall if used to kill a fly.

If you need to exit a deeply nested or critical routine fast because of an error that might corrupt data it could be the right thing to use but for a simple logical decision tree or a tricky speedup a switch statement can usually do the same thing almost as fast. A good compiler/linker has no problems using goto at the ASM level to implement structured C so let IT generate spaghetti code instead of you.

Good use of goto:
http://www.xml.com/ldd/chapter/book/ch02.html#buierr
 

takao21203

Joined Apr 28, 2012
3,702
Won't compile neither. You cannot cast to a function. You cannot do this:

Rich (BB code):
typedef int type_of_y;
type_of_y *y_function();

y_function = (type_of_y*())+1;
Where did you read I leave the brackets empty?
Of course it complies, i even made screenshots.

It can be mistaken for a function tough. For this reason I wrote earlier it is not good style. Instead one should use

Rich (BB code):
x=(unsigned char*(y));
;

You tell me this wont compile? It is a typecast, actually. EVIL!

The closest you can get is this:

Rich (BB code):
typedef int type_of_y;
type_of_y*(*y_function)();

y_function = (type_of_y*(*)())+1;
Now you introduce function pointers or something like that. Better not play around with that for academic purpose, just use it as plain as possible. Yes, for instance you can store function pointers in a table, select one with an index + execute...just one example.


This is not correct. The evaluation of the expression in C does not depend on where the result is going to be assigned to.
Ohhhhhhh...I would not count on that. It does, sometimes. Because typecasts use the same operator as multiplication. If the result isnt a pointer, of course its a multiplication.

I actually tried it in the simulator (MPLABX). No real MCU required. Its quite powerful now, like Visual Studio you can hover over variables and see their values.
 

takao21203

Joined Apr 28, 2012
3,702
GOTO is not evil but like a loaded shotgun it's the right weapon to use on a charging bear but will blow a hole in your wall if used to kill a fly.

If you need to exit a deeply nested or critical routine fast because of an error that might corrupt data it could be the right thing to use but for a simple logical decision tree or a tricky speedup a switch statement can usually do the same thing almost as fast. A good compiler/linker has no problems using goto at the ASM level to implement structured C so let IT generate spaghetti code instead of you.

Good use of goto:
http://www.xml.com/ldd/chapter/book/ch02.html#buierr
What if you want to go back some lines, and repeat, not always, but by some condition, and in some circumstances, repeat an initialization some lines earlier?

There is no sane way to do that with control structures, you have to introduce flags on top of them and it's bad if you already deal with flags for other purposes.

Simple, 2 reloop points, 2 gotos.

If you use GOTO now and then, at a few places, it does not produce spaghetti code.

Sure you could replace FOR with GOTO if you wanted to...but why not use all available instructions somehow when it makes sense?
 

takao21203

Joined Apr 28, 2012
3,702
Also
Rich (BB code):
x=(unsigned char*)y;
is used for typecasting.

Yes it is spelled like a function, the result is a pointer to the type of this object/variable,
Rich (BB code):
y*(y)
, and the parameter is converted into the address the pointer points to.

It is not really nice but can make sense for some purposes, and it does compile (with a warning tough).

And it depends on what it is assigned to. I tried with char, and then it just does arithmetic multiplication.
 

takao21203

Joined Apr 28, 2012
3,702
Rich (BB code):
typedef int y;

x = (y*(y))+1;
This would be a typecast, but it is illegal because you try to cast something to a function. Shouldn't compile.
Maybe you are unfamiliar with the fact you can either write:

Rich (BB code):
unsigned char *a;
or

Rich (BB code):
unsigned char* a;
Some years ago I experimented with Aztec C for the 68000, looked at the disassembly for certain kinds of typecasts and promotions.

If you dont know these things, C is quite difficult, for instance you dont neccessarily get the right initializations when you just assign values lets say the result from char and int, and assign to longint.

You have to use typecasts. Well when you worked with a debugger for a while and examined the disassembly, you know what I am talking about.

I consider
Rich (BB code):
char* a
as better, and there are more such alternative spellings in C language. And also many wrong ones, which compile, but result in garbage without warning.
 

NorthGuy

Joined Jun 28, 2014
611
Maybe you are unfamiliar with the fact you can either write:

Rich (BB code):
unsigned char *a;
or

Rich (BB code):
unsigned char* a;
You know, in C space between tokens don't matter at ll. You can write in any of these ways:

Rich (BB code):
unsigned char*a;
unsigned char* a;
unsigned char *a;
unsigned char * a;

unsigned char /* comment can be here too*/
* // or here 
a;
 

BobTPH

Joined Jun 5, 2013
8,942
i dont think you properly understand what you are talking about.

of .course y* () is a typecast. It should be avoided, so you better write type_of_y* ().

if you write y*y+1, guess what is the result? Multiplication is evaluted first.

Im my simulator session, SHOWDispWhat is 3, and x is 4.
if a multiplication would be the result of the construct, it would yield 9.

On the other hand, if x is defined as numeric, then the construct will indeed result in a multiplication.
I am sorry takao, but it you who does not know what he is talking about.

Rich (BB code):
int y;
 
x = (y*(y))+1;
Has no typecast. It is, as NorthGuy said, an assignment of y squared + 1 to x.

The syntax for a typecast is:

(type) operand

There is no type in the code you show, and the parentheses are wrong for a typecast.

(y *)(y)

Would have the syntax of a typecast, but would result in a compiler error because y is not a type name.

(int *)(y)

is a proper typecast that would take the value of y and make it a pointer to an integer (with undefined result).

The * is not the operator for a typecast, is the () with a type inside that makes this a typecast. In the above case,

int *

is a type, i.e. pointer to integer.


Bob
 

takao21203

Joined Apr 28, 2012
3,702
I am sorry takao, but it you who does not know what he is talking about.

Rich (BB code):
int y;
 
x = (y*(y))+1;
Has no typecast. It is, as NorthGuy said, an assignment of y squared + 1 to x.

The syntax for a typecast is:

(type) operand

There is no type in the code you show, and the parentheses are wrong for a typecast.

(y *)(y)

Would have the syntax of a typecast, but would result in a compiler error because y is not a type name.

(int *)(y)

is a proper typecast that would take the value of y and make it a pointer to an integer (with undefined result).

The * is not the operator for a typecast, is the () with a type inside that makes this a typecast. In the above case,

int *

is a type, i.e. pointer to integer.


Bob
I tried it in the simulator and I posted screenshot. What else can I do?

Yes it does a typecase, if the left side variable is a pointer type.
When it is an integer, it does a multiplication.

type_of_y* is just a placeholder, it means I'd write (unsigned char*)y.
i did not know y*(y) actually also does the job.

Maybe its a communication problem, not the posters not knowing what they are talking about.

More like "I dont exactly understand what you mean".

And I remember using unsigned char * a, Aztec did not like that. Putting it on the left side resulted in the least of problems.

I had some source codes written for SAS C, and they totally did not even compile with Aztec, and seemed to be full of mistakes.

So I looked at the disassembly, and determined how does that make sense, and what kinds of register trash do I need to get rid of (it is tedious since when the register is already zero, there is no consequence, but otherwise, you have to take care of that).

Nowadays with MPLABX SImulator, it is so easy.
 

BobTPH

Joined Jun 5, 2013
8,942
Takao,

There is no communication problem on my part. I did exactly what you said, took the expression:
int y;

(y*(y))+1;

And assigned it to an x which is defined as:

int *x;

When y is 10 the result is 101, which is y squared + 1.

C does not take into account the left side of an assignment statement when evaluating the right side. So the right side is evaluated as an integer to 101. When the assignment is done to x, the compiler does the implicit conversion (not the same thing as a typecast) from integer to pointer, then assigns it to x. The implicit conversion from integer to pointer does nothing, it merely preserves the integer value.

Here is the program, compiled by Microsoft C and then run in a DOS box on Windows 8.

foo.JPG

Bob
 
Top