[SOLVED] Tried to write something "serious" and have failed once again
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.
Introduction to Linux - A Hands on Guide
This guide was created as an overview of the Linux Operating System, geared toward new users as an exploration tour and getting started guide, with exercises at the end of each chapter.
For more advanced trainees it can be a desktop reference, and a collection of the base knowledge needed to proceed with system and network administration. This book contains many real life examples derived from the author's experience as a Linux system and network administrator, trainer and consultant. They hope these examples will help you to get a better understanding of the Linux system and that you feel encouraged to try out things on your own.
Click Here to receive this Complete Guide absolutely free.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
Quote:
Originally Posted by ntubski
Could that be a due to a difference in tab size?
Quote:
Originally Posted by rtmistler
Or perhaps the presence of tabs entirely. I suggest to never use TABS, except in a Makefile where they are required, or any other particular file similar in nature. C source files, I feel should all contain spaces as opposed to tabs.
Just my humble opinion.
I was using spaces, not tabs. All I know is the since I changed distro's, it's been happening - but wasn't before. In CentOS 7 (my old distro) I was using KDE 4, but OpenMandriva Lx 4.0 (the distro I'm using now) uses KDE 5 - therefore before KWrite was the 4.x series (KDE Applications 4.x series), but now I've got the 5.x series of KWrite (KDE Applications 5.x series).
Quote:
And sorry once again for posting code, which was not compiled, just typed off the cuff. Obviously caused a bit of confusion there.
That's ok RT, I still learnt something, and at least I know how to deal with nested structures now. So your post was still quite useful - particularly in relation to pointers. Speaking of which...
I wrote another version of the same structures I posted before, this time using a pointer so I could use the structure pointer operator. It compiles without any warnings or errors, and does the same thing as before. So your post RT was how I figured out how to add the pointer and use the structure pointer operator.
Here's the code;
Code:
#include <stdio.h>
int main(void) {
struct date {
int day;
int month;
int year;
struct time *timePtr;
struct time {
int hour;
int minute;
int seconds;
} now;
};
struct date today;
struct time now;
today.timePtr = &now;
today.day = 18;
today.month = 8;
today.year = 2019;
today.timePtr->hour = 1;
today.timePtr->minute = 51;
today.timePtr->seconds = 32;
printf("Date and time is: %i/%i/%i %i:%i:%i\n", today.day, today.month, today.year, today.timePtr->hour, today.timePtr->minute, today.timePtr->seconds);
return 0;
}
But for some reason, if I comment out the following line, gcc will still complain when trying to compile it - even though "now" is already declared before it. So donno what's going on there.
Code:
struct time now;
This is the result;
Code:
james@jamespc: devel> ./nested_struct_ptr
Date and time is: 18/8/2019 1:51:32
Meanwhile this seems a great opportunity to use, yes my favorite, GDB and examine the structure, the pointer it contains, and determine exactly what it is pointing to.
But for some reason, if I comment out the following line, gcc will still complain when trying to compile it - even though "now" is already declared before it. So donno what's going on there.
Code:
struct time now;
No, after removing that line, "now" is only defined as a field in struct date values. There isn't any "now" variable, just like there aren't any "day" or "month" variables.
and after this line all memory will now have been allocated for the entire structure including the nested time structure.
What is happening here is you have created a separate time structure called 'now' with this line:
Quote:
struct time now;
and THAT is what 'today.timePtr' is pointing to:
Quote:
today.timePtr = &now;
So when you comment out this line "struct time now;" you will get an error because now 'now' won't exist but 'today.now' still does because it was already defined.
If the pointer 'today.timePtr' is meant to point to the 'now' member of the time structure, then you would do this:
Quote:
today.timePtr = &today.now;
How the code currently is you are assigning values to the time structure 'now' NOT the 'now' member of the today structure. Add this line to the code after the rest of the printf statements:
Quote:
printf("%i\n", today.now.minute);
and you will see it prints a garbage value because nothing has been assigned to it. If you make the changes I mentioned your values will get assigned to the 'today.now' members and the program will print those values.
Last edited by Mechanikx; 08-18-2019 at 02:54 PM.
Reason: Clarified.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
Thanks guys, and thank you to ntubski and Mechanikx for explaining that! As that's what I was misunderstanding.
So I did what you said Mechanikx which fixed it, and like RT, and ntubski; you are very good at explaining things too! I wanted to get ya's more rep, but the bloody reputation system keeps blocking my attempts to do that - but I would've if I could've.
So first I tried to print what I was actually trying to point the pointer to, which is indeed the "time" structure within the "date" structure. Then I got rid of the "struct time now;" line and changed the "today.timePtr = &now;" line to "today.timePtr = &today.now;", and also added the line below the first printf "printf("today.now.hour = %i\n", today.now.hour);" (the rest of the code is the same as above tho), which prints the correct results.
Code:
james@jamespc: devel> gcc -g -Wall -Werror nested_struct_ptr.c -o nested_struct_ptr
nested_struct_ptr.c: In function ‘main’:
nested_struct_ptr.c:30:5: error: ‘today.now.hour’ is used uninitialized in this function [-Werror=uninitialized]
30 | printf("today.now.hour = %i\n", today.now.hour);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
james@jamespc: devel> gcc nested_struct_ptr.c -o nested_struct_ptr
james@jamespc: devel> ./nested_struct_ptr
Date and time is: 18/8/2019 1:51:32
today.now.hour = 4195440
james@jamespc: devel> gcc -g -Wall -Werror nested_struct_ptr.c -o nested_struct_ptr
james@jamespc: devel> ./nested_struct_ptr
Date and time is: 18/8/2019 1:51:32
today.now.hour = 1
Thanks again guys
Also, I wanted to ask you RT about this comment you made:
Quote:
Originally Posted by rtmistler
...
Aside: What I DON'T like is that they are using THAT as a passing argument. Use pointers instead. Structures can be huge in size. Eating stack.
While I think I get what you mean about structures could be huge in size; what exactly do you mean about using pointers instead beyond the obvious? Like for example; how would I use pointers to avoid blowing up the stack? As while I sorta get what the stack is; I can't say I fully understand how it works yet. So if you could explain that a bit more (and perhaps an example of what you mean), that would be helpful, if you would be so kind.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
Quote:
Originally Posted by rtmistler
Function passing arguments use your stack.
The more or larger they are, the more stack you're using.
It's not illegal, but I'd not recommend it.
I understand what you're saying, but I'm still not clear exactly what you mean when you say "use pointers instead". Could you explain what I'm missing there? Like; how exactly would I use pointers so I'm not "eating the stack"? As I'm honestly just not clear on what exactly you mean there, let alone how I would go about taking your advice. Could you give an example so I can see what you mean? Can you give an example of how I would use pointers to avoid "eating the stack"? Because without an example and more context, I really don't know what to make of your comment beyond what's already been said.
I understand what you're saying, but I'm still not clear exactly what you mean when you say "use pointers instead". Could you explain what I'm missing there? Like; how exactly would I use pointers so I'm not "eating the stack"? As I'm honestly just not clear on what exactly you mean there, let alone how I would go about taking your advice. Could you give an example so I can see what you mean? Can you give an example of how I would use pointers to avoid "eating the stack"? Because without an example and more context, I really don't know what to make of your comment beyond what's already been said.
Don't write any more code to figure this out.
Use your mind to think about it.
If you consider a structure. Just estimate how many bytes it takes up. Like the one you've been using. How many bytes does that up in space?
Now, consider a pointer. How many bytes of space does that take up? Just the pointer, not what it's pointing at.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
So you're saying that I would setup a pointer to point to the structure, and pass the pointer (that's pointing to the structure) as an argument for the function, instead of passing the actual structure as an argument for the function?
So you're saying that I would setup a pointer to point to the structure, and pass the pointer (that's pointing to the structure) as an argument for the function, instead of passing the actual structure as an argument for the function?
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
Thanks guys, I think I get it now.
So now that structures are at least a little clearer to me now; I figured it was time to revisit GazL's example of of reallocating memory in post #149. While I've still gotta read up on some of the functions Gazl has used in their example, it does make a little more sense to me now. But putting aside some of the functions used like strrchr(), strdup(), etc, and while I see in the CODE block below "lines" is a pointer (I think) pointing to the "count" member of the "Lines" structure inside the square brackets (?); Am I right is saying "lineArray" is an "array of pointers"? Also, am I right in saying that "lines" is a pointer?
Code:
lines->lineArray[lines->count++] = s;
I can't say I completely understand the example though.
So now that structures are at least a little clearer to me now; I figured it was time to revisit GazL's example of of reallocating memory
As stated before, I do not recommend you play with dynamic allocation, and especially re-allocation. Just my opinion that you're asking for difficulties.
Quote:
Originally Posted by jsbjsb001
I see in the CODE block below "lines" is a pointer (I think) pointing to the "count" member of the "Lines" structure inside the square brackets (?); Am I right is saying "lineArray" is an "array of pointers"? Also, am I right in saying that "lines" is a pointer?
Code:
lines->lineArray[lines->count++] = s;
"lines" is a pointer, it is passed as such (bottom line below) as a function passing argument.
Yes, lineArray is declared as a pointer to character pointers, therefore it can be said that it represents an array of pointers.
Code:
struct Lines
{
size_t count;
size_t capacity;
char **lineArray;
};
// later declaration as part of a function
char *addLine( struct Lines *lines, char *line )
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,827
Original Poster
Rep:
Thank you RT.
Quote:
Originally Posted by rtmistler
As stated before, I do not recommend you play with dynamic allocation, and especially re-allocation. Just my opinion that you're asking for difficulties.
...
If you ignore the pointer 'lines' for a moment, all that line of code is doing is simply:
Code:
linesArray[count] = s;
count++;
The lines-> prefix just tells it to use the count and linesArray members that are in the structure 'lines' points to.
'linesArray' is just a list of pointers, and works exactly like argv that you see in main(), except it point to the lines of input it reads in with getline(). Similarly, 'count' is the equivalent of argc, but keeps count of the number of lines.
To fully understand what's going on here, you will need to learn about the functions used and how they work.
P.S. I think rtmistler is right, dynamic memory managementis probably a bit beyond you at this point. Keep playing with pointers and structures, and pointers to structures until you get it down solid. then, you might want to try some simple linked lists using structures allocated with malloc() or strings with strdup() to get you started with dynamic memory. If I remember rightly, I think there's a chapter on linked lists in the book. There's also a chapter on malloc().
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.