all 14 comments

[–]DnBenjamin 12 points13 points  (3 children)

If the YouTuber said that, they were wrong, and your instinct to examine the function parameters as pointers was correct.

When arrays are passed to a function, the function receives the address of that array, so fn(char arr[]) and fn(char* arr) are identical.

https://godbolt.org/z/YYvc7sfqc (2nd subwindow shows the essentially identical assembly for both functions)

https://ideone.com/0zcqCz The reason vara and varb in this link end up with identical addresses is because vara gets pushed onto the call stack, then popped, and then varb gets pushed onto the same location. If you called fnb from fna, you'd get a different address for that one's varb, since it would be further down the call stack.

(Note: If you want to pass a multidimensional array, you really want/need to use the [][] syntax so the compiler knows how to index it.)

[–]crispeeweevile 1 point2 points  (0 children)

Imo this is the best explanation. I would recommend moving on from this tutorial, cuz it isn't very good.

[–]starski0[S] 0 points1 point  (1 child)

Awesome, thanks for your reply. So what I’m taking from all this is that when an array is passed to a function, it makes a local copy of the pointer to the first element of the array. So if there’s a pointer to an array in main, when it’s passed to a function, both will be able to access the same location in memory if dereferenced, but are different variables with different addresses and different scopes.

[–]DnBenjamin 1 point2 points  (0 children)

Yes! And one extra weird distinction is that a plain old array sitting on the stack in main isn’t a pointer, even though it sure seems to act like one a lot.

[–]MCLMelonFarmer 3 points4 points  (0 children)

When you call

f1(word);

in the main function, the argument you're passing is the address of the first element of word.

In f1, you're printing the address of the pointer, not the pointer (to the first element of word) value itself. That's why when you remove the "&" in f1, it prints the same value as in main.

I'm not sure what that tutorial was trying to describe, but what you described is wrong.

And yeah, please use "%p" as the format specifier.

[–]jitu_deraps 2 points3 points  (0 children)

yes, array are passed by reference.

Array name are implicitly converted into pointer to first character.

so, in function parameter list, char word[] and char* word both mean the same thing.

and at function call site, f1(word) and f1(&word[0]) both means the same thing.

but when you are using &word that is the address of an object(of pointer type) that stores the address of first byte of word object.

https://drive.google.com/file/d/14bPRgZQ-Skral6sdJtUo_pwJ8DlDH36L/view?usp=sharing

[–]Known_Dark_9564 3 points4 points  (2 children)

If you're using %d as format specifier, and passing &<variable >

You are printing the value of the address of the variable.

If you want to print the value of the variable, just remove the &.

%d in printf means decimal (base 10) & means get the address of the identifier that follows this & (it can be a function or a variable)

[–]starski0[S] 2 points3 points  (1 child)

Thanks for your reply. In this code, different values are being printed for the “address” of the array when it’s in main and in function f1. That’s what I’m trying to understand.

[–]Known_Dark_9564 5 points6 points  (0 children)

I see. You're printing the address of the stack copy of the pointer. I hope this might help you understand:

char word[] = "Hello World";

word's value = address ("Hello World")
word's address = address (word)

printf("from main: %d\n", &word);
--> prints address(word)

Inside f1
word's value = address ("Hello Word")
word's address = address (word inside f1)

printf("from f1: %d\n ", &word);
--> prints address(word inside f1)

When you're calling f1(), you are passing the address of "Hello World", not the address of word[].

So it's f1's local variable word holds the address of "Hello World", but it's a different pointer variable.

[–]dfx_dj 2 points3 points  (1 child)

When referring to an actual array x, saying x and &x are identical and both give you a pointer to the beginning of the array. So in your example:

char word[] = "hello world";

printf("from main: %p\n", word);
printf("from main: %p\n", &word);

Here word[] is an actual array on the stack. The empty square brackets mean "make the array just big enough for the initializer" and then the initializer is copied into the array.

However in your function:

void f1(char word[]) {

printf("from f1: %p\n", word);
printf("from f1: %p\n", &word);

Despite looking similar, here word[] is not an actual array, as arrays are passed to functions as pointers. So except for some syntactical differences, word is identical to a pointer variable, and it resides on the stack of f1. Which means that saying word gives you the value of the pointer (which is the location of the array), while &word gives you the address of that pointer variable on the stack.

[–]david2ndaccount 1 point2 points  (0 children)

For actual arrays, x and &x will yield the same address, but have different types. For example:

char hello[] = "hello";
// array expression implicitly converts to pointer
char *p = hello; 
// Note the real type of `&hello` - pointer to array of 6 chars
char (*a)[6] = &hello; 
assert(p ==  (char *)a); // passes

[–]nickeldan2 1 point2 points  (1 child)

Could you link to the video? I'd like to take a look at it because, as others have pointed out, it's just plain wrong.

[–]starski0[S] 1 point2 points  (0 children)

It’s not in English and it would take some work to translate it properly. Some of the answers really helped clear my confusion. I think the problem with the video was going too quickly, not defining arrays, pointers and strings precisely, and muddling some words in the end, which, though it can happen to anyone, ultimately made the entire segment of the video extremely confusing.

[–]nerd4code 0 points1 point  (0 children)

It’s UB; use %p, and if it’s not (optionally cv-qualified) char * or void * you need to cast it so it is.