I am very rusty with c, I do try to learn it but every time I get stuck on something. I need to know something that's bugging me. Not what is a pointer, but why? I can have a value but why use it as a pointer? What is the reason and benifits?
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (73)
Could you provide a language you are familiar with where you don't use pointers and I'll explain how it uses pointers (not as a language construct).
Sure so my day to day would be spent in Javascript / Typescript.
OK so this is harder than I thought. I wanted to use some form of ideomatic code, but I'm not really seeing it. All interactions with objects and array is by reference, much like pointers in C.
If you pass the object to a function, modification within that function will be visible to the parent. But I am not really seeing this approach taken with javascript.
C does not have reference types. If javascript was passing objects by value, the list would not see the modification.
Using D shows the behavior without "pointers". Now if you asked why use pointers in D, my answer would be to interface with C. There are other uses, but it is not frequent enough to try and cover.
The javascript semantic are like the C semantics here because neither of them pass by reference.
An object value in javascript allows you to reach the properties associated with that object value in a similar way that a pointer allows you to reach the elements of the array that it indexes into.
In both languages there is only pass by value semantics.
I understand that, array in C isn't a great example because they are pointers. However this still fits well with answering the question, "why use pointers"
I provided another example using
struct
the point was this could be extrapolated into the C and Javascript languages, because this is where you'll see javascript behavior differ from C.Sorry this post kind of exploded and so there is so much information to go through, il have a good read later on today π
I don't think that it does differ, except in-so-far as javascript doesn't have a data structure like struct, which means that you can't make a reasonable comparison.
If javascript did have a data structure like struct, then it would work just like in C, since both use pass-by-value semantics. :)
Javascript has objects and classes. Objects are pass by reference and if C had them, it too would be pass by reference.
Hold up. References are passed by value. Crap if you pass a reference by value, are you passing by value or reference? π€
Well, it is by value, language like C++ and C# can define functions which take the argument by reference. But this topic wasn't really about if javascript was C then it would behave the same.
No the question was about why use pointers. C does not provide objects like javascript, Javascript does not provide the same value semantics as in C. If the OP can understand his use of reference semantics in Javascript, he would also understand why he would pointers in C.
If you read the ecmascript standard you'll see that javascript doesn't have object references -- just object values.
The object properties are just reached indirectly via the object value, which is where the confusion comes in.
This is very similar to how array elements are reached indirectly via a pointer in C.
And here C and javascript have the same semantics -- you pass a thing by value which lets you reach other things later on.
In neither case does the language provide reference types.
Interesting, so it implements a vtable as the object. And yes such an approach is exactly like C with pointers to access the properties. That continues to fit with my exact point and why I'm using it as an example for why you would use pointers.
A particular javascript implementation might use a vtable, or it might not -- that's an implementation strategy.
I agree that object values provide indirect access to properties, just as pointer values provide indirect access to elements in C -- it's a clear correspondence.
My only disagreement is about introducing 'object references' or claiming that there is 'pass by reference' -- these exist in neither language.
Any chance you could explain to me what the semantic difference would be if javascript did pass objects by reference rather than by value with property lookup?
Sure.
As javascript passes by value, this will print {"value":1}.
If javascript passed by reference, this would print {"value":2} instead.
But that is the same semantics as Java, C#, and D have, and their objects are reference.
By assigning a new object to
a
the reference is what is changing. This is why I did bring up true pass by reference provided in affirmentioned languages.But now you took issue with calling javascript objects being references and that the properties are. Thus I'm interested in the importance of this distinction.
The semantics of these languages differ from both javascript and between themselves.
You can draw analogies between the various mechanisms, but the detail of how things work, and the internal language of the specifications differ.
If you're going to claim that javascript has object references because you can assess things indirectly though object values, then you'll need to explain why pointers in C++ aren't object references as well (in which case you'll run into trouble since C++ has object references, which aren't pointers), or why numbers aren't object references (because you could set up a scheme where you use a number to look up an object).
When we talk about a language it's important to use the terms of the language specification, otherwise you end up with nonsense like "javascript passes objects by reference, but the references are passed by value."
If you twist your brain enough you can try to make that model fit, but it's like adding epicycles to a geocentric model in preference to switching to a heliocentric model.
Java
Java does not support pass-by-reference.
docs.oracle.com/javase/specs/jls/s...
It does have a concept of 'reference values', which it clarifies as "The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object."
So within Java we can talk about passing "reference values" -- which are values that allow indirect access, rather than being direct references.
These "reference values" are passed like any other value -- by value.
|C#|
On the other hand C# does support pass-by-reference using the 'ref' keyword to annotate a parameter that should receive arguments by reference.
C# also has "reference type" values.
docs.microsoft.com/en-us/dotnet/cs...
These "reference type" values are values that provide indirect access to objects, and these "reference type" values are passed like any other value -- by value unless to a parameter annotated to receive-by-reference.
D
D supports pass-by-reference but has no reference types.
In D you use 'ref' to annotate a parameter to indicate that it receives an argument by reference.
D has pointer values, which are passed as usual, by value or by reference depending on the receiving parameter.
dlang.org/spec/type.html
Javascript
Javascript does not support pass-by-reference, or have "reference types".
It has immutable object values which can be used to access mutable properties associated with that object value.
These object values are passed by value, just like any other value in javascript.
ecma-international.org/publication...
The important distinction is that the javascript language doesn't have anything called object references.
You might as well call them pointers, because they're kind of pointery if you look at them just right, and don't think about it very much.
You might as well call them spoons, because the fork language has a spoon type that allows you to get bites indirectly, and then you could say that javascript passes object spoons by value.
But that would be silly, wouldn't it?
If I just combine statements you made with the quote you took from the Java spec.. strip some things down we end up with
"we can talk about passing by reference"
And since the we know from the quote that these "references" are not the object but instead "are pointers to these objects" we can now extrapolate that by the words of the spec we are in fact passing objects by reference and not by value.
Now this provides no counter argument to your claim about Javascript objects being values and not references. But the way the spec is written indicates that their objects are not referenced as we see in Java, C#, and D.
Should I continue with dissecting your misrepresentation of C# as well?
"A reference type is a class type[...]"
Oh, so Objects (instances of a class) are references types. As you say these references are passed by value... the object they point to, passed by reference.
What you're passing are arguments.
Pass by reference means that the parameter and the argument refer to the same thing -- modifying the parameter modifies the argument.
This doesn't occur in Java -- changing the value of a parameter does not change the value of the argument.
Likewise, this doesn't occur in C -- changing the value of a parameter does not change the value of the argument.
Which is why Java and C both have only pass-by-value.
Being able to change some indirect object via a pointer or via a "reference value" (which is a pointer to an object) is irrelevant to this for the simple reason that the indirect object wasn't passed at all.
Which means that you can't reasonably claim that the object was passed -- instead a pointer (or reference value in Java) was passed by value, and later used to reach it.
I think this shortcut you're taking here is the root of the confusion.
Passing a pointer is not passing the object pointed at.
The statement initially made that you took issue with was, "All interactions with objects and array is by reference, much like pointers in C."
It spoke not of "pass by reference" and in light of all we have gone over is still a true statement for Java and in so far as Javascript the interactions are with properties.
Your objection suggested that this statement was wrong and it was because "neither of them pass by reference." But my stance is that the statement is correct that a reference is in fact passed, but now you claim that "the indirect object wasn't passed at all."
This is a new term, "indirect object," for which I now don't know of which you refer.
I think it comes down to the same confusion in language.
Since you're claiming an equivalence between pointers and references, let's use C where this should be all very clear. :)
It seems to me that you're claiming that x was passed by reference to foo.
Are you making this claim?
My claim is that x wasn't passed to foo at all. Instead a pointer to x was passed to foo by value, demonstrable by independent reassignment of the parameter p in foo.
Do you disagree with my claim?
No, I'm claiming a pointer was passed to foo.
OK, right, the pointer was passed by value, to foo.
No.
So yes it would appear to be down to the same confusion of languages. I'm using the language of the spec and that confuses you.
I think the key disagreement here is on the claim that "an object is passed by reference by value to foo".
I think the correct thing to say is that "a reference value (referring to an object) is passed by value to foo".
But if you could show me where in the language of the spec they talk about "an object is passed by reference by value" I'd be grateful.
Woohoo. Hold up. I have responded to each of your points about whether there is a disagreement in the statement. By highlighting a "key disagreement" does that mean we still have disagreement on other points or that there a statements I'm making which are agreed upon.
Lets stick with Java as we have more language coming from the spec than with Javascript (and I've already conceded that in that context you appear to be correct that these statements are not accurate)
"All interactions with objects [...] is by reference"
The spec defines: "Reference Value -> A reference (pointer) to an object" by stating, and I quote "The reference values (often just references) are pointers to these objects"
I think the actual key disagreement is what the mean of 'by' is. How do you feel if I change it to:
"an object is passed [via] reference by value to foo"
Lets take your C code again, with a slight change from
X
toint
, because I don't want confusion withx
Since we have switched to C really quick I need to dig into the C spec, "A pointer type describes an object whose value provides a reference to an entity of the referenced type"
Ah crap, they used the term object, lets just ignore that for now.
With that put down, we can now utilize language from the C spec that says, the int is passed by reference to foo.
Ok, it's good that you've worked your logic through to produce the claim that C passes by reference.
This is good, because we know that it is clearly untrue, which means that your logic has a faulty premise. :)
Let's check to see if x was passed by reference.
If x was passed by reference, then modifying the parameter would modify the argument.
Does the assignment to p affect x?
No.
Therefore p is not a reference to x.
Therefore x was not passed by reference.
So, what is the reference to x?
It is *p.
We can test this with *p = 4; which will change the value of x, since *p is a reference to x.
Which solves the problem nicely.
Therefore foo(&x) does not pass x by reference to foo, and there is no way to pass a reference to x to foo.
(Which is unsurprising, since C does not support pass by reference)
What you can do is to pass the value of a pointer from which an alias (reference) may later be constructed -- but this is not pass by reference, and it is not passing the object pointed at by the pointer.
OK so I see what is happening, you are talking about passing the symbol by reference, when I clearly state the int was passed by reference. But it looks like we need to define some more items from the spec so that we are clear.
Reference operator -> &
Dereference operator -> *
This creates a difference from the way you described these synthetic descriptions. Going forward keep in mind that I have already established that the C spec has specified that pointers are references.
p
is a reference*p
removes reference to allow modifying the referenced data&x
creates a reference to xfoo(&x)
a reference to x is passed into foo by valueSince you brought up passing symbols by reference, let's take a look at that.
You can't pass symbols in C.
I'm talking about passing the argument, which may be an lvalue.
However, I think your terms are quite off regarding C.
& is not a reference operator.
open-std.org/jtc1/sc22/wg14/www/do...
&x just produces a pointer to x -- that's all.
*x just produces the lvalue (the object, not the value of the object) that x points at.
An lvalue in C corresponds with what is called a reference in other languages -- it's what allows you to write things like *x = y;
This is in contrast with 'reference values' in Java, and so on, which correspond with restricted pointers, rather than references (and why they're qualified as 'reference values').
And you can see this in how languages which do have first class references, like C++, work.
A pointer doesn't correspond with a reference -- but it allows you to later produce an lvalue which does.
How many times do I need to quote the Java spec you referenced.
"The reference values (often just references)"
So let's ignore that I already established that the spec equates pointers as references.
lvalue -> reference
lvalue -> object
x
-> is an lvaluex
-> argumentlvalue is not the value.
Good, I'm glad this is at least consistent with your claim.
x
being an lvalue and it is an argument, we know that the argument is passed by value. We can conclude thatNo, seriously, more and more terms are being thrown in and to define them existing terms we have not come to a consensus on are used. This just makes the entire conversation an battle of adding terms. Luckily I did not see 'references' or 'Dereference' in the spec so those can be thrown out.
So let me try again, do you agree and why:
For Java
Reference values -> commonly just reference
Reference value -> points to an object
Reference values are passed by value
For C:
Pointer -> reference to an entity
The spec does not equate references with pointers, and it's trivial to demonstrate that pointers do not have the semantics of references.
This is a critical requirement for pass-by-reference semantics.
This is also why C does not support pass-by-reference while it does support passing pointers.
What that means is that people often abbreviate "reference value" as "reference".
It doesn't mean that "reference value" means "a reference" in the sense of other languages, such as C++.
Here's a nice article which explains this in detail for Java, with references to the standard.
javadude.com/articles/passbyvalue.htm
the C spec, "A pointer type describes an object whose value provides a reference to an entity of the referenced type"
See C did not need to worry about conflating reference type semantics because they did not have the feature.
We are back to the same problem, you do not accept the language of the spec because you have a different language spec which you prefer to use over the others.
Yes, C is very clear that a pointer isn't a reference.
Its value can provide a reference (via *p).
The problem is that you're taking words from different specifications and conflating them without considering the semantics of the word within that specification.
And this is leading to clearly false conclusions, such as your assertion that pointers are references, and that passing pointers is pass by reference.
I am taking words from the C spec when talking about C. I'm taking words from the Java spec when talking about Java. You are the one taking words from the C++ spec when talking about languages that are not C++.
Are you still claiming that in C passing the value of a pointer to an int object to a function is passing the int object by reference?
"All interactions with objects and array is by reference, much like pointers in C."
Does this mean Java is pass by reference?
Is this statement wrong for Java?
Why won't you answer my questions for clarifying our disagreement?
Let's write it out properly.
"All interactions with objects and arrays is by reference values, much like pointers in C."
This does not mean that Java is pass-by-reference.
Reference values in Java are values and are passed by value like any other value in Java.
This is easy to test, since modifying a parameter in Java does not affect the corresponding argument.
It means that like pointers, they are not references, but can be operated upon to access an object indirectly.
In C, *p is used to access the object that pointer p points at.
In Java, p.x is used to access member x of the object that p refers to (if p happens to refer to an object, that is).
"The reference values (often just references)"
The Java spec has defined use of the word "reference" to mean "reference value?"
Feel free to disagree with the Java spec. I needed to know if when we read something we can come to the same conclusion about what it says. And that if we discuss things on an agreed upon definition it does not change because a different definition exists for the same term and is better suited for the argument at hand.
The Java spec has defined "reference values" and then said that "reference value" is often abbreviated as "references".
This is what "The reference values (often just references)" means.
Which means that when you read "references" in Java, you need to mentally expand it back out to "reference values".
If you don't do this, you'll end up making errors like claiming that Java supports pass-by-reference.
That sounds more like a no to me. Should have chosen yes.
Since it appears that we can choose our preferred definition with no authority on the matter, I choose Wikipedia.
Yes.
Feel free to change my mind by updating the Wikipedia page. I'm sure it will go through unquestioned with your references.
If you believe that C has pass-by-reference semantics, there's really no point continuing the conversation.
Best of luck.
That isn't what you asked.
This is what I asked
This is what you answered
Passing by reference requires pass-by-reference semantics.
So, it is what I asked.
Do you believe that C have pass-by-reference semantics?
If you pass an address to a function then you have passed the int by reference.
C does not have pass-by-reference semantics and will not pass int by reference.
Java interacts with objects by reference. When you call a method you pass the object by reference.
Java does not have pass-by-reference semantics and will not pass an object reference by reference.
Passing an int * in C does not pass an int.
Right you're passing a reference to int.
No, you're passing the value of an int *.
You're spending so much effort being right rather than communicate.
You're trying to prove that this scotsman is not a true scotsman. And fail to recognize that he is in fact a scotsman.
Rather than directly addressing the definition of reference. You run me in circles. First by saying I needed to use the words of the spec, then by saying those words aren't the same in this other spec.
I pull in a third-party which you completely ignore, probably because it doesn't match your true scotsman. You try to show me differences, even though I clearly demonstrated an understanding of the different semantics.
You can only accept being right and have no interest in communicating.
Had you accepted the words used in the Java spec I could have answered No to the question about the behavior of C.
C did use the word reference, but it was not trying to define a language construct, instead it was using the word to help explain the semantics of a pointer, this matches the definition provided by Wikipedia.
Java on the other hand is defining a language construct. It has different semantics then C++'s use with the same name.
So we have reference as a concept, reference as a language construct in Java, and reference as a language construct in C++. Thus in order to communicate we have to agree to which of these we mean.
I thought that you would use the one defined in the language spec since that is what requested at the start. When I realized you were not sticking to that requirement, I was able to pull in more language into the mix and see how you would contort your logic to make it seem that all of these uses are consistent (they are not). But I was sadly disappointed when you wouldn't even touch Wikipedia definition.
Since we are talking about pass-by-reference, it is the semantics of pass-by-reference that are significant.
If your definition of 'reference' is 'something that can be used to find something', then there will be nothing that is not a reference.
Have a string? I can use that to reference something .: strings are references!
Have an integer? I can use that to reference something .: integers are references!
Have anything? I can use that to reference something .: anything is a reference.
Which is the path down which you are going by claiming that pointers are references, because they can reference things, and therefore passing a pointer to something is passing that something by reference.
It's meaningless -- which is why I have kept bringing it back to the semantics required by pass-by-reference.
And why I started with your ask, to use the Java spec which does not define them as you have here. My point was that we never established an agreed and consistent definition for reference.
I never once saw you pull out a definition from your sources. Even definition I had to dig for and you would deflect because it wasn't the one you wanted.
And I talked about the Java spec, which defines "references values" (abbreviated sometimes to references).
These are not references in the sense of pass-by-value, as I've demonstrated many times above.
You might claim that they're references in the sense that anything can be used to refer to something else.
But that won't get you references with the semantics required by pass-by-reference, which means that you can't claim that passing one is pass-by-reference.
Let's just imagine that they were called "oranges" -- would you be claiming that passing an "orange" gave you pass-by-reference?
If not, then it's clear that this is simply due to being confused by a name choice.
Let's try it.
"reference values (often just oranges)"
"All interactions with objects and array is by oranges, much like pointers in C."
Yep, I'd use it.
"Objects are pass by oranges and if C had them, it too would be pass by oranges."
Ok, and does pass-by-orange have pass-by-reference semantics, or does it have pass-by-value semantics? :)
Have we defined what we are discussing as passed and the definition of reference yet?
I've done so several times.
Here is the simplest requirement, again.
When passing by reference, modifying the parameter modifies the argument.
Under that definition, no passing by oranges does not have the same semantics as pass by reference.
This however changes the subject to the parameters of the functions. I have been talking about the object for which the parameter refers. Could we stick with talking about the concept I'm actually trying to get across rather than introducing a introducing a different one.
Since pass by oranges is not a term used in the Java spec, could you describe the pass by oranges semantics using spec terms?
No, that is written in the spec meaning they can use "reference" to mean reference value. Reference is just an alias to reference value. Like
"The values of a reference type are references to objects."
But now you are doing what you told me not to do. That is the specification of a different language not for Java.
"All interactions with objects and array is by reference, much like pointers in C."
I had not made reference to either of those things, yet you did take issue with my statement
If that statement means objects are pass by reference. Then I need to defend that Java has it. If it does not, then why do you take such great efforts to disagree with it?
It's trivial to show that pass by reference doesn't occur in Java, since changes to the parameter are independent of changes to the argument.
Once you understand that, it should be clear that the "reference value" is not the object that it refers to.
Which means that passing a "reference value" is not passing the object is refers to -- it just passes a means by which to interact with the object it refers to.
This is what I have been saying. The object is not passed. A reference is passed and that reference, points to an object.
This is impressively long. I feel like you have both made important connection, perhaps you should make a post together π certainly a lot to digest here.
The simplest use case is passing things by reference.
Say you have a string like, "hello my name is Bob", and you want to make it all capitals?
It's fine to send that string over to a function in its entirety, wait for it to be tinkered with and copy it back.
But say you have something bigger, like an image, potentially a gigabyte in size, and you want to send it over to a function that finds the brightest colour in it? You don't want to be copying all that information across every time, so you use a pointer to tell the function, "here's my image, use it directly".
Pointers also allow you to do other stuff like links in linked lists or have variables of indeterminate size or even to directly change something on the display (what they call "memory mapping") and a few other tricks.
Pointers also allow you to keep references to multiple variables of the same type, kind of like an array, except with the help if
malloc
,calloc
, andrealloc
you can point to as many variables of the same type as you want, provided the memory still has space to allocate.Pointers enable you to have things like Strings in your C code (in the form of
char*
) since Strings arenβt native to C.Let's check my loose understanding of char. char represents an integer type uint8 from 0 - 255 which is somehow synonymous with utf8 encoding. char* is somehow array like of chars by reference?
I think malloc does direct allocation of a value to memory? Not sure about the rest.
Thank you, This is fun!
Youβre right on the money with
char
s,malloc
doesnβt necessarily allocate a value, it allocates a segment of memory for that pointer based on how many bytes you tell it to allocate. This is whysizeof
is an extremely important function to use when working with pointers, because it tells you how large any variable or struct is in bytes. If you wanted to make a pointer that was large enough to hold X amount of any type, youβd want to allocateX * sizeof(type)
for that pointer, and you would want to advance it bysizeof(type)
to get to the next thing it points to.Pointers are what make me not like programming in C because itβs where a lot of very common problems can happen: segmentation faults happen a lot and the same code that might run fine on one OS might not behave the same on another.
I think it's important to note that passing a pointer by value is not pass by reference.
Passing the pointer by value grants the means to reference the thing pointed at on the other side, but it doesn't have pass-by-reference semantics.
e.g., this code can't change the value of p, so bar will always receive a null pointer value.
If p were passed by reference then the value of p could be changed by the call to foo.
That makes sense, an image would be like 4 channels of uint8 so yes that's a lot of data. What happens if I pass the string "hello world" into a function not as a pointer, does the function create a copy in memory.
Hard-coded strings are considered to be of type
const char*
when compiled down, so the same rules that you would apply to anywhere that achar*
is used. I canβt remember ifconst
prevents you from reallocating the memory, or changing the address of the pointer. If I remember correctly, hard-coded strings are allocated in the heap, whereas otherchar*
that are allocated at runtime are allocated on the stack.I donβt think it creates a copy because pointers by their very nature are just memory addresses, but you can test this by examining the address as shown in this example: codingame.com/playgrounds/14589/ho...
Actually, they're not const char *.
A string literal produces a char array, so the type of "hello" is char[6], which evaluates to a value of type char *.
It is undefined behavior to mutate an object produced from a string literal, so it would be nice if the type system did help you out with a const, but backward compatibility ... :)
Note that there is no heap or stack in C. C has allocated, static, auto, and register storage instead.
Objects produced by modifying string literals can be allocated however the compiler likes, providing they have sufficient storage duration that nothing will ever notice them not being there anymore.
Because modifying them has undefined behavior they're often allocated in a read only part of the program's storage, like functions.
They may also be consolidated -- so you cannot expect "a" and "a" to produce distinct objects (but you also cannot rely on them not doing so).
In most cases you don't. Pointers are usually a bit further down the ladder of abstraction. Languages like Java, Python, JS, do use pointers internally, but you as a user don't really need to worry about it. Knowing about pointers is helpful in the sense that you'll have a better grasp of how things work "under the hood", but you can make do without knowing them.
NOTE: Reference types are NOT pointers, though they are implemented USING pointers, they're a lot less flexible (in a good way) and it's a lot harder to shoot yourself in the foot with them
So you can say, to your great grandkids, as they're writing in AmazonMongoose4000
For low level programming (drivers development), you might want to have a value stored at specific address. Although you will probably use a combination of pointers, and special linker/compiler instructions.
In general though, it is hard to write c code without pointers. Just passing stuff around would be tough.
There are multiple reasons for using a pointer. I will give you some :
For example, pointers allow to βreturnβ arrays from functions (de name of an array is a pointer to the first element of the array). They also allow abstraction; you can pass a pointer to a function in drivers development to abstract hardware layer.
Ahhh I see, the quotation marks are important because we don't actually return the array, the body of the function defined the array, then placed it into memory? And so now we can access that spot in memory by it's address, I guess you could even get the size of the array and other such things.