Mercy me, that's a confusing hunk of code you've been given man.
First, about declaring external variables static... It will only affect their linkage, which doesn't mean a darn thing unless your program is multiple files, so I'm just gonna get rid of those.
Code:
#include <stdio.h>
#include <string.h>
struct sample {
char *name;
int *id;
float price;
};
char product[] = "Greggs Coffee";
float price1 = (float) 3.20;
int id = 733;
//This function does not just print the record it is given...
// It also changes the record.
void printrecord(struct sample *goods)
{
// 1. Print the record.
printf("Name = %s\n", goods->name);
printf("ID = %d\n", *goods->id);
printf("Price = %.2f\n", goods->price);
// 2. Change the values in the record to the globals.
goods->name = &product[0]; //Greggs Coffee
goods->id = &id; //733
goods->price = price1; //3.20
}
main()
{
int code = 123, number;
char name[] = "Apple Pie";
struct sample item;
item.id = &code; //pointer to 123
item.price = (float) 1.65;
item.name = name; //Apple Pie
number = *item.id; //123
printrecord(&item);
// item was printed to the screen, then changed
// now we print item again, but the values in item will
// have changed due to printrecord.
printf("Name = %s\n", item.name); //Apple Pie
printf("ID = %d\n", *item.id); //123
printf("Price = %.2f\n", item.price); //1.65
return 0;
}
Now for your questions...
1. printrecord(struct sample *); is called a prototype. Your code will work fine without it, but here's what prototypes are for.. consider the following code...
Code:
main ()
{
float f = addFloats(1.23, 4.56);
printf ("%f", f);
return;
}
float addFloats (float a, float b)
{
return (a + b);
}
When the compiler encounters the call of addFloats in main, it had not yet encountered the function, so it does not know exactly what format the functions arguments are, nor what the format of it's return type it. If the function addFloats was written before main, then this wouldn't have been a problem. This still leaves a dillema, for example, what if two functions call each other, which to put first? The solution is to declare prototypes for each function around the beginning of your program, which tell the compiler what type all the arguments are. Prototypes are also very handy simply because it's nice to have a list of your functions available when you start to use a lot of them.
2. number = *item.id; You are correct, it is pretty useless, but like I said, this is super confusing code, so it needs some useless stuff. I think that line is just there to hammer in the idea that item.id is not an int, just a pointer to an int.
3. Understand, this is what happens...
printrecords is called...
the structure is printed...
the structure is changed to global variables...
printrecords ends...
the structure is printed.
The lines that change the struct are right there in printrecords...
goods->name = &product[0]; //Greggs Coffee
goods->id = &id; //733
goods->price = price1; //3.20