English Amiga Board


Go Back   English Amiga Board > Coders > Coders. General

 
 
Thread Tools
Old 06 May 2007, 14:58   #1
Jherek Carnelia
Dazed and Confused
 
Jherek Carnelia's Avatar
 
Join Date: Dec 2001
Location: portsmouth/uk
Posts: 242
C code prob

I'm trying to learn C and am stuck on what (at least to) me seems a very simple bit of code. Any ideas what I'm doing wrong??

/* ***************************************** */
/* returning a file pointer from a function */

#include <stdio.h>
#include <stdlib.h>

FILE *source; /* pointer to a file structure */

FILE *open_file(void); /* function to return a file pointer */

main()
{
source = open_file();

if(source != NULL)
/* this line is never printed */
printf("from main file opened\n");

fclose(source);
getch();
return 0;
}

FILE *open_file(void)
{
FILE *s;

printf("in function\n");
if(s=fopen("test.txt", "wb") == NULL)
{
printf("cant open");
return s;
}
/* this line prints and the file is created */
printf("from function file opened\n");
return s;
}

I get a warning when I build the code on this line:

if(s=fopen("test.txt", "wb") == NULL)
pointer type mismatch "FILE *" does not match "int"
and the value returned from the function is NULL
Jherek Carnelia is offline  
Old 06 May 2007, 15:22   #2
eLowar
Citizen of Elthesh
 
eLowar's Avatar
 
Join Date: Sep 2003
Location: UK
Posts: 949
It's a problem with operator precedence. What your code means is:

Code:
if ( s = (fopen("test.txt", "wb") == NULL) )
Note that the highlighted (red) parentheses are added implicitly. The result of the comparison (==) operator is of type int, which you then assign to s of type FILE*, hence the warning. What you meant is:

Code:
if ( (s = fopen("test.txt", "wb")) == NULL )
Note that you have to add the highlighted (blue) parantheses explicitly. The result of the assignment (=) is the value on the right side of the operator, which is of type FILE*, which you then compare with NULL, which you can compare with any pointer type.

The lesson here being that for practical reasons, = has a very low priority among the operators. Think of it as + vs. * in maths, e.g. a + b * c. That too is like a + (b * c), and if you want (a + b) * c you have to write so explicitly.

Hope this helps and good luck with your studies.
eLowar is offline  
Old 06 May 2007, 15:38   #3
Calgor
(Amigas && Amigos)++
 
Calgor's Avatar
 
Join Date: Sep 2005
Location: Anrea
Posts: 999
When I was learning C, I found it always handy to have a reference table for operator precedence. For example:
http://www.difranco.net/cop2220/op-prec.htm

On the webpage, you will see that == is higher in the table than =, just as eLowar has explained. Any C learning book worth its salt should also have such a table.

EDIT: And when in doubt, I put parentheses around to group exactly what I want.
Calgor is offline  
Old 06 May 2007, 15:42   #4
eLowar
Citizen of Elthesh
 
eLowar's Avatar
 
Join Date: Sep 2003
Location: UK
Posts: 949
Very nice link, I was trying to find something like that online to post here.
eLowar is offline  
Old 06 May 2007, 15:45   #5
Jherek Carnelia
Dazed and Confused
 
Jherek Carnelia's Avatar
 
Join Date: Dec 2001
Location: portsmouth/uk
Posts: 242
Doh! I've been tearing my hair out over that!! I just couldn't see it! Thanks guys!
Jherek Carnelia is offline  
Old 06 May 2007, 20:23   #6
thomas
Registered User
 
thomas's Avatar
 
Join Date: Jan 2002
Location: Germany
Posts: 7,005
Quote:
if ( (s = fopen("test.txt", "wb")) == NULL )
As a beginner you should always write it like this:

Code:
s = fopen("test.txt", "wb");
if (s == NULL)
Also this part of your code looks a bit funny:

Quote:
if (s == NULL)
{
printf("cant open");
return s;
}
You test if s is NULL and if so, you return s. You could as well return NULL, just to make it a bit more readable.
thomas is offline  
Old 07 May 2007, 03:36   #7
Zetr0
Ya' like it Retr0?
 
Zetr0's Avatar
 
Join Date: Jul 2005
Location: United Kingdom
Age: 49
Posts: 9,768
Its a good start!

just a couple of syntax problems and its away...



firstly i will mention that global FILE pointers are asking for trouble LOL so its best not to use them.. just declare thier use in each function parsing if need be

such that

Code:
void main( void )
{
	FILE *fp;


	if( !open_file("text.txt", fp) ) // error occured
	{
		printf("\n\nError opening file...\n\n");
		exit(0);// you dont need to use this its just a habbit of mine!
	}
	else
	{
		/*


			nice lump of code here		

	
		*/
        fclose( fp ); // always close the FILE pointer after use
	}
}


bool open_file( char *filename, FILE *fp )
{
 	fp = fopen( filename, "rb" );  // rb = mode read binary

	if( fp != NULL )
		return true;
	else
		return false;
}
Zetr0 is offline  
Old 07 May 2007, 03:51   #8
eLowar
Citizen of Elthesh
 
