C help please - C newbie

Hi, I am an Assembly language programmer of 12 years, now starting to code in C. I am still a C newbie and have some confusion.

I am finding that I am getting bogged down with uses of static / extern for functions and variables. I am also getting a bit confused with function prototyping and header files. I have searched the internet quite a bit but I am still confused.

I think that I know the following; (Please clarify)

Static variables are local to the .c file. Static variables also can stay around after the function is exited. A variable declared outside of Main is global and a .c file that wants to use it must extern it.

Static functions are visible to the .c file. My problem here is why declare them static? Isn't static assumed? A function can be called by other .c files if its prototype is External.

I have read that it is good C practice to code prototypes for each function. Should I code the prototypes in a .h file associated with the .c file? Where do I extern the prototype if I plan to use the function in multiple .c files ?

Any help / suggestions would be greatly appreciated.

thank you

Bradley

Reply to
Bradley
Loading thread data ...

snipped-for-privacy@canoemail.com (Bradley) wrote in news: snipped-for-privacy@posting.google.com:

Yes, but you want to restrict scope of all functions but those that external files require to use your .c file.

No, if it is not declared static. The prototype is needed to tell the compiler what the function signature looks like.

It is good practice but only put functions, constants, etc. in a header file for general consumption if they are needed in files other than your main .c file. That is, leave your static functions in your .c file along with "private" file scoped variables and manifest constants.

Also, here's a response I gave to a person in comp.lang.c, I hope it helps.

If foo() preceeded main() in the file you got the prototype from the definition. E.g.

static int foo(void) /* definition and prototype in one */ { return 0; }

/* Since foo() is above main(), C already has foo's prototype.

*/ int main(void) { return foo(); }

A simplistic view can be used if not too picky: "static means the static thing has duration for the life of the program and is restricted in scope to the nearest enclosing brace or translation unit." My words, not the spec. So using my smushy definition, you can say that a static function will exist for the life of the program and be visible (scoped) to only the file that contains it. Similarly,

int foo(void) { static int butter;

return ++butter; }

int main(void) { foo(); return 0; }

butter will exist for the life of the program and be visible only within foo() since foo's opening brace the nearest enclosing brace.

The question is the otherway round, why make a function visible outside a module? Answer, because it is absolutlely essential to using the module. Many functions to work within a module but have not externally usable benefit.

Try to think about a module and what interfaces into it you feel are the minimal ones you should provide to consumers of the module and make only those functions non-static and then prototype them in the module's accompanying header file.

Example disk.c:

static unsigned char readRegister(int regOffset) { unsigned char regValue;

regValue = /* some system specific stuff */;

return regValue; }

static void writeRegister(unsigned char regValue, int regOffset) { /* some system specific stuff */ = regValue; }

int dsk_readSector(void *pBuf, size_t bufSize, unsigned long sectorLba) { writeRegister(sectorLba, LBA_OFFSET); writeRegister(WRITE_PIO, CMD_OFFSET); dma_configRead(pBuf, bufSize); return !(readRegister(STATUS_OFFSET) & ERR); }

So here I, the consumer disk.c, care only about reading a sector, I don't care how disk.c does this. I care only about reading. Thus, as the implementer I hide read/writeRegister() in the file and expose only dsk_readSector() in disk.h for external consumers. Also, as the implementer, I keep consumers away from the disk registers by not publishing a means to screw with them (this is good).

Does this make sense now?

--
- Mark ->
--
Reply to
Mark A. Odell

get a copy of K&Rs The C Programming Language. do all the exercises. many people agree that though the book was written in the seventies, it's still the best book for students and professional reference.

static variables have file level scope and typically presist throughout operation.

all vaiables that are decleared outside of any functions are going to have external linkage or static (i,e,. not auto).

no, the default is non-static and externally accessable to other c files.

correct.

yes.

Where do I extern the prototype if I plan to use the

extern is assumed.

get the book.

-bryan

Reply to
Bryan Bullard

"Mark A. Odell" wrote in news:Xns94369C9B87C51CopyrightMarkOdell@130.133.1.4:

No! I'm thinking assy. now. Functions have static duration but not static scope by default. You *must* add static to them to reduce their scope to the current translation unit.

--
- Mark ->
--
Reply to
Mark A. Odell

"Bryan Bullard" wrote in news:ggaub.1010$ snipped-for-privacy@newssvr23.news.prodigy.com:

Why typically? I believe the *must* persist for the duration of the program.

--
- Mark ->
--
Reply to
Mark A. Odell

C is just high-level assy. You should do well when you get this syntax figured out.

