ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
int userInput(int enteredNumber);
float staticFunction(void);
See what happens if you remove these 2 lines. (hint: your program will perform the same).
The only time function prototypes are needed is when the function definitions appear after the functions themselves are called.
You'll find that sometimes you'll want to put your definitions *below main()*, so in that case, use prototypes *above* main(). (Note that the compiler doesn't care whether or not you put your definitions above or below main, it only needs to know how they're prototyped at the time the function is called.) The location is about style and how you want things organized.
When you have functions other than main() that call other functions, you'll also need prototyping if the function isn't defined before it's called. For example, if userInput() called staticFunction(), then you'd need a prototype for staticFunction() preceding the point where staticFunction() is first called. In your current code example, you'd leave the prototype for staticFunction() right where it is, but could remove the userInput() prototype.
(Note that as your programs get more complex, your function prototypes and definitions will be in other files, separated from the file that main() is in. but no need to think about the details on that now).
Also, since these two function calls don't actually do anything with the value that's returned it's not necessary for the functions to return a value.
Code:
int main(void)
{
staticFunction();userInput(0);
//printf("Entered Number is: %i\n", userInput(0));
//printf("Value of staticFunctionVar: %f\n", staticFunction());
puts("Returned to main() function");
return 0;
}
Essentially what you're left with after the function calls have been evaluated is (imagine enteredNumber = 6):
Code:
int main(void)
{
5; // Not an instruction
6; // Not an instruction
//printf("Entered Number is: %i\n", userInput(0));
//printf("Value of staticFunctionVar: %f\n", staticFunction());
puts("Returned to main() function");
return 0;
Last edited by Mechanikx; 03-09-2019 at 10:50 AM.
Reason: Added info.
You should not be sending a value of zero, or any static value, as input to a function which manipulates that passing argument. That function also should not use the passing argument as a return value.
Sorry I'm using a mobile. Someone please explain this with more clarity. Too much to tap on a small screen, soft keyboard.
Actually, it looks fine to me, enteredNumber is an int, so it is passed by value and the function is free to do what it likes with its copy of it. If scanf() encounters a matching failure, enteredNumber will be unchanged and the passed value will be returned, acting like a default return value in case of error.
What rtmistler is saying however is that you probably didn't intend that behaviour, in which case you should have written it something like this:
Code:
int userInput(void)
{
int enteredNumber = 0;
puts("Enter a number: ");
scanf("%i", &enteredNumber);
printf("Entered Number is: %i\n", enteredNumber);
return (enteredNumber);
}
... and called it simply as userInput(); though you're completely ignoring any errors from scanf() by doing this.
Also, I'd just like to point out that your 'static' function really doesn't demonstrate static variables at all, and please note that: static float staticFunctionVar = 1 + 4;
is not at all the same as:
static float staticFunctionVar;
staticFunctionVar = 1 + 4;
I'd recommend you give the chapter on functions a second read to clear up some of these topics as they are quite fundamental to the language.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881
Original Poster
Rep:
Thanks again guys.
I know exactly what you mean about trying to post on a phone RT - I hate posting on a phone for the same reasons. As I find it harder to type on a soft keyboard too.
Sorry for the late reply, I just wanted to read the chapter again completely. I think I understand what you guys are saying, and it seems I didn't read it properly the first time. But reading it again has cleared up some things for me, but I might have another read of it anyways - just to be as sure as I can be about it. Plus I've found that reading each chapter seems to make the previous chapters more clear for me too. But at the same time I don't want to be reading forever, or practising forever.
I'll hold off on creating a program for ffmpeg for now, as I wanna wait until I've read enough concepts, and done enough practice before trying to write anything serious.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881
Original Poster
Rep:
I've been reading about (and practising) structures (struct), and I always thought given it's name it would be what you would call a "data structure", but it seems not. As, I've always wondered exactly what is meant when for example, you read about some piece of malware that "corrupts data structures". I was reading this (and Wikipedia) about "data structures" and while "arrays" are considered to be "data structures", "structures" are not from what I read. My thinking is that the devil is in the detail, or in other words: "structures" are basically like a bunch of normal variables "grouped" together as "one unit/entity", as in, a "structure of variables". I was wondering if this thinking is correct?
I've also written some code so I could visually see what an array within a structure looks like below;
It should (and does on my machine) look like this when run:
Code:
Array element Structure Member
------------- ----------------
element 1, .member1 contents: 1
element 1, .member2 contents: 2
element 1, .member3 contents: 3
element 2, .member1 contents: 4
element 2, .member2 contents: 5
element 2, .member3 contents: 6
element 3, .member1 contents: 7
element 3, .member2 contents: 8
element 3, .member3 contents: 9
element 4, .member1 contents: 10
element 4, .member2 contents: 11
element 4, .member3 contents: 12
element 5, .member1 contents: 13
element 5, .member2 contents: 14
element 5, .member3 contents: 15
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881
Original Poster
Rep:
Quote:
Originally Posted by rtmistler
Why did you think this was the best way to define your C struct?If you look at typical struct examples, each variable in them will have a type.
Your example is fine, however I would have written it as:
Code:
struct example {
int example1;
int example2;
int example3;
}
In all honesty, no particular reason, other than I wanted to see if I could declare it on one line. I figured given that they are all the same data type, there would be no harm in doing that. Although the C book example's do write it the same way you would have. I changed it to the way the examples in the C book and you've listed do it though. Thanks for your help RT.
Quote:
Originally Posted by GazL
Pascal refers to them as 'records' which IMO is a little clearer.
I have tried to do a loop, and while it does listed the contents of the struct members in the array correctly, I cannot figure out how to get it to list the right number for the array elements. The problem is that there is 5 array elements with 3 struct members for each element, which adds up to 15 (5 x 3). I tried adding the "const" keyword for the struct array, but depending on how I do it, it doesn't make any difference. Whatever I seem to try messes up the content of my struct array, below is the closest I've been able to get. I've also posted the code where it just messes up my struct array below the code below. I don't know what else I can do. In other words: I know what the problem is, but I have no idea how to solve it, nor how to get the newline between the output for the different array elements. I tried looking at the example in the C book, being "Program 9.6", but I still don't get what I'm doing wrong.
Code:
#include <stdio.h>
int main(void) {
struct example {
int example1;
int example2;
int example3;
};
int index;
const struct example vars[5] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, { 13, 14, 15 } };
puts("\nArray element Structure Member");
puts("------------- ----------------");
for( index = 0; index < 5; ++index) {
printf("element 1 .member1 contents: %2i\nelement 2 .member2 contents: %2i\nelement 3 .member3 contents: %2i\n", vars[index].example1, vars[index].example2, vars[index].example3);
}
printf("\n\n");
return 0;
}
Which gives me:
Code:
Array element Structure Member
------------- ----------------
element 1 .member1 contents: 1
element 2 .member2 contents: 2
element 3 .member3 contents: 3
element 1 .member1 contents: 4
element 2 .member2 contents: 5
element 3 .member3 contents: 6
element 1 .member1 contents: 7
element 2 .member2 contents: 8
element 3 .member3 contents: 9
element 1 .member1 contents: 10
element 2 .member2 contents: 11
element 3 .member3 contents: 12
element 1 .member1 contents: 13
element 2 .member2 contents: 14
element 3 .member3 contents: 15
I tried this (among other things, like adding three variables and listing the same variable (element) three times in the printf statement - which just messes up the array values):
Code:
#include <stdio.h>
int main(void) {
struct example {
int example1;
int example2;
int example3;
};
int index, element;
const struct example vars[5] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, { 13, 14, 15 } };
puts("\nArray element Structure Member");
puts("------------- ----------------");
for( element = 1, index = 0; element < 5 && index < 5; ++element, ++index) {
printf("element %i .member1 contents: %2i\nelement %i .member2 contents: %2i\nelement %i .member3 contents: %2i\n", element, element, element, vars[index].example1, vars[index].example2, vars[index].example3);
}
printf("\n\n");
return 0;
}
Which gives me:
Code:
Array element Structure Member
------------- ----------------
element 1 .member1 contents: 1
element 1 .member2 contents: 1
element 2 .member3 contents: 3
element 2 .member1 contents: 2
element 2 .member2 contents: 4
element 5 .member3 contents: 6
element 3 .member1 contents: 3
element 3 .member2 contents: 7
element 8 .member3 contents: 9
element 4 .member1 contents: 4
element 4 .member2 contents: 10
element 11 .member3 contents: 12
Which is clearly incorrect. Any ideas would be really good, thanks again for your help GazL.
You can keep the printf as one call, but long printfs get unreadable pretty quickly, so IMO it's best to split it at points that make sense.
Although your example makes it look like each struct is an array of 3 ints, it isn't, and you can't loop over the individual members of a struct.
Also don't use two loop control variables if you don't actually need them, it just complicates things. If you really don't like to see your elements presented as zero indexed, then do something like this instead: printf("element %i .member1 contents: %i\n", index + 1, vars[index].example1);
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881
Original Poster
Rep:
I changed the code like you said, and of course it done the trick, and it works! I'm actually glad you suggested to do a loop, it's nice to put it all together. Particularly now I can practice "sizeof" as well. I even figured out how to get some newlines between the array elements too. I'll leave the 0 indexing there, cuz I've gotta remember that array elements start at 0 and not 1. I'll try and remember what you said GazL. I can over-think things, so the advice to keep it simple when in doubt is very much worth remembering, and helps a lot. I also cleaned up the output a bit too. Thank you very much GazL!
Anyhow, I've posted the code below. Thanks again!
Code:
#include <stdio.h>
int main(void) {
struct example {
int example1;
int example2;
int example3;
};
int index;
const struct example vars[5] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 }, { 13, 14, 15 } };
puts("\nArray element Structure Member Contents of struct array");
puts("------------- ---------------- ------------------------\n\n");
for( index = 0; index < sizeof vars / sizeof vars[0] ; ++index ) {
printf(" element %i .member1 %i\n", index, vars[index].example1);
printf(" element %i .member2 %i\n", index, vars[index].example2);
printf(" element %i .member3 %i\n\n\n", index, vars[index].example3);
}
printf("\n\n");
return 0;
}
Here's the output now;
Code:
Array element Structure Member Contents of struct array
------------- ---------------- ------------------------
element 0 .member1 1
element 0 .member2 2
element 0 .member3 3
element 1 .member1 4
element 1 .member2 5
element 1 .member3 6
element 2 .member1 7
element 2 .member2 8
element 2 .member3 9
element 3 .member1 10
element 3 .member2 11
element 3 .member3 12
element 4 .member1 13
element 4 .member2 14
element 4 .member3 15
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881
Original Poster
Rep:
I've started reading about "pointers" and while the code below seems to make sense to me (it's code I wrote myself based on what the "pointers" chapter said);
Code:
#include <stdio.h>
int main(void) {
int address_op_ex = 10, indirection_op_ex;
int *pointer_example;
pointer_example = &address_op_ex; // this tells gcc that "pointer_example" points to "address_op_ex".
indirection_op_ex = *pointer_example; // this tells gcc to assign the value of "pointer_example" to "indirection_op_ex".
printf("\naddress_op_ex = %i\nindirection_op_ex = %i\n", address_op_ex, indirection_op_ex);
return 0;
}
I'm not sure I'm understanding the following properly. From what I can see in the code below what I've quoted below;
A structure called "entry" is defined to have a member called "value", and a "pointer" structure also called "entry" within the first "entry" structure defined. And I *think* another structure also called "entry" with 3 more structures called n1, n2 and n3 defined, with members i, and a "value" member for each of those 3 structures. That have values 100, 200 and 300 assigned to n1, n2 and the n3 structures respectively, with members n1.next and n2.next, pointing to structures n2 and n3 respectively. While I'm not 100% sure I've understood what I just said properly/if it's correct or not, and while I get that the "->" operator points to an actual structure, and not a member of a structure(?), I'm not at all sure I do understand what I've highlighted in bold below. I did verify what it's bold below, but I'm still not sure I really understand what the meaning of what's said below is. Could someone help me out here?
Quote:
The structures n1, n2, and n3 are defined to be of type struct entry, which consists of
an integer member called value and a pointer to an entry structure called next.The
program then assigns the values 100, 200, and 300 to the value members of n1, n2, and
n3, respectively.
The next two statements in the program
Code:
n1.next = &n2;
n2.next = &n3;
set up the linked list, with the next member of n1 pointing to n2 and the next member
of n2 pointing to n3.
Execution of the statement
Code:
i = n1.next->value;
proceeds as follows:The value member of the entry structure pointed to by n1.next is
accessed and assigned to the integer variable i. Because you set n1.next to point to n2,
the value member of n2 is accessed by this statement.Therefore, this statement has the
net result of assigning 200 to i, as verified by the printf call that follows in the pro-
gram. You might want to verify that the expression n1.next->value is the correct one
to use and not n1.next.value, because the n1.next field contains a pointer to a struc-
ture, and not the structure itself. This distinction is important and can quickly lead to
programming errors if it is not fully understood.
The example program 11.6 from the C book I'm reading;
> A structure called "entry" is defined to have a member called "value", and a "pointer" structure also called "entry" within the first "entry" structure defined.
No, this is just a pointer to the same type. This pointer in an actual record is supposed to point to another record (or set to NULL).
You might want to verify that the expression n1.next->value is the correct one to use and not n1.next.value, because the n1.next field contains a pointer to a structure, and not the structure itself.
Don't get too caught up on that sentence. I can remember having a problem parsing this sentence too, so you're not alone. IMO it is confusingly phrased. Basically, all he's saying is that n1.next->value is correct, but that n1.next.value would not be, and that it's important to understand why.
Remember, n1.next->value is simply a fancy way of saying (*n1.next).value, whereas n1.next.value would be invalid because n1.next is not a structure but a pointer to a structure.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.