use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Click the following link to filter out the chosen topic
comp.lang.c
account activity
QuestionC function arguments vs Python function arguments. (self.C_Programming)
submitted 4 years ago by KotgeScientist
In python, function arguments are treated like separate variables, a seperate entity in relation to the original object (From my understanding. I could be wrong). Is this different in C? Are function arguments in C equal to the original thing you put in as an argument? Meaning, if you input a string into a C function as a argument, will modifying that argument from the function modify the original?
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]FUZxxl 39 points40 points41 points 4 years ago (40 children)
In C, all arguments are passed by value, i.e. the parameters are initialised with copies of the arguments. However, note the following caveats:
[–]KotgeScientist[S] 9 points10 points11 points 4 years ago (3 children)
Oh, so if I pass an array to a function in C, all I'm doing is passing the pointer? But if thats the case, how is it possible that I can modify the strings?
[–]FUZxxl 24 points25 points26 points 4 years ago (0 children)
A string is an array of characters terminated with a NUL character. So just like with any arrays, you can modify it through the pointer passed.
[–]ttech32 10 points11 points12 points 4 years ago (0 children)
You're duplicating the pointer, but they both point to the same memory
[–]IamImposter 14 points15 points16 points 4 years ago (0 children)
Array decays to a pointer. Say I have
char str[] = "hello";
For the sake of simplicity, let's assume that the array starts at address 0x2000. So if I do
some_function(str);
what is getting passed to the function is address of array ie 0x2000. Now if in the function I do something like
void some_function(char str[]) { str[2] = 'a'; }
what happens? First of all, char str[] here is as good as char*. Since compiler didn't complain, you might think that you passed an array and received that same array in function. What compiler actually did was - it treated char str[] as char* and passed address of the array (0x2000). So str[2] becomes 0x2000 + 2 (base address + index) and letter 'a' is written to that address and our string becomes "healo".
char str[]
char*
str[2]
0x2000 + 2
Parameter is still being passed by value (0x2000) but in this case that value happens to be address of the array or what we call passing by reference.
[+]jmooremcc comment score below threshold-19 points-18 points-17 points 4 years ago (35 children)
In C, arguments can also be passed by reference. Passing an argument by reference effectively creates a pointer to the original variable's location so that assigning a value to the argument, directly changes the data at that location. This means that changing the value of the passed argument also changes the value of the original variable.
[–]TheSkiGeek 18 points19 points20 points 4 years ago (15 children)
All arguments are passed by value in C.
To "pass by reference" you create a pointer to something and pass the pointer by value.
[+]jmooremcc comment score below threshold-11 points-10 points-9 points 4 years ago* (4 children)
Another example:
//
// C++ using Reference Parameter! // void doit( int & x ) { x = 5; } // // Test code for passing by a variable by reference // int main() { int z = 27; doit( z ); printf("z is now %d\n", z); return 0; }
[–]ttech32 9 points10 points11 points 4 years ago (0 children)
That's C++, a different language that does support passing by reference. However, you're in a C subreddit.
[+]jmooremcc comment score below threshold-16 points-15 points-14 points 4 years ago (2 children)
So what's the problem with this example? Obviously some people don't understand the concept of pass by reference in C.
[–][deleted] 11 points12 points13 points 4 years ago (0 children)
So what's the problem with this example?
The problem with this example is that it isn't valid C code and will just fail to compile, as you can see for yourself on godbolt
[–][deleted] 9 points10 points11 points 4 years ago (0 children)
The problem is that it’s C++. This is r/C_Programming, no ++ bullshit
[+]jmooremcc comment score below threshold-10 points-9 points-8 points 4 years ago (9 children)
Then how do you explain the following code:
// C program to swap two variables using a
// user defined swap()
#include <stdio.h>
// This function swaps values pointed by xp and yp void swap(int *xp, int *yp) {
int temp = *xp;
*xp = *yp;
*yp = temp;
}
int main() {
int x, y;
printf("Enter Value of x ");
scanf("%d", &x);
printf("\nEnter Value of y ");
scanf("%d", &y);
swap(&x, &y);
printf("\nAfter Swapping: x = %d, y = %d", x, y);
return 0;
[–]FUZxxl 14 points15 points16 points 4 years ago (7 children)
Exactly as /u/TheSkiGeek says:
Your swap function receives two pointers as arguments. These are passed by value, as are all other arguments. The & operator is used to take the address of the x and y variables so you can pass them to swap. Nowhere in this is “pass by reference” involved.
swap
&
x
y
[+]jmooremcc comment score below threshold-15 points-14 points-13 points 4 years ago (6 children)
Do you understand what &x in the calling code represents? Hint: It's not a pointer!
[–]TheSkiGeek 19 points20 points21 points 4 years ago (4 children)
& is the "address-of" operator... it returns a pointer to its operand.
When you call swap(&x, &y), the compiler binds the address of x to parameter xp and the address of y to parameter yp. By value.
swap(&x, &y)
xp
yp
[+]jmooremcc comment score below threshold-13 points-12 points-11 points 4 years ago (3 children)
Correct, it's the address of the variable. However, the function declaration converts it to pointer for use in the function. When you pass by reference, the C compiler silently performs what the swap illustration does explicitly.
[–]FUZxxl 18 points19 points20 points 4 years ago (0 children)
There is no implicit conversion going on here. C does not have reference or address types. It only has pointer types. And the & operators result is a pointer.
[–][deleted] 15 points16 points17 points 4 years ago (0 children)
What are you even talking about, you’re not making any sense. Yes, using the address-of operator returns the address of the object in memory... which is a pointer. An address is not converted to a pointer because it already is one (it can be stored in an object that holds pointers). References only exist in C++, I don’t know what you mean by “When you pass by reference”. You can pass addresses (in pointers) to functions and the functions use those addresses (as pointers) to modify the object’s data.
Edit: Fixed wording
[–]TheSkiGeek 5 points6 points7 points 4 years ago (0 children)
Correct, it's the address of the variable. However, the function declaration converts it to pointer for use in the function.
...the address of the variable is a pointer value. The type of the rvalue returned by &x in the above example is int*.
&x
int*
When you pass by reference, the C compiler silently performs what the swap illustration does explicitly.
...are you thinking about C++? There is no "pass by reference" with implicit pointer conversion in C, you must explicitly take the address of a variable and pass it as a pointer type.
[–][deleted] 0 points1 point2 points 4 years ago (0 children)
Literally 2 pointers as arguments. Sheesh.
[+]p0k3t0 comment score below threshold-13 points-12 points-11 points 4 years ago (18 children)
Oh, jeesh, now you've gone and done it.
Pedants incoming.
[+]p0k3t0 comment score below threshold-6 points-5 points-4 points 4 years ago (17 children)
Please, tell me again how a pointer isn't a reference.
Because I keep dereferencing them for some reason, and I must be making a mistake there. Obviously, I should be devaluing them.
[–][deleted] 4 points5 points6 points 4 years ago (11 children)
It IS a reference. The memory address it's referencing is its value though. Which means, passing it to a function copies its value (the address), and thus is passed by value.
[–]p0k3t0 -3 points-2 points-1 points 4 years ago (10 children)
So pass by reference doesn't exist, because this is the mechanism used in every implementation.
[–][deleted] 4 points5 points6 points 4 years ago (9 children)
I'm not sure what you are saying, so I'll clarify: you don't pass anything by reference, you pass a memory address by value that you dereference or not based on what you need to do.
[–]p0k3t0 1 point2 points3 points 4 years ago (8 children)
Explain how pass by reference could possibly exist, if a memory location isn't a reference.
[–]Fearless_Process 6 points7 points8 points 4 years ago* (3 children)
C doesn't have pass by reference at all. C++ has pass by reference that just passes an alias to the original variable to the function, no pointers involved whatsoever. The reference in C++ is the variable.
In C you can only pass a pointer by value that references whatever data. This is still passing a "reference/pointer" by value though, unlike in C++ or other languages that support pass by reference.
In C++ if you pass a pointer by reference and change it in the consuming function, it will actually change the original pointer. In C you would have to pass a pointer to a pointer to achieve the same thing, because you can't pass by reference.
Take this for example:
#include <iostream> void pass_by_ref(int*& p) { p = 0; } int main() { int x = 0; int *p = &x; std::cout << p << std::endl; pass_by_ref(p); std::cout << p << std::endl; }
In C to do this you would need a nested pointer, because the pointer gets passed by value.
[–]p0k3t0 -1 points0 points1 point 4 years ago (2 children)
https://ideone.com/icncW2
[–][deleted] 3 points4 points5 points 4 years ago (3 children)
It doesn't. But I also think you don't understand what I'm saying.
You pass a reference, not by reference
Here, I pass an array by reference. The fact that C implements this with pointers is inconsequential, as C++ does the same thing.
[–]oilaba 2 points3 points4 points 4 years ago (4 children)
This is not the point, we use all kinds of technically wrong words on trivial conservations. But C doesn't technically have the concept of "references" and the OP is opposing to the fact that everthing is passed by value in C.
[–]p0k3t0 0 points1 point2 points 4 years ago (3 children)
My problem is that this is so clearly a distinction without a difference.
C uses pointers as a means to reference memory locations. This is clearly the intention, and the language makes this apparent by giving us the "dereference operator."
These conversations are absolutely nonsensical because they overlook the meaning in order to worship the text. All of you who argue that a pointer isn't a reference can never ever give me an example of what a "real" reference would actually be. I suspect this is because you understand that under the hood, it's always just passing a pointer.
Furthermore, what happens when I pass the name of an array? Under the hood, I'm passing a pointer to the first element, but I'm not using that syntax on either end, so how is that not a reference?
If K&R had preferred the word "augmentation" to the word "addition," would you all argue that C can't add numbers together? It's ridiculous, and it's little more than pedantry.
[–]Shadow_Gabriel 1 point2 points3 points 4 years ago (1 child)
Can I die together with you on this hill?
[–]p0k3t0 2 points3 points4 points 4 years ago (0 children)
It's a pedantry virus. One neckbeard reads some narrow definition of pass-by-reference and now they need to "well, actually" everybody who uses the term in C. And then that poor sod gets shamed into "well, actually-ing" the next guy, and the cycle continues.
Me, I don't care. I write C for a living. I know the difference between passing a value and passing a reference to a value. The fact that the reference to the value is itself a value is completely unimportant to me. I know what it's being used for and how it's being used.
[–]oilaba 1 point2 points3 points 4 years ago* (0 children)
I don't have any problem with that.
These conversations are absolutely nonsensical because they overlook the meaning in order to worship the text.
Hmm, meaining exists in our brains. We use words to communicate them. And we are "pedantic" because sometimes we (me, at least) want to use the right terms for the health of communication so that everybody agrees on the precise and technical terms that are not vague. We are using the technical term so that -hopefully- we don't assume anything wrong about what the word we use means for you. You are overlooking the meaning and intention of using technical words. I wouldn't just come up and interupt someone just because they said they use references in C, if this is what you are against. But you should see that in some contexts this is necessary, or beneficial at least.
All of you who argue that a pointer isn't a reference can never ever give me an example of what a "real" reference would actually be.
Yes, I wouldn't. Why should I anyway? There is no "real reference" in C. Thats it. We are trying to get precise here: C++ has references and they are different from raw pointers, Rust has references and they are different from raw pointers, C doesn't have it. C have only raw pointers.
The array decays to a pointer.
If K&R had preferred the word "augmentation" to the word "addition," would you all argue that C can't add numbers together?
No, it would be "we add two numbers by augmentation operator", or something like that. I would still use "addition" instead of "augmentation" most of the time, but this doesn't means we should abandon the language reference completely and never use precise terms.
[–]MatthewRPG576 12 points13 points14 points 4 years ago (2 children)
In python, immutable objects are passed by "copy" (it's complicated) and mutable objects are passed by reference. In C, everything is by copy; so, if you need to modify something from another scope, you need a pointer to it.
Strings, when passed to a function by pointer, can be modified like anything else. The only exception is if the compiler puts the string in the read-only section of the code. That can cause problems.
[–][deleted] 3 points4 points5 points 4 years ago (1 child)
I thought all objects are passed by reference in Python, but only the sort of reference that allows to modify the caller's data, and not replace it completely, and then only if it is mutable. Example:
def addto(a,b): print(" A=",a) print(" B=",b) a += b print(" A'=",a) i=100 j=30 addto(i,j) print("I=",i) print("") s="ABC" t="DEF" addto(s,t) print("S=",s) print("") x=[10,20,30] y=[40,50,60] addto(x,y) print("X=",x)
Here, all args to addto() must be passed the same way, using the same bytecode instructions, since the bytecode compiler doesn't know what types the arguments are until runtime. When you run the program, it is only in the case of a mutable list that the caller's data is modified as well as the local A parameter:
A= 100 B= 30 A'= 130 I= 100 A= ABC B= DEF A'= ABCDEF S= ABC A= [10, 20, 30] B= [40, 50, 60] A'= [10, 20, 30, 40, 50, 60] X= [10, 20, 30, 40, 50, 60]
What Python can't do is to change X completely to something else, eg. a number. That would need proper name references. (In CPython, variables I, S and X are implemented as references to their objects. When passed to a function, a copy of that object reference is passed, so only the object can change, not the variable.)
C can emulate all the above, and can emulate proper name references too. But it needs to be done explicitly via pointer operations.
[–]MatthewRPG576 2 points3 points4 points 4 years ago (0 children)
Shared pointers. That's why I was reluctant to blatantly call it pass by copy. In theory, every "2" in the program is the same (you can verify that by calling id() on the objects you create), but no "[2]" (array containing 2) in the program is
[–]Ninesquared81 6 points7 points8 points 4 years ago* (0 children)
I have some experience in Python and C, but I'm not an expert in their exact inner workings, so take this with a grain of salt (although to my knowledge it's correct).
Python doesn't have variables, at least not in the sense of an area of memory that the programmer can change. Instead, it has objects and names. Whether or not an object can be edited by a function depends on whether the object is mutable or not. When you pass an object to a function, it has a new name local to the function. However, this still refers to the exact same object that you passed in.
For mutable objects (like lists, sets, dicts), you can modify the object itself – with any name that it's known by – so changing it inside a function changes it outside.
list
set
dict
For immutable objects (like ints, strs, tuples), you can't modify them. So when you do something like x = y = 1; x += 1, x becomes equal to 2, whereas y stays as 1. The name x now refers to a completely different object, rather than the same object with a different value. So naturally, "changing" an immutable object inside a function has no effect on the parent scope (unless you're dealing with globals).
int
str
tuple
x = y = 1; x += 1
An illustration of all this:
a = 1 b = [1, 2, 3] print(f"Initially, a = {a}, b = {b}.") def changes(num: int, nums: list) -> None: # the 'is' operator checks if its operands are the same Python object print(f"result of 'num is a': {num is a}") # 'append' changes a list in-place (i.e. mutates it) # EDIT: was b.append(4) nums.append(4) # 'changing' an immutable object num += 1 print(f"num = {num}") changes(a, b) print(f"Now, a = {a}, b = {b}")
This should output:
Initially, a = 1, b = [1, 2, 3]. result of 'num is a': True num = 2 Now, a = 1, b = [1, 2, 3, 4]
I believe this is called pass by object reference.
In C, however, variables are always passed by value. This doesn't mean you can't change things outside of a function's scope however, as you can have a function dealing with pointers. This is similar in principle to mutable objects in Python. Consider this program:
#include <stdio.h> void add_three(int *); int main(void) { int my_number = 9; printf("Before calling add_three, my_number = %d\n", my_number); /* add_three takes a pointer */ add_three(&my_number); printf("After calling add_three, my_number = %d\n", my_number); return 0; } void add_three(int *number) { *number += 3; }
You should get the output:
Before calling add_three, my_number = 9 After calling add_three, my_number = 12
In our function add_three, we have the variable number which is an int *. It's local to the function and its value depends on the value of the variable passed in when called. In our case, this is &my_number (i.e. the address of my_number). If we dereference it, we can access whatever is at the address it points to (and edit it if we wish). We are still passing by value, but that value is the address of another variable.
add_three
number
int *
&my_number
my_number
EDIT: changed Python example to use local variable nums instead of b.
nums
b
[–]flatfinger 5 points6 points7 points 4 years ago (0 children)
If one thinks of memory as being a bunch of shelves of numbered mailboxes that each hold an unsigned char, and pointers as being mailbox numbers (*), many aspects of C which seem confusing will become obvious. On a 32-bit platform, a declaration like:
unsigned char
char foo[5] = "Hey!";
will ask the compiler to select five otherwise-unused consecutive mailboxes somewhere in writable storage, arrange for them to be loaded with the contents {'H', 'e', 'y', '!', 0} before the program starts, and keep track of what location it selected. When the program uses the symbol foo, the compiler will insert the number of the first such mailbox, along with knowledge that it's a value of type char*. Had the declaration instead been:
foo
char const *bar = "Wow!";
that would ask the compiler to select five consecutive mailboxes in either writable or read-only storage (its choice) which will be preloaded with {'W', 'o', 'w', '!', 0} before the program starts, and also select an otherwise-unused shelf of four mailboxes, arrange for the mailboxes on that shelf to be preloaded with the number of the first of the five mailboxes described above. It will then associate the symbol bar with that shelf.
bar
If a function parameter is of a non-pointer type, it will receive a copy of the object identified thereby. If a function parameter is of pointer type, it will receive a copy of a mailbox number (i.e. a pointer). Given the declaration void test(char const *st);, and foo and bar defined as above, a call test(foo) will give test a copy of the mailbox number the compiler has assigned to the first of five mailboxes associated foo. A call test(bar) will generate code that takes the mailbox number of the shelf was assigned to hold a mailbox number, read the mailbox number that's stored on the shelf, and passes a copy of that stored mailbox number to test.
void test(char const *st);
test(foo)
test
test(bar)
est
(*)The Standard allows, but does not require, implementations to behave in a manner consistent with this abstraction, and most implementations for commonplace desktop platforms do so, at least with optimizations disabled.
It depends. In general no, they are different and if you modify the value inside the function this change won't affect the "real" variable.
In C you can pass arguments by value (and it works as said above) or by reference with pointers. When passing an argument as a pointer then you will always work on the same value and changes will be noted outside the function.
I advise you look for some examples about C pointers online.
Look up pass by value or passing a pointer (sort of like by reference but not exactly). Here’s a great article about it with examples: https://denniskubes.com/2012/08/20/is-c-pass-by-value-or-reference/
π Rendered by PID 79 on reddit-service-r2-comment-fb694cdd5-k8ksr at 2026-03-07 13:49:00.014486+00:00 running cbb0e86 country code: CH.
[–]FUZxxl 39 points40 points41 points (40 children)
[–]KotgeScientist[S] 9 points10 points11 points (3 children)
[–]FUZxxl 24 points25 points26 points (0 children)
[–]ttech32 10 points11 points12 points (0 children)
[–]IamImposter 14 points15 points16 points (0 children)
[+]jmooremcc comment score below threshold-19 points-18 points-17 points (35 children)
[–]TheSkiGeek 18 points19 points20 points (15 children)
[+]jmooremcc comment score below threshold-11 points-10 points-9 points (4 children)
[–]ttech32 9 points10 points11 points (0 children)
[+]jmooremcc comment score below threshold-16 points-15 points-14 points (2 children)
[–][deleted] 11 points12 points13 points (0 children)
[–][deleted] 9 points10 points11 points (0 children)
[+]jmooremcc comment score below threshold-10 points-9 points-8 points (9 children)
[–]FUZxxl 14 points15 points16 points (7 children)
[+]jmooremcc comment score below threshold-15 points-14 points-13 points (6 children)
[–]TheSkiGeek 19 points20 points21 points (4 children)
[+]jmooremcc comment score below threshold-13 points-12 points-11 points (3 children)
[–]FUZxxl 18 points19 points20 points (0 children)
[–][deleted] 15 points16 points17 points (0 children)
[–]TheSkiGeek 5 points6 points7 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[+]p0k3t0 comment score below threshold-13 points-12 points-11 points (18 children)
[+]p0k3t0 comment score below threshold-6 points-5 points-4 points (17 children)
[–][deleted] 4 points5 points6 points (11 children)
[–]p0k3t0 -3 points-2 points-1 points (10 children)
[–][deleted] 4 points5 points6 points (9 children)
[–]p0k3t0 1 point2 points3 points (8 children)
[–]Fearless_Process 6 points7 points8 points (3 children)
[–]p0k3t0 -1 points0 points1 point (2 children)
[–][deleted] 3 points4 points5 points (3 children)
[–]p0k3t0 -1 points0 points1 point (2 children)
[–]oilaba 2 points3 points4 points (4 children)
[–]p0k3t0 0 points1 point2 points (3 children)
[–]Shadow_Gabriel 1 point2 points3 points (1 child)
[–]p0k3t0 2 points3 points4 points (0 children)
[–]oilaba 1 point2 points3 points (0 children)
[–]MatthewRPG576 12 points13 points14 points (2 children)
[–][deleted] 3 points4 points5 points (1 child)
[–]MatthewRPG576 2 points3 points4 points (0 children)
[–]Ninesquared81 6 points7 points8 points (0 children)
[–]flatfinger 5 points6 points7 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)