This question already has answers here:
Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?
(5 answers)
Closed 7 years ago.
#include <stdio.h>
int add(int a, int b)
{
int c =a+b;
return c;
}
int main()
{
int a=20,b=45;
int (*p)(int , int);
p=&add;
printf("%d\n%d\n%d\n\n",*add,&add,add);
printf("%d\n%d\n%d\n\n",*add+1,&add+1,add+1);
return 0;
}
Outupt is
4199392
4199392
4199392
4199393
4199393
4199393
So why the *add, &add, add are same?
I also doubt that 'add' act like an array, correct me if I am wrong, because, address of array and array itself are same.
In C the only things you can do with a function is to call it or taking its address. So if you aren't calling it, you're pretty much taking its address.
"C11 §6.5.6 Additive operators" /6 discusses adding to a pointer
When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, ... . If the result points one past the last element of the array object, ...
Nowhere does the C spec define adding an integer type to a function pointer. Thus undefined behavior.
Related
This question already has answers here:
Array changed in a void function, is still changed outside! why? (scope)
(4 answers)
Passing an array as a parameter in C
(3 answers)
Passing Arrays to Function in C++
(5 answers)
Passing an array as an argument to a function in C
(11 answers)
Closed 11 months ago.
I don't get it why you can alter the values inside the array, without using a reference or a pointer (&, *), I'm a freshmen student, and I don't know the reason behind, I hope someone can provide a logical answer, please refer to the code below, Thank You in Advance.
#include <iostream>
using namespace std;
void a(int x[]){
for(int i = 0; i < 5; i++){
x[i] += 2;
}
}
int main(){
int x[5] = {1,2,3,4,5};
a(x);
for(auto b : x){
cout << b << " ";
}
return 0;
}
A function parameter is never an array in C++. When you declare a function parameter as an array, it is automatically adjusted to be a pointer to element of such array. These declarations are effectively identical:
void a(int x[]); // looks like an array of int of unknown bound
void a(int* x); // declaration above is adjusted to this
void a(int x[1234]); // the size is ignored completely
An array implicitly converts to a pointer to the first element of the array (such conversion is called decay). Hence, you can call the function that doesn't accept an array parameter by passing an array argument:
int* ptr1 = x; // implicit conversion
int* ptr2 = &x[0]; // same conversion explicitly
a(x); // same conversion happens here
These two rules (function parameter adjustment and array to pointer decay) make it so that what syntactically looks like passing arrays by value, is actually done using indirection. Within the function, you modify the elements by indirecting through the pointer parameter that points to the array that exists outside of the function.
Important note: The adjustment of array to pointer in function parameter does not apply in other contexts. Arrays and pointers are distinct types with different properties.
Another note: The adjustment does not apply to parts of compound types. For example, a function parameter of type "pointer to array" will not be adjusted to be "pointer to pointer" and "reference to array" will not be adjusted to be "reference to pointer".
The parameter having the array type in this function declaration
void a(int x[]){
is adjusted by the compiler to pointer type to array elements type. That is the above declaration is equivalent to
void a(int *x){
In this call of the function
a(x);
the array designator is implicitly converted to pointer to its first element. That is the call is equivalent to
a( &x[0]);
So within the function you have a pointer to the first element of the array declared in main.
Using the pointer arithmetic you can access elements of the array. That is the elements of the array are passed to the function by reference in the C meaning indirectly through a pointer to them.
Within the function the variable x has the type int *. And this expression statement
x[i] += 2;
is equivalent to
*( x + i ) += 2;
Beacuse
void a(int x[]){
is the same as
void a(int *x){
and so you are using a pointer
Why?
Because an array like
int x[10];
'decays' to a pointer when passed to a function (and in other places). This can be very confusing but at the same time is very flexible
It mens that I can have a function like strlen that can accpet a 'real' array, or a pointer. These 'strings'
char *s1 = malloc(10);
strcpy(s1, "hello");
char s2[] = "hello";
char *s3 = "hello";
store their data in different ways but all can be handled by
size_t strlen(const char *s);
note that this is exactly the same as
size_t strlen(const char s[]);
they are 2 different ways of writing the same thing. Personal preference is for the second type if its really is an 'array' vs a pointer to maybe an array.
One issue with this 'decay' is that inside strlen (or any pointer/array accepting function) it is impossible to 'know' the length just from the parameter. The compiler knows that the size of s2 is 6 but this information is not carried forward to the function.
Regularly SO sees this
void my_func(int *arr){
int len = sizeof(arr)/sizeof(arr[0]);
....
}
int a[10];
my_func(a);
This will give len = 1 or 2 (depending on 32 or 64 bit machine), never 10
The flexibility costs a litle power
This question already has answers here:
Order of incrementing and dereferencing pointer in C++
(3 answers)
Closed 1 year ago.
Why is it that when I use *a++ it doesn't affect my answer and gives me a warning. However it works fine with *a=*a+1 in the below code?
#include <bits/stdc++.h>
using namespace std;
void incrementptr(int* a)
{
//*a++;
*a=*a+1;
}
int main()
{
int a=10;
cout<<a<<endl;
// increment(a);
// cout<<a<<endl;
incrementptr(&a);
cout<<a<<endl;
return 0;
}
operator precedence: postfix ++ has higher precedence than *, hence *a++ is parsed as *(a++). It increments the pointer and dereferences a (the value before the increment) and the result of the expression is unused.
I suppose this is just to practice pointers, but there shouldn't be any pointer in your code. Only use pointers as argument, when a nullptr is a valid input to the function. Otherwise pass a reference (and use preincrement when you don't need the value before the increment, it won't make a difference for an int, but in general post can be more expensive than pre):
void increment(int& a) { ++a; }
The ++ operator has preference over the * operator so when you are doing *a++ it first increments the pointer and then reaches its value. If you want to increment the value of *a you can do it with (*a)++.
Here you have the preference table: https://en.cppreference.com/w/cpp/language/operator_precedence
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I was studying for my exam then ı saw this on the net.My question is that are not the arrays are basically constant pointers in c (so that there were an error ) ? At first I wanted to get an error about this "b+=2" but there was none.
int func ( int b[])
{
b +=2;
printf("%d",*b);
}
int main()
{
int arr[]={1,2,3,4};
func(arr);
return 0;
}
( output of this program is 3 btw)
are not the arrays are basically constant pointers in c
No, they are not. Arrays are contiguous sequences of objects. Pointers are objects that refer to another object by storing the memory address.
Why am I able to change the array
b +=2;
b is not an array. b is a pointer. Initially, you pass a pointer to the first element of the array arr. Adding 1 to a pointer changes it to point to a successive element of the array. Adding 2 changes it to point to second successive element. Starting from the first element, the second successive element is the one at the index 2, which in this case has the value 3. This pointer arithmetic is why pointers can be used to iterate array elements.
But it's declared using syntax that's normally associated with arrays
Function arguments cannot be arrays. You can declare the argument to be an array, but that declaration is adjusted to be a pointer to an element of the array. These two function declarations are semantically identical:
int func ( int b[]); // the adjusted type is int*
int func ( int *b );
Both of them declare a function whose argument is a pointer to int. This adjustment does not imply that arrays are pointers. This adjustment is complementary to the rule that the array implicitly converts into pointer to first element - this conversion is called decaying.
Note that argument declaration is the only case where this adjustment occurs. For example in variable declaration:
int arr[]={1,2,3,4}; // the type is int[4]; not int*
// the length is deduced from the initialiser
int *ptr; // different type
Also note that the adjustment occurs only at the "top" level of compound types. These declarations are different:
int funcA ( int (*b)[4]); // pointer to array
int funcB ( int **b ); // pointer to pointer
P.S. You've declared the function to return int, but have failed to provide a return statement. Doing so in C++ results in undefined behaviour of the program.
Arrays decay to pointers to their first element when passed to functions. Hence the function is equivalent to
int func ( int* b)
{
b +=2;
printf("%d",*b);
}
The pointer is advanced by 2 and then the element at that position is printed. For the constness consider that parameters are passed by value. Ie b is a copy. You cannot do
int arr[] = {1,2,3,4};
arr+=2;
But you can do
int arr[] = {1,2,3,4};
int* p = arr;
p += 2; // p now points to the third element
For the sake of completeness, main could be written as
int main()
{
int arr[]={1,2,3,4};
func(&arr[0]);
return 0;
}
Actually it is uncommon to write &arr[0] when passing arrays to functions, but this is just to illustrate what happens.
When declaring a parameter, int b[] means int *b. It's not an array. In fact, sizeof b will even return sizeof int *.
From the C spec,
A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to type’’, where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.
This leaves you with code passing an array to a function requiring a pointer, and that's perfectly fine. In such circumstances, the array will degrade into a pointer to its first element. It's as if
func(arr)
was
func(&(arr[0]))
Hi Buddy you are very right at your position that arrays are constant pointers but while passing the address to the function the modification is seen only in the pointer variable b , not arr . This is because b is local to the function.
If the print statement would have been in the main() function as:
printf("%d",arr[0]);
or
printf("%d",*arr);
output would have been 1 . Just because the increment has affected the local value but not the real one.
Hope it helps!!
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 7 years ago.
Below is a C program:
#include<stdio.h>
void func(int a[])
{
printf("%d\n",sizeof(a));
}
int main()
{
int arr[10];
printf("%d\n",sizeof(arr));
func(arr);
return 0;
}
Now the problem is that the sizeof() operator returns 40 when I use sizeof(arr) but 8 when I use sizeof(a).
What is the reason for this behavior?
Simple, yet confusing: A function parameter such as int a[] or int a[42] gets adjusted to int* a. func(int a[]) is adjusted to
void func(int* a)
Here, a really is no more than a pointer. So sizeof(a) is sizeof(int*).
On top of that, arrays can decay to pointers in many situations, such as when you pass arr to func. That allows this to happen
func(arr);
even if func's parameter is a pointer.
You are comparing size of a "pointer" to the actual size of an array.
This question already has answers here:
How do I use arrays in C++?
(5 answers)
Why can't I assign an array variable directly to another array variable with the '=' operator?
(5 answers)
Closed 8 years ago.
Hello I am beginner in c++ , can someone explain to me this
char a[]="Hello";
char b[]=a; // is not legal
whereas,
char a[]="Hello";
char* b=a; // is legal
If a array cannot be copied or assigned to another array , why is it so that it is possible to be passed as a parameter , where a copy of the value passed is always made in the method
void copy(char[] a){....}
char[] a="Hello";
copy(a);
It isn't copying the array; it's turning it to a pointer. If you modify it, you'll see for yourself:
void f(int x[]) { x[0]=7; }
...
int tst[] = {1,2,3};
f(tst); // tst[0] now equals 7
If you need to copy an array, use std::copy:
int a1[] = {1,2,3};
int a2[3];
std::copy(std::begin(a1), std::end(a1), std::begin(a2));
If you find yourself doing that, you might want to use an std::array.
The array is silently (implicitly) converted to a pointer in the function declaration, and the pointer is copied. Of course the copied pointer points to the same location as the original, so you can modify the data in the original array via the copied pointer in your function.