If you write a C++ function like
void readEmStar( int *arrayOfInt )
{
}
vs a C++ function like:
void readEmSquare( int arrayOfInt[] )
{
}
What is the difference between using [square brackets] vs *asterisk, and does anyone have a style guide as to which is preferrable, assuming they are equivalent to the compiler?
For completeness, an example
void readEmStar( int *arrayOfInt, int len )
{
for( int i = 0 ; i < len; i++ )
printf( "%d ", arrayOfInt[i] ) ;
puts("");
}
void readEmSquare( int arrayOfInt[], int len )
{
for( int i = 0 ; i < len; i++ )
printf( "%d ", arrayOfInt[i] ) ;
puts("");
}
int main()
{
int r[] = { 2, 5, 8, 0, 22, 5 } ;
readEmStar( r, 6 ) ;
readEmSquare( r, 6 ) ;
}
When you use the type char x[] instead of char *x without initialization, you can consider them the same. You cannot declare a new type as char x[] without initialization, but you can accept them as parameters to functions. In which case they are the same as pointers.
When you use the type char x[] instead of char *x with initialization, they are completely 100% different.
Example of how char x[] is different from char *x:
char sz[] = "hello";
char *p = "hello";
sz is actually an array, not a pointer.
assert(sizeof(sz) == 6);
assert(sizeof(sz) != sizeof(char*));
assert(sizeof(p) == sizeof(char*));
Example of how char x[] is the same as char *x:
void test1(char *p)
{
assert(sizeof(p) == sizeof(char*));
}
void test2(char p[])
{
assert(sizeof(p) == sizeof(char*));
}
Coding style for passing to functions:
It really doesn't matter which one you do. Some people prefer char x[] because it is clear that you want an array passed in, and not the address of a single element.
Usually this is already clear though because you would have another parameter for the length of the array.
Further reading:
Please see this post entitled Arrays are not the same as pointers!
C++ Standard 13.1.3
— Parameter declarations that differ
only in a pointer * versus an array []
are equivalent. That is, the array
declaration is adjusted to become a
pointer declaration (8.3.5). Only the
second and subsequent array dimensions
are significant in parameter types
(8.3.4). [Example:
int f(char*);
int f(char[]); // same as f(char*);
int f(char[7]); // same as f(char*);
int f(char[9]); // same as f(char*);
int g(char(*)[10]);
int g(char[5][10]); // same as g(char(*)[10]);
int g(char[7][10]); // same as g(char(*)[10]);
int g(char(*)[20]); // different from g(char(*)[10]);
—end example]
There is no difference between your two codes, apart from the different style obviously. In both cases the array is passed by reference and not by value, as function parameters type *x and type x[] are semantically the same.
On the style question I'll stick my neck out and say int *arrayOfInt is better. Which ever syntax you use you are passing a pointer and the type should make that clear.
This is just my opinion.
The two expressions are equivalent. They each evaluate to the address of the first element of the array arrayOfInt.
Related
please excuse my bad english,
let me clarify, here is an example,
this is our main :
main()
{
int a1 []= {1,2,3,4,5,6,7,8,9} ;
int size = sizeof(a1) /sizeof(a1[0]) ;
point (a1 , size);
return 0 ;
}
and this is the function:
void point(int a[] , int size)
{
int i ;
for (i = 0 ; i<size ; i++)
printf("%d\n", a[i])) ;
}
From my knowledge, when an array is passed as an argument to a function, we are actually sending a pointer to the first element to the array..
With that being said, how come the function "point"'s parameter is an ARRAY variable, NOT a POINTER variable...?
The reason I thought this was weird, so for example in main we pass int* to some function :
int* a = &b ;
point2(a) ;
The function:
void point2 (int a) // this would be invalid, it has to be int* a
{
.
.
}
We would have to specify that the function receives a pointer, How are arrays an exception?
PLEASE NOTE: I do understand that arrays decay to pointers; that's why my question never was "why can we send arrays as arguments, to functions that have pointers of that same type?". My question is, "How come even though arrays decay to POINTERS, its fine to keep the parameter of the function as an ARRAY?". Hope it is clear how this is different that the first question.
Thank you!
The language specifications of both C and C++ state that a function parameter of type array of T is adjusted to type pointer to T. So these function declarations are one and the same:
void foo(int a[42]);
void foo(int a[]);
void foo(int* a);
All of these will accept a pointer parameter, be it the result of an array decay or not.
Syntactic sugar.
Like juanchopanza noticed, in function arguments it's equivalent to have an array or a pointer.
For fun, try this:
void foo(int a[42])
{
printf("%zu\n", sizeof(a));
}
int main(int argc, char **argv)
{
int a[42];
printf("%zu\n", sizeof(a));
foo(a);
}
I just don't know how to explain my question precisely. So I wrote that title above.
Here is my confusion about a very simple program. Exactly, the results.
#include <iostream>
using namespace std;
char * tmp[]={"aaa", "bbb", "ccc"};//there are 3 members
int main(int argc, char* argv[], char* env[])
{
cout << sizeof(env)/sizeof(char*) << endl;
cout << sizeof(tmp)/sizeof(char*) << endl;
}
Results:1 3
What I want is the length of env[]. How can this possible that I got number 1 of env[], while the length of 'tmp'(3) is absolutely rigth.
There's no way that the length of env is 1, cause I tested it and the number is 47.
Why this happened?
Thanks!
The difference is that tmp is an array, whereas env is a pointer. Arrays and pointers are different. It's a bit confusing because array syntax in a function formal parameter list is actually a pointer in disguise.
There is no way to get the number of elements pointed to by env using sizeof. You have to go through them until you find the NULL element terminating the list.
The important thing to remember is that argv and env are pointers, not arrays. In the context of a function parameter declaration, T a[] and T a[N] are interpreted as T *a, so the types of both argv and env are char **, not char *[N].
The only way to determine how many elements each points to is by iterating through them until you find a NULL pointer:
size_t i;
for ( i = 0; argv[i] != NULL; i++ )
; // empty loop body
printf( "There are %zu elements in argv\n", i );
for ( i = 0; env[i] != NULL; i++ )
; // empty loop body
printf( "There are %zu elements in env\n", i );
The language C has certain syntactical features that are convenient for the experienced programmer, but confusing for the new learner. While the syntax T * X[] looks the same in your two cases, they actually mean two very different things:
int a[] = { 1, 2, 3}; is the same as int a[3] = { 1, 2, 3 };. Here a is an array, and the size of the array is deduced from the initializer.
void f(int b[]) is the same as void f(int * b). Here b is a pointer, and the notation is merely suggestive of the fact that you should call f with a pointer to an element of an array. For instance, you could call f(a), or equivalently f(&a[0]), or even f(a + 2). But the declarator syntax is purely a cosmetic convenience, and b is not an array, but a pointer.
This has little to do with these being parameters to main, sizeof anything is a compile time expression. Obviously, the environment and arguments passed to your program aren't. sizeof(array)/sizeof(element_type) is only the length of the array if that array was declared with a static size. Otherwise, sizeof(array) will be equivalent to sizeof(element*) (and because sizeof(char**) == sizeof(char*) you get 1 in your program).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to find the sizeof(a pointer pointing to an array)
I have the following code
int myfunc(char *arr)
{
const int sizearr = sizeof( arr ) / sizeof(char);
}
This yields the size of the pointer, not the size of the char array[17] I passed to the function.
I know that I may use strlen and solve the problem, but is there any way to convert the char*arr pointer back to the char array[17] I passed to the function in order to use the sizeof(char array[17]) ?
If you want to pass an array of 17 chars, you need to pass it by reference (C++ only):
int myfunc(char (&arr)[17])
{
unsigned int const sizearr = sizeof arr;
// ...
}
Or make a template to deduce the size:
template <unsigned int sizearr>
int myfunc(char (&arr)[sizearr])
{
// ...
}
In C, you cannot pass arrays as arguments at all, so it is your responsibility to communicate the array size separately.
Update: As #David suggests, you can fix the array type in C by passing a pointer to the array:
int myfunc(char (*arr)[17])
{
unsigned int const sizearr = sizeof *arr;
// ...
}
int main()
{
char s[17];
return myfunc(&s);
}
No, there is no such way. But in C++ you can make function template parametrized by array size and pass array by reference:
template <size_t size> void myfunc(char (&arr)[size])
{
for(size_t i = 0; i < size; ++i) std::cout << arr[i];
}
// Usage
char array[] = "My char array";
myfunc(array);
No.
There is no such way. The type char * does not contain any information about the "source", i.e. the array. This is why it's said that the array "decays" into a pointer; the pointer has less information than the array.
Also, sizeof (char) is 1.
Not really, because once the array has decayed to a pointer all information regarding its "original" form has been lost. You can always cast the pointer to a char[17] but that's bad practice.
If you really need to have an array, change the function signature to accept an array.
I've a little question.
I'm trying to define an array of function pointers dynamically with calloc.
But I don't know how to write the syntax.
Thanks a lot.
The type of a function pointer is just like the function declaration, but with "(*)" in place of the function name. So a pointer to:
int foo( int )
would be:
int (*)( int )
In order to name an instance of this type, put the name inside (*), after the star, so:
int (*foo_ptr)( int )
declares a variable called foo_ptr that points to a function of this type.
Arrays follow the normal C syntax of putting the brackets near the variable's identifier, so:
int (*foo_ptr_array[2])( int )
declares a variable called foo_ptr_array which is an array of 2 function pointers.
The syntax can get pretty messy, so it's often easier to make a typedef to the function pointer and then declare an array of those instead:
typedef int (*foo_ptr_t)( int );
foo_ptr_t foo_ptr_array[2];
In either sample you can do things like:
int f1( int );
int f2( int );
foo_ptr_array[0] = f1;
foo_ptr_array[1] = f2;
foo_ptr_array[0]( 1 );
Finally, you can dynamically allocate an array with either of:
int (**a1)( int ) = calloc( 2, sizeof( int (*)( int ) ) );
foo_ptr_t * a2 = calloc( 2, sizeof( foo_ptr_t ) );
Notice the extra * in the first line to declare a1 as a pointer to the function pointer.
I put a small example here that may help you
typedef void (*fp)(int); //Declares a type of a void function that accepts an int
void test(int i)
{
printf("%d", i);
}
int _tmain(int argc, _TCHAR* argv[])
{
fp function_array[10]; //declares the array
function_array[0] = test; //assings a function that implements that signature in the first position
function_array[0](10); //call the cuntion passing 10
}
You'd declare an array of function pointers as
T (*afp[N])();
for some type T. Since you're dynamically allocating the array, you'd do something like
T (**pfp)() = calloc(num_elements, sizeof *pfp);
or
T (**pfp)() = malloc(num_elements * sizeof *pfp);
You'd then call each function as
T x = (*pfp[i])();
or
T x = pfp[i](); // pfp[i] is implicitly dereferenced
If you want to be unorthodox, you can declare a pointer to an array of pointers to functions, and then allocate that as follows:
T (*(*pafp)[N])() = malloc(sizeof *pafp);
although you would have to deference the array pointer when making the call:
x = (*(*pafp)[i])();
typedef R (*fptr)(A1, A2... An);
where R is the return type, A1, A2... An are the argument types.
fptr* arr = calloc(num_of_elements,sizeof(fptr));
Assuming all your functions are of type void ()(void), something like this
typedef void (*fxptr)(void);
fxptr *ptr; // pointer to function pointer
ptr = malloc(100 * sizeof *ptr);
if (ptr) {
ptr[0] = fx0;
ptr[1] = fx1;
/* ... */
ptr[99] = fx100;
/* use "dynamic array" of function pointers */
free(ptr);
}
I have a structure usually containing a pointer to an int. However, in some special cases, it is necessary that this int pointer points to another pointer which then points to an int. Wow: I mentioned the word pointer 5 times so far!
Is this even possible?
I thought about it that way: Instead of using a second int pointer, which is most likely not possible as my main int pointer can only point to an int and not to another int pointer, I could make it a reference like this:
int intA = 1;
int intB = 2;
int& intC = intB;
int* myPointers[ 123 ];
myPointers[ 0 ] = &intA;
myPointers[ 1 ] = &intB;
myPointers[ 3 ] = &intC;
So the above would do what I want: The reference to intB (intC) behaves quite like I want it to (If it gets changed it also changes intB)
The problem: I can't change references once they are set, right? Or is there a way?
Everything in short: How do I get a value to work with * (pointers) and ** (pointers to pointers)?
int* and int** are different types so you can't use one as the other without using a potentially non-portable cast.
In the declaration:
int& intC = intB;
The reference intC will always refer to the int intB. The binding cannot be changed.
You could use a union to support a type that could be either an int* or an int** but you would need to be certain when you're reading, which member of the union is valid at any point.
union PIntOrPPInt
{
int* pint;
int** ppint;
};
int intA;
int intB;
int* pintC = &intB;
PIntOrPPInt myPointers[ 123 ];
myPointers[ 0 ].pint = &intA;
myPointers[ 1 ].pint = &intB;
myPointers[ 3 ].ppint = &pintC;
You could put a pointer to intB in both array elements:
myPointers[ 1 ] = &intB;
myPointers[ 3 ] = &intB;
This way both elements point to the same variable and *myPointers[1] will always be the same as *myPointers[3]. Is this what you want to achieve?
We rarely if ever use pointers to pointers in C++. Instead, like you suggest, we use reference to pointers. That said, C++ is a strongly-typed, static-typed language. So you have to decide at compile-time what your array elements are going to point to.
One approach is to wrap the array elements in a class:
struct P {
P() : p(0) { }
P(int* p) : p(p) { }
P(int** p) : p(*p) { }
operator int*() const { return p; }
int *p;
};
int main(int argc, char* argv[])
{
int *i1 = new int(5);
int **i2 = &i1;
int *&i3 = i1;
P arr[4] = {i1, i2, i3, P()};
delete i1;
return 0;
}