LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 06-19-2019, 07:17 AM   #421
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513

K&R is terse because it is trying to teach a new language to people that already know programming in a different language.
 
1 members found this post helpful.
Old 06-19-2019, 08:39 AM   #422
WideOpenSkies
Member
 
Registered: May 2019
Location: /home/
Distribution: Arch Linux
Posts: 166

Rep: Reputation: 61
Quote:
Originally Posted by jpollard View Post
K&R is terse because it is trying to teach a new language to people that already know programming in a different language.
It's best to view it as a reference manual instead of a beginner book. I've found N.K. King's Modern C to a better alternative.
 
Old 06-19-2019, 08:43 AM   #423
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
Quote:
Originally Posted by Contrapak View Post
It's best to view it as a reference manual instead of a beginner book. I've found N.K. King's Modern C to a better alternative.
The only difference is the examples provided on how to use the features.

Quite frequently, these are left for a "programming guide" rather than a reference.
 
1 members found this post helpful.
Old 06-19-2019, 09:50 AM   #424
Beryllos
Member
 
Registered: Apr 2013
Location: Massachusetts
Distribution: Debian
Posts: 529

Rep: Reputation: 319Reputation: 319Reputation: 319Reputation: 319
Quote:
Originally Posted by chrism01 View Post
I haven't read all 28 pages of this thread ( ),
I set my Thread Display Option to 50 posts/page, so I only have to read 9 pages.
 
Old 06-22-2019, 06:22 PM   #425
anon033
Member
 
Registered: Mar 2019
Posts: 188

Rep: Reputation: 13
Quote:
Originally Posted by hazel View Post
I've never used a full-scale IDE but I find the geany editor ideal for writing code.
I never found IDEs helpful. They just get in the way, I am using VI/Neovim (both Vi and neovim) myself at the moment. I plan to either use ED or write my own, I love syntax highlighting and really having my code in view; but ED is just a nice way to not have anything in my way.
 
Old 06-24-2019, 12:20 AM   #426
WideOpenSkies
Member
 
Registered: May 2019
Location: /home/
Distribution: Arch Linux
Posts: 166

Rep: Reputation: 61
Quote:
Originally Posted by FOSSilized_Daemon View Post
I never found IDEs helpful. They just get in the way, I am using VI/Neovim (both Vi and neovim) myself at the moment. I plan to either use ED or write my own, I love syntax highlighting and really having my code in view; but ED is just a nice way to not have anything in my way.
ED is THE standard editor!
 
Old 06-30-2019, 02:46 AM   #427
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881