the "static" keyword means two totally differnt things in C (and C++ added yet a third meaning :-( ).

1) static int foo(void) is an example of a function that can only be referenced (called) by code in the same C file (translation unit) that foo is in. The linker will not be able to resolve foo called by other C file code to this version of foo. This form of static applies to variables too. (e.g. static float x is invisible to other C modules) 2)Inside a function, static means that the variable retains its value between calls of the function. As you know, normally (non static) automatic varaibles are allocated on the stack and can have any old garbage in them when a function begins execution. static allocates the variable elsewhere in RAM.

corollary to 1) linkage (the ability of the linker to resolve a reference to function or variable) is global by default (works across all source files). The static keyword *prevents* the linker from resolving a reference. This makes static good for hiding code and data from modules that shouldn't be messing with them. Think of it as an early form of encapsulation.

The "extern" keyword tells the compiler about a function or variable that is not defined (coded or allocated ) in the currrent C file. Using extern, you tell the compile that foo is a function returning int that takes no arguments. The compiler can then call foo with the appropriate boilerplate (e.g. don't push anything onto the stack but do allow the returned int to be assigned).

Good practices:

1) read K&R and keep it handy. bookmark the precedence table and the declaration syntax pages. 2) turn the compiler warning level up to full (use lint too) 3) encapsulate functional units in separate C files. Each C file should have an H file that defines the functions and variables that other code needs to use the C file AND NOTHING ELSE. If you find that you need to put an extern into a C file to refernce a different C file then take a little time to ponder why your H file doesn't provide an adequate interface. 4) step through some of your code on the target system in assy mode. If you can't do that, then at least look at the assy output of the compiler (usually a command line arg will generate an assy listing for you). The assy code never lies!

good luck, Bob

Reply to
Bob

you're right mark, what i wrote isn't proper for a standard c context and was misleading.

however, once a data range is fixed in the image you can do whatever you like with it. as i'm sure you're well aware that "static" is only enforced by the c compiler and or linker.

again sorry for the confusion.

-bryan

Reply to
Bryan Bullard

In article , Mark A. Odell writes

You mean linkage? static when used on a finction is different to static applied to a variable.

This is good practice.

/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/\ /\/\/ snipped-for-privacy@phaedsys.org

formatting link
\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Reply to
Chris Hills

In article , Bryan Bullard writes

Do NOT get a copy of K&R

Do NOT do the exercises

Not it is NOT. K&R was written for desktop/ Unix programmers in 1978

K&R SECOND edition was in 1988 the year before the ANSI C standard (C90) and two years before the ISO C standard C90.

Most embedded compilers adhear to C90+ the TC's and Amendment A1.... Effectively C95.

So K&R is well out of date. There are many better books available for C programmers doing embedded work. What sort of targets are you looking at?

See the book reviews at

formatting link

This is a C programmers web site with reviews of over 3000 books. NB the ACCU does not sell books

Regards Chris

PS, just for the record I do have a copy of K&R (2nd ed) but I would not use it to learn from.

/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\/\/\ Chris Hills Staffs England /\/\/\/\/\ /\/\/ snipped-for-privacy@phaedsys.org

formatting link
\/\/ \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

Reply to
Chris Hills

chris,

i can respectfully acknowledge you're point of view. however, i and many others believe the k&r book is still valid for learning simply because all the concepts are plainly stated and explained. it is an easily and quickly digestible text.

also, i will remind you that off all the c code out there a relatively small percentage of it adheres to C90+.

-bryan

still

Reply to
Bryan Bullard

You'll find a lot of people here who disagree with you. I still recommend K&R as the best C tutorial available, for those who are willing to take the time to read and understand it.

It's also one of the best day-to-day reference books available.

--
Al Balmer
Balmer Consulting
removebalmerconsultingthis@att.net
Reply to
Alan Balmer

-Hi, I am an Assembly language programmer of 12 years, now starting to

-code in C. I am still a C newbie and have some confusion.

-

-I am finding that I am getting bogged down with uses of static /

-extern for functions and variables. I am also getting a bit confused

-with function prototyping and header files. I have searched the

-internet quite a bit but I am still confused.

-

-I think that I know the following; (Please clarify)

-

-Static variables are local to the .c file.

Global statics are. Local statics are local to their block (typically a function).

- Static variables also can stay around after the function is exited.

Correct. This applies specifically for local statics, because global varaibles both static and external always have this property.

-A variable declared outside of Main is global

Outside of any function.

- and a .c file

other than the file the global is declared in...

- that wants to use it must extern it.

Correct.

-

-Static functions are visible to the .c file. My problem here is why

-declare them static? Isn't static assumed?

Nope. Actually extern is the default for all global entities. So if you don't want outsiders to the file to use global functions/variables you must attach the static tag.

-A function can be called by other .c files if its prototype is

-External.

Yes, which again is the default.

-

-I have read that it is good C practice to code prototypes for each

-function.

Absolutely. Want an example? try this:

-------- file1.c --------------- main() { f1(3); }

--------------------------------

--------file2.c----------------- #include

void f1(double val,int junk1,int junk2) { printf("val = %f junk1 = %d, junk2 = %d\n",val,junk1,junk2); }

--------------------------------

Compile and link together. Fails miserably but still runs. A big mess. However if you include the prototype in file 1:

-------- file1.c --------------- void f1(double val,int junk1,int junk2);

main() { f1(3); }

--------------------------------

It magically generates an error because the prototype gives the compiler enough info to know that the call is incorrect. Also if f1 had the correct number of parameters, the int to double conversion of the 1st parameter also automagically happes because of the prototype.

Definitely prototype before you use. I wish there was a way to force the compiler to require prototypes before use.

- Should I code the prototypes in a .h file associated with

-the .c file?

There are different ways of doing it. It depends on usage. Generally I'll dump all of the prototypes into a single project .h file then include it into all the source files. However if it's a bit of code, like a hash table for example, that has multiple uses in multiple projects, then I'll give it its own header file.

There isn't necessarily one perfect has to do it. But there is no doubt that it needs to be implemented somehow.

- Where do I extern the prototype if I plan to use the

-function in multiple .c files ?

See above.

BAJ

Reply to
Byron A Jeff

small

These things are all a matter of opinion, of course, so here's mine...

The original K&R book was written in the seventies, when C was new. However, we are no longer living in the seventies, and C has changed a great deal in the last 30 years. Obviously it is still lumbered with many of the design decisions that don't fit with modern language design (for example, the idiotic idea that everything at file scope has global linkage unless it is explicitly declared static, or the joys of "break" in switch statements), but a great deal has changed for the better.

The O/P wants to learn to *write* C code. He should learn to make the best of C as it stands *today*, in popular compilers *today*, and if it turns out that one day he has to write code for an ancient non-ANSI C compiler, then he can deal with it at that time. In the meantime, he should be writing C code that is as solid and readable as possible - all functions should be prototyped, using // comments, static inline functions, consts and enums instead of #defines, and so on.

The K&R book may be a great teaching book - it is a long time since I read it, so I can't remember - and it may be better in that sense than some modern text trying to teach you everything in 24 hours or 21 days or whatever. The trouble is, it would be teaching him the wrong thing.

David

Reply to
David Brown

To everyone that has posted a reply, I will try to put your suggestions into practice.

thank you,

Bradley

Reply to
Bradley

Not if the compiler can determine that they're no longer needed after some point in program flow. They must behave *as if* they persisted for the duration of the program --- but if the program doesn't look, the compiler is allowed to re-use the space otherwise.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

But DO get K&R2, a.k.a. Kernighan, Ritchie:

The C Programming Language Second Edition, ANSI C

It has all the strong points of the original K&R, plus one: it's as up-to-date to ANSI/ISO Standard C as you're likely to find in any published work other than the Standard document itself.

And DO get the comp.lang.c[.moderated] FAQ from the net.

I'm reasonably sure there's not a single textbook on C that comes anywhere close to really covering C95.

Strongly seconded.

--
Hans-Bernhard Broeker (broeker@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.
Reply to
Hans-Bernhard Broeker

Right now I am working on a eZ8 system. This will have an LCD 20x4, I2C, key pad interface, Serial port (USB may come after) some other I/O doing miscellaneous stuff.

Reply to
Bradley

Chris Hills wrote in news:fyCIDIAmRVu$ snipped-for-privacy@phaedsys.demon.co.uk:

I was thinking assy. where things are "private" by default (aren't they)? As for static on a function vs. variable are they really that different? Static on a variable means it duration is program but doens't exclude reducing it scope to the current file. Likewise, static on a function means scope to file but doesn't exclude meaning program duration.

--
- Mark ->
--
Reply to
Mark A. Odell

Hans-Bernhard Broeker wrote in news:bpd43j$8ue$ snipped-for-privacy@nets3.rz.RWTH-Aachen.DE:

I'd like to know if you have an example of such a condition as I'm having a hard time seeing how a compiler could know that it will swap out a function for use by another. Maybe I'm too used to Harvard architectures.

--
- Mark ->
--
Reply to
Mark A. Odell

Observe.

static int switch = 0; static int x; static int y;

void test(void){ if (switch == 0) { do a whole bunch of stuff with x if (some interesting case) { switch = 1; } do a bunch of stuff with y; } else { do a bunch of other stuff with y; } }

Observe that the switch initially points to x, and the program uses x. Once the switch is thrown to y, the program only uses y, and NEVER AGAIN TOUCHES X. A sufficiently-advanced compiler could, in principle, notice that x and y have disjoint lifetimes, and use the same storage location for the two variables.

Reply to
John R. Strohm

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.