eLowar's Avatar
 
Join Date: Sep 2003
Location: UK
Posts: 949
Quote:
Originally Posted by Zetr0
Code:
bool open_file( char *filename, FILE *fp )
{
 	fp = fopen( filename, "rb" );  // rb = mode read binary

	if( fp != NULL )
		return true;
	else
		return false;
}
A few problems with that.

For starters there is no pre-defined bool type in C (there is in C++, and many C libraries define a bool or BOOL type, but it's not built into C), also no true or false.

Also this will just overwrite a local copy of the file pointer with the result of fopen, with no effect on the variable outside that function whatsoever. If you want to use an output parameter like that in C (in C++ there are references), you have to pass a pointer to the type you want to overwrite and then dereference it when assigning. Like so:

Code:
int open_file( char *filename, FILE **fp )
{
	/* [...] */
	*fp = fopen( filename, "rb" );  /* rb = mode read binary */
	/* [...] */
}
In C parameters are always passed by value.

That said, I agree, global variables are a bad idea and will likely get you in trouble in the future if you get into the habit of using them without thinking about it. Make sure you understand variable scopes and their consequences before going on.

That's all from me for now.

Last edited by eLowar; 07 May 2007 at 04:02. Reason: edited out // style comment in light of my latter comment ;)
eLowar is offline  
Old 07 May 2007, 03:54   #9
Zetr0
Ya' like it Retr0?
 
Zetr0's Avatar
 
Join Date: Jul 2005
Location: United Kingdom
Age: 49
Posts: 9,768
damn M$ i am getting soft!
Zetr0 is offline  
Old 07 May 2007, 04:00   #10
eLowar
Citizen of Elthesh
 
eLowar's Avatar
 
Join Date: Sep 2003
Location: UK
Posts: 949
No // style comments either, btw.

Not officially until C99 at any rate, which does also have a _Bool type. If you want to use "bool" you have to #include <stdbool.h> though.

I love people talking about languages I know instead of all that assembler talk I can contribute nothing to.
eLowar is offline  
Old 07 May 2007, 15:55   #11
Jherek Carnelia
Dazed and Confused
 
Jherek Carnelia's Avatar
 
Join Date: Dec 2001
Location: portsmouth/uk
Posts: 242
The point of my previous post was to enable me to write the following little prog. As noted, I owe a debt to Thomas Nokielski for his copdis routine and structure (and also you guys for your help!). I needed something that would allow me to read the output from AR3 save memory dumps. It seemed a good project to try and learn C for...

As it is my first real C prog I am fairly pleased with it, although I am absolutely sure it could have been done far more elegantly than the way I have...

Anyway, for those that are interested here it is...

Last edited by Jherek Carnelia; 09 April 2011 at 22:22.
Jherek Carnelia is offline  
Old 07 May 2007, 17:06   #12
eLowar
Citizen of Elthesh
 
eLowar's Avatar
 
Join Date: Sep 2003
Location: UK
Posts: 949
At a quick glance it looks pretty clean.

Unfortunately I can't test it because I don't have an Amiga development environment installed. Next task for you: portable version.
eLowar is offline  
Old 07 May 2007, 17:24   #13
Jherek Carnelia
Dazed and Confused
 
Jherek Carnelia's Avatar
 
Join Date: Dec 2001
Location: portsmouth/uk
Posts: 242
Hmm. How to make it portable when I use Amiga Libraries? (although to be fair, I never intended to use it anywhere else than in WinUAE).

I guess that filerequesters are out! I will have to study the standard libs and see what's available. Without looking, I suppose it would have to use command line arguments (which is what I was trying to avoid!)

Still, a good exercise, I will see what I can do - although as I'm going out tonight (and beer and programming don't mix well) it may take a day or two.
Jherek Carnelia is offline  
Old 07 May 2007, 17:40   #14
eLowar
Citizen of Elthesh
 
eLowar's Avatar
 
Join Date: Sep 2003
Location: UK
Posts: 949
The cheapest way, and the way a lot of oldschool *nix programs do things by default, is not to use files at all, but simply read from stdin and write to stdout and then use pipes. That way the shell has to do all the dirty work. I'm not sure how well this works on an Amiga, but I do know that the Amiga does support pipes.

Alternatively get your arguments from the optional parameters of main (int main(int argc, char* argv[])), it's really easier than you might think.