Original Poster
Rep: Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063
@RT, FOSSilized_Daemon's first post #413 was very much on-topic and was directly responding to my OP (as they quoted, although they didn't need to quote the whole post). FOSSilized_Daemon's second post #415 was in response to Contrapak's question, which we can hardly blame FOSSilized_Daemon for in all "fairness". I was not saying otherwise. I did not mark either of FOSSilized_Daemon's posts as "helpful" (not saying they weren't) - my guess would be that was Contrapak that did, but only FOSSilized_Daemon really knows the answer to that (and I'm not asking them for it either). But since Contrapak has derailed this thread enough as it is, I don't wish to argue the point with you all the same. But that said, I still maintain what I said, and I believe I do have a right to say that given I am the one that started this thread to begin with. But moving on...

I've been re-reading the chapter about "Pointers", and while they do make more sense to me now; I do still have a question that isn't quite clear to me. Now it say's the following;

Quote:
Originally Posted by C book
One thing worth remembering when dealing with pointers that are sent to
functions as arguments: The value of the pointer is copied into the formal parameter
when the function is called. Therefore, any change made to the formal parameter by the
function does not affect the pointer that was passed to the function. But here’s the catch:
Although the pointer cannot be changed by the function, the data elements that the
pointer references can be changed!
What I've highlighted in bold above isn't clear to me. I DO understand the second part of that same sentence, which if I'm right means that; you CAN change the "value" of whatever the pointer is pointing to from within a function that you have passed the pointer to as an "argument". But my question is; does what I've highlighted mean that, while you CAN change the value of what's being pointed to by the pointer in question; you CANNOT change what the pointer is pointing to ? Correct or Incorrect?

I have written some code based on the example in the book below where it say's what I've quoted above, and while my test code does seem to clarify my "theory" above, I'm still not quite sure I get the point of what I've highlighted in what I've quoted above.

Here's the test code I wrote to test my theory;

Code:
#include <stdio.h>

void test (int *int_pointer);

int main(void) {

    int i = 50, *p = &i;
    
    printf("Value of \"i\" before the function call: %i\n", i);
    test(p);
    printf("\nValue of \"i\" after the function call: %i\n", i);

    return 0;

}

void test (int *int_pointer) { 

         int testvar = 0;
         *int_pointer = 100;
	 int_pointer = &testvar;
	 *int_pointer = 200;
	 printf("\nValue of \"testvar\" inside function \"test\": %i\n", *int_pointer);

}
Here's the result of it when run;

Code:
[james@jamespc devel]$ ./ptr_test_func 
Value of "i" before the function call: 50

Value of "testvar" inside function "test": 200

Value of "i" after the function call: 100
Thanks for any help with this.
 
Old 06-30-2019, 04:26 AM   #428
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
It is talking about the pointer "p" used in "test(p)".

Changes to "int_pointer" (note: not what is pointed to by "int_pointer") will change the "p" pointer in main.

To make that clearer you needed to print the value of "int_pointer" in the test function (remove the indirection, and instead of using %i in the format, use %p). Then in the main print the "p" variable.

This is the same thing that happens with
Code:
void test(int val)
{
  val = 256;
  printf("in test: val = %d\n",val);
}

int main(void)
{
   int main_val = -500;
   printf("main_val = %d\n",main_val);
   test(main_val);
   printf("after calling test; main_val = %d\n",main_val);
   return(0);
}
The value of main_val doesn't change just because the parameter passed was changed. This is the "pass by value" of C parameters. The only change is that the value passed is the pointer to the value, not the value itself.

But the limitation on the parameter remain.

What makes it look confusing is when you DO want to change the pointer... You then have to pass a pointer to the pointer...

So you get a different test program

Code:
#include <stdio.h>

int value = 256;
int *a = &value;
int other_value = 0;

void test(int **ptr_ptr)
{
  printf("in test: ptr_ptr = %p\n",ptr_ptr);
  *ptr_ptr = &other_value; // note the indirection
}

int main(void)
{
   printf("main value = %d, and a= %p\n",value, a);
   test(&a);
   printf("after calling test; a = %p\n",a);
   return(0);
}
Now you can see the pointer a changed... but that is due to the value being passed was a pointer to the pointer....

BTW, I put the test function first simply to avoid having to put a forward declaration. It is a style variation I use because I have found that if I change the function, I sometimes forget to change the forward declaration, thus creating extra errors when the parameters change.

Last edited by jpollard; 06-30-2019 at 04:29 AM.
 
1 members found this post helpful.
Old 06-30-2019, 05:58 AM   #429
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881

Original Poster
Rep: Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063
Quote:
Originally Posted by jpollard View Post
It is talking about the pointer "p" used in "test(p)".

Changes to "int_pointer" (note: not what is pointed to by "int_pointer") will change the "p" pointer in main.
...
The value of main_val doesn't change just because the parameter passed was changed. This is the "pass by value" of C parameters. The only change is that the value passed is the pointer to the value, not the value itself.
...
Thanks again for your help jpollard!

While I'm little clearer now; I'm still not sure I'm totally clear on what you mean. I can see what your example programs are doing, but I'm still not sure I'm clear about what actually changes and what doesn't.

To use your first example program as an example; do you mean that the "main_val" variable being passed to the "test" function is still pointing to "var", but this CAN be changed; but the actual "value" of "main_val" CANNOT be by the "test" function? Because I'm still not clear.
 
Old 06-30-2019, 06:32 AM   #430
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,897

Rep: Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019Reputation: 5019
Quote:
Originally Posted by jpollard View Post
Changes to "int_pointer" (note: not what is pointed to by "int_pointer") will change the "p" pointer in main.
I think that should have read "will not". The function gets an independent copy of the pointer, though they will both initially have the same value (i.e. point to the same memory location).

Code:
#include <stdlib.h>
#include <stdio.h>

static int x = 1000 ;
static int y = 2000 ;

void change_value( int *my_pointer )
{
    *my_pointer = 10 ;
    printf("my_pointer before change= %p\n", my_pointer) ;

    my_pointer = & y ;
    printf("my_pointer after change= %p\n", my_pointer) ;
    
    return ;
}

int main( )
{
    int *p = & x ;

    printf("before p = %p, *p = %d\n", p, *p ) ;
    change_value( p ) ;
    printf("after p = %p, *p = %d\n", p, *p ) ;  
    
    return EXIT_SUCCESS ;
}
output:
Code:
before p = 0x404030, *p = 1000
my_pointer before change= 0x404030
my_pointer after change= 0x404034
after p = 0x404030, *p = 10
The change to my_pointer does not change p. The value of x, a.k.a *p, a.k.a *my_pointer (before we changed it) is changed however.

Last edited by GazL; 06-30-2019 at 06:46 AM. Reason: cleanup whitespace
 
1 members found this post helpful.
Old 06-30-2019, 06:41 AM   #431
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
Quote:
To use your first example program as an example; do you mean that the "main_val" variable being passed to the "test" function is still pointing to "var", but this CAN be changed; but the actual "value" of "main_val" CANNOT be by the "test" function? Because I'm still not clear.
When the function "test" is called, it is a COPY of the value of "main_val" that is the parameter.

Changing the parameter value in the test function does nothing to the value of "main_val".

This is where a bit of assembly COULD make things clearer, but it needs a decent machine architecture to keep things simple. Unfortunately, we don't have one.

The parameters are copies of values pushed on the stack, any changes within the function called can only change the value on the stack. When the function returns, the value(s) on the stack are discarded.

The only way to make changes to the original value is if it is an ADDRESS of where the original value is what gets placed on the stack. Then the function can use indirection to change the original value as what is on the stack is a pointer. The function can usually change the pointer (unless it is defined as const) but now the pointer points elsewhere; and when the function returns the pointer value on the stack is discarded.
 
1 members found this post helpful.
Old 06-30-2019, 08:31 AM   #432
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881

Original Poster
Rep: Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063
Thanks again GazL and jpollard!

I think I get what ya's are saying now, it's just the way it's phrased in the C book is really confusing. Thanks also for the example programs, as with that and what you guys have said it makes a lot more sense now. I think I was getting confused between the value of the actual variable and the actual pointer in hindsight.

You two have been really helpful to me, and I'm really grateful for the help both of you have given me. I wish I could thank you both in person. Thanks a lot again, and sorry about the confusion - it'll hopefully all make sense one day (not that what you guys have said so far doesn't). A BIG thanks to both of you again!

Quote:
Originally Posted by jpollard View Post
...
The parameters are copies of values pushed on the stack, any changes within the function called can only change the value on the stack. When the function returns, the value(s) on the stack are discarded.

The only way to make changes to the original value is if it is an ADDRESS of where the original value is what gets placed on the stack. Then the function can use indirection to change the original value as what is on the stack is a pointer. The function can usually change the pointer (unless it is defined as const) but now the pointer points elsewhere; and when the function returns the pointer value on the stack is discarded.
I have read a little bit about the "stack", but nowhere near enough to be any expert on it though. But I would like to get a better understanding of exactly what the "stack" is and how exactly it works. But I might wait until I've got a better handle on C before tackling Assembly tho.
 
Old 06-30-2019, 09:32 AM   #433
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
Quote:
Originally Posted by jsbjsb001 View Post
Thanks again GazL and jpollard!
I have read a little bit about the "stack", but nowhere near enough to be any expert on it though. But I would like to get a better understanding of exactly what the "stack" is and how exactly it works. But I might wait until I've got a better handle on C before tackling Assembly tho.
It isn't that it is difficult, it just has some ticky details - and the Intel architecture is one of the worst for ticky details before getting to comparisons with high level languages.

Personally, I like the PDP-11 as being the simplest yet sufficiently complete for explanations.

It is a 16 bit architecture and has only 8 registers (register 7 is the program counter, register 6 is the stack pointer, the others - 0,1,2,3,4,5 are general purpose 16 bit registers that CAN be used for implementing stacks... for 32 bit integers you have to combine [0,1], [2,3] and [4,5]. But the basic calling sequence is pretty much the same for all languages. The # below is for constant values. A number with "." is generally a decimal, without it then it is octal...
Code:
    MOV  value,-(SP)   ; meaning push the contents of address value on the stack
    JSP  PC,address    ; meaning save the program counter register on the stack and jump to the address
    ADD  #2,SP         ; meaning discard the top element on the stack (the value pushed).
Now the subroutine (address) above has a bit more to do:
Code:
address: MOV R1,-(SP)  ; save registers. R0 is always considered the return value,
         MOV R2,-(SP)  ;      but it too could be saved
         MOV R3,-(SP)
         MOV R4,-(SP)
         MOV R5,-(SP)  ; this one is special by convention.
         MOV SP,R5     ; this saves the current stack pointer in R5. this allows the function
                       ; to use R5 with an offset to locate the parameter, or other offsets
                       ; for local variables
         MOV 12(R5),R0   ; this copies the value of the parameter to R0
         ADD #5,R0       ; so now add 5 to it.

                       ; assuming that is all...
         MOV R5,SP     ; restore the stack (and discard local variables.
         MOV (SP)+,R5  ; restore the old r5
         MOV (SP)+,R4
         MOV (SP)+,R3
         MOV (SP)+,R2
         MOV (SP)+,R1
         RTS PC        ; which restores the PC, (a MOV (SP)+,PC would work too, but is slower)
Now the usage of R5 is that of a "frame pointer" that is a reference to WHERE on the stack the parameters, saved registers, and any local variables may be. You might also find references to "activation record" which is the area of the stack used for that information.

And this function is equivalent to

Code:
int address(int value)
{
    return(value+5);
}
Because it is so short and doesn't use registers 1,2,3,4 - they don't even have to be saved or restored. Only the frame pointer (r5 here) is used. And if the registers aren't saved, it could just as easily use the stack pointer directly. It gets more useful when there are local variables as it provides a "fixed" reference for where they are on the stack.

But you can ignore this post... :-)
 
1 members found this post helpful.
Old 06-30-2019, 10:20 AM   #434
jsbjsb001
Senior Member
 
Registered: Mar 2009
Location: Earth, unfortunately...
Distribution: Currently: OpenMandriva. Previously: openSUSE, PCLinuxOS, CentOS, among others over the years.
Posts: 3,881

Original Poster
Rep: Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063Reputation: 2063
I won't pretend I "completely" understand all of that, but from what I can tell, it seems that's assembly code. Hopefully I'm right there. I must say though, that explanation is quite good in my non-expert opinion. The "SP" means the "stack pointer" ?

I'll try to remember your post above jpollard when I can hopefully be in a better position to learn assembly and more about "stacks". But no, I won't ignore your post

But while I get an integer takes up a certain amount of "bits", and the processor deals in "bits"; I can't say I'm entirely clear on exactly what's meant by a 32 bit integer beyond the obvious. Let alone am any expert on "bits" and "bytes" in general, but hopefully one day it becomes more clear. Maybe when I know more about math it might be more clear.

But thanks for the info though jpollard!
 
Old 06-30-2019, 10:42 AM   #435
jpollard
Senior Member
 
Registered: Dec 2012
Location: Washington DC area
Distribution: Fedora, CentOS, Slackware
Posts: 4,912

Rep: Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513Reputation: 1513
Quote:
Originally Posted by jsbjsb001 View Post
I won't pretend I "completely" understand all of that, but from what I can tell, it seems that's assembly code. Hopefully I'm right there. I must say though, that explanation is quite good in my non-expert opinion. The "SP" means the "stack pointer" ?
yes. For some reason my old teacher hat got kicked... :-)
Quote:

I'll try to remember your post above jpollard when I can hopefully be in a better position to learn assembly and more about "stacks". But no, I won't ignore your post
I found assembly rather easy. My second language learned after FORTRAN - and the Fortran compiler gave me help as I could get it to print the assembly of the fortran program, annotated by the fortran itself. So it was mostly self taught.

The PDP-11 was the simplest general purpose stack machine I've ever used.

Quote:
But while I get an integer takes up a certain amount of "bits", and the processor deals in "bits"; I can't say I'm entirely clear on exactly what's meant by a 32 bit integer beyond the obvious. Let alone am any expert on "bits" and "bytes" in general, but hopefully one day it becomes more clear. Maybe when I know more about math it might be more clear.
Well, like earlier Intel processors, the registers were limited in size to 16 bits. But certain operations COULD do 32 bit arithmetic, but only if two registers were used. So r0,r1 combined provide a 32 bit integer.

It could also be done manually, by adding the low order 16 bit values togetether, adding a carry to the high order 16 bits, and add the high order 16 bit values together. But that takes more instructions, so the vendor added the hardware 32 bit add/subtract/multiply/divide as an option, then added 32 bit and 64 bit floating point. But the base machine remained a 16 bit processor, with 16 bit addressing. And like the 8086 with its expanded memory - the PDP-11 had an MMU that added either 2 or 6 bits to the physical address. The 2 bit addition allowed up to 262K (- 4K for memory mapped I/O registers), the 6 bits allowed up to 4MB (again, minus the 4K for I/O registers).
Quote:
But thanks for the info though jpollard!
You are welcome.

Last edited by jpollard; 06-30-2019 at 10:44 AM.
 
1 members found this post helpful.
  


Reply

Tags
c programming, learning c



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Finally decided to try to get libinput to work Timothy Miller Linux - Hardware 3 01-04-2018 08:04 PM
Decided to try Lubuntu 14.04 on my netbook... pcninja Ubuntu 4 04-20-2014 08:18 PM
Finally decided to get serious & learn a302svt LinuxQuestions.org Member Intro 1 07-19-2007 12:27 PM
Decided to try Debian some guidance required ninadb Debian 2 08-20-2004 11:40 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:29 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration