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.
I'm left thinking, "How did this get broken from a week or so ago when you seemed to understand the fundamental points?"
What exactly is your current question, in ten words or less?
I'll take the blame for breaking the thread in as much as it has resulted from my suggestions to modify my original base conversion program. The intent was to suggest a very simple real-world use for bit shift operations in code already familiar to answer the question asked - "How can I see the numbers in binary?". So let's forget modifying the program.
Quote:
Originally Posted by jsbjsb001
So I honestly have no idea how to fix it. Maybe I should just move on instead,
But you have already covered everything necessary so why are you so confused by it? That is real question that you should try to answer for yourself.
Don't think in terms of "fixing" anything - we are not debugging! Think exclusively in terms of understanding how and why it works as it does - even why it works incorrectly such as the leading zeros. Put your efforts into understanding why pow2 << x adds a number of leading zeroes proportional to x before trying to "fix" it. Literally ask yourself, "Why does it do that?".
Do not ask yourself "How can I fix this?". Ask yourself, "What does this line of code actually do?", for each and every line in your code, whatever that code may be.
Do not move on before you can answer. Doing so will only lead into another round of, "I honestly have no idea". You really, really need to break that cycle - right now.
Consolidate your knowledge gains at every point and never move on before you can confidently make use of each new bit of knowledge gained - confidently! Otherwise you will have gained nothing at all.
To repeat a point made much earlier in this tread...
Code:
There is absolutely no substitute for understanding what you are doing - none!
That includes "moving on".
Quote:
Originally Posted by rtmistler
I'm sorry, but it seems no matter what I try, I hit yet another roadblock. I can see what the code is doing, but I don't honestly know why it's doing it (even how it correctly figures out the correct binary conversion). I honestly don't know why it's doing the maths it is, other than that's how it figures out the binary number.
The recurring roadblocks are the basic math ideas. Your ability to learn the programming will forever be limited by your inability to deal with the basic math. Simple harsh truth.
At the beginning of this thread there were several posters who stated that basic math knowledge was not necessary to learning programming. I invite those holding that opinion to jump in at this point and remove your roadblocks without the math... [silence?]...
You are a smart person and have shown your ability to understand the various programming concepts (even the math at times) - you can get it. But it also appears to me that you have not actually learned much of it in the sense that you seem unable to reuse it.
What I mean by that is you have clearly understood c-strings, pointers and functions within the examples given, but you seem completely flummoxed by the suggestion of using them. Here is the core problem as expressed by a very smart person...
Quote:
"I can see what the code is doing, but I don't honestly know why it's doing it..."
The missing part is the why, and most of the why is, and will always be, "the math".
Sorry if this seems harsh, I mean it as encouragement, and to again point the way forward. You can and should use the programming knowledge to further the math knowledge, and the math knowledge to further the programming knowledge. But the effort to progress one without the other will ultimately meet with very limited success in my opinion, and each roadblock you hit will be an indicator of those limits.
So I encourage you again to learn the math, as math, then understand the why of programming, as math. Only then will you begin to understand why a left shift multiplies by powers of two, and how to make effective use of it.
With that I'll wish you luck and let the thread get back on track.
did you try ddd for example (already)? This is a tool to help understanding your code, a c debugger. Probably you could try it to better understand how the program you wrote works.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881
Original Poster
Rep:
Thanks again guys.
The reason I haven't used a debugger yet was because that hasn't been covered in the chapters I've read so far, and I didn't want to jump the gun so to speak. I think I might leave trying to fix that code for the time being. But thank you for your help all the same pan64.
the reason I suggest you to use ddd is: you can display all the variables you use in your code as you execute it line by line.
I think you will understand what's happening much easier. But obviously it depends on you, if you wish you can try.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881
Original Poster
Rep:
Thanks again for all of your help pan64, it's very much appreciated. Thank you again pan.
I have installed ddd like you suggested, as it's in the CentOS repo's. But because I haven't learnt debugging yet; I'm not sure how to use gdb, as from what I can see, ddd is a graphical "frontend" for gdb.
Sorry for the verrry late reply, I haven't been ignoring this thread. But I've had another member helping me with the old mathematics out-of-thread so to speak (I would say who that is, but I haven't asked them if that's ok with them, so I don't want to make them feel uncomfortable or anything). I wasn't going to reply to this thread this soon, and was going to wait until they had given me some more "lessons"; but I've been reading the C book, and I have a quick question about some code mentioned for the malloc() function;
Quote:
Originally Posted by C book
Using malloc, the function call looks like this:
Code:
intPtr = (int *) malloc (1000 * sizeof (int));
Does the "int *" part mean, "all integers" ? Because I have seen that part of the code before, but it hasn't been clear what it actually means. I think I understand the rest of it, but not quite sure of that bit tho. I'd be grateful if anyone could make the meaning a little clearer for me.
I modified an earlier program I wrote below to "allocate memory at runtime" for the array I've got it in, to try and drive the point home. I *think* that's what it's doing anyway.
Because I wanted to try and make sure I'm getting the point right by making it fail to allocate memory, by putting in a really high number, so at least in what I'm thinking; my machine won't have that amount of memory available to allocate to it. It does work if I change "199999999999999000" to a far more reasonable number - which seems to confirm what I'm thinking.
Here's my modified program anyway;
Code:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int index;
int *varsPtr;
varsPtr = (int *) malloc (199999999999999000 * sizeof (int));
if ( varsPtr == NULL ) {
fprintf (stderr, "malloc failed\n");
return 1;
}
struct example {
int example1;
int example2;
int example3;
};
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;
}
That code as it is when run on my machine, fails with the "malloc failed" message above, to be clear. But does work if I change the number mentioned above.
I'm not totally sure what you mean by "all integers". Malloc returns a pointer to void. What you're doing here is typecasting the pointer to type pointer-to-int because intPtr is of type pointer-to-int(I'm assuming based on the name). So after malloc creates a block of 1000 int sized objects in memory it returns a pointer, of type pointer-to-void, that points to the first one. This pointer is then typecast to type pointer-to-int and stored in intPtr. If the intPtr was of type pointer-to-double then you would typecast to type pointer-to-double.
Malloc has returned a void pointer since ANSI C I believe. Before that it was a char pointer and I believe that's where the need arose to typecast. You can assign a void pointer to a pointer of another type but typecasting is considered clearer.
Also, just in case you didn't know, you should use free() to free the pointer used with malloc.
Quote:
free(varsPtr)
It is true that the system you're on most likely will do clean up once the program exits, like freeing memory, but it's not a good idea to rely on that. As a general rule you should free memory as soon as you're done with it.
Last edited by Mechanikx; 06-13-2019 at 05:23 AM.
Reason: See post #400
Does the "int *" part mean, "all integers" ? Because I have seen that part of the code before, but it hasn't been clear what it actually means. I think I understand the rest of it, but not quite sure of that bit tho. I'd be grateful if anyone could make the meaning a little clearer for me.
it is just the type to convert the return value of what malloc returns, which is a pointer. You want that pointer (which is void *) to be an (int *) which is the data type of varsPtr.
I'm not totally sure what you mean by "all integers". Malloc returns a pointer to void. What you're doing here is typecasting the pointer to type 'int' because intPtr is of type 'int'(I'm assuming based on the name). So after malloc creates a block of 1000 int sized objects in memory it returns a pointer, of type void, that points to the first one. This pointer is then typecast to type 'int' and stored in intPtr. If the pointer was of type double then you would typecast to double.
Oops - from the program intPtr is "int *" so the cast is supposed to be (int *). The type the cast is applied to is the value returned by malloc which is (void *). So the cast is always to a pointer type.
Quote:
Malloc has returned a void pointer since ANSI C I believe. Before that it was a char pointer and I believe that's where the need arose to typecast. You can assign a void pointer to a pointer of another type but typecasting is considered clearer.
Also, just in case you didn't know, you should use free() to free the pointer used with malloc.
yep
Quote:
It is true that the system you're on most likely will do clean up once the program exits, like freeing memory, but it's not a good idea to rely on that. As a general rule you should free memory as soon as you're done with it.
The only systems I know of that don't necessarily clean up on exit are in embedded software - and there may not be an operating system as expected.
Oops - from the program intPtr is "int *" so the cast is supposed to be (int *). The type the cast is applied to is the value returned by malloc which is (void *). So the cast is always to a pointer type.
"Oops" is right! :P I meant pointer to type int. Thanks for pointing that out. I'll make the necessary edits.
Quote:
Originally Posted by jpollard
The only systems I know of that don't necessarily clean up on exit are in embedded software - and there may not be an operating system as expected.
Sure. The point I was trying to make was whether a system cleans up for you or not it's good practice to free the memory you use.
Before ANSI/ISO Standard C introduced the void * generic pointer type, these casts were typically required to silence warnings (and perhaps induce conversions) when assigning between incompatible pointer types.
Under ANSI/ISO Standard C, these casts are no longer necessary. It can also be argued that they are now to be discouraged; see question 7.7b.
The compiler STILL has the option to complain about improper casting though. Casting to an int introduces truncation.
And casting a pointer to anything but another pointer is also wrong. That is what unions are for, and a union avoids the problem of arbitrary truncation.
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881
Original Poster
Rep:
Thanks guys.
It is a little more clear now, although I can't say I completely understand yet. I'll probably have to do some more reading of both your posts, and the book to "fully get it".
By "all integers", I meant does the * mean "all" ? Like if I typed rm *.txt I know this means "delete all files with the extension .txt", so does the * have the same meaning in C ? (I know the * also means multiply, and it defines pointers in C as well)
I did read about the free() function, but I totally forgot to include it in my code. But yes, I see your point Mechanikx. So I'll try to remember to do that next time, and thanks for the example too.
It is a little more clear now, although I can't say I completely understand yet. I'll probably have to do some more reading of both your posts, and the book to "fully get it".
By "all integers", I meant does the * mean "all" ? Like if I typed rm *.txt I know this means "delete all files with the extension .txt", so does the * have the same meaning in C ? (I know the * also means multiply, and it defines pointers in C as well)
I did read about the free() function, but I totally forgot to include it in my code. But yes, I see your point Mechanikx. So I'll try to remember to do that next time, and thanks for the example too.
Just to be clear: The * also means void ?
Oh, I see what you mean now. In this context it's just specifying a pointer.
(int) var - cast to type int
(int *) var - cast to type pointer-to-int
You're only typecasting malloc's return value which is a pointer. You're not doing anything to the elements of the actual block that you've allocated.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.