Your third option is to look into cross platform GUI toolkits, although that will be much more complex (as you'll have to learn the ways of the particular library) and definitely less portable.

Lastly you could implement any combination of what you have and the above and either decide at compile time what to use (#ifdef __AmigaBuild__ or suchlike) or at runtime (e.g. read from stdin, unless -f parameter is specified, write to stdout unless -o parameter is specified).

Have fun (both drinking and coding).
eLowar is offline  
Old 08 May 2007, 11:18   #15
Jherek Carnelia
Dazed and Confused
 
Jherek Carnelia's Avatar
 
Join Date: Dec 2001
Location: portsmouth/uk
Posts: 242
This *should* be portable, but I have no way to check and not enough knowledge to tell!

Attached is a re-written code with sample Shadow of the Beast copper list disassembly output.

Last edited by Jherek Carnelia; 09 April 2011 at 22:22.
Jherek Carnelia is offline  
Old 08 May 2007, 11:39   #16
eLowar
Citizen of Elthesh
 
eLowar's Avatar
 
Join Date: Sep 2003
Location: UK
Posts: 949
Two minor warnings:

Code:
NewCopDis.c:271: warning: comparison between pointer and integer
NewCopDis.c:232: warning: return type of 'main' is not `int'
The first is due to the fact that you use NULL as an integer (NULL is often defined as (void*)0). fread returns the number of complete objects read, which you should compare with the number 0. NULL is for the null-pointer.

The second is simply because a command line program should return an integer value to the operating system (other languages like ISO C++ won't even give you a choice). Just make the return value int and return 0 in the end.

I'd also just get rid of the getch in the end. It's ugly and it doesn't really serve any purpose if you run the program from a command window.

Other'n that good job, except I can't really test it for lack of a binary example file.

First Edit: Oh and, when you add a return value to main, you could as well change exit(1) to return 1. Just as a side note.

Second Edit: I ought probably to have mentioned what I compiled this with. This is with GCC/MinGW 3.4.2 under Windows.

Last edited by eLowar; 08 May 2007 at 11:59.
eLowar is offline  
Old 08 May 2007, 12:22   #17
Jherek Carnelia
Dazed and Confused
 
Jherek Carnelia's Avatar
 
Join Date: Dec 2001
Location: portsmouth/uk
Posts: 242
Thanks for your time elowar.

Just for completeness is a memory dump of Shadow of the Beast's copperlist. Zipped because it has no filetype really.

Last edited by Jherek Carnelia; 09 April 2011 at 22:22.
Jherek Carnelia is offline  
Old 08 May 2007, 12:28   #18
eLowar
Citizen of Elthesh
 
eLowar's Avatar
 
Join Date: Sep 2003
Location: UK
Posts: 949
Here's the output. Looks good as far as I can tell.

Edit: Maybe not... It doesn't match the one that comes with your code. Well, I have to go now, you figure it out.
Attached Files
File Type: zip beastlist.zip (4.9 KB, 136 views)
eLowar is offline  
Old 08 May 2007, 14:31   #19
Jherek Carnelia
Dazed and Confused
 
Jherek Carnelia's Avatar
 
Join Date: Dec 2001
Location: portsmouth/uk
Posts: 242
The problem is the "endianess" differences between the Amiga and the PC. As you know, PCs store the bytes of a word with the MSB at the highest address and Amigas the opposite way round.

The program now does a check (thanks to a quick google!) to see which way around the host machine stores bytes in a word.

Hopefully this will fix it...

Last edited by Jherek Carnelia; 09 April 2011 at 22:22.
Jherek Carnelia is offline  
Old 08 May 2007, 17:02   #20
eLowar
Citizen of Elthesh
 
eLowar's Avatar
 
Join Date: Sep 2003
Location: UK
Posts: 949
Yeah I started wondering about that on the way out, but I didn't have time to come back and post. Very good job!

First Edit: Sorry, I spoke too fast, your check does not seem to work, my Windows PC is detected as an Amiga. When I hardcode it to PC the output still differs. Seems to need some more work.

Maybe this was a bad (or very good ) choice for an exercise in portability.

Second Edit: I'm not yet sure what the problem is, but to avoid problems with differently sized file types on different systems/compilers, you might want to have a look at the header stdint.h, which contains (or should contain) system and compiler specific typedefs for exact size datatypes. Just a thought.

Third Edit: The differences are actually minor, so you're probably on the right way (except for the non-working check), e.g.

DC.W $db01,$ff00 ;WAIT: VP=$db (219),HP=$01 (1):VE=$ff (255),HE=$00 (0) (correct) vs.
DC.W $db01,$ff00 ;WAIT: VP=$01 (1),HP=$db (219):VE=$00 (0),HE=$ff (255) (incorrect)

You'll notice that the majority of lines as well as the general structure is identical.

FYI, I also tested it on an x86 Linux system with gcc 3.3.4 now and the check doesn't work there either.
Attached Files
File Type: zip beastlist-le.zip (4.3 KB, 138 views)

Last edited by eLowar; 08 May 2007 at 17:34.
eLowar is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
CF Prob. Eclipse support.Hardware 10 01 May 2008 12:11
C code prob continued - How a PC stores bytes? Jherek Carnelia Coders. General 5 11 May 2007 18:10
Not really a prob amiga support.WinUAE 1 20 March 2007 20:31
Not really a prob amiga support.WinUAE 1 25 May 2005 18:53
3D code and/or internet code for Blitz Basic 2.1 EdzUp Retrogaming General Discussion 0 10 February 2002 11:40

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 23:25.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.11435 seconds with 14 